AppArmor 为什么同一程序换路径后权限不同
来源:17golang原创
时间:2026-11-11 08:48:42 177浏览 收藏
程序只是从 /usr/local/bin/reportd 复制到 /opt/reportd,权限却突然不同,通常不是“同名程序被识别成了另一个对象”,而是 AppArmor 的 profile attachment 没有匹配新的可执行文件路径。自动套用 profile 看的是 exec 时的路径匹配;profile 文件名和程序显示名并不能代替这个条件。
先查实际执行的 ELF 路径,再查 profile 是否已经加载并挂到进程;只有确认已经匹配后,才去判断是文件规则拒绝。单纯把规则体写得更宽,解决不了 attachment 没命中的问题。
- attachment 是 profile 自动套用到可执行文件的路径条件,精确路径换了,匹配就可能消失。
- “没有 profile 标签”和“有标签但出现 DENIED”是两类问题,排查入口不同。
- 安装路径确实有多个固定选择时再用受控 glob,优先保留明确边界。
这不是程序本身的逻辑变更,也不是系统 BUG,是 AppArmor 设计之初就默认的路径绑定匹配特性,只要修改对应策略文件里的路径规则,就能让不同位置的同程序继承统一权限。
AppArmor 自动匹配看的不是程序名字,而是 attachment
AppArmor profile 可以有一个便于识别的名称,也可以带 attachment。attachment 描述的是哪些可执行文件路径会在 profile 加载后自动套用它。比如下面的写法把自动匹配条件限定为一个绝对路径:
profile reportd /usr/local/bin/reportd {
# 这里只放程序需要的文件访问规则,路径匹配由 profile 头部决定
/var/lib/reportd/** rw,
}
这个 profile 的规则体允许访问 /var/lib/reportd/ 下的内容,但不等于它会自动约束所有名为 reportd 的文件。程序若从 /opt/reportd 启动,前面的 attachment 没有命中,进程可能仍显示为 unconfined;此时你看到的“权限变宽”其实是 profile 没有挂上。

换路径后的排查顺序:先看实际执行文件,再看标签和规则
我排这类问题时会先把“程序从哪里启动”钉死。软链接、复制安装、服务文件中的 ExecStart,以及脚本的 shebang,都可能让你以为运行的是一个路径,内核实际执行的却是另一个路径。下面的命令只负责收集事实,不会修改 profile:
# 查看命令解析到的文件和软链接目标
command -v reportd
readlink -f "$(command -v reportd)"
# 查看指定 PID 当前的 AppArmor 标签
cat /proc/1234/attr/current
# 查看已加载的 profile 名称和模式
sudo aa-status
如果实际路径是 /opt/reportd,而标签仍是 unconfined,优先检查 attachment 是否覆盖它,以及 profile 是否在你启动程序前已经加载。AppArmor 通常在 exec 时完成约束,程序已经启动后再加载匹配 profile,不会把当前进程 retroactively 变成受限状态。
如果标签已经是目标 profile,再看内核审计记录中的 profile=、name= 和操作类型。此时出现 DENIED 才说明路径匹配成功但规则体缺少相应权限;把它和“标签根本没换上”分开,修复方向会完全不同。

精确路径与受控通配符怎么选
如果发布包只允许安装在一个位置,精确 attachment 最容易审查:路径变更就让部署流程同步更新 profile。若确实存在两个或多个固定目录,可以把选择写进 attachment,例如 /{usr/local/bin,opt}/reportd,但要确认目标发行版和当前 parser 对该写法的行为,不要把“目录通配”当成无条件兼容。
| 现象 | 优先检查 | 处理方向 |
|---|---|---|
| 标签是 unconfined | 实际 ELF 路径、attachment、加载时机 | 修正路径条件或加载顺序 |
| 已有目标 profile 标签但 DENIED | 审计记录的 name 与操作 | 补最小必要规则 |
| 规则改了却行为不变 | 是否重新加载 profile、是否重启进程 | 确认加载结果后重新 exec |
生产环境我更愿意先列出允许的安装路径,再逐个写入 attachment,而不是直接使用覆盖范围很大的 /**。路径条件越宽,越难判断哪个副本被自动套用,也越容易把本来应该隔离的程序纳入同一 profile。
相关问题
profile 文件名和 profile 名称必须等于可执行文件名吗?
不必须。文件名主要方便管理,profile 名称也可以与程序不同;自动套用是否发生,关键仍是 attachment 或显式的 profile 切换方式。
为什么 aa-status 显示 profile 已加载,进程仍是 unconfined?
“已加载”只说明策略进入内核,不代表当前进程的 exec 路径命中了 attachment。先用 readlink -f 确认实际路径,再对照 profile 头部。
只补一条文件读取规则能修复换路径问题吗?
不能。如果问题是 attachment 没匹配,规则体根本没有机会约束该进程。先让正确的 profile 标签出现,再处理具体的 DENIED。
-
405 收藏
-
426 收藏
-
387 收藏
-
242 收藏
-
238 收藏
-
405 收藏
-
106 收藏
-
159 收藏
-
254 收藏
-
377 收藏
-
275 收藏
-
245 收藏
-
500 收藏
-
394 收藏
-
436 收藏
-
137 收藏
-
409 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 立即学习 543次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 立即学习 516次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 立即学习 500次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 立即学习 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 立即学习 485次学习