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

Pet*_*ter 5 c linux ubuntu

这是一个演示我的问题的程序的完整源代码(操作系统是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以及为什么结果与我的预期不同?

Ctx*_*Ctx 2

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

initgroups("ubuntu", 1000);
Run Code Online (Sandbox Code Playgroud)

在 - 调用之前setgid()那么该进程应该具有dialout组的权限。