Difference between sudo -i and sudo su

Based on the descriptions from the man pages for su and sudo I would assume the following things.

  1. Since sudo -iu <user> means a login shell this would be equivalent to an su - <user> or su -l <user>.
  2. An su without any arguments changes your effective user ID but you're still using your original <user> environment and a who am i will report you're still <user>.

excerpt sudo man page

-i [command]
        The -i (simulate initial login) option runs the shell specified in
        the passwd(5) entry of the target user as a login shell.  This means
        that login-specific resource files such as .profile or .login will 
        be read by the shell.  If a command is specified, it is passed to 
        the shell for execution.  Otherwise, an interactive shell is 
        executed.  sudo attempts to change to that user's home directory 
        before running the shell.  It also initializes the environment, 
        leaving DISPLAY and TERM unchanged, setting HOME, MAIL, SHELL, 
        USER, LOGNAME, and PATH, as well as the contents of 
        /etc/environment on Linux and AIX systems.  All other environment 
        variables are removed.

Example

I have a user account, saml with a UID of 500.

$ egrep "Uid|Gid" /proc/$$/task/$$/status
Uid:    500 500 500 500
Gid:    501 501 501 501

In the above output, the 1st column is my real UID (uid) and the 2nd is my effective UID (euid).

Becoming root via (su)

$ su

Now I'm root, but I still maintain my environment and my real UID is still 500. Notice that my euid is now 0 (root).

$ egrep "Uid|Gid" /proc/$(pgrep su -n)/task/$(pgrep su -n)/status
Uid:    500 0   0   0
Gid:    501 501 501 501

However my environment is still saml's. Here's one of he environment variables, $LOGNAME.

$ env | grep LOGNAME
LOGNAME=saml

Becoming root via (su -) or (sudo -i)

$ su -

With an su - or sudo -i not only do I change my effective UID to a new user, but I also source their files as if it was a login, and my environment now becomes identical as if I were them directly logging in.

$ egrep "Uid|Gid" /proc/$(pgrep su -n)/task/$(pgrep su -n)/status
Uid:    500 0   0   0
Gid:    501 501 501 501

However my environment is now root's. Same variable, $LOGNAME, now it's set with root.

$ env | grep LOGNAME
LOGNAME=root

So then what's the difference?

Well let's try the above with sudo -i and find out.

$ sudo -i

Now let's look at the same info:

$ egrep "Uid|Gid" /proc/$(pgrep su -n)/task/$(pgrep su -n)/status
Uid:    0   0   0   0
Gid:    501 501 501 501

Well one major thing is my effective ID and real ID are both 0 (root) with this approach. The environment variable $LOGNAME is as if we logged in as root.

$ env | grep LOGNAME
LOGNAME=root

Comparing environments

If we count the number of lines in say the 3 methods, perhaps there is some additional info to be had.

$ env > /tmp/<method used to become root>

We are left with these 3 files:

  • -rw-r--r-- 1 root root 1999 Nov 2 06:43 sudo_root.txt
  • -rw-r--r-- 1 root root 1970 Nov 2 06:44 sudash_root.txt
  • -rw-r--r-- 1 root root 4859 Nov 2 06:44 su_root.txt

Already we can see that something is up with just a plain su. The env. is over 2x the size of the others.

Number of lines in each:

$ wc -l su*
  28 sudash_root.txt
  32 sudo_root.txt
  92 su_root.txt

There's really no need to look further at the su_root.txt file. This file contains a much of user's environment that ran the su command. So let's look at the other 2 files.

They're virtually identical except for a few cosmetic variables, such as $LANG being slightly different. The one smoking gun in the list is the $PATH.

sudo

 PATH=/usr/lib64/ccache:/usr/local/sbin:/sbin:/bin:/usr/sbin:/usr/bin:/usr/brlcad/bin:/root/bin

su -

PATH=/usr/lib64/qt-3.3/bin:/usr/lib64/ccache:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/usr/brlcad/bin:/root/bin

As you can see sudo -i gives us some additional protection by stripping out suspicious paths, but it also keeps our $DISPLAY and $TERM intact in case we were displaying a GUI to different location.

Take aways?

  1. So the big take away is that the method used to become root sudo -i is advantages over the others because you use your own password to do so, protecting root's password from needing to be given out.
  2. There is logging when you became root, vs. mysteriously some one becoming root via su or su -.
  3. sudo -i gives you a better user experience over either su's because it protects your $DISPLAY and $TERM.
  4. sudo -i provides some protection to the system when user's become root, by limiting the environment which they are given.

What about sudo su, you didn't even discuss it?

I intentionally avoided bringing that into the discussion even though the OP asked about it because doing so would only of confused the issue, IMO. When you run sudo su the sudo command masks the effects of the su and so much of the environment that you'd get from a regular su is lost. Sudo is doing its job and providing a limited and protected environment regardless of whether it's sudo su or sudo -i.

Example

Here's the result of the sudo su environment being dumped:

ls -l /tmp/sudosu_root.txt
-rw-r--r-- 1 root root 1933 Nov  2 14:48 /tmp/sudosu_root.txt

And the number of lines:

$ wc -l /tmp/sudosu_root.txt 
31 /tmp/sudosu_root.txt

These are the only variables that differ between a sudo su - and a sudo -i:

$ sdiff /tmp/sudosu_root.txt /tmp/sudo_root.txt  | grep ' |'
USERNAME=saml                             | USERNAME=root
PATH=/usr/lib64/ccache:/sbin:/bin:/usr/sbin:/usr/bin:/usr/brl | PATH=/usr/lib64/ccache:/usr/local/sbin:/sbin:/bin:/usr/sbin:/
MAIL=/var/spool/mail/saml                 | MAIL=/var/spool/mail/root
PWD=/home/saml/tst                        | PWD=/root
SUDO_COMMAND=/bin/su                      | SUDO_COMMAND=/bin/bash
XAUTHORITY=/root/.xauthYFtlL3             | XAUTHORITY=/var/run/gdm/auth-for-saml-iZePuv/datab

So as you can see there really isn't much of a difference between them. Slightly different $PATH, the $SUDO_COMMAND, and the $MAIL and $USERNAME are the only differences.

References

  • Real and Effective IDs

I think @slm misread the question, so providing another answer.

He did hit on the main point, about one being a login shell and the other not.
When running sudo -i the shell will become a login shell, and so it will read things like ~/.profile where as a non-login shell will only read ~/.bashrc.

When chaining sudo with su (as in sudo su), neither the sudo nor the su invoke a login shell. The equivalent to sudo -i when using su would instead be sudo su -l.

I personally consider sudo su to be along the lines of "useless use of cat" examples. You can get the same behavior with sudo -s.

There are basically 5 common ways of invoking a root shell via sudo

  • sudo su

    • non-login shell
    • sets HOME to /root
    • Prunes the environment
  • sudo -i

    • login shell
    • sets HOME to /root
    • Prunes the environment
  • sudo su -l

    • login shell
    • sets HOME to /root
    • Prunes the environment

    When invoking a shell, this is equivalent to sudo -i

  • sudo -s

    • non-login shell
    • sets HOME to /root
    • Prunes the environment

    When invoking a shell, this is equivalent to sudo su

  • sudo -Es

    • non-login shell
    • Leaves HOME alone
    • Leaves the environment alone (except for $PATH and $LD_LIBRARY_PATH iirc)

Note, that these rules only apply when using them to gain a shell. There is a difference between sudo -s somecommand and sudo su -c somecommand.


The second one preserves the current directory (pwd) but the first command drops the user to the root's home directory.

Tags:

Command

Sudo

Su