我刚刚注意到chmod
取消设置 setgid 位时的一些有趣行为:
$ mkdir test
$ chmod 2755 test
$ stat -c '%a %n' test
2755 test # as expected
$ chmod 0755 test
$ stat -c '%a %n' test
2755 test # what? see below
$ chmod 00755 test
$ stat -c '%a %n' test
755 test # double what?!
尝试取消设置 setgid 位chmod 0755
不起作用,这令人惊讶。但是,手册页表明这是预期的行为:
SETUID 和SETGID 位
如果文件的组 ID 与用户的有效组 ID 或用户的补充组 ID 之一不匹配,则 chmod 会清除常规文件的 set-group-ID 位,除非用户具有适当的权限。其他限制可能会导致 MODE 或 RFILE 的 set-user-ID 和 set-group-ID 位被忽略。此行为取决于底层 chmod 系统调用的策略和功能。如有疑问,请检查底层系统行为。
chmod 保留目录的 set-user-ID 和 set-group-ID 位,除非您另外明确指定。您可以使用 u+s 和 gs 等符号模式设置或清除位,以及您可以使用数字模式设置(但不能清除)这些位。
(强调已添加)
所以它似乎chmod 0755
并不意味着取消设置 setgid 位。那么,为什么要chmod 00755
取消它呢?chmod
似乎没有任何用处五数字模式的数字。再次从手册页:
数字模式来自一到四八进制数字 (0-7),通过将值 4、2 和 1 的位相加得出。省略的数字假定为前导零。
(强调已添加)
这里发生了什么?为什么chmod
决定忽略单个前导 0?为什么会这样不是忽略两个前导 0?
(Debian Stretch 9.1,带有 chmod (GNU Coreutils) 8.6)
答案1
我找到了!手册页中缺少此信息,但 Coreutils 在线手册中有此信息。以机智:
在大多数系统上,如果设置了目录的 set-group-ID 位,则新创建的子文件将继承与该目录相同的组,并且新创建的子目录将继承父目录的 set-group-ID 位。在某些系统上,目录的 set-user-ID 位对新子文件的所有权和新子目录的 set-user-ID 位具有类似的影响。这些机制减少了使用
chmod
或chown
共享新文件的需要,使用户可以更轻松地共享文件。这些便利机制依赖于目录的 set-user-ID 和 set-group-ID 位。如果像
chmod
和 之类的命令mkdir
定期清除目录上的这些位,则该机制将不太方便,并且共享文件将变得更加困难。因此,类似的命令chmod
不会影响目录的 set-user-ID 或 set-group-ID 位,除非用户以符号模式特别提及它们,或者使用运算符数字模式(例如“=755”),或者设置在数字模式下清除它们,或在具有五个或更多八进制数字的数字模式下清除它们。
参考:https://www.gnu.org/software/coreutils/manual/html_node/Directory-Setuid-and-Setgid.html
答案2
也许这是 Debian Stretch 9.1 中 chmod 的一个错误?它在 Ubuntu 12.04、Ubuntu 16.04.3、CentOS 6.9 和 CentOS 7.4 上正常工作。