setgid: chmod g+s,gx 可执行文件

setgid: chmod g+s,gx 可执行文件

我不理解我的平台(ubuntu)上可执行文件的 setgid 。g-x,g+s没有向进程授予程序所有者的有效组权限。

$ gcc perms.c -o perms; ls -l ; ./perms
-rwxr-xr-x 1 ubuntu ubuntu 9302 Feb 24 01:00 perms*
-rw-r--r-- 1 ubuntu ubuntu 1437 Feb 21 08:41 perms.c
ruid: ubuntu:1000 group:1000
euid: ubuntu:1000 group:1000

$ sudo useradd alice; groups alice $USER
alice : alice
ubuntu : ubuntu sudo rvm

$ chmod g+s ./perms; ls -l ./perms ; sudo -u alice ./perms
rwxr-sr-x 1 ubuntu ubuntu 9302 Feb 24 01:00 perms*
ruid: alice:1001 group:1002
euid: alice:1001 group:**1000**

这一切都在意料之中,问题是:

$ chmod g-x ./perms; ls -l ./perms ; sudo -u alice ./perms
-rwxr-Sr-x 1 ubuntu ubuntu 9302 Feb 24 01:00 perms*
ruid: alice:1001 group:1002
euid: alice:1001 group:**1002**

我的理解是,这为g+s进程提供了程序所有者的有效组 ID,但事实并非如此。显然,这是因为g-x这是唯一的变化。

Edit1:删除了有关目录如何工作的部分g-x,g+s,因为人们认为我在询问S目录。我不是。

Edit2:因为我从一个答案中得到了屈辱。这也与以下情况不同u-x,u+s

$ rm -rf perms temp/; gcc perms.c -o perms
$ chmod ug-x,ug+s ./perms; ls -l ./perms; sudo -u alice ./perms
-rwSr-Sr-x 1 ubuntu ubuntu 9302 Feb 24 21:22 ./perms*
ruid: alice:1001 group:1002
euid: ubuntu:1000 group:1002

这里u-x,u+s受到尊重,但g-x,g+s并非如此。

我的问题:为什么capital S sgid可执行文件被忽略?
g-x,g+s在目录中受到尊重。
u-x,u+s在可执行文件上受到尊重。
g-x,g+s在可执行文件上不受尊重。
为什么?

回答: 我的研究似乎已经陷入了“因为 System V 武断地决定它意味着其他东西”的死胡同。

答案1

好吧,RTFM 的一个回复对我没有多大帮助。经过几个小时的挖掘,我在当前的 Linux 内核中找到了这些行。

https://github.com/torvalds/linux/blob/e816c201aed5232171f8eb80b5d46ae6516683b9/fs/exec.c

/* Be careful if suid/sgid is set */
inode_lock(inode);

/* reload atomically mode/uid/gid now that lock held */
mode = inode->i_mode;
uid = inode->i_uid;
gid = inode->i_gid;
inode_unlock(inode);

/* We ignore suid/sgid if there are no mappings for them in the ns */
if (!kuid_has_mapping(bprm->cred->user_ns, uid) ||
     !kgid_has_mapping(bprm->cred->user_ns, gid))
    return;

if (mode & S_ISUID) {
    bprm->per_clear |= PER_CLEAR_ON_SETID;
    bprm->cred->euid = uid;
}

if ((mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP)) {
    bprm->per_clear |= PER_CLEAR_ON_SETID;
    bprm->cred->egid = gid;
}

很明显,这是故意的。

这可以追溯到 2005 年 5 月最初上传到 github 的时间:

https://github.com/torvalds/linux/blob/3677209239ed71d2654e73eecfab1dbec2af11a9/fs/exec.c

bprm->e_uid = current->euid;
bprm->e_gid = current->egid;

if(!(bprm->file->f_vfsmnt->mnt_flags & MNT_NOSUID)) {
    /* Set-uid? */
    if (mode & S_ISUID) {
        current->personality &= ~PER_CLEAR_ON_SETID;
        bprm->e_uid = inode->i_uid;
    }

    /* Set-gid? */
    /*
     * If setgid is set but no group execute bit then this
     * is a candidate for mandatory locking, not a setgid
     * executable.
     */
    if ((mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP)) {
        current->personality &= ~PER_CLEAR_ON_SETID;
        bprm->e_gid = inode->i_gid;
    }
}

谷歌搜索评论会导致:

https://www.kernel.org/doc/Documentation/filesystems/mandatory-locking.txt

  1. 将文件标记为强制锁定
    文件被标记为强制锁定的候选者在其文件模式中设置组 ID 位,但删除组执行位。这是一个没有任何意义的组合,并且是由 System V 实施者选择以免破坏现有的用户程序。
    请注意,当写入 setgid 文件时,内核通常会自动清除 group-id 位。这是一项安全措施。内核已被修改为识别强制锁定候选者的特殊情况并避免清除该位。同样,内核已被修改为不运行具有 setgid 权限的强制锁定候选者。

所以答案似乎是“因为它被选择来表示其他含义。

答案2

当您编辑问题以包含以下内容时:

我的问题:为什么可执行文件会忽略大写的 S sgid?

它并没有被忽视。S在你的情况下意味着该文件不能由组执行,因此它是良性的。如果您希望可执行文件以组的权限运行,那么它需要可由组执行。你把它拿走了,g-x这就是你得到的原因S。它将以执行它的人的权限运行,而不是以组的权限运行。

相关内容