用户删除root权限时打开文件时权限被拒绝

时间:2017-10-13 17:04:41

标签: c linux

下面的情况是我有一个由root拥有的文件但是具有adm组中任何人的读取权限。我有一个用户,haen和uid 1000,这是adm组的一部分。我可以从命令行中读取它:

haen@haen-Precision-5510:~/tmp$ id
uid=1000(haen) gid=1000(haen) groups=1000(haen),4(adm),6(disk),20(dialout),24(cdrom),27(sudo),30(dip),46(plugdev),100(users),120(lpadmin),121(sambashare),122(vboxusers),999(bumblebee)
haen@haen-Precision-5510:~/tmp$ ll file 
-rw-r----- 1 root adm 13 okt 13 17:24 file
haen@haen-Precision-5510:~/tmp$ cat file 
file content
haen@haen-Precision-5510:~/tmp$

此外,我可以在c程序test.c中将其作为O_RDONLY打开,如果我将编译后的程序作为haen运行:

#define _GNU_SOURCE
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <grp.h>
#include <stdlib.h>
#include <sys/types.h>

int main(const int argc, char *argv[]) {
    gid_t rgid, egid, sgid;
    uid_t ruid, euid, suid;
    int ret, test_fd;

    ret = getresgid(&rgid, &egid, &sgid);
    printf("1: getresgid() returned %d rgid: %d, egid: %d, sgid: %d\n",
           ret, rgid, egid, sgid);

    ret = getresuid(&ruid, &euid, &suid);
    printf("2: getresuid() returned %d ruid: %d, euid: %d, suid: %d\n",
           ret, ruid, euid, suid);

    test_fd = open("file", O_RDONLY);
    printf("3: test_fd: %d\n", test_fd);
    close(test_fd);

    if(ruid == 0) {
        rgid = sgid = egid = 1000;
        ruid = euid = suid = 1000;

        ret = setresgid(rgid, egid, sgid);
        printf("4: setresgid() returned %d\n",ret);
        ret = getresgid(&rgid, &egid, &sgid);
        printf("5: getresgid() returned %d rgid: %d, egid: %d, sgid: %d\n",
               ret, rgid, egid, sgid);

        ret = setresuid(ruid, euid, suid);
        printf("6: setresuid() returned %d\n",ret);
        ret = getresuid(&ruid, &euid, &suid);
        printf("7: getresuid() returned %d ruid: %d, euid: %d, suid: %d\n",
               ret, ruid, euid, suid);

        test_fd = open("file", O_RDONLY);
        printf("8: test_fd: %d\n", test_fd);
        close(test_fd);
    }

    return 0;
}

输出:

haen@haen-Precision-5510:~/tmp$ ./test 
1: getresgid() returned 0 rgid: 1000, egid: 1000, sgid: 1000
2: getresuid() returned 0 ruid: 1000, euid: 1000, suid: 1000
3: test_fd: 3
haen@haen-Precision-5510:~/tmp$

但是,如果我以root身份运行程序,并且在程序内部将我的权限放入haen(在if子句中),就像我在运行程序时一样,这就是困扰我的事情,然后我再也无法打开“文件”进行阅读,输出:

haen@haen-Precision-5510:~/tmp$ sudo ./test
1: getresgid() returned 0 rgid: 0, egid: 0, sgid: 0
2: getresuid() returned 0 ruid: 0, euid: 0, suid: 0
3: test_fd: 3
4: setresgid() returned 0
5: getresgid() returned 0 rgid: 1000, egid: 1000, sgid: 1000
6: setresuid() returned 0
7: getresuid() returned 0 ruid: 1000, euid: 1000, suid: 1000
8: test_fd: -1
haen@haen-Precision-5510:~/tmp$

有谁知道为什么权限从root用户删除到特定用户,与启动那些用户权限不同?我用strace检查过,尝试打开时得到的错误代码是:

17:54:39.339041 open("file", O_RDONLY)  = -1 EACCES (Permission denied)

因此打印输出“8”上的test_fd的值为-1

就我所知,

strace没有显示解释这种行为的其他任何内容。

环境:

haen@haen-Precision-5510:~/tmp$ uname -a
Linux haen-Precision-5510 4.4.0-97-generic 120-Ubuntu SMP Tue Sep 19 17:28:18 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux
haen@haen-Precision-5510:~/tmp$

我能想到的唯一解释是linux内核列出了用户所属的所有gid,当我执行sudo然后回到c-program中的原始用户时,这个列表被“删除”了,但我不知道。据我所知,内核不读取/ etc / group,但在某种程度上它需要知道用户在检查权限时属于一个组。

1 个答案:

答案 0 :(得分:4)

您尚未处理辅助组(setgroups)。

当您sudo时,您将失去所有群组成员资格。请尝试以下方法:

$ sudo id
uid=0(root) gid=0(root) groups=0(root)

因此,您使用仅包含0的组列表运行程序。然后,您将实际,有效和已保存的GID显式设置为1000.这使组列表仅包含0。

由于您现在不是adm组的成员,因此您的文件无法打开。

请记住,呼叫setresgid与通过系统登录不同。发生这种情况时,它还会检查您所属的组,并使用setgroups相应地设置您的进程权限。