What /etc/shells is and isn't

January 14, 2015

In traditional Unix, /etc/shells has only one true purpose: it lists programs that chsh will let you change your shell to (if it lets you do anything). Before people are tempted to make other programs use this file for something else, it is important to understand the limits of /etc/shells. These include but are not limited to:

  • Logins may have /etc/passwd entries that list other shells. For example, back when restricted shells were popular it was extremely common to not list them in /etc/shells so you couldn't accidentally chsh yourself into a restricted shell and then get stuck.

    Some but not all programs have used the absence of a shell from /etc/shells as a sign that it is a restricted shell (or not a real shell at all) and they should restrict a user with that shell in some way. Other programs have used different tests, such as matching against specific shell names or name prefixes.

    (It's traditional for the FTP daemon to refuse access for accounts that do not have a shell that's in /etc/shells and so this is broadly accepted. Other programs are on much thinner ice.)

  • On the other hand, sometimes you can find restricted shells in /etc/shells; a number of systems (Ubuntu and several FreeBSD versions) include rbash, the restricted version of Bash, if it's installed.

  • Not all normal shells used in /etc/passwd or simply installed on the system necessarily appear in /etc/shells for various reasons. In practice there are all sorts of ways for installed shells to fall through the cracks. Of course this makes them hard to use as your login shell (since you can't chsh to them), but this can be worked around in various ways.

    For example, our Ubuntu systems have /bin/csh and /bin/ksh (and some people use them as their login shells) but neither are in /etc/shells.

  • The (normal and unrestricted) shell someone's actually using isn't necessarily in either /etc/shells or their /etc/passwd entry. Unix is flexible and easily lets you use $SHELL and some dotfile hacking to switch basically everything over to running your own personal choice of shell, per my entry on using an alternate shell.

    (Essentially everything on Unix that spawns what is supposed to be your interactive shell has been clubbed into using $SHELL, partly because the code to use $SHELL is easier to write than the code to look up someone's /etc/passwd entry to find their official login shell. This feature probably came into Unix with BSD Unix, which was basically the first Unix to have two shells.)

  • Entries in /etc/shells don't necessarily exist.
  • Entries in /etc/shells are not necessarily shells. Ubuntu 14.04 lists screen.

  • Not all systems even have an /etc/shells. Solaris and derivatives such as Illumos and OmniOS don't.

In the face of all of this, most programs should simply use $SHELL and assume that it is what the user wants and/or what the sysadmin wants the user to get. It's essentially safe to assume that $SHELL always exists, because it is part of the long-standing standard Unix login environment. As a corollary, a program should not change $SHELL unless it has an excellent reason to do so.

Note particularly that a user's $SHELL not being listed in /etc/shells means essentially nothing. As outlined above, there are any number of non-theoretical ways that this can and does happen on real systems that are out there in the field. As a corollary your program should not do anything special in this case unless it has a really strong reason to do so, generally a security-related reason. Really, you don't even want to look at /etc/shells unless you're chsh or ftpd or sudo or the like.

(This entry is sadly brought to you by a program getting this wrong.)

Written on 14 January 2015.
« Our tradeoffs on ZFS ZIL SLOG devices for pools
General ZFS pool shrinking will likely be coming to Illumos »

Page tools: View Source, Add Comment.
Search:
Login: Password:
Atom Syndication: Recent Comments.

Last modified: Wed Jan 14 01:23:10 2015
This dinky wiki is brought to you by the Insane Hackers Guild, Python sub-branch.