从set-root-id程序调用的函数seteuid()有效,但显示错误消息

时间:2014-01-02 18:33:58

标签: c setuid

我编译了这个示例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)

1 个答案:

答案 0 :(得分:2)

旧的EPERM仍在前一次通话的errno中。成功的系统调用不会将errno设置为0;你必须自己做。

通常,您不需要将errno设置为0.您检查系统调用的返回值,如果这表示失败,则检查errno以获取更多详细信息。 errno没有告诉你 某些事情失败了 - 它告诉你 某些事情失败了。

这个函数的一般规则有一个例外,它们的返回值没有明确的错误指示符,例如strtoul,但seteuid不是其中之一。它具有干净的回报价值。如果它返回0,则根本不应打印错误消息。

依靠strerror(0)生成“成功消息”也不干净 - 在当前的glibc中它说"Success"但我仍记得strerror(0)何时"Unknown error 0" }。也许在某个地方它仍然存在。