SUID-bit not working for executables within /tmp directory

permissionssetuidtmp

Printing the value of getuid() and geteuid() from an executable with SUID-bit (chmod +s) turned-on, seems to result with the original caller ID instead of the owner id if the executable is located within the /tmp directory.

When compiling the exact same code to home directory (and executing chmod +s), this seems to work as expected.

I've searched a lot and could not find any reference to such behavior.

Does anybody know why is this happening?

this source is simple as that:

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>

int main(){
    printf("%d\n%d\n", getuid(), geteuid());
    return 0;
}

Best Answer

Setuid executables can be disabled in filesystem mount options, the option is called nosuid. This is always done for filesystems that can be mounted by untrusted users (the user mount option in /etc/fstab automatically implies nosuid) or whose content can be modifed arbitrarily by untrusted users, for example on removable media or over the network from machines that aren't fully trusted. It is sometimes done for other filesystems as well.

Many systems use tmpfs for /tmp: a filesystem whose content remain in memory and isn't preserved on a reboot. (A tmpfs filesystem can be faster than relying on the disk cache because it doesn't need to care about data consistency.) Some setups mount it with the nosuid option, because there usually isn't any call for setuid temporary files and this could occasionally be part of an attack vector (setuid files in /tmp are not a security risk per se, but disabling them can limit the damage caused by a few vulnerabilities).

You can check the mount options for a directory by first looking up the mount point that contains it with df:

df /tmp/somefile

Then look up the mount point in the output from mount, or on Linux in /proc/mounts.

mount | awk '$3 == "/tmp"'
Related Question