This action requires saving a cookie to remember the page's state. You can read more about that on the cookies page.

 

The difference between sudo -i and su -

Released on: 2023-12-14

A couple of weeks ago, there was a question posed on Reddit, where almost all of the responses were dangerously incomplete, or simply wrong. That question was

What’s the difference between sudo -i and su -?

Let’s fix that now.

Table of contents

Some misconceptions

Who’s password gets used?

After a bit of fumbling, most threads landed on:

  • su uses the destination user’s password.
  • sudo defaults to using the origin user’s password, but can be configured differently.

Excellent… Or is it?

PAM vs /etc/shadow

One myth that came up, but seems to be deleted/edited now, is that sudo uses PAM, while su re-implements the authentication against /etc/shadow.

Both use PAM:

PAM config for both utilities in Fedora 39.
Above: PAM config for both utilities in Fedora 39.

These configurations define how authentication works for each utility, so it’s possible to change how su authenticates the user (including which password is used). Although I don’t recommend it (Spoiler: That’s what sudo is for.)

PAM config for su in Fedora 39.
Above: PAM config for su in Fedora 39.

Note that while the following PAM config controls how authentication works for sudo, there will rarely be a need to touch this. Instead you’ll want to change /etc/sudoers or /etc/sudoers.d.

PAM config for sudo in Fedora 39.
Above: PAM config for sudo in Fedora 39.

I also did the same checks on Debian, Ubuntu and OpenSUSE. Only OpenSUSE was ambiguous (there’s likely an easy way to tell, but I didn’t see value in pursuing it further.)

The myth that su uses /etc/shadow has been popping up from time-to-time for many years, and I suspect that it might have been true at some point. But it certainly hasn’t been true for a very long time. Here’s a couple of screenshots from Fedora Core 2 (from 2004):

PAM config files for both su and sudo on Fedora Core 2.
Above: PAM config files for both su and sudo on Fedora Core 2.

This is what the su config looks like.

PAM config for su on Fedora Core 2.
Above: PAM config for su on Fedora Core 2.

Running a command vs becoming a user

Many commenters stated that sudo runs a command with escalated privileges, while su becomes the user.

In reality, both commands can be used to run a command with escalated privileges:

Both commands being used to escalate privileges for a single command.
Above: Both commands being used to escalate privileges for a single command.

And both commands can be used to become a different user:

Both commands being used to become a user.
Above: Both commands being used to become a user.

Becoming users other than root

There were a whole heap of combinations of ideas around which utility could become a different user directly, and which couldn’t.

Both can become a specific non-root user:

Both commands being used to become another user.
Above: Both commands being used to become another user.

Both commands can run a command as a specific user:

Both commands being used to run whoami as anotheruser.
Above: Both commands being used to run whoami as anotheruser.

What was nailed in the Reddit conversation

Environment variables setup

While both sudo -i and su - perform a login shell to give you the full environment of the destination user, they do it a little differently:

How many environment variables are available via each method.
Above: How many environment variables are available via each method.

Here is the key in the su man page:

       -, -l, --login
           Start the shell as a login shell with an environment similar to a real login:

           •   clears all the environment variables except TERM and variables specified by
               --whitelist-environment

           •   initializes the environment variables HOME, SHELL, USER, LOGNAME, and PATH

           •   changes to the target user’s home directory

           •   sets argv[0] of the shell to '-' in order to make the shell a login shell

Specifically:

           •   clears all the environment variables except TERM and variables specified by
               --whitelist-environment

Meanwhile from the sudo man page:

       -i, -‐login
               Run the shell specified by the target user’s password database entry as a login shell.  This
               means  that login‐specific resource files such as .profile, .bash_profile, or .login will be
               read by the shell.  If a command is specified, it is passed to the shell as a simple command
               using the -c option.  The command and any args are concatenated, separated by spaces,  after
               escaping  each  character (including white space) with a backslash (‘\’) except for alphanu‐
               merics, underscores, hyphens, and dollar signs.  If no command is specified, an  interactive
               shell is executed.  sudo attempts to change to that user’s home directory before running the
               shell.   The  command  is run with an environment similar to the one a user would receive at
               log in.  Most shells behave differently when a command is specified as compared to an inter‐
               active session; consult the shell’s manual for details.  The Command environment section  in
               the sudoers(5) manual documents how the -i option affects the environment in which a command
               is run when the sudoers policy is in use.

Notice that there is no mention of clearing existing environment variables.

Some history

su

su has been around for as long as I can remember. In the 90s, it seemed magical to be able to switch to another user without having to log out and in again. You needed to know the password of the account that you want to switch to, but that was well worth the time saving of not having to log out and in again.

Since then, it hasn’t changed a lot from a user perspective. If there’s any truth to the idea of it reading /etc/shadow directly in the past, I’m guessing that authentication via PAM probably has.

A result of needing the destination user’s password, is that if you needed root access on a machine, you needed to have the root password. On single-user systems, this wasn’t a big deal. But on multi-user systems, this means everyone who needs root access would need to have the root password. If there was a need to change the password (eg after an employee leaves), then the password needed to be changed, and everyone would have a new password to remember. It also meant that there were many potential places for the root password to get leaked. - Only one person needed to make a mistake for it to be exposed. Basically, it was a security nightmare.

Enter sudo

sudo came in to address this in a couple of ways:

  • Use the origin user’s password instead of the destination user’s password, and only allow specific users to use sudo.
  • Encourage only escalating privileges when needed, rather than switching user for the entire time.

At this point, the root account’s password can now be disabled, and you never need to log in to anything using the root account. - In the early days of Ubuntu, this was one of selling points of it compared to other distros. There was a lot of FUD surrounding it, because people were so used to using the root account. But as we all got used to it, it slowly became the norm, and we are in a better place now because of it.

Real world differences

So far, the only differences between the two utilities are:

  • Using the destination account’s credentials vs using the origin account’s credentials, by default.
  • Which environment variables get created when simulating a login shell.

While PAM configuration can be changed to influence authentication behaviour, you shouldn’t do so unless there is a good reason (Eg you want to add support for Google Authenticator, or Yubikey.) Therefore we can assume that those bullets won’t change much.

Meanwhile, we’ve yet to explore the sudoers config.

sudoers

/etc/sudoers and /etc/sudoers.d is where the magic happens that really sets the two utilities apart.

For personal desktop use, you probably don’t need to change the defaults, and so barely look at these files, if ever. But when you need to restrict access in a multi-user environment, or you need to track command-line usage for compliance with regulations, this configuration is so, so important.

You can specify things like:

  • Who can escalate privileges, or change to different accounts.
  • What accounts they can change to, or not change to.
  • What they can run, or not run.
  • How long their authentication is valid before they have to enter it again.

You need to take some care when editing these files, but you can help yourself with a tool like visudo, which wraps your text editor in a sanity check, and rolls-back the changes if you’ve created a breaking change.

Current intention

  • su - Ideal in scripts that run in non-interactively, like service management. These have mostly been taken over by systemd now.
  • sudo - Ideal for anything user-facing.

In general, the use-cases that make sense for a user to use su in any capacity, are now very rare. If you catch yourself wanting to use it over sudo, it’s worth asking your self why; you’re probably doing something wrong.

In fact, if a system requires you to know the passwords for multiple accounts, take that as an indication that you’re probably doing something wrong. Especially if you have multiple people using the same account. If you can get that root account disabled, you’ll have removed a big attack surface.

Why is sudo su - a bad habbit?

It’s an extra process, more typing, and it’s duplicating common functionality (Ie sudo -i or su - do almost identical jobs.) But most of the time, it probably doesn’t matter on a modern system.

However, it does come into play when you are obligated to lock down how people get what access to what stuff, and to track everything that they do. When I was involved in such an operation, and a user used sudo -i, we could be certain that the appropriate tracking was being used. But if they loaded up a shell via any other method, we couldn’t be certain.

We had a few weeks of cat & mouse while we patched the holes, and tried to find the short-comings of the permissions that we had granted users. Ie Why did they want a shell? And why didn’t they want to use -i? - Sometimes it was just education. Sometimes they were doing something they weren’t supposed to be doing, but unaware that it was a problem.

Updating OpenSUSE to use the origin credentials

Throughout this post, you may have noticed that I’m on a system that uses the destination user’s password rather the origin’s:

Sudo asking for the password of root rather than the origin account.
Above: Sudo asking for the password of root rather than the origin account.

Sudo asking for the password of anotheruser rather than the origin account.
Above: Sudo asking for the password of anotheruser rather than the origin account.

That’s sudo’s default configuration on OpenSUSE.

Let’s fix that.

Steps

Add any user that you want to be able to sudo, to the wheel group. You can do it like this:

$ sudo gpasswd -a `whoami` wheel
Adding user ksandom to group wheel

Now we need to edit the /etc/sudoers file. We can do that with the visudo command.

Find the lines that look like this:

Defaults targetpw   # ask for the password of the target user i.e. root
ALL   ALL=(ALL) ALL   # WARNING! Only use this together with 'Defaults targetpw'!

and comment them out to look like this:

#Defaults targetpw   # ask for the password of the target user i.e. root
#ALL   ALL=(ALL) ALL   # WARNING! Only use this together with 'Defaults targetpw'!

Now find this line:

# %wheel ALL=(ALL:ALL) ALL

And uncomment it like this:

%wheel ALL=(ALL:ALL) ALL

Save, and exit. If you’re using vim, you can exit and save like this:

:wq

You might need to log out, and log back in again to get the groups applying. So you can test it first like this:

Triggering a fresh login shell to make sure that the groups are applied.
Above: Triggering a fresh login shell to make sure that the groups are applied.

And then test sudo:

Sudo is now working using the origin password.
Above: Sudo is now working using the origin password.

Notice that it is now asking for my password, instead of root’s password.

Log out, and back in again to get the behaviour across all shells.

Tip

It’s worth having an extra shell running as root while you make these changes, so that if you make a mistake, you can run visudo again to restore the previous configuration while you figure out the problem. visudo protects against configuration failures. But it doesn’t protect against permissions failures.

This post references

I've been in the computer industry for well over two decades. It has changed so much that it is barely recognisable compared to what it was. Most of the changes are for the better. Some are things that we have always sucked at. And some are very much worse. The weCanDoThisBetter series of blog posts is for addressing the areas where we could do better.

Posts using the same tags

Timezones are surprisingly hard already. But there's one practice in communication that makes them so much harder that they need to be in international settings. Luckily the solution is really easy.
Why portrain-only designs on mobile devices are a bug. And why that matters.
A recent question on Reddit resulted in many incomplete and wrong answers. It seemed valuable to dive a little deeper.
If your technical documentation would sound amazing when narrated by someone like Morgan Freeman, or Judi Dench, it's not documentation.
Why you should think carefully before requesting refunds from a crowdfunding campaign.
CentOS, as we know it, is ending. What? Why? And what we should do next.
I've been in the computer industry for well over two decades. It has changed so much that it is barely recognisable compared to what it was. Most of the changes are for the better. Some are things that we have always sucked at. And some are very much worse. The weCanDoThisBetter series of blog posts is for addressing the areas where we could do better.
calibrate multiple touch and non touch screens on a single linux system." This is to address the issue on multi-display Linux desktops where the touch panel is automatically calibrated to operate over all of the displays, and even if you get the calibration right, it's then wrong again when you ...
Home | About | Contact | Cookies | Site map