DAC(自主访问控制)只看 UID/GID → 一旦进程被入侵就拥有该用户的全部权限。MAC(强制访问控制)在 DAC 之上加一层强制策略。
一、先看图
flowchart TD
SYSCALL[系统调用] --> DAC[DAC 检查<br/>UID/GID/权限位]
DAC --> LSM{LSM hooks}
LSM --> SE[SELinux<br/>类型强制]
LSM --> AA[AppArmor<br/>路径强制]
LSM --> OTHER[其他 LSM<br/>SMACK/TOMOYO]
SE --> ALLOW[允许 / 拒绝]
AA --> ALLOW
classDef dac fill:#f0883e22,stroke:#f0883e,color:#adbac7;
classDef mac fill:#388bfd22,stroke:#388bfd,color:#adbac7;
class SYSCALL,DAC dac
class LSM,SE,AA,OTHER,ALLOW mac
二、LSM 框架
Linux Security Modules → 内核在关键操作前调用安全钩子:
// security/security.c
int security_file_open(struct file *file)
{
return call_int_hook(file_open, file);
}多个 LSM 可以堆叠(SELinux + Landlock + BPF_LSM)。
三、SELinux
3.1 类型强制(Type Enforcement)
每个进程有类型(domain),每个文件有类型:
httpd_t → 读 httpd_sys_content_t ✓
httpd_t → 读 shadow_t ✗
3.2 策略语言
allow httpd_t httpd_sys_content_t:file { read open getattr };
3.3 模式
getenforce # Enforcing / Permissive / Disabled
setenforce 0 # 临时切换到 Permissive
# /etc/selinux/config 永久配置3.4 容器标签
# 每个容器自动分配 MCS 标签
docker run → svirt_lxc_net_t:s0:c123,c456不同容器的标签不同 → 互相隔离。
四、AppArmor
4.1 路径基础
AppArmor 用文件路径(不是 inode 标签):
profile /usr/bin/nginx {
/var/www/** r,
/var/log/nginx/** w,
/etc/nginx/** r,
network tcp,
}
4.2 优势与劣势
| 方面 | SELinux | AppArmor |
|---|---|---|
| 模型 | 类型标签 | 路径 |
| 粒度 | 更细 | 较粗 |
| 复杂度 | 高 | 低 |
| 默认发行版 | RHEL/Fedora | Ubuntu/SUSE |
| 重命名文件 | 标签跟随 inode | 路径变化可能失效 |
五、audit 日志
# SELinux 拒绝日志
ausearch -m avc -ts recent
# type=AVC msg=audit(...): avc: denied { read } for pid=1234
# scontext=httpd_t tcontext=shadow_t tclass=file
# AppArmor 拒绝日志
dmesg | grep "apparmor=\"DENIED\""六、编写策略
6.1 SELinux
# 从拒绝日志生成策略
ausearch -m avc | audit2allow -M mypolicy
semodule -i mypolicy.pp6.2 AppArmor
# 学习模式
aa-complain /usr/bin/nginx
# 运行程序 → 记录访问
aa-logprof # 从日志生成策略
aa-enforce /usr/bin/nginx # 切换到强制模式七、BPF_LSM
SEC("lsm/file_open")
int BPF_PROG(my_lsm, struct file *file)
{
// 动态安全策略
if (should_deny(file))
return -EPERM;
return 0;
}可编程的 LSM → 不需要写内核模块。
八、多 LSM 堆叠
Linux 5.1+ 支持 LSM 堆叠:
cat /sys/kernel/security/lsm
# lockdown,capability,landlock,yama,apparmor,bpf九、观察
# 当前 LSM
cat /sys/kernel/security/lsm
# SELinux
getenforce
sestatus
seinfo -t | wc -l # 类型数量
# AppArmor
aa-status
cat /sys/kernel/security/apparmor/profiles十、小结
- MAC 在 DAC 之上强制执行安全策略
- SELinux = 类型强制 → 精细但复杂
- AppArmor = 路径强制 → 简单但粒度较粗
- LSM 框架允许多个安全模块堆叠
- BPF_LSM 提供可编程安全策略
参考文献
security/selinux/security/apparmor/Documentation/admin-guide/LSM/- SELinux Project wiki
工具
getenforce/setenforcesestatus/seinfoaa-status/aa-enforceausearch
同主题继续阅读
把当前热点继续串成多页阅读,而不是停在单篇消费。
【操作系统百科】内核与用户态的边界:copy_from_user、pin、seccomp、capability
内核代码不能像用户代码那样自由访问任何指针。本文围绕 Linux 的 access_ok / copy_from_user / get_user_pages / pin_user_pages / __user 注解,说明用户页在内核视角的生命周期;再把视角扩展到 capability、namespace、seccomp、Landlock、LSM 等软件边界机制,汇成一张内核对用户态信任的全景图。
【操作系统百科】内存回收
Linux 内存回收是 VM 最复杂的子系统之一。本文讲 active/inactive LRU、kswapd 与 direct reclaim、watermark 三线、swappiness 的真实含义、MGLRU 改造、memcg 回收与 PSI。
【操作系统百科】交换
swap 还值得开吗?本文讲 swap area 基础、swap cache、zram 压缩内存、zswap 前端压缩池、swappiness 的真实含义、容器里的 swap 策略,以及为什么现代 Android 全靠 zram 不靠磁盘。
【操作系统百科】Slab/SLUB 分配器
buddy 只管页粒度(4K+),内核大多数对象只有几十到几百字节。slab/SLUB 在 buddy 之上做对象级缓存。本文讲 slab 历史、SLUB 接手、SLOB 退场、kmem_cache、per-CPU cache、KASAN 集成。