Tuesday, August 21, 2007

Tutorial: Caveat with redirecting from su or sudo

One of the reasons why Linux is more secure than its competition is because it clearly distinguishes between running programs as an administrator and running programs as an "ordinary" user.

You should always run your programs with the least amount of privileges needed for them to work. Running a web browser as root for example is just looking for trouble. So you've embraced the idea and you are logging in as an ordinary, unprivileged user most of the time for normal work, using su or sudo for the occasional change you need to make to a printer configuration or to mount a new disk, etc.

This is a highly recommended practice. But there are a few situations where the use of su or sudo to raise privileges does not do what may at first seem logical.

Example: You want to append a line to your /etc/fstab file using the echo command

$ NEW_LINE="/dev/scd0 /media/cdrom0 udf,iso9660 user,noauto 0 0" $ sudo echo "$NEWLINE" >> /etc/fstab
bash: /etc/fstab: Permission denied
If you were to try the above you will notice that sudo doesn't even prompt for your password.

The problem occurs because of the permissions with which the redirection is being done.

What happens in the above case is that the shell, which is running as your ordinary, unprivileged user, tries to open the output stream attached to the file, /etc/fstab before it tries to execute the command "sudo". This fails, so sudo never gets executed. The same would happen with su (though this particular example would require some quoting trickery to make it work).

There are two ways to work around this problem. The first is to put the echo command, with its redirection, into a little one-line script, and then use su or sudo to execute the script. This is cumbersome as you need to first create the scriptlet.

The second workaround is to use a command which will open the file in append mode. Linux supplies us with the handy "tee" command, which can be used like this:

$ tee -a /etc/vfstab
This command will save a copy of all of its output in the file /etc/vfstab. the -a option means it will be appended to the existing file. To obtain the desired effect, we need to run the command with root privileges, and we obviously need to give it some input, like this:

$ echo "$NEW_LINE" | sudo tee -a /etc/fstab
What happens here is:
  • Firstly, echo is executed with the priviledges of the normal user. There is no need, buit if you do add "sudo" to the echo command it would not cause any problems besides wasting some CPU-time.
  • Secondly, the shell then re-directs the output from the echo to the sudo command.
  • The sudo command runs "tee" as root, and attaches tee to its own standard input and output streams. Therefore tee receives the standard input redirected from the echo command.
  • The tee command, running as root, opens the output file. This is important - in the case of the redirection the output file was being opened by the parent shell, not by the command which has got raised privileges as in this case!
  • Once all of this preparation work is in place, the output goes through and all is well and done.
So to summarise, redirecting the output from su or sudo to a restricted file or directory does not work because the redirection itself is done by the parent shell and therefore with the current user's privileges.