Help me understand sudo $PATH weirdness.

Hello. I’m trying to understand how sudo works, but I am having trouble understanding some details.

As I understand it when I run “sudo <command>”, the command is basically executed with a whitewashed version of my environment variables (including $PATH), but with root permissions. That also seems to be how it works. For example, I don’t have /sbin in my $PATH, so executing sudo ifconfig (ifconfig being located in /sbin/ifconfig) gives me:

$ sudo ifconfig
sudo: ifconfig: command not found

This I understand and is no problem. The proper way to do this is like so:

$ sudo -i ifconfig
eth0 [lots of output]

My confusion basically comes from what happens when I try inspecting what the $PATH actually is when running sudo. For example my path is:

$ env | grep ^PATH=
PATH=/usr/lib64/mpi/gcc/openmpi/bin:/home/qbd/bin:/usr/local/bin:/usr/bin:/bin:/usr/bin/X11:/usr/X11R6/bin:/usr/games:/usr/lib64/jvm/jre/bin

And with sudo I get:

$ sudo env | grep ^PATH=
PATH=/usr/sbin:/bin:/usr/bin:/sbin

Also I can try looking for ifconfig using which. Without sudo, which (correctly) does not find it:

which ifconfig
which: no ifconfig in (/usr/lib64/mpi/gcc/openmpi/bin:/home/qbd/bin:/usr/local/bin:/usr/bin:/bin:/usr/bin/X11:/usr/X11R6/bin:/usr/games:/usr/lib64/jvm/jre/bin)

But with sudo which indicates that ifconfig can be found:

$ sudo which ifconfig
/sbin/ifconfig

But recall that ifconfig won’t actually be found using just sudo.

So basically my question is why env and which seem to indicate that the path includes /sbin when running sudo, but in actuality it does not (sudo correctly inherits my $PATH as far as I can tell). Is there a good explanation for this behaviour?

Okay so I have a theory about what’s happening. It seems to me like sudo is correctly inheriting my $PATH, but any application run by sudo (like sh, env, which, etc.) does not inherit my $PATH but rather that of root, which does have /sbin in it’s $PATH. I was assuming that an application would see the environment variables of whatever environment that launched it, but that seems not to be the case when using sudo. Does my puzzled-penguin attempt at an explanation make sense?

Your guess is right, typing the command with sudo you’re still in the user environment. The command will be executed in the superuser/root environment. If this seems counter-intuitive, use “su -” instead. From this you’ll be in the root environment with full root access.

The command is searched using your $PATH, but the command inherits a $PATH which is cut down. That’s why sudo can find commands which are in your ~/bin. Try:

ln -s /usr/bin/env ~/bin/environment
sudo environment

Assuming you have ~/bin on your $PATH of course.

Thanks for the replies :).

ken_yap, I’ve already checked that ~/bin is indeed being searched by sudo. However my observation is that the command launched by sudo does not inherit a cut down version of my path, but rather a cut down version of root’s path. So commands are being searched for using my path, but launched with root’s path.

After some searching I see that I’m definitiely not the only one that’s been confused by this :p. But at least I can somewhat understand it if commands launched by sudo inherit root’s environment, not mine.

Sure, that’s the way it’s supposed to work.

In contrast to sudo “su -c” is completely different. It will execute as root but with your users path

su -c 'set | grep ^PATH= && set | grep UID'

Okay, so it seems /sbin and /usr/sbin gets added to my path by su:

[qbd@linux-x8ou ~]$ su -c env | grep ^PATH
Password: 
PATH=/usr/lib64/mpi/gcc/openmpi/bin:/home/qbd/bin:/usr/local/bin:/usr/bin:/sbin:/usr/sbin:/bin:/usr/bin/X11:/usr/X11R6/bin:/usr/games:/usr/lib64/jvm/jre/bin
[qbd@linux-x8ou ~]$ env | grep ^PATH
PATH=/usr/lib64/mpi/gcc/openmpi/bin:/home/qbd/bin:/usr/local/bin:/usr/bin                :/bin:/usr/bin/X11:/usr/X11R6/bin:/usr/games:/usr/lib64/jvm/jre/bin

And su -c finds commands in /sbin like ifconfig etc.

The man page for su is extremely short and doesn’t really explain what’s happening. In this context it looks like su -c does what alot of people actually want sudo to do, i.e. use the users path but add /sbin and /usr/sbin. It does however change/remove alot of other environment variables. Is there some more documentation for OpenSUSE’s su implementation available somewhere?

info coreutils

There is no “openSUSE implementation”. It is just compiled from the upstream source pacakge.

On 08/21/2011 09:26 AM, Quantumboredom wrote:

> But at least I can somewhat understand it if
> commands launched by sudo inherit root’s environment, not mine.

that is not what happens…try this:

while logged in as yourself, open a new instance of a terminal and run
these (give the root password when requested):


echo $PATH
sudo echo $PATH
su
echo $path
su -
echo $PATH

and compare the resulting paths…

the first two paths should be identical, because sudo keeps the
environment of the user, but allows some root powers (as set in sudoer

the path obtained by “su” will be different from the first two…

and the results of the “su -” path will be different from the first
three, and as it will be the only path not mentioning /home/[your
userID] it is the only one showing root’s true path (as root’s
environment doesn’t include /home)

hence, if you read how to become root in a terminal
<http://tinyurl.com/ydbwssh> it will say to always use “su -” (and, it
does not say to use sudo or su because neither of those allow you to
become root–do some root stuff yes, but not become root.)

yes, i know other distros use “su” and “sudo” a lot…and, some of those
distros make it almost impossible to become root…why? ask them…i
don’t understand their reasoning…


DD Caveat
openSUSE®, the “German Engineered Automobile” of operating systems!

While it is not quite true that commands launched by sudo inherit root’s environment, it does inherit a kind of stripped-down version of root’s environment. My point was that programs launched via sudo do not inherit my $PATH, even though sudo itself uses my $PATH to search for programs.

Also the example with “sudo echo $PATH” isn’t valid, since $PATH is expanded by the shell before sudo is invoked (at least that is how I understand it). Indeed I still haven’t figured out how to actually inspect the environment that sudo is using. When doing something like “sudo echo $PATH” it’s my environment variable that is inspected, and when doing “sudo env” it’s the environment that env inherits that’s inspected, which seems to be different from what sudo is using. Anyone know of a way to print out the explicit path (and other environment variables, though I don’t know if they matter?) that sudo is using, or is this not possible to do?

I do however understand that the commands sudo -i and su -l seem to be really giving you a root environment (I don’t know if there’s any meaningful difference between the two), while plain sudo is more stripped down (allowing you to do some root stuff as you say).

Yes, but not inherit anything. It just sets a minimal $PATH. To get root’s $PATH, or in fact the target’s $PATH, -i is used.

Also the example with “sudo echo $PATH” isn’t valid, since $PATH is expanded by the shell before sudo is invoked (at least that is how I understand it). Indeed I still haven’t figured out how to actually inspect the environment that sudo is using. When doing something like “sudo echo $PATH” it’s my environment variable that is inspected, and when doing “sudo env” it’s the environment that env inherits that’s inspected, which seems to be different from what sudo is using. Anyone know of a way to print out the explicit path (and other environment variables, though I don’t know if they matter?) that sudo is using, or is this not possible to do?

env; sudo …

shows you the environment sudo is working in.

sudo env

shows you the environment the child command of sudo is working in. That’s what you want, no?

Nothing is impossible. I habitually use

sudo su -

when I want to be as good as logged in root on such distros.

Sorry but my knowledge of bash syntax is not the best. Is “env; sudo …” a valid command? It just seems to first print my environment, then sudo does not recognize “…” as a valid command. Did you just mean to say that sudo will use my environment without any alterations when searching for commands, and then set the different root-ish environment for the launched application (that environment being based on either options in /etc/sudoers and also options at compile time)? If so then I think I’m finally starting to understand it somewhat. I had the idea that sudo would somehow alter my environment, but I don’t know where I got that idea from at this point.

It’s the same as:

env
sudo …

where … is replaced by whatever you want to execute. … is just a placeholder in the explanation.

I had the idea that sudo would somehow alter my environment, but I don’t know where I got that idea from at this point.

No external command can alter the existing environment.

Ok, what I meant was that I thought sudo would operate as though my environment was different. For example adding or removing locations to search for commands, just using my $PATH as a starting point. Or just searching other locations, ignoring my $PATH completely. Not that sudo would actually go in and change my environment.

Actually as I understand it that’s what the --with-secure-path compile-time option of sudo does. The only documentation I’ve found for it is a bit unclear though, so I can’t tell whether the option affects the search path used by sudo, or whether it changes the path seen by the application launched by sudo. Also I don’t know if OpenSUSE compiles it’s sudo with that option or not, just that Debian/Ubuntu is using it.

If it affects the path searched by sudo then my question still stands, is it possible to determine what locations are searched by sudo without having to infer it from compile time options (and possibly options set in config files elsewhere)?

Well if sudo opts to bypass the normal $PATH seach of the execlp(3) and execvp(3) functions when invoking a command, then then only way would be to read the source code. Or strace it. But AFAIK it doesn’t do that.

On 08/22/2011 12:16 AM, ken yap wrote:
> Nothing is impossible. I habitually use

agree…
which is one reason i used ‘almost’…
and, like my daddy used to say “locks are to keep honest people
out”…likewise, disto attempts to lock users out of root will only work
for the those who don’t know how to pick the lock…


DD
openSUSE®, the “German Engineered Automobile” of operating systems!