`sudo -i` and `sudo su -` behave differently

I ran into a problem over at NS8 installation on Rocky Linux fails - Bug - NethServer Community, and in troubleshooting it I encountered something unexpected. I’d installed Rocky 9.1 with the minimal installation, adding only the hypervisor guest packages as it was running as a VM under Proxmox. I’d set up a non-root user as an administrator during the installation. Then, to install the software I wanted, I used sudo -i to become root and ran the installer–which failed, due to a $PATH problem.

Further investigation revealed that $PATH is different depending on whether I become root using sudo -i or sudo su -:

[dan@rocky9-2 ~]$ echo $PATH
/home/dan/.local/bin:/home/dan/bin:/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin
[dan@rocky9-2 ~]$ sudo -i
[sudo] password for dan:
[root@rocky9-2 ~]# echo $PATH
/root/.local/bin:/root/bin:/usr/local/sbin:/sbin:/bin:/usr/sbin:/usr/bin
[root@rocky9-2 ~]#
logout
[dan@rocky9-2 ~]$ sudo su -
Last login: Wed Mar  8 06:19:38 EST 2023 on tty1
[root@rocky9-2 ~]# echo $PATH
/root/.local/bin:/root/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin

/usr/local/bin is in the unprivileged user’s path, and it’s also in root’s path if I do sudo su -–but it isn’t there if I do sudo -i. OTOH, /sbin is in root’s path if I do sudo -i, but not if I do sudo su -.

This isn’t what I’d expected–in my past experience (and according to the sudo man page), sudo -i gives root’s login environment, but that clearly isn’t happening here. Is this a bug, or am I just missing something?

You are comparing commands:

  • su --login
  • sudo --login

man su writes:

-, -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

man sudo writes:

-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 for execution via the shell’s -c option. 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. Note that most shells behave differently when a command is specified as compared to an interactive 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.

Lets see what PATH do I get:

  • Console login:
    /root/.local/bin:/root/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin
  • su --login
    /root/.local/bin:/root/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin
  • sudo --login
    /root/.local/bin:/root/bin:/usr/local/sbin:/sbin:/bin:/usr/sbin:/usr/bin

The PATH is not preserved by sudoers and man 5 sudoers writes:

If the PATH and TERM variables are not preserved from the user’s environment, they will be set to default values.

The /etc/sudoers has also:

Defaults    secure_path = /sbin:/bin:/usr/sbin:/usr/bin

The /etc/profile has:

pathmunge /usr/local/sbin

And /root/.bashrc has:

PATH="$HOME/.local/bin:$HOME/bin:$PATH"

The question is, where does the /usr/local/bin come from, although the man bash notes that
“common value” for PATH is
/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin:/bin:/sbin

1 Like