3

I was writing some bash code and I wanted to check if the script had root privileges. All of the code I see from other people only checks for $EUID == 0. It is perfectly possible to have other programs run with UID = 0 and EUID > 0. Shouldn't my code check for both? Or is there something about bash which prevents this (strange) situation?

For those who want to see such a situation, here's a proof of concept:

[root@new-host bennett]# cp /bin/sleep .
[root@new-host bennett]# chown bennett sleep
[root@new-host bennett]# chmod 4755 sleep
[root@new-host bennett]# ll sleep 
-rwsr-xr-x. 1 bennett root 32188 Sep  9 02:38 sleep
[root@new-host bennett]# ./sleep 1000 &
[root@new-host bennett]# ps -e -o user= -o ruser= -o comm= | awk '$1 != $2'
bennett  root     sleep

To recap the question: Can bash ever encounter a situation where (( $UID == 0 && $EUID > 0 )), under any circumstances? Other programs can.

JdeBP
  • 68,745
  • 3
    Why on Earth did you not try your "proof of concept" with /bin/bash directly? Or indeed your script? – JdeBP Sep 09 '17 at 07:32
  • Good question! Some shells switch things around on you. Here is a snippet from the man page for /bin/sh on Solaris. Pardon my formatting... I can't seem to get it to work for comments. The Bourne shell has a limitation on the effective UID for a process. If this UID is less than 100 (and not equal to the process' real UID), then the UID is reset to the process' real UID. – Erik Bennett Sep 09 '17 at 14:34

3 Answers3

6

Yes:

$ env UID=0 EUID=90 bash -c 'echo $UID $EUID'
0 90

Note that the above just alters the values of variables. The actual UID and EUID are not affected.

You should use id instead. See e.g. the question How to stop a script from running if it's not root (and echo "Not running as root! Exiting...")

The effective user ID will also be different from the real ID if the script has its set-uid bit set (and running such scripts set-uid is a thing on your Unix). In that case, the UID will be that of the user invoking the script while the EUID will be that of the owner of the script.

Related: Allow setuid on shell scripts

Kusalananda
  • 333,661
  • Well, that's just about broken. If the $UID and $EUID don't mean anything, I wonder why they are there. Just for yuks, I tried env UID="Spam and" EUID=goat\ cheese. bash -c 'echo $UID $EUID'. It went about like you described. It seems a little misleading. – Erik Bennett Sep 09 '17 at 14:08
  • “The effective user ID will also be different from the real ID if the script has its set-uid bit set (and running such scripts set-uid is a thing on your Unix)” First, that condition is rare: most unices don't allow setuid scripts. Second, bash drops privileges, so even if the kernel runs a bash script setuid, bash itself will drop its euid to its ruid. – Gilles 'SO- stop being evil' Sep 09 '17 at 14:47
  • 2
    Yeah, I know it's bad form, and some Unicies don't allow setuid scripts. My question was more about how reliable $EUID and $UID are. @Kusalananda pointed out that they are pretty much useless. – Erik Bennett Sep 09 '17 at 14:53
3

Bash drops privileges when it starts, so you won't often encounter a bash process running with different effective and real UIDs. This is possible with other sh implementations.

Note that if you want to test whether your script is running as root, checking the EUID is correct, and you should not care about the real UID.

And even checking the EUID is often not right. How do you know that root access is required? Maybe all the files and devices have permissions that allow a non-root user to access them, and if you need to use some tools that do require privileges not controlled by access permissions, your script may be running with the capabilities they require, or may be mocked (i.e. simulated for testing purposes).

  • Yeah, I know it's bad form, and some Unicies don't allow setuid scripts. My question wasn't really about setuid scripts, but rather more about how reliable $EUID and $UID are, under any circumstances. @Kusalananda pointed out that they are pretty much useless because anyone can change them to anything for any reason. It makes me wonder why they are there. – Erik Bennett Sep 09 '17 at 15:18
1

It is possible if you launch bash as a child process with -p option and your parent process has ruid=0 but different euid.

As per the bash(1) man page:

If the shell is started with the effective user (group) id not equal to the real user (group) id, and the -p option is not supplied, no startup files are read, shell functions are not inherited from the environment, the SHELLOPTS, BASHOPTS, CDPATH, and GLOBIGNORE variables, if they appear in the environment, are ignored, and the effective user id is set to the real user id. If the -p option is supplied at invocation, the startup behavior is the same, but the effective user id is not reset.

theh2o
  • 11