# /bin/sh as a fallback login shell



## Cthulhux (Jan 21, 2014)

Is there a reason why login(8) behaves so _interesting_?

I'm currently _tabularasaing_ my server, reinstalling all applications, leaving out stalled dependencies and all that. Now I noticed that there is no fallback shell; if `zsh` is set as the login shell and it is (temporarily) removed, login(8) says "access denied" which is, in my opinion, not a good error message.

I'd propose an automatic fallback to /bin/sh if the set shell is invalid and/or not accessible.

edit: I just noticed that the "Feedback" forum is not meant for "FreeBSD feedback". Some moderator and/or administrator might want to move this where it belongs, sorry for the inconveniences.


----------



## SirDice (Jan 22, 2014)

How would the fallback work if the shell is set to /usr/sbin/nologin?


----------



## kpa (Jan 22, 2014)

It's definitely for historical reasons and every UNIX like OS probably does the same thing. It's not a bad idea though but implementing it would require a thorough review of the login(8) process so that no security holes are introduced in the process. On another thought, login(8) is not used in ssh(1) connections is that right? This kind of fallback would probably belong in PAM I think.


----------



## worldi (Jan 22, 2014)

There's no need for this. Mishaps like this can easily be fixed in single-user mode (whose shell defaults to /bin/sh). Another option is to not change you root's shell to something that requires 3rd-party libs (e.g. use a statically linked binary and copy it to /bin).


----------



## Cthulhux (Jan 22, 2014)

SirDice said:
			
		

> How would the fallback work if the shell is set to /usr/sbin/nologin?



Well, this special case should be treated differently of course.


----------



## SirDice (Jan 22, 2014)

I think there would be too many exceptions and not all of the exceptions are known in advance (/usr/bin/false is another that would work). Which would make the system quite unpredictable. At least now it fails on very predictable occasions.


----------



## Cthulhux (Jan 22, 2014)

With no chance to fix it when it happens. No access to the shell means you can't even fix the mistake.
(Also, "access denied" is still not really helpful, is it?)


----------



## worldi (Jan 22, 2014)

SirDice said:
			
		

> How would the fallback work if the shell is set to /usr/sbin/nologin?


Login could simply stat(2) the user's shell and default to /bin/sh in case it does not exist. The real problem is that having such a fallback would change the default behavior from deny to allow.


----------



## SirDice (Jan 22, 2014)

worldi said:
			
		

> SirDice said:
> 
> 
> 
> ...


That doesn't solve the problem of bash not being able to open libc for example. The file exists, you just cannot execute it properly because some of the libraries it needs have gone missing. And checking the dependency chain each time a user logs in doesn't scale very well.


----------



## throAU (Jan 24, 2014)

2c. 

You can already do this - leave your shell set to /bin/sh and run /usr/local/bin/zsh from your .profile or the system's /etc/profile.

Yes, you will need to exit two shells to log out, but the alternative, having a fall-back shell for a non-existent shell specified in your account will break existing behaviour.

Presumably you are complaining about this because you locked yourself out of root by changing root's shell?  If so maybe create/use a fallback account (such as toor) with the default /bin/sh.


----------



## nanotek (Jan 24, 2014)

Cthulhux said:
			
		

> Is there a reason why login(8) behaves so _interesting_?
> 
> I'm currently _tabularasaing_ my server, reinstalling all applications, leaving out stalled dependencies and all that. Now I noticed that there is no fallback shell; if `zsh` is set as the login shell and it is (temporarily) removed, login(8) says "access denied" which is, in my opinion, not a good error message.
> 
> ...



I actually think this is a very good idea and precisely the type of forward-thinking that is needed.


----------



## SirDice (Jan 24, 2014)

throAU said:
			
		

> 2c.
> 
> You can already do this - leave your shell set to /bin/sh and run /usr/local/bin/zsh from your .profile or the system's /etc/profile.
> 
> Yes, you will need to exit two shells to log out, but the alternative, having a fall-back shell for a non-existent shell specified in your account will break existing behaviour.


Start the other shell with exec. That will replace the running process (/bin/sh) with the new one (/usr/local/bin/zsh for example). Also note that zsh and bash will also execute ~/.profile. You don't want to start an infinite loop.


----------



## worldi (Jan 24, 2014)

throAU said:
			
		

> You can already do this - leave your shell set to /bin/sh and run /usr/local/bin/zsh from your .profile or the system's /etc/profile.


Nice, very clever. The use of `exec` should probably be reserved for statically linked binaries:


```
SHELL2="/usr/local/bin/zsh"
SHELL2_ARGS="-l"

get_shell_type() {
  if test -f "$1" -a -r "$1" -a -x "$1"
  then
    file "$1" | grep -q "dynamically linked" && echo 1
    file "$1" | grep -q  "statically linked" && echo 2
  fi
}

if [ "$SHELL" != "$SHELL2" ]
then
  case $(get_shell_type "$SHELL2") in
  1) SHELL="$SHELL2"      "$SHELL2" $SHELL2_ARGS;;
  2) SHELL="$SHELL2" exec "$SHELL2" $SHELL2_ARGS;;
  *) logger -s -t "WARNING" "cannot run $SHELL2, using $SHELL instead";;
  esac
fi
```


----------



## Cthulhux (Jan 24, 2014)

throAU said:
			
		

> Presumably you are complaining about this because you locked yourself out of root by changing root's shell?



Almost, but only with one of two SSH processes, so I could avert worse things happening.


----------



## SirDice (Jan 24, 2014)

Next time you do a similar upgrade, make sure root's shell is default (/bin/csh) and set the shell for an admin account to /bin/tcsh. Also make sure your admin user is a member of the wheel group. Not only can 3rd party shells break after a major upgrade but also tools like sudo. With an admin account that's a member of wheel you should be able to login and use su(1) to become root.


----------



## Cthulhux (Jan 24, 2014)

Good idea, I'll consider that.

(Still hoping that my immature idea might mature some day...)


----------

