setuid() returns 0 但没有效果

setuid() returns 0 but has no effect

我有以下代码:

#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());
}

这样编译和运行:

 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

为什么uid不变?还有为什么setuid会报成功呢? (根据手册页,0 表示成功)

setuid() 设置有效的用户ID,而不是真正的进程ID。来自 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.

为了能够更改真实用户 ID,进程必须将有效用户 ID 设置为 0。因为在您的示例中不是这种情况,所以它不会更改。 setuid() 成功,因为您只是将其设置为进程已有的相同有效用户 ID。