3

Running # su - oliver --command bash gives a shell but also prints the warning bash: no job control in this shell, and indeed Ctrl+Z and fg/bg don't work in that shell.

Running # su - oliver --session-command bash gives a shell without printing the warning, and job control indeed works.

The suggestion to use --session-command comes from Starting a shell from scripts using su results in "no job control in this shell" which states "[a security fix for su] changed the behavior of the -c option and disables job control inside the called shell".

But I still don't quite understand this. When should one use --command and when should one use --session-command? Is --command (aka -c) more secure? Or should one always use --session-command, and --command is just left in for backwards compatibility?

FWIW, I'm using RHEL 6.4.

Cristian Ciupitu
  • 6,396
  • 2
  • 42
  • 56
oliver
  • 405
  • 1
  • 7
  • 18
  • I wonder why you're getting a non-interactive shell in the first case. The bash documentation says it starts an interactive shell when you don't give any filename arguments, don't give the `-c` option, and stdin and stderr are both connected to terminals. What are you doing that you didn't show? – Barmar May 31 '14 at 07:15
  • @Barmar: I think in both cases I do get an interactive shell, at least according to http://www.tldp.org/LDP/abs/html/intandnonint.html; it's just that the first shell has no job control. – oliver Jun 02 '14 at 13:00

3 Answers3

1

Generally, you should prefer --command (-c) to --session-command. You should not be using -c with interactive shells (maybe you wanted --shell /bin/bash ?), but you should be using it with background processes.

--session-command does not call setsid() to allocate a new session (which has the effect, as you found, of allowing the continued use of the controlling tty and thus bash will give you process control being an interactive shell). This means its children can be assigned to any process group of the parent session, perhaps the session foreground pg or to avoiding killpg() or other classification based on process group id. It also retains the ability to send SIGCONT to any process in the session, though I'm not sure how abuseable that is.

Andrew Domaszek
  • 5,163
  • 1
  • 15
  • 27
  • So if I understand this correctly, `--command` will create a new session, which is more secure as the executed command no longer has access to the old session (but removes access to the terminal)? And `--session-command` will execute the new command in the old session, which gives it access to the terminal, which is necessary for job control but might also open up security holes? – oliver Jun 02 '14 at 13:49
  • Well in my use case I want to have a single "command wrapper" binary which allows to run non-interactive as well as interactive commands, so `--session-command` might be a good compromise here. For a more secure system I probably should have two distinct command wrappers: one for starting interactive shells (using `--shell`) and one for starting non-interactive commands (using `--command`). – oliver Jun 02 '14 at 13:51
0

Considering --session-command isn't on the man page of any major distro that I've heard of, it's likely a custom RHEL thing (google didn't help either).

-c makes su execute the command you specify using whatever shell is defined in /etc/passwd for the specified user. This makes it much like sudo, but as whatever user you select and know the password for. -c does not give an interactive shell, so anything requiring a tty will not work.

Nathan C
  • 15,059
  • 4
  • 43
  • 62
  • Scientific Linux 6.0 (EL6 compatible) has `--session-command` in the **su(1)** man page. It's also in this [man page](http://man7.org/linux/man-pages/man1/su.1.html). – Cristian Ciupitu May 30 '14 at 13:15
  • Ah good...weird that I couldn't just find it. In any case, i'd just use `-c` in any case. It's well-supported and the command's even listed as "discouraged". – Nathan C May 30 '14 at 13:22
  • Huh - "discouraged" sounds bad. I can see that in the man7.org link, but the man page on my system looks more like the one at http://unixhelp.ed.ac.uk/CGI/man-cgi?su and explains `--session-command` like this: "pass a single COMMAND to the shell with -c and do not create a new session". From which I still don't understand when to use this option and when to use `-c`. – oliver May 30 '14 at 14:21
  • The no "session" means you have no shell variables or anything of the sort...you're literally just calling whatever shell the user has by default and executing the command as them. It's dangerous because the lack of environment variables may cause programs to do weird things... – Nathan C May 30 '14 at 14:31
  • Just a side note: according to http://www.openwall.com/lists/oss-security/2011/06/15/4 there are several versions of `su` available; at least Ubuntu seems to use the one from shadow-utils, while the /bin/su on my RHEL6.4 system is provided by coreutils-8.4-19.el6.x86_64. – oliver May 30 '14 at 14:44
  • And on Fedora 20 **su** is part of **util-linux**. – Cristian Ciupitu May 30 '14 at 15:12
0

I've also found that using -c does not create a tty:

# su nobody -s /bin/bash -c "echo hi >/dev/tty"
bash: /dev/tty: No such device or address
#
# su nobody -s /bin/bash --session-command="echo hi >/dev/tty"
hi
#
andy
  • 1