在常见的 Linux 文件系统(如 ext3/ext4/xfs)中,除了基本的读(r)、写(w)、执行(x)权限,还存在被称为“特殊权限”的强制位(setuid 和 setgid)与粘贴位(sticky)。它们是针对用户(u)、组(g)和其他用户(o)权限模型的扩展。
特殊权限的标记方法有其独特规则:它们被添加在原本用于表示执行权限(x)的位置上。如果该位置原本已有执行权限,则特殊权限会以小写字母(s 或 t)表示;反之,若原本没有执行权限,则以大写字母(S 或 T)表示。具体来说:
setuid 作用于文件属主(u)的 x 位,标记为 s 或 S。
setgid 作用于文件属组(g)的 x 位,标记为 s 或 S。
sticky 作用于其他用户(o)的 x 位,标记为 t 或 T。
例如,一个文件的原始权限为 rwx r-- r-x,在设置了全部特殊权限后,新的权限表示会变为 rws r-S r-t。
1. setuid:针对文件属主的强制位(作用于可执行文件)
默认情况下,用户执行一个命令时,进程会以该用户的身份和权限运行。当对一个可执行文件设置了 setuid 位后,任何用户(只要有执行权)在运行该程序时,进程的有效用户 ID(EUID)将临时变更为文件属主的 ID,从而拥有文件属主的权限。
这常用于系统命令,使其能完成需要更高权限(如 root)才能执行的操作。一个经典的例子是 /bin/passwd 命令。修改用户密码需要写入 /etc/shadow 文件,而该文件通常只有 root 用户可写。通过给 /bin/passwd 设置 setuid(并且其属主是 root),普通用户在执行该命令修改自己密码时,便临时获得了 root 权限来完成写操作。
语法(符号模式):
chmod u+s <文件名>
chmod u-s <文件名> # 取消设置
示例:
chmod u+s /bin/ls
2. setgid:针对文件属组的强制位(主要作用于目录)
setgid 位通常作用于目录。在默认情况下,用户在某目录中创建新文件或子目录时,其属组是该用户的主属组(primary group)。如果对一个目录设置了 setgid 位,那么任何用户(只要有权限)在此目录中创建的新文件或子目录,其属组将自动继承该目录的属组,而非创建者的主属组。这对于需要多人协作、共享文件的目录场景非常有用。
语法(符号模式):
chmod g+s <目录名>
chmod g-s <目录名> # 取消设置
示例:
chmod g+s /shared_project
3. sticky:针对其他用户的粘贴位(仅作用于目录)
Linux 的删除机制是:删除一个文件,需要的不是对该文件本身的写权限,而是对其父目录的写权限。这可能导致一个问题:如果一个目录对所有人开放写权限(如权限为 777),那么任何用户都可以删除该目录下的任意文件,包括他人创建的文件。
sticky 位就是为了解决这个问题而设计的。当对一个目录设置 sticky 位后(例如权限为 1777),所有用户仍可以在该目录下创建和修改自己的文件,但只能删除或重命名自己创建的文件和目录(root 用户除外)。这有效地保护了共享可写目录下的用户文件。
语法(符号模式):
chmod o+t <目录名>
chmod o-t <目录名> # 取消设置
4. 使用符号模式统一设置
总结一下使用 chmod 命令的符号模式设置这三种特殊权限的方法:
- setuid:
chmod u+s <文件名>
- setgid:
chmod g+s <目录名>
- sticky:
chmod o+t <目录名>
5. 使用数字(八进制)模式设置
特殊权限也可以通过一个额外的数字前缀,与代表基本权限的三位数字组合来设置。这个额外的数字是以下值的和:
- 4 代表
setuid
- **2
代表setgid`
- 1 代表
sticky
这个数字放在读写执行三位数字之前,形成一个四位数的权限码。
示例:
# 设置 setuid,基本权限为755 (rwxr-xr-x)
chmod 4755 <文件名> # 结果:rwsr-xr-x
# 同时设置 setuid 和 setgid,基本权限为711 (rwx--x--x)
chmod 6711 <文件名> # 结果:rws--s--x
# 设置 setuid,但属主没有执行权限,基本权限为611 (rw---x--x)
chmod 4611 <文件名> # 结果:rwS--x--x
一个重要提示:在上面的第三个例子中,权限显示为 rwS--x--x,其中 S 为大写。这表示文件属主(u)的 x 位并未被设置,而 setuid 位却被设置了。这种组合在现实中是“无用”的,因为属主自己都不能执行这个文件,setuid 位也就失去了意义。你可以忽略这种设置,chmod 命令本身不会对这种不合理的权限组合进行检查。
同样需要注意的是,chmod 命令本身并不对权限的逻辑合理性做完整性检查。它可以给一个文本文件赋予执行权限,或给一个目录设置 setuid 位(这通常无意义)。因此,不要看到一个文件具有执行权限,就理所当然地认为它一定是一个程序或脚本,这可能只是一个权限设置错误。
理解并正确应用 setuid、setgid 和 sticky 位,是深入掌握 Linux 系统权限管理和安全机制的关键一步。这些特性使得系统在提供必要功能灵活性的同时,又能维持良好的安全边界。如果你想了解更多底层原理或探讨其他系统管理话题,欢迎来 云栈社区 交流。