Linux 权限、安全上下文与特殊权限
Linux 的安全机制可以理解为多个层次。
最基础的一层是传统 Unix 权限模型:
User / Group / Other
+
r / w / x
在此基础上还有:
SUID
SGID
Sticky Bit
ACL
更高级的安全机制还包括:
Capabilities
SELinux
AppArmor
seccomp
Namespaces
本章主要讨论:
传统 Linux 文件权限 + 特殊权限位 + ACL。
一、Linux 权限判断的基本对象
例如:
ls -l test.txt
得到:
-rw-r----- 1 userA group1 1024 Oct 1 10:00 test.txt
可以拆解为:
- rw- r-- ---
│ │ │ │
│ │ │ └── Other 权限
│ │ └─────── Group 权限
│ └──────────── Owner 权限
└──────────────── 文件类型
文件:
Owner = userA
Group = group1
权限:
Owner → rw-
Group → r--
Other → ---
二、Linux 判断权限时看的是进程身份
需要建立一个非常重要的概念:
真正访问文件的不是“登录用户”这个抽象概念,而是进程。
例如:
userA
↓
启动 bash
↓
bash 启动 cat
↓
cat 进程
↓
访问 test.txt
内核最终判断的是:
这个进程以什么 UID / GID 身份运行,它是否有权限访问这个文件?
因此 Linux 文件权限本质上是:
Process Credentials
↓
与
↓
File Owner / Group / Mode
↓
进行匹配
三、进程中的 UID
Linux 进程实际上存在多种 UID,其中最重要的是:
Real UID RUID
Effective UID EUID
Saved UID SUID / Saved-set-user-ID
注意这里的:
Saved UID
也经常缩写为 SUID,但它和文件权限中的:
Set User ID
不是完全相同的概念。
Real UID
表示:
谁启动了这个进程。
例如:
userA
↓
执行 passwd
通常:
Real UID = userA
Effective UID
表示:
当前进程实际进行权限检查时使用的用户身份。
Linux 内核在进行传统文件权限判断时,重点使用的是:
Effective UID
因此可以简单记忆:
RUID → 谁启动了我
EUID → 我现在以谁的权限工作
SUID 程序的核心作用,就是可能让:
RUID ≠ EUID
四、Linux 文件权限匹配规则
假设:
-rw-r----- 1 userA group1 test.txt
某个进程准备访问 test.txt。
Linux 会按照一定顺序判断。
第一步:判断 Owner
如果进程的有效用户身份与文件 Owner 匹配:
Process EUID
==
File Owner UID
那么:
只使用 Owner 权限。
例如:
-rw-r----- userA group1 test.txt
如果:
EUID = userA
则检查:
rw-
五、Owner 匹配后不会继续检查 Group
这一点非常重要。
假设:
----rwx--- userA group1 test
userA 同时也是 group1 成员。
此时 userA 访问文件:
Owner 权限 = ---
Group 权限 = rwx
因为:
EUID == Owner
所以直接使用:
Owner = ---
不会因为 Group 有 rwx 就继续尝试 Group 权限。
因此权限判断不是:
“Owner 不够,再看看 Group 能不能补权限。”
而是:
身份匹配到哪一类,就使用哪一类权限。
六、第二步:判断 Group
只有 Owner 不匹配时,才判断 Group。
Linux 会检查进程的组身份是否匹配文件 Group。
这里不仅涉及:
Effective GID
还涉及:
Supplementary Groups
即用户的附加组。
例如:
id userB
可能得到:
uid=1001(userB)
gid=1001(userB)
groups=1001(userB),2000(group1)
虽然:
Primary Group = userB
但是:
Supplementary Group = group1
因此 userB 的进程仍然可以匹配:
File Group = group1
然后使用 Group 权限。
七、第三步:Other
如果:
Owner 不匹配
&&
Group 不匹配
那么:
使用 Other 权限
因此传统 Unix 权限判断可以总结成:
Process
│
▼
EUID == File Owner?
│
┌───┴───┐
YES NO
│ │
Owner ▼
权限 Group 匹配?
│
┌───┴───┐
YES NO
│ │
Group Other
权限 权限
一句话记忆:
Owner → Group → Other,匹配成功后立即使用对应权限,不会继续向后叠加权限。
八、root 的权限
root:
UID = 0
在传统 DAC 权限模型中拥有非常高的权限,并且可以绕过大量普通文件权限检查。
但是不能简单理解成:
root 永远拥有无限权限。
现代 Linux 还可能受到:
SELinux
AppArmor
Capabilities
Namespaces
只读文件系统
Immutable 属性
等机制影响。
因此:
rwx
只是 Linux 安全模型的一层。
九、SUID
SUID:
Set User ID
主要用于:
可执行文件。
假设:
-rwxr-xr-x 1 root root program
userA 执行:
./program
正常情况下:
RUID = userA
EUID = userA
也就是说:
普通用户执行一个属于 root 的程序,并不意味着程序自动获得 root 权限。
十、设置 SUID
执行:
chmod u+s program
文件权限可能变成:
-rwsr-xr-x root root program
此时 userA 执行:
./program
进程可能变成:
RUID = userA
EUID = root
因此程序在执行某些权限检查时具有:
root
的有效身份。
所以更准确地说:
SUID 使可执行程序运行时的 Effective UID 设置为该可执行文件 Owner 的 UID。
而不是简单地说:
“整个进程变成了文件所有者。”
因为:
RUID
通常仍然记录真正启动程序的用户。
十一、passwd 为什么需要 SUID?
经典例子:
/usr/bin/passwd
查看:
ls -l /usr/bin/passwd
可能看到:
-rwsr-xr-x 1 root root ... /usr/bin/passwd
普通用户执行:
passwd
需要修改系统保存密码信息的受保护资源。
普通用户本身没有直接修改这些系统文件的权限。
但是 passwd:
Owner = root
SUID = enabled
因此执行过程中可以获得完成特定受保护操作所需要的权限。
注意:
这并不意味着普通用户可以通过 passwd 任意修改系统文件。
因为程序自身的代码逻辑仍然会限制:
允许修改什么
允许修改谁的密码
需要进行什么认证
SUID 只是提供程序完成受保护操作所需要的权限基础。
十二、SUID 的 s 和 S
例如:
-rwsr-xr-x
Owner 权限中的:
s
实际上表示两个权限同时存在:
x
+
SUID
即:
Owner 有执行权限
SUID 已设置
如果:
-rwSr-xr-x
大写:
S
表示:
SUID 已设置
但是 Owner 没有 x 权限
因此:
s = SUID + x
S = SUID,但是没有 x
十三、设置 SUID
符号方式:
chmod u+s FILE
取消:
chmod u-s FILE
数字方式:
SUID = 4
例如:
chmod 4755 program
其中:
4 755
│ │
│ └── 普通 rwx 权限
│
└───── SUID
十四、SUID 主要针对可执行文件
不要随意给普通程序设置:
chmod u+s
尤其:
Shell
解释器
编辑器
脚本
用户可修改的程序
因为 SUID 程序可能形成严重的提权风险。
特别是:
Owner = root
+
SUID
意味着程序可能拥有非常高的系统权限。
因此 SUID 是 Linux 安全审计中的重点对象。
可以搜索:
find / -perm -4000 -type f 2>/dev/null
查找系统中的 SUID 文件。
十五、SGID
SGID:
Set Group ID
数值表示:
2
设置:
chmod g+s FILE
或者:
chmod 2755 FILE
SGID 有两种非常重要的用途:
SGID on Executable File
SGID on Directory
二者必须分开理解。
十六、SGID 用于可执行文件
如果:
-rwxr-sr-x root group1 program
那么执行这个程序时:
进程的 Effective GID 可以设置为该文件所属组的 GID。
也就是说:
SUID
→ 改变 Effective UID
SGID
→ 改变 Effective GID
十七、SGID 用于目录
SGID 更常见、更实用的场景是:
共享目录。
假设创建:
groupadd group1
useradd a1
useradd a2
usermod -aG group1 a1
usermod -aG group1 a2
创建共享目录:
mkdir /var/tmp3
chown root:group1 /var/tmp3
chmod 2775 /var/tmp3
查看:
ls -ld /var/tmp3
得到:
drwxrwsr-x root group1 /var/tmp3
这里:
s
表示目录设置了 SGID。
十八、目录 SGID 的作用
正常情况下,用户创建文件时,新文件的 Group 通常根据进程的文件创建规则决定,通常与创建进程的文件系统凭据有关。
但是:
如果父目录设置了 SGID,新创建的文件和子目录通常会继承父目录的 Group。
例如:
/var/tmp3
Owner = root
Group = group1
SGID = enabled
a1 创建:
touch /var/tmp3/a.txt
a2 创建:
touch /var/tmp3/b.txt
可能得到:
-rw-rw-r-- a1 group1 a.txt
-rw-rw-r-- a2 group1 b.txt
重点:
Owner 不同
Group 相同
这非常适合:
多人共享工作目录。
十九、SGID 不代表组成员一定可以修改文件
这是非常容易混淆的一点。
SGID 只保证:
新文件继承父目录的 Group。
至于 group1 是否真的能够修改文件,还要看:
文件的 Group 权限
+
umask
+
ACL
例如:
-rw-r--r-- a1 group1 test
即使:
a2 ∈ group1
a2 仍然没有写权限。
因为:
Group = r--
因此多人共享目录经常需要:
SGID
+
合适的 Group 权限
+
umask / Default ACL
一起使用。
二十、目录删除文件看什么权限?
这是理解 Sticky Bit 前最重要的知识。
很多人认为:
“我没有文件的写权限,所以我不能删除它。”
这并不准确。
Linux 中:
删除文件,本质上是在修改父目录中的目录项。
因此删除文件主要看:
父目录的权限
而不是文件本身的 w 权限。
假设:
drwxrwxrwx shared/
里面:
-rw------- a1 a1 secret.txt
即使 a2:
不能读取 secret.txt
不能修改 secret.txt
但如果 a2 对:
shared/
拥有足够的:
w + x
目录权限,那么在没有 Sticky Bit 等额外限制时,a2 可能仍然能够:
删除
重命名
这个文件的目录项。
二十一、Sticky Bit
Sticky Bit 主要用于:
共享可写目录。
设置:
chmod o+t /var/tmp3
或者数字方式:
chmod 1777 /var/tmp3
例如:
drwxrwxrwt root root /tmp
最后:
t
就是 Sticky Bit。
二十二、Sticky Bit 的作用
在一个所有人都可写的共享目录中,如果没有 Sticky Bit:
a1 创建 file1
a2 创建 file2
只要目录权限允许:
a1 可能删除 file2
a2 可能删除 file1
设置 Sticky Bit 后,会对删除和重命名增加额外限制。
通常只有:
文件所有者
目录所有者
或具有相应特权的进程
才能删除或重命名目录中的对应文件。
因此:
Sticky Bit
≈
共享目录中限制用户删除/重命名其他用户的文件
二十三、最经典的 Sticky Bit:/tmp
执行:
ls -ld /tmp
通常可以看到:
drwxrwxrwt root root /tmp
即:
777
+
Sticky Bit
为什么?
因为:
/tmp
需要允许大量用户和程序创建临时文件。
如果只有:
777
那么用户之间可能互相删除对方的文件。
因此使用:
1777
二十四、Sticky Bit 的 t 和 T
和 SUID/SGID 类似:
t
表示:
Sticky Bit
+
Other 有 x 权限
而:
T
表示:
Sticky Bit
+
Other 没有 x 权限
例如:
drwxrwxrwt
↑
t
二十五、特殊权限位总结
三个特殊权限:
SUID 4
SGID 2
Sticky 1
因此:
chmod 4755 file
↑
SUID
chmod 2755 directory
↑
SGID
chmod 1777 directory
↑
Sticky
可以记成:
4 → SUID
2 → SGID
1 → Sticky
二十六、三种特殊权限的核心区别
SUID
│
└─ 可执行文件
→ 影响 Effective UID
SGID
│
├─ 可执行文件
│ → 影响 Effective GID
│
└─ 目录
→ 新文件继承目录 Group
Sticky Bit
│
└─ 目录
→ 限制共享目录中删除/重命名他人文件
这是最值得记住的模型。
二十七、SGID + Sticky Bit
例如:
mkdir /shared
chown root:group1 /shared
chmod 3770 /shared
这里:
3
=
2 + 1
=
SGID + Sticky
因此:
SGID
↓
新文件继承 group1
Sticky
↓
限制成员删除/重命名其他成员拥有的文件
适用于某些共享目录场景。
但是:
不能简单地说“SGID + Sticky 通常用于
/var日志目录”。
不同日志目录和服务有不同权限模型。现代 Linux 日志服务还可能使用:
systemd-journald
ACL
专用用户
专用组
logrotate
SELinux
因此 SGID + Sticky 更准确的典型场景是:
多人或多进程共享、需要统一 Group,同时又希望限制互相删除文件的目录。
二十八、ACL:Access Control List
传统 Linux 权限只有:
一个 Owner
一个 Group
一个 Other
有时不够灵活。
例如:
hello.c
Owner = userA
Group = userA
现在希望:
userB → rw
userC → r
groupDev → rw
如果只使用传统:
Owner / Group / Other
就比较麻烦。
因此 Linux 支持:
POSIX ACL
即:
Access Control List
二十九、查看 ACL
使用:
getfacl hello.c
例如:
# file: hello.c
# owner: userA
# group: userA
user::rw-
user:userB:rw-
group::r--
mask::rw-
other::---
三十、给指定用户授权
例如:
setfacl -m u:userB:rw hello.c
表示:
-m
=
modify ACL
然后:
u:userB:rw
表示:
userB
=
read + write
三十一、给指定组授权
例如:
setfacl -m g:groupDev:rw hello.c
表示:
groupDev
=
read + write
注意你原笔记这里写成了:
g:userB
如果 userB 是用户名而不是组名,就不应该这样写。
三十二、删除指定用户 ACL
删除 userB 的 ACL:
setfacl -x u:userB hello.c
注意:
-x
删除 ACL 项时一般不再写:
:rwx
所以正确形式:
setfacl -x u:userB hello.c
而不是:
setfacl -x u:userB:rwx hello.c
三十三、删除指定组 ACL
例如:
setfacl -x g:groupDev hello.c
三十四、删除所有扩展 ACL
可以:
setfacl -b hello.c
其中:
-b
=
remove all extended ACL entries
三十五、ACL 中非常重要的 mask
ACL 中经常看到:
mask::rw-
这是非常重要的一项。
例如:
user:userB:rwx
mask::rw-
虽然给 userB 配置:
rwx
但 mask:
rw-
会限制相关 ACL 条目的最大有效权限。
因此 userB 实际有效权限可能只有:
rw-
getfacl 有时会显示:
user:userB:rwx #effective:rw-
因此 ACL 排错时一定要检查:
mask
三十六、ACL 与 ls -l
如果文件存在扩展 ACL:
ls -l hello.c
可能看到:
-rw-rw----+ 1 userA userA hello.c
↑
+
最后的:
+
通常表示该文件存在扩展 ACL。
这时不能只看:
rwx
还应该:
getfacl hello.c
三十七、Default ACL
ACL 对目录还有一个非常实用的功能:
Default ACL
它可以让:
在目录中新创建的文件自动继承预设 ACL。
例如共享开发目录:
mkdir /project
chown root:groupDev /project
chmod 2770 /project
设置默认 ACL:
setfacl -m d:g:groupDev:rwx /project
这里:
d:
=
default
以后在 /project 中创建的新文件和子目录,就可以继承相应 ACL。
查看:
getfacl /project
可能看到:
default:user::rwx
default:group::rwx
default:group:groupDev:rwx
default:mask::rwx
default:other::---
三十八、SGID + Default ACL 是共享目录的常见组合
多人协作目录经常可以使用:
SGID
+
Default ACL
SGID 负责:
继承 Group
Default ACL 负责:
继承更精细的权限
例如:
chown root:developers /project
chmod 2770 /project
setfacl -m d:g:developers:rwx /project
形成:
/project
│
├── SGID
│ ↓
│ 新文件继承 developers 组
│
└── Default ACL
↓
新文件继承指定 ACL
三十九、Linux 权限体系整体关系
到这里可以把 Linux 文件权限理解成:
Linux 文件访问
│
▼
Process Credentials
│
┌────────┴────────┐
│ │
UID GID
│ │
└────────┬────────┘
▼
DAC 权限检查
│
┌──────────────┼──────────────┐
▼ ▼ ▼
Owner Group Other
│ │ │
└──────────────┴──────────────┘
│
rwx 权限
│
┌────────┴────────┐
▼ ▼
特殊权限位 ACL
│ │
┌─────┼─────┐ 精细用户/组权限
▼ ▼ ▼
SUID SGID Sticky
在现代 Linux 中,上面这些还可能继续受到:
SELinux / AppArmor
Capabilities
seccomp
Namespaces
文件系统属性
Mount Options
等安全机制限制。
四十、最终记忆模型
传统 Linux 权限最核心的规则:
Owner 匹配
↓
使用 Owner 权限
↓
结束
否则
↓
Group 匹配
↓
使用 Group 权限
↓
结束
否则
↓
使用 Other 权限
特殊权限:
SUID
→ 执行程序时影响 Effective UID
SGID
→ 可执行程序:影响 Effective GID
→ 目录:新文件继承目录 Group
Sticky Bit
→ 共享目录中限制删除/重命名他人的文件
ACL:
传统 rwx 不够
↓
使用 ACL
↓
针对特定 User / Group 单独授权
↓
同时注意 ACL Mask
因此可以把这一章浓缩成一句话:
Linux 传统文件安全模型的核心,是内核根据进程的有效身份(UID/GID)与文件的 Owner、Group、Other 权限进行匹配;SUID/SGID 可以影响进程执行身份或目录的组继承,Sticky Bit 用于保护共享目录中的文件,而 ACL 则在传统 rwx 模型之上提供更加精细的用户和组权限控制。
浙公网安备 33010602011771号