以root身份运行程序时出现奇怪的结果

下面是一个程序的完整源代码,这个程序演示了我的问题(操作系统是Ubuntu 14.04 32位):

#include <stdio.h> #include <string.h> #include <errno.h> #include <fcntl.h> #include <unistd.h> int main(int argc, const char *argv[]) { int status, fd; printf("CURRENT UID: %d, CURRENT GID: %d\n", getuid(), getgid()); fd = open("/dev/ttyS0", O_WRONLY); if(fd < 0) { printf("Error opening /dev/ttyS0: %s\n", strerror(errno)); return 1; } printf("Successfully opened /dev/ttyS0\n"); close(fd); /* DROP PRIVILEGES */ setgid(1000); setuid(1000); printf("CURRENT UID: %d, CURRENT GID: %d\n", getuid(), getgid()); fd = open("/dev/ttyS0", O_WRONLY); if(fd < 0) { printf("Error opening /dev/ttyS0: %s\n", strerror(errno)); return 1; } printf("Successfully opened /dev/ttyS0\n"); return 0; } 

系统中有两个用户:root和一个普通的非root用户(我们称他为“ubuntu”),id = 1000。 上面的程序试图打开一个串口(/ dev / ttyS0)两次:第一次作为根或Ubuntu(取决于它如何被调用),第二次总是作为Ubuntu的。 首先不成功的尝试导致程序中止。 用户ubuntu是拨出组的成员,理论上他有必要的权限来打开/ dev / ttyS0。 我用四种不同的方式调用程序:

1)直接运行Ubuntu

调用:

<我的程序的path>

2)作为Ubuntu的运行,但使用sudo

调用:

sudo -u ubuntu <我的程序的path>

3)以root身份运行,但权限下降到Ubuntu的(所以,有效地,作为Ubuntu的运行):

调用:

sudo su
sudo -u ubuntu <我的程序的path>

在所有三种情况下,我得到以下预期的结果:

 CURRENT UID: 1000, CURRENT GID: 1000 Successfully opened /dev/ttyS0 CURRENT UID: 1000, CURRENT GID: 1000 Successfully opened /dev/ttyS0 

在最后一种情况下,发生了一些奇怪的事情:

4)以root身份直接运行

调用:

sudo su
<我的程序的path>

结果:

 CURRENT UID: 0, CURRENT GID: 0 Successfully opened /dev/ttyS0 CURRENT UID: 1000, CURRENT GID: 1000 Error opening /dev/ttyS0: Permission denied 

当然,这是输出的最后两行,我不明白:这一次,当root放弃他的权限,事实certificate,Ubuntu没有足够的权限打开/ dev / ttyS0,但为什么? 情况与案例1-3有何不同?

最后一件值得一提的事情是:如果我改变了我的代码这一行:

 setgid(1000); 

对此:

 setgid(20); /* 20 is the id of dialout group */ 

那么最后一次尝试打开/ dev / ttyS0也是成功的。

这是否意味着作为拨号组成员的Ubuntu的信息会因为某些原因而丢失,当我作为根用户运行程序,然后通过更改uid和gid到1000的权限下降到Ubuntu的权限? 你能否给我详细的解释,我的例子中的情况4发生了什么,为什么结果与我预期的不同?

设置用户标识和组标识不会自动设置所有补充组(即所有组,不是用户的主要组,而是在/etc/groups分配给他的所有/etc/groups )。 尝试使用

 initgroups("ubuntu", 1000); 

setgid()调用。 那么这个过程应该有dialout- group的权限。