Linux目录权限继承规则_setgid实践解析【教程】

10次阅读

mkdir 创建的子目录未继承父目录组,是因为默认由进程主组决定;只有父目录设置了 setgid 位(权限中为小写 s),子目录才会强制继承其组 ID 且递归生效。

Linux 目录权限继承规则_setgid 实践解析【教程】

Linux 目录的权限继承不是自动发生的,setgid 是唯一能实现“新建文件 / 子目录自动继承父目录所属组”的机制,但它对文件和目录的行为不同,且不控制所有权或读写权限本身。

为什么 mkdir 创建的子目录没继承父目录的组?

默认情况下,新创建的目录所属组由进程的 primary group 决定(通常是用户登录组),与父目录无关。只有父目录设置了 setgid 位(即权限中的 sS),内核才会在创建子目录时强制将其组 ID 设为父目录的组 ID。

  • setgid 对目录有效:子目录自动继承父目录的 group,且自身也带上 setgid 位(递归生效)
  • setgid 对普通文件无效:新建文件不会继承父目录组,且其 setgid 位会被内核自动清除(除非是可执行文件)
  • 必须用 chgrp 先改父目录所属组,再用 chmod g+s 设置 setgid,顺序不能反

chmod g+schmod 2755 区别 在哪?

两者效果一致,但表达方式不同:g+s 是符号模式,明确表示“给 group 加 setgid 位”;2755 是八进制模式,其中首位 2 就代表 setgid。注意:如果目录已有 rwxr-xr-x(即 755),加 setgid 后显示为 rwxr-sr-x(小写 s);如果 group 没有执行权(如 744),则显示为 rwxr-Sr--(大写 S),此时 setgid 实际不生效。

  • 小写 s = group 有 x 权限 + setgid 已启用
  • 大写 S = group 无 x 权限,setgid 被设置但被忽略
  • ls -ld /path 查看,确认是小写 s 才算真正生效

如何验证 setgid 是否起作用?

不能只看父目录权限,必须实测新建项的所属组。普通用户在该目录下创建内容后,用 ls -l 观察结果:

mkdir /shared chgrp devteam /shared chmod g+s /shared # 切换到非 devteam 成员用户执行:touch /shared/testfile mkdir /shared/testdir ls -ld /shared/testfile /shared/testdir

预期输出中:testdir 的组应为 devteam,且权限含 rwxr-sr-xtestfile 的组通常仍是创建者主组(除非系统启用了 bsdgroups 模式或设置了 umask 002 配合 setgid)。

  • 文件是否继承组,取决于 umask 和内核策略:Linux 默认不继承,但若 umask002 且父目录 setgid,新文件组可能碰巧一致(非 guaranteed)
  • 子目录一定继承,这是 POSIX 明确要求的行为
  • 如果测试失败,先检查 mount 是否带 noexecnosuid(部分文件系统会禁用 setgid

真正容易被忽略的是:即使 setgid 设置正确,如果用户不属于目标组,chgrp 会失败;而一旦父目录组设错,后续所有继承都无效——所以先确认 getent group devteam 能查到成员,再动手改权限。

text=ZqhQzanResources