这是一个演示我的问题的程序的完整源代码(操作系统是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;
}
Run Code Online (Sandbox Code Playgroud)
系统中有两个用户:root和一个普通的非root用户(让我们称他为"ubuntu"),id = 1000.上面的程序试图打开一个串口(/ dev/ttyS0)两次:第一次作为root或ubuntu(取决于它是如何被调用的),第二次总是作为ubuntu.第一次尝试失败导致程序中止.用户ubuntu是拨出组的成员,因此理论上他有必要的权限来打开/ dev/ttyS0.我以四种不同的方式调用该程序:
1)直接作为ubuntu运行
调用:
<我的程序的路径>
2)以ubuntu运行,但使用sudo
调用:
sudo -u ubuntu <我程序的路径>
3)以root身份运行,但是权限被删除到ubuntu的权限(因此,有效地,以ubuntu运行):
调用:
sudo su
sudo -u ubuntu <我的程序的路径>
在所有三种情况下,我得到以下预期结果:
CURRENT UID: 1000, CURRENT GID: 1000
Successfully opened /dev/ttyS0
CURRENT UID: 1000, CURRENT GID: 1000
Successfully opened /dev/ttyS0
Run Code Online (Sandbox Code Playgroud)
然而,在最后一种情况下,发生了一些奇怪的事情
4)直接以root身份运行
调用:
sudo su
<我的程序的路径>
结果:
CURRENT UID: 0, CURRENT GID: 0
Successfully opened /dev/ttyS0
CURRENT UID: 1000, CURRENT GID: 1000
Error opening /dev/ttyS0: Permission denied
Run Code Online (Sandbox Code Playgroud)
当然这是我不理解的输出的最后两行:这次,当root放弃他的权限时,事实证明ubuntu没有足够的权限来打开/ dev/ttyS0,但为什么呢?这种情况与案例1-3有什么不同?
最后一件值得一提的事:如果我改变我的代码行:
setgid(1000);
Run Code Online (Sandbox Code Playgroud)
对此:
setgid(20); /* 20 is the id of dialout group */
Run Code Online (Sandbox Code Playgroud)
那么打开/ dev/ttyS0的最后一次尝试也是成功的.
当我以root用户身份运行程序然后通过将uid和gid更改为1000来删除ubuntu的权限时,是否意味着有关ubuntu成为拨出组成员的信息会丢失?你能否详细解释一下我的例子中的案例4以及为什么结果与我的预期不同?
设置userid和groupid并不会自动设置所有补充组(即所有组,不是用户的主组,而是在 中分配给他的/etc/groups)。尝试使用
initgroups("ubuntu", 1000);
Run Code Online (Sandbox Code Playgroud)
在 - 调用之前setgid()。那么该进程应该具有dialout组的权限。
| 归档时间: |
|
| 查看次数: |
165 次 |
| 最近记录: |