ACL 与特殊权限¶
本文你会学到:
- 传统权限的三层结构局限与 ACL 的改进
- 文件系统对 ACL 的支持状态检查
getfacl查询与setfacl设置 ACL 的命令- ACL 中默认权限、掩码的含义
- 使用 ACL 实现细粒度权限控制
- SUID、SGID、Sticky Bit 的原理与危险性
- 特殊权限在不同场景中的实际应用
- 文件属性(chattr、lsattr)的使用
- SELinux 与传统权限、ACL 的关系
传统权限的局限¶
想象一个场景:/srv/project 目录属于 devteam 组,你想让 alice 只读访问,但她不是 devteam 成员,也不该加入。传统权限无法做到"仅对 alice 开放读权限",只能在三种主体里二选一,精度不够。
ACL(Access Control List,访问控制列表)在传统 rwx 之上叠加了一层细粒度控制:可以针对**任意指定用户**或**任意指定组**单独设置权限,互不干扰。
ACL 基础¶
确认文件系统支持¶
现代 Linux 系统(ext4、XFS)默认支持 ACL,无需额外配置。可以通过以下命令确认:
XFS 无需显式启用
RHEL 8+/CentOS Stream 的系统盘通常是 XFS,ACL 开箱即用,ls -l 看到 + 号即说明 ACL 已生效。
getfacl:查看 ACL¶
getfacl 输出解读(以 acl_test1 为例):
当文件设置了 ACL 后,ls -l 权限字符串末尾会出现 + 号:
setfacl:设置 ACL¶
针对用户授权¶
针对组授权¶
默认 ACL(目录继承)¶
在**目录**上设置默认 ACL 后,该目录下**新建的文件和子目录**会自动继承这些规则:
设置后,getfacl 输出中会出现 default: 前缀的条目:
删除与清除¶
递归与批量¶
mask 的作用¶
ACL mask 是**实际生效权限的上限**,它约束的对象是除文件 owner 和 others 以外的所有 ACL 条目(包括命名用户和组)。
setfacl 会自动更新 mask
每次用 -m 修改命名用户/组的权限时,mask 会被自动更新为所有命名权限的并集。手动设置 mask 之后,若再次 setfacl -m u:...,mask 会再次被覆盖。生产中通常将 mask 设为 rwx,再单独限制各用户/组。
SUID(Set User ID)¶
当你执行 /usr/bin/passwd 修改密码时,这个普通用户凭什么能写入只有 root 才能访问的 /etc/shadow?答案就是 SUID。
SUID 设置在**可执行文件**上,任何用户执行该文件时,进程临时以文件拥有者的身份运行,而非调用者本身。
设置 SUID¶
权限字符说明:
| 显示 | 含义 |
|---|---|
-rwsr-xr-x |
owner 有 x + SUID → 显示小写 s,正常生效 |
-rwSr-xr-x |
owner 无 x + SUID → 显示大写 S,通常是错误配置 |
审计系统中的 SUID 文件¶
SUID 是高危权限
随意在自定义脚本上设置 SUID 是重大安全漏洞。攻击者只需找到一个带 SUID 的可利用文件,即可完成提权。定期执行上面的 find 命令审计 SUID 文件清单。
SGID(Set Group ID)¶
SGID 有两种完全不同的使用场景。
用于可执行文件¶
执行时**临时以文件所属组身份运行**(类似 SUID,但换成了组身份)。实际使用较少。
用于目录(常用!)¶
在目录上设置 SGID 后,该目录下**新建的文件和子目录自动继承目录的所属组**,而不是创建者的默认组。这对团队协作目录非常实用:
SGID 目录 + ACL 的组合
协作目录的标准做法:目录设 SGID(保证组归属一致)+ ACL(精细控制特定成员权限),两者互补。
Sticky Bit¶
/tmp 目录权限是 1777,任何人都可以在里面创建文件——但为什么你不能删除别人的文件?因为它设置了 Sticky Bit。
Sticky Bit 设置在目录上时,即使你对该目录有 w 权限,也**只能删除自己创建的文件**,不能删除他人的文件。
| 显示 | 含义 |
|---|---|
drwxrwxrwt |
others 有 x + Sticky → 小写 t,正常生效 |
drwxrwxrwT |
others 无 x + Sticky → 大写 T,权限存在但无执行 |
特殊权限数字速查¶
| 特殊权限 | 数字前缀 | 对文件的效果 | 对目录的效果 |
|---|---|---|---|
| SUID | 4 |
执行时以 owner 身份运行 | 无意义 |
| SGID | 2 |
执行时以所属组身份运行 | 新建文件自动继承目录的所属组 |
| Sticky Bit | 1 |
无意义 | 只有文件 owner 能删除自己的文件 |
组合示例:chmod 6755 file(SUID + SGID = 4+2 = 6),chmod 3777 dir(SGID + Sticky = 2+1 = 3)。
chattr / lsattr(不可变属性)¶
chattr 提供了一层超越权限系统的保护——即使是 root 也无法直接修改或删除设置了 +i 的文件。
lsattr 输出示例:
常用属性速查:
| 属性 | 全称 | 作用 |
|---|---|---|
i |
immutable | 不可删除/修改/重命名/硬链接,root 也不行 |
a |
append-only | 只能追加内容,不能覆盖或删除,适合日志文件 |
s |
secure delete | 删除时用 0 覆盖磁盘数据(安全删除) |
u |
undeletable | 删除后内容仍保留,可恢复 |
c |
compressed | 文件在磁盘上自动压缩存储 |
防止关键配置被覆盖
chattr +i /etc/resolv.conf 可以防止 DHCP 客户端或某些脚本自动覆盖 DNS 配置。修改前记得先 chattr -i 解除保护。
发行版差异¶
ext4 在 Debian/Ubuntu 上默认启用 ACL,大多数情况下无需额外操作。
扩展属性(xattr)¶
传统文件元数据(权限/时间/大小)是固定字段,无法存储自定义信息。当你需要给文件附加安全标签、版本号、审计备注时,这些字段无处安放——这就是扩展属性(Extended Attributes,xattr / EA)存在的理由。
xattr 允许在文件 inode 上附加任意键值对,格式为 namespace.name = value,完全独立于文件内容本身。
命名空间(Namespace)¶
xattr 按命名空间划分用途,共有 4 类:
| 命名空间 | 用途 | 权限要求 |
|---|---|---|
user.* |
普通用户自定义元数据(最常用) | 文件读权限(读)/ 写权限(写) |
security.* |
SELinux/AppArmor 安全标签、文件能力 | 系统/安全模块管理 |
system.* |
内核使用,如 POSIX ACL 内部存储(system.posix_acl_access) |
内核内部 |
trusted.* |
特权进程专用 | CAP_SYS_ADMIN |
user 命名空间的限制
user.* 只能用于**普通文件和目录**,不可用于符号链接、设备文件、套接字或 FIFO。
此外,若目录设置了 sticky 位(如 /tmp)且非当前用户所有,普通进程不能在其上创建 user.* EA。
基本操作命令¶
| 查看扩展属性 | |
|---|---|
| 设置与删除扩展属性 | |
|---|---|
| SELinux 安全上下文查看(security 命名空间) | |
|---|---|
文件系统支持¶
| 文件系统 | xattr 支持 | 备注 |
|---|---|---|
| ext4 | 需 user_xattr 挂载选项 |
现代 Linux 发行版默认已启用 |
| XFS | 默认支持,无需额外配置 | RHEL 8+ 根文件系统首选 |
| Btrfs | 原生支持 | 备份工具大量使用 user.* |
| JFS | 支持,总量上限 128 KB | 另有 os2 命名空间 |
ext4 单条 xattr 大小不能超过一个逻辑块(通常 4 KB),且单个文件所有 EA 总量不能超过一个块大小(1024 / 2048 / 4096 字节,视格式化参数而定)。
user_xattr 挂载选项¶
ext4 在 Debian/Ubuntu 上**默认启用** user_xattr,通常无需手动配置。若需显式开启,在 /etc/fstab 中为对应分区添加 user_xattr 挂载选项:
典型应用场景¶
- 安全标签:SELinux/AppArmor 将上下文信息存储在
security.*中,ls -Z即可查看 - 版本与审计:用
user.version、user.audit_status标记文件状态,无需修改文件内容 - 备份元数据:Btrfs 增量备份工具使用
user.*记录快照信息 - 容器运行时:Docker 等运行时使用 xattr 存储镜像层和容器配置信息
- POSIX ACL 存储:
setfacl设置的 ACL 规则实际存储在system.posix_acl_access中
注意事项:复制与归档¶
xattr 不会自动随文件一起传递,常见工具需显式指定:
| 保留 xattr 的复制与归档 | |
|---|---|
跨文件系统复制
将文件复制到不支持 xattr 的文件系统(如 FAT32、NFS v3)时,xattr 会静默丢失,不会报错。跨服务器传输重要 xattr 时,优先使用 rsync -aX 并确认目标文件系统支持。