我编译了这个示例set-root-id程序:
#define _GNU_SOURCE
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <errno.h>
void print_ids()
{
uid_t ruid, euid, suid, rgid, egid, sgid;
getresuid(&ruid, &euid, &suid);
printf("\nruid=%d, euid=%d, suid=%d\n", ruid, euid, suid);
getresgid(&rgid, &egid, &sgid);
printf("rgid=%d, egid=%d, sgid=%d\n\n", rgid, egid, sgid);
}
void main(int argc, char *argv[])
{
print_ids();
seteuid(1000); printf("seteuid(1000): %s\n", strerror(errno));
print_ids();
seteuid(1001); printf("seteuid(1001): %s\n", strerror(errno));
print_ids();
seteuid(0); printf("seteuid(0): %s\n", strerror(errno));
print_ids();
}
调用seteuid(0)有效,但会显示错误消息:&#34;操作不被允许&#34;:
$ gcc -Wall ./p3.c -o p3
./p3.c:32: warning: return type of ‘main’ is not ‘int’
$ su -c "chown root:root ./p3 ; chmod 4755 ./p3"
Password: ****
$ ls -l ./p3
-rwsr-xr-x 1 root root 7697 2 gen 19.21 ./p3
$ ./p3
ruid=1000, euid=0, suid=0
rgid=1000, egid=1000, sgid=1000
seteuid(1000): Success
ruid=1000, euid=1000, suid=0
rgid=1000, egid=1000, sgid=1000
seteuid(1001): Operation not permitted
ruid=1000, euid=1000, suid=0
rgid=1000, egid=1000, sgid=1000
seteuid(0): Operation not permitted
ruid=1000, euid=0, suid=0
rgid=1000, egid=1000, sgid=1000
$
为什么seteuid(0)有效但显示错误信息? 我注意到省略对seteuid(1001)的调用或调用seteuid(1000)没有出现错误消息。
谢谢
(我在Debian 6上工作,gcc版本4.4.5)
答案 0 :(得分:2)
旧的EPERM
仍在前一次通话的errno
中。成功的系统调用不会将errno
设置为0;你必须自己做。
通常,您不需要将errno
设置为0.您检查系统调用的返回值,如果这表示失败,则检查errno
以获取更多详细信息。 errno没有告诉你 某些事情失败了 - 它告诉你 某些事情失败了。
这个函数的一般规则有一个例外,它们的返回值没有明确的错误指示符,例如strtoul
,但seteuid
不是其中之一。它具有干净的回报价值。如果它返回0,则根本不应打印错误消息。
依靠strerror(0)
生成“成功消息”也不干净 - 在当前的glibc中它说"Success"
但我仍记得strerror(0)
何时"Unknown error 0"
}。也许在某个地方它仍然存在。