Linux 权限进阶:一文读懂 SUID、SGID 与粘滞位
概述
Linux 的基础权限(读 r、写 w、执行 x)能满足绝大多数文件访问控制需求,但碰到系统管理(比如普通用户改密码)和多人协作(比如团队共享文件)这些场景,普通权限就有点「力不从心」了。
SUID、SGID 和粘滞位(Sticky Bit)是 Linux 给的特殊权限位,它们打破了「用户只能以自己身份操作文件」的限制,既能让普通用户执行高权限命令,又能在多人共享时保住文件安全。搞懂这三个特殊权限,是从「Linux 入门」跨到「系统运维进阶」的关键一步。
一、SUID:让普通用户以文件所有者身份执行命令
1. SUID 是什么?
SUID(Set User ID on Execution)是一种「执行时切换身份」的机制:一个文件设了 SUID 位之后,普通用户跑这个文件时会临时拿到文件所有者的权限(执行完权限自动收回),而不是以自己身份跑。
最典型的例子就是 /usr/bin/passwd 命令。这命令所有者是 root,普通用户改自己密码得往 /etc/shadow(只有 root 能写的密码文件)里写——正是 SUID 让普通用户能临时以 root 身份执行 passwd,才把密码改成功了。
2. SUID 的核心特点与限制
| 特点 / 限制 | 说明 |
|---|---|
| 仅作用于可执行文件 | 非可执行文件设 SUID 没意义(执行权限是 SUID 生效的前提) |
| 仅支持二进制文件 | Shell 脚本没法设 SUID(Linux 为了安全,禁止脚本靠 SUID 提权) |
| 执行时临时获所有者权限 | 只在文件执行期间生效,执行完立即收回,避免权限泄露 |
| 对目录无效 | SUID 位设在目录上时,Linux 会忽略(目录的特殊权限归 SGID 管) |
3. 如何查看与设置 SUID?
(1)查看 SUID 位
用 ls -l 看文件权限时,要是文件所有者的「执行位」(x)被换成了 s,就说明这个文件已经设了 SUID:
# 查看 passwd 命令的权限(所有者执行位为 s,即 SUID 已启用)
ls -l /usr/bin/passwd
# 输出示例:-rwsr-xr-x 1 root root 68232 5月 10 2023 /usr/bin/passwd
# ↑ 所有者权限位的 x 变成 s,代表 SUID 生效
要是显示 S(大写),说明文件有 SUID 位但缺所有者执行权限(x),SUID 没法生效,得补上执行权限。
(2)设置 SUID 位
用 chmod 命令,通过 u+s(user + setuid)参数给文件加 SUID 位:
# 语法:chmod u+s 文件名
# 示例:为 test.bin(二进制文件)设置 SUID
chmod u+s /path/to/test.bin
# 验证设置结果
ls -l /path/to/test.bin
# 输出示例:-rwsr-xr-x 1 root user 12345 5月 31 2024 /path/to/test.bin
(3)取消 SUID 位
用 u-s 参数去掉 SUID 位:
chmod u-s /path/to/test.bin
4. SUID 的典型应用场景
- 系统命令提权:除了 passwd,su、sudo、ping 这些命令都靠 SUID 实现「普通用户执行高权限操作」;
- 自定义工具提权:要是你写了个需要访问系统级文件的二进制工具(比如读系统日志),可以给工具设 SUID(所有者设为 root),让普通用户不用 sudo 就能跑。
安全提醒:SUID 是把「双刃剑」——要是给某个恶意的二进制文件设了 SUID(所有者是 root),攻击者就能借这个文件拿到 root 权限。所以得定期用 find / -perm -4000 -type f 2>/dev/null 把系统里设了 SUID 的文件翻一遍,排查异常文件。
二、SGID:解决多用户共享文件的权限难题
1. SGID 是什么?
SGID(Set Group ID on Execution)有两种作用场景:作用在文件上和作用在目录上,其中「作用在目录上」最常用也最实在。
- 作用在文件上:跟 SUID 类似,普通用户跑这个文件时会临时拿到文件所属组的权限(而不是自己默认的组权限);
- 作用在目录上:这是 SGID 的核心用法——在设了 SGID 的目录里,所有新建的文件 / 子目录的所属组,会自动继承这个目录的所属组,而不是创建者自己的默认组。
拿团队协作举个例子:开发团队有个共享目录 /data/project,所属组是 dev。给这个目录设了 SGID 之后,不管团队成员(都属于 dev 组)用自己的账号在里面建文件还是子目录,新文件的所属组都会是 dev,而不是成员个人的默认组,于是「团队成员自动就有文件的访问权限」了。
2. SGID 的核心特点
| 作用对象 | 核心效果 |
|---|---|
| 可执行文件 | 执行文件时,临时获得文件所属组的权限(类似 SUID,但切换的是组权限) |
| 目录 | 目录内新建的文件 / 子目录,自动继承目录的所属组(解决多用户共享的权限继承问题) |
| 依赖组执行权限 | 作用在文件时,文件所属组需有执行权限(x);作用在目录时,目录所属组需有执行权限(x,目录的执行权限代表 “进入目录”) |
3. 如何查看与设置 SGID?
(1)查看 SGID 位
用 ls -l 看时,文件 / 目录的「所属组执行位」(x)被换成 s,就说明已经设了 SGID:
# 查看一个设置了 SGID 的共享目录
ls -l /data/
# 输出示例:drwxr-sr-x 2 root dev 4096 5月 31 2024 project/
# ↑ 所属组权限位的 x 变成 s,代表 SGID 生效
- 要是显示 S(大写),说明有 SGID 位但缺所属组执行权限,SGID 没法生效。
(2)设置 SGID 位
用 chmod 命令,通过 g+s(group + setgid)参数给文件 / 目录加 SGID 位:
# 场景1:为共享目录设置 SGID(最常用)
# 1. 创建共享组 dev
groupadd dev
# 2. 创建共享目录 /data/project
mkdir -p /data/project
# 3. 修改目录所属组为 dev(确保团队成员属于该组)
chgrp dev /data/project
# 4. 为目录设置 SGID,并开放组写权限(允许成员修改文件)
chmod g+s,g+w /data/project
# 验证设置结果
ls -l /data/
# 输出示例:drwxrwsr-x 2 root dev 4096 5月 31 2024 project/
# 场景2:为可执行文件设置 SGID(较少用)
chmod g+s /path/to/test.bin
(3)取消 SGID 位
用 g-s 参数去掉 SGID 位:
chmod g-s /data/project
4. SGID 的实战配置:搭建团队共享目录
拿「开发团队共享代码目录」为例,完整配置流程如下:
# 1. 创建共享组 dev,添加团队成员(如 user1、user2)
groupadd dev
usermod -aG dev user1
usermod -aG dev user2
# 2. 创建共享目录,设置所属组和 SGID
mkdir -p /data/dev_code
chgrp dev /data/dev_code
chmod g+s,g+w /data/dev_code # g+s 设 SGID,g+w 允许组内成员写
# 3. 配置成员的 umask(确保新建文件对组可写)
# umask 002 表示:新建文件权限为 664(rw-rw-r--),目录为 775(rwxrwxr-x)
echo "umask 002" >> /home/user1/.bashrc
echo "umask 002" >> /home/user2/.bashrc
source /home/user1/.bashrc
source /home/user2/.bashrc
# 4. 测试:user1 在共享目录新建文件
su - user1
cd /data/dev_code
touch test_code.py
# 查看文件权限:所属组为 dev,组有读写权限
ls -l test_code.py
# 输出示例:-rw-rw-r-- 1 user1 dev 0 5月 31 2024 test_code.py
到这步,user2 就能直接编辑 test_code.py(因为文件所属组是 dev,而且组有写权限),不用手动改文件权限,实现「无缝共享」。
三、粘滞位(Sticky Bit):保护多用户共享目录的文件安全
1. 粘滞位是什么?
粘滞位(Sticky Bit)只作用在目录上,是一种「防删除保护」机制:在设了粘滞位的目录里,只有文件的所有者、目录的所有者,以及 root 用户,才能删除或重命名这个目录下的文件——就算别的用户对目录有「写权限」,也删不了别人建的文件。
最典型的例子就是系统的 /tmp 目录(所有用户都能读写的临时目录):
ls -l /
# 输出示例:drwxrwxrwt 14 root root 4096 5月 31 2024 tmp/
# ↑ 其他用户权限位的 x 变成 t,代表粘滞位生效
要是 /tmp 没粘滞位,谁都能删别人的临时文件,会出大安全问题。
2. 粘滞位的核心特点
- 只作用在目录:文件设粘滞位没意义(Linux 会忽略);
- 限制「删除 / 重命名」操作:只允许 3 类角色动文件:文件所有者、目录所有者、root;
- 不影响「读写执行」:别的用户照样能对文件读、写、执行(只要有对应权限),只是限制删除和重命名。
3. 如何查看与设置粘滞位?
(1)查看粘滞位
用 ls -l 看目录权限时,要是「其他用户执行位」(x)被换成 t(小写),就说明设了粘滞位:
ls -l /tmp
# 输出示例:drwxrwxrwt 14 root root 4096 5月 31 2024 tmp/
# ↑ 其他用户权限位的 x 变成 t,代表粘滞位生效
- 要是显示 T(大写),说明有粘滞位但缺其他用户执行权限(x),粘滞位没法生效(目录的执行权限是「进目录」的前提)。
(2)设置粘滞位
用 chmod 命令,通过 o+t(other + sticky)参数给目录加粘滞位:
# 语法:chmod o+t 目录名
# 示例:为团队共享目录 /data/share 设置粘滞位(防止成员删别人的文件)
chmod o+t /data/share
# 验证设置结果
ls -l /data/
# 输出示例:drwxrwxr-t 2 root dev 4096 5月 31 2024 share/
(3)取消粘滞位
用 o-t 参数去掉粘滞位:
chmod o-t /data/share
4. 粘滞位的应用场景
- 公共临时目录:比如 /tmp、/var/tmp,保证所有用户能建临时文件,但删不了别人的;
- 团队共享目录:就算给目录开了「其他用户写权限」,靠粘滞位也能防误删别人的文件(比如设计团队的素材共享目录)。
四、总结:特殊权限位对比与使用建议
| 权限位 | 作用对象 | 核心效果 | 典型应用场景 | 安全注意事项 |
|---|---|---|---|---|
| SUID | 可执行文件 | 执行文件时,临时获文件所有者权限 | passwd、sudo 等系统命令 | 禁止给 Shell 脚本设 SUID;定期排查异常 SUID 文件 |
| SGID | 目录(主要) | 目录内新建文件 / 子目录,自动继承目录所属组 | 团队共享目录(如代码、素材目录) | 确保共享组只包含需要访问的用户,避免权限泄露 |
| 粘滞位 | 目录 | 仅文件所有者、目录所有者、root 可删除 / 重命名目录内文件 | /tmp、公共共享目录 | 仅给 “多用户可写” 的目录设粘滞位,避免过度限制 |
实用命令速查
| 需求 | 命令示例 |
|---|---|
| 查找系统中所有 SUID 文件 | find / -perm -4000 -type f 2>/dev/null |
| 查找系统中所有 SGID 目录 | find / -perm -2000 -type d 2>/dev/null |
| 查找系统中所有粘滞位目录 | find / -perm -1000 -type d 2>/dev/null |
| 同时设置 SGID 和粘滞位 | chmod g+s,o+t /data/share |
搞懂 SUID、SGID 和粘滞位,不光能解决 Linux 里实际的权限难题,更能帮你体会「Linux 权限设计的安全思路」——既要满足灵活的操作需求,又得用机制限制权限滥用,这也是 Linux 能成为服务器主流系统的核心原因之一。