Why does sudo fail with strace?

Posted on

Problem :

I can run this command without issue.

/tmp $ sudo echo "hello world"
hello world

However, this command fails:

/tmp $ strace -o /tmp/out.log sudo echo "hello world"
sudo: effective uid is not 0, is /usr/bin/sudo on a file system with the 'nosuid' option set or an NFS file system without root privileges?

The origin of this error message is supposedly based on the file system configuration.

The question boils down to, how does strace influence sudo such that some nosuid file system becomes relevant?

The current working directory is /tmp.

/tmp $ df .
Filesystem     1K-blocks     Used Available Use% Mounted on
/dev/tmpn1p1 101584140 60379868  41187888  60% /
/tmp $ mount | grep tmpn1p1
/dev/tmpn1p1 on / type ext4 (rw,relatime,discard,data=ordered)

Solution :

sudo must be run as root, and it uses the Set UID bit to achieve this (the ---s------, or the 0o4000 in octal, shown below). With the bit set, the program is always executed as if the owning user had run it, instead of the currently logged in user.

$ ls -l /usr/bin/sudo
-rwsr-xr-x 1 root root 149080 Jan 31  2020 /usr/bin/sudo
$ stat -c '%a' /usr/bin/sudo
4755

As you’re running sudo via strace, you’ll probably find that strace will call a variant of exec(), and won’t respect the Set UID bit, and thus sudo isn’t running as root:

$ strace -e execve sudo echo "hello world"
execve("/usr/bin/sudo", ["sudo", "echo", "hello world"], 0x7fffc171e2e0 /* 36 vars */) = 0
sudo: effective uid is not 0, is /usr/bin/sudo on a file system with the 'nosuid' option set or an NFS file system without root privileges?
+++ exited with 1 +++

Inverting the order of strace and sudo will do what you want though, so long as you’re not trying to inspect the operation of sudo itself:

$ sudo strace -e execve echo "hello world"
[sudo] password for attie:
execve("/bin/echo", ["echo", "hello world"], 0x7ffc300dbb28 /* 17 vars */) = 0
hello world
+++ exited with 0 +++

The root issue here is that strace will attach to the process (much like a debugger) using ptrace(), and in this state, it is not possible to obey the Set UID bit without presenting a security issue.

The same thing happens when running under gdb:

$ gdb sudo -ex 'run echo "hello world"' -ex quit
GNU gdb (Ubuntu 8.1-0ubuntu3.2) 8.1.0.20180409-git
Copyright (C) 2018 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from sudo...(no debugging symbols found)...done.
Starting program: /usr/bin/sudo echo "hello world"
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
sudo: effective uid is not 0, is /usr/bin/sudo on a file system with the 'nosuid' option set or an NFS file system without root privileges?
[Inferior 1 (process 27480) exited with code 01]

Leave a Reply

Your email address will not be published. Required fields are marked *