在 linux 中调用 setgid 和 setuid 后,我无法访问属于某个组的文件

Posted

技术标签:

【中文标题】在 linux 中调用 setgid 和 setuid 后,我无法访问属于某个组的文件【英文标题】:I cannot access a file belonging to a group after calling setgid and setuid in linux 【发布时间】:2012-09-10 16:11:17 【问题描述】:

让我们添加一个新组和用户并将其添加到系统组video

$ sudo addgroup --system mydaemon
$ sudo adduser --system --no-create-home --ingroup mydaemon mydaemon
$ sudo adduser mydaemon video

创建一个文件并将其所有者更改为 root 并将组更改为video

$ touch video0
$ sudo chown root:video video0
$ sudo chmod 0660 video0

现在考虑一个使用setgid()setuid() 用C 编写的简单应用程序

/* perms.c */
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <fcntl.h>
#include <pwd.h>
#include <grp.h>


int main(int argc, char const *argv[])

    int ret;
    int gid;
    int uid;
    struct passwd *pw;
    struct group  *gr;

    pw = getpwnam("mydaemon");
    if (pw) 
        ret = setgid(pw->pw_gid);
        if (ret < 0) 
            printf("error with setgid\n");
            exit(1);
        

        ret = setuid(pw->pw_uid);       
        if (ret < 0) 
            printf("error with setuid\n");
            exit(1);
        
    

    pw = getpwuid(getuid());
    gr = getgrgid(getgid());

    printf("gid: %d gr_name: %s\n", gr->gr_gid, gr->gr_name);
    printf("uid: %d user_name: %s\n", pw->pw_uid, pw->pw_name);

    ret = open("video0", O_RDWR);

    printf("open status: %d (errno %d)\n", ret, errno);

    return 0;

编译后就可以正常运行了:

$ ./perms
error with setgid

失败是因为我们没有 setgid 的权限 所以直接作为mydaemon运行:

$ sudo -u mydaemon ./perms
gid: 126 gr_name: mydaemon
uid: 116 user_name: mydaemon
open status: 3 (errno 0)

好的,我可以setgidsetuid(我是同一个用户),我可以按预期打开文件

现在以 root 身份运行它:

$ sudo ./perms
gid: 126 gr_name: mydaemon
uid: 116 user_name: mydaemon
open status: -1 (errno 13)

我可以执行setgidsetuidgetgidgetuid 说我正在作为mydaemon 运行但我无法打开文件。 (errno 13 是 EACCES:权限被拒绝)

问题出在哪里?

【问题讨论】:

能否在守护进程中统计设备节点并通过访问struct stat的st_mode字段检查是否有读/写权限? (详见 man 2 stat) “我希望现在我应该可以访问...” - 这可能是一个错误的假设。应检查 setuid() 的返回码是否成功。 我已经对问题进行了一些编辑,现在可能有更多信息。 【参考方案1】:

您应该使用 initgroups() 调用来根据组数据库初始化组。

【讨论】:

以上是关于在 linux 中调用 setgid 和 setuid 后,我无法访问属于某个组的文件的主要内容,如果未能解决你的问题,请参考以下文章

Linux理解setuid()setgid()和sticky位

linux系统调用之用户管理

setuid setgid stick bit 特殊权限 粘滞位

linux 3.10 串口注册

五大权限:UGO权限SetUID SetGID StickyACL权限chattr(文件系统级别的权限)SELINUX

Linux常用命令之--强制位与冒险位