3

I have a user switcher that has different use-cases. It's PATH should depend on whether the current shell is restricted or not. Thus I've added to the end of /home/switcher/.bashrc:

[[ $- == *r* ]] && PATH='' && echo 'restricted' || echo 'unrestricted' 

Yet it doesn't work as expected when switching users:

root@host:~$ sudo -u switcher rbash
unrestricted
switcher@host:~$ echo $PATH
/home/switcher/bin:/usr/local/bin:/usr/bin:/bin
switcher@host:~$ echo $- $SHELL
himrBHs /usr/sbin/nologin

This tells me that .bashrc was in fact executed but apparently outside rbash. What am I missing here? What do I need to change so that PATH='' is set when executing rbash but not in bash?

Note that having different users for the different use-cases unfortunately isn't an option for me.

2
  • You can't set / change PATH in restricted bash: gnu.org/software/bash/manual/html_node/… (But you can probably use env to start the restricted bash with a different PATH.)
    – Tom Yan
    Apr 21, 2022 at 14:52
  • 2
    @TomYan From the page you linked to: "These restrictions are enforced after any startup files are read". It's absolutely possible to change PATH from within .bashrc processed automatically by a restricted bash. The restrictions kick in later. Apr 21, 2022 at 17:04

1 Answer 1

5

My tests show that r appears in $- after rbash reads ~/.bashrc, as if the shell was not restricted during processing the file. This corresponds to what the manual says about restrictions:

These restrictions are enforced after any startup files are read.

One of the restrictions is the inability to change PATH. Since you do want to change PATH, it's actually good for your case the restrictions are enforced later. It seems r in $- indicates that the shell is effectively restricted at the moment. You want to detect if it's going to be effectively restricted. You cannot use $- for this.

There is a mechanism designed deliberately for what you need to do. It's in shopt [emphasis mine]:

restricted_shell

The shell sets this option if it is started in restricted mode […]. The value may not be changed. This is not reset when the startup files are executed, allowing the startup files to discover whether or not a shell is restricted.

Use it like this:

shopt -q restricted_shell && PATH='' && echo 'restricted' || echo 'unrestricted'

Or better:

if shopt -q restricted_shell; then
   PATH=''
   echo 'restricted'
else
   echo 'unrestricted'
fi

The latter is better because the second echo depends only on the exit status from shopt. For comparison: in the former snippet (and in your original code) failing first echo would trigger the second echo. With echos this seems marginal, irrelevant or harmless, but if you add more commands then a line with many && and || may surprise you if one of them fails unexpectedly.

Also note that printing anything from .bashrc will break scp and similar software (even printing to stderr may), unless your .bashrc is smart enough.

1
  • This answer is perfect! You're awesome, thank you so much for sharing your knowledge and research. I only added the echos for debugging purposes, I won't use them in the final solution. But your notes are appreciated regardless.
    – morrow
    Apr 21, 2022 at 17:42

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .