An irritating and interesting su change from Ubuntu 12.04 to 14.04

June 10, 2014

In Ubuntu 12.04, the su manpage describes the -c option with this minimal description:

-c, --command COMMAND
Specify a command that will be invoked by the shell using its -c [option].

In Ubuntu 14.04, the following note was added as well:

The executed command will have no controlling terminal. This option cannot be used to execute interactive programs which need a controlling TTY.

This change broke part of my customary environment. For years I have been su'ing to root but running an alternate shell once I got there by actually doing '/bin/su -c "exec $myshell"' (generally this incantation is hiding behind other scripts). On the traditional su, as found on 12.04 and previous LTS releases as well as on, eg, Fedora, this works fine. On 14.04 my shell started spitting out errors about 'tcsetgrp: Inappropriate ioctl for device' (probably because my shell has readline support these days) and bash complained:

bash: cannot set terminal process group (14684): Inappropriate ioctl for device
bash: no job control in this shell

Contrary to what the manpage says, interactive programs do not actually fail. Pretty much everything runs fine, except of course there's no job control and my shell whined incessantly; the former doesn't bother me since I don't use it anyway, but the latter was rather annoying.

That's the irritating part. The interesting part is why this change was made, because it turns out not to be an arbitrary one; instead it's actually sort of a security fix. In Ubuntu, su comes from the shadow package, which in May of 2012 was updated to a new upstream version that included the following change (from the Ubuntu changelog):

  • su: Fix possible tty hijacking by dropping the controlling terminal when executing a command (CVE-2005-4890). Closes: #628843

A longer description of the problem CVE-2005-4890 is about is here, with links to various discussions of the issue. This writeup notes that a number of people don't think that this is a bug and are not fixing it. This includes some Linux distributions and also some upstream authors of versions of su.

(That's right, Linux has multiple versions of su. Fedora 20 uses the util-linux version, for example, and neither Fedora nor the upstream has changed su to fix this CVE's issue.)

On the one hand I can't exactly blame the upstream 'shadow' maintainers for fixing this; it is a possible security issue. On the other hand it is a change to long-standing behavior in order to fix what is very likely to be an extremely rare vulnerability and it doesn't even apply in this situation (since I am su'ing to root, not away from it). So on the whole I selfishly wish that they hadn't changed the behavior of 'su -c', at least for people su'ing to root.

Fortunately the fix is easy. I just need to use '/bin/su -s $myshell' instead of my old incantation. Unfortunately this is slightly less portable as the -s option is not present on things like Solaris (well, OmniOS) while -c goes back to the mists of time.

(I only discovered that this was a CVE fix when I started writing this entry and decided to dig into the exact versions involved, read the changelogs, and so on so that I could write an informed entry. Once again blogging has proved educational.)


Comments on this page:

By Ewen McNeill at 2014-06-10 06:06:50:

If you're already teaching your fingers to type something else, maybe it is worth teaching them to type something with more Hamming Distance, such as "sudo -s"? AFAICT, if you set SHELL in your environment to whatever you want the shell to be, it'll use that in preference to the /etc/passwd value, eg "SHELL=python sudo -s" seems to launch a python interpreter. And if that's not sufficient, "sudo -s /bin/bash", "sudo -s /bin/sh", etc, seem to work.

I do tend to agree with you that its a bug fix that probably warranted special casing the "to root" direction. If only for finger-compatiblity with other unix systems where root's shell is often not the preferred one for interactive use.

Ewen

By mancha at 2014-08-24 14:40:05:

This was indeed a change to address the potential for injecting commands to a privileged tty.

As I explain in su -c, tty hijacking, and some breakage, the fix is overkill because it also cripples the case where su -c is being used to escalate privileges.

After all, the threat vector of concern is injection from unprivileged to privileged (not of root injecting commands).

The url above contains a link to my relax patch - currently used by Slackware Linux - that preserves the controlling tty when the callee is root.

--mancha

Written on 10 June 2014.
« A challenge in new languages: learning to design good APIs
Some thoughts on testing parsers »

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

Last modified: Tue Jun 10 01:15:46 2014
This dinky wiki is brought to you by the Insane Hackers Guild, Python sub-branch.