Search code examples
clinuxpermissionsoperating-systemsetuid

setuid() returns 0 but has no effect


I have the following code:

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>

void main(int argc, char* argv[]) {
    printf("uid=%u euid=%u\n", getuid(), geteuid());
    printf("%d = setuid(euid)\n", setuid(geteuid()));
    printf("uid=%u euid=%u\n", getuid(), geteuid());
}

Compiled and run this way:

 val@particle:/tmp $ sudo gcc foo.c
 val@particle:/tmp $ sudo chown dev-misc:dev-misc a.out
 val@particle:/tmp $ sudo chmod u+s a.out
 val@particle:/tmp $ ./a.out
uid=1000 euid=1006
0 = setuid(euid)
uid=1000 euid=1006

Why does the uid remain unchanged? And why does setuid report success? (according to the man page, 0 means success)


Solution

  • setuid() sets the effective user ID, not the real process ID. From the manual:

    setuid() sets the effective user ID of the calling process. If the effective UID of the caller is root (more precisely: if the caller has the CAP_SETUID capability), the real UID and saved set-user-ID are also set.

    To be able to change real user ID, the process must have effective user ID set to 0. Since, it's not the case in your example, it doesn't change. setuid() succeeds because you are just setting it to the same effective user ID the process already has.