Android SELinux排错实录:我的te文件改了,为什么权限还是不生效?
Android SELinux排错实战:当te修改后权限依然失效的深度排查指南
在Android系统开发中,SELinux权限配置堪称"安全守门员",但当你按照标准流程添加了allow规则、重新编译并替换sepolicy文件后,却发现预期的权限依然没有生效——这种挫败感就像精心设计的钥匙却打不开门锁。本文将带你以数字侦探的视角,系统性地排查那些容易被忽略的"隐藏关卡"。
1. 案件现场重建:确认你看到的avc log是最新证据
很多开发者会直接执行adb logcat | grep avc就开始修改te文件,但这样可能遗漏关键线索。正确的日志采集需要多角度取证:
# 方法1:实时监控avc拒绝日志(适合动态调试) adb shell "su -c 'cat /proc/kmsg | grep avc'" # 方法2:获取完整内核日志(包含历史avc记录) adb shell dmesg | grep avc > avc_denials.txt # 方法3:针对特定进程的详细审查 adb shell "cat /proc/<pid>/avc_stats"关键验证点:
- 时间戳比对:确保日志是修改sepolicy后新生成的
- 进程上下文一致性:确认
scontext与目标te文件匹配 - 拒绝类型完整性:检查是否有多个关联的
denied条目
提示:在Android 9+系统上,可能需要先执行
adb shell su root dmesg -w来实时跟踪内核消息
2. 证据链分析:te文件真的放对位置了吗?
不同Android版本和厂商定制会导致te文件路径存在显著差异。以下是一张常见路径对照表:
| 系统版本 | 标准路径 | 厂商定制路径 | 编译产物位置 |
|---|---|---|---|
| AOSP 8.0 | system/sepolicy | device/<vendor>/sepolicy | system/etc/selinux |
| AOSP 9.0+ | system/sepolicy/public | vendor/<vendor>/sepolicy | vendor/etc/selinux |
| MIUI 12 | device/xiaomi/sepolicy | vendor/xiaomi/sepolicy | vendor/etc/selinux/precompiled_sepolicy |
排查步骤:
使用
find命令定位目标te文件:cd /path/to/android/source find . -name "*untrusted_app*.te" -o -name "*hal_*.te"检查编译脚本中的策略覆盖顺序:
# 在BoardConfig.mk中查看策略优先级 BOARD_SEPOLICY_DIRS += \ device/vendor/sepolicy/legacy \ device/vendor/sepolicy/common验证最终合并结果:
adb shell ls -Z /vendor/etc/selinux/
3. 物证检验:编译产物是否真的被正确替换?
即使编译过程没有报错,生成的策略文件也可能因为各种原因未能生效。这里有一个完整的验证流程:
# 步骤1:确认编译产物哈希值 sha1sum $OUT/vendor/etc/selinux/precompiled_sepolicy # 步骤2:推送到设备并验证 adb push precompiled_sepolicy /vendor/etc/selinux/ adb shell sha1sum /vendor/etc/selinux/precompiled_sepolicy # 步骤3:强制重载策略(无需重启) adb shell "setenforce 0; setenforce 1" # 步骤4:检查当前生效策略 adb shell getenforce adb shell "cat /sys/fs/selinux/policy | strings | grep -A 5 'your_rule'"常见陷阱:
- 某些设备需要同时替换
/system/etc/selinux和/vendor/etc/selinux下的文件 - OTA升级可能会恢复默认策略文件
- 部分厂商使用
sepolicy_neverallows进行二次校验
4. 关联案件调查:是否存在隐藏的级联拒绝?
一个操作往往涉及多个SELinux检查点。例如访问设备文件可能需要:
- 对父目录的
search权限 - 对文件本身的
open权限 - 对设备类的
read/write权限 - 对设备驱动的
ioctl权限
使用策略依赖分析工具可以揭示这些隐藏关系:
# 使用sesearch分析策略依赖 adb shell "sesearch -A -s untrusted_app -t sysfs_leds -c dir" # 检查类型转换规则 adb shell "seinfo -t sysfs_leds -x" # 生成权限图谱(需要policy.xml) sepolicy-analyze -p policy.xml --dot | dot -Tpng > graph.png注意:Android 11开始引入了
dontaudit规则,可能需要先执行adb shell semodule -DB来禁用静默拒绝
5. 环境变量干扰:SELinux模式与特殊配置的影响
当所有修改似乎都正确但权限依然不生效时,可能是运行环境在作祟:
调试模式干扰:
# 检查当前模式 adb shell getenforce # 验证是否有强制策略覆盖 adb shell "cat /sys/fs/selinux/enforce" # 检查特殊标签状态 adb shell "cat /sys/fs/selinux/deny_unknown"厂商定制检查:
查找可能覆盖策略的init脚本:
adb shell "grep -r 'sepolicy' /vendor/etc/init/"检查SELinux功能开关:
adb shell "getprop | grep selinux"验证SELinux模块状态:
adb shell "semodule -l"
6. 高阶侦查工具:动态分析与策略验证
对于顽固案例,需要动用更专业的工具:
实时策略分析:
# 跟踪特定进程的SELinux检查 adb shell "strace -p <pid> -e trace=security" # 动态策略修改测试 adb shell "audit2allow -p precompiled_sepolicy < avc_denials.txt"策略有效性测试:
创建最小测试策略:
make -j$(nproc) sepolicy_test加载测试策略:
adb push test_policy /data/local/tmp/ adb shell "load_policy /data/local/tmp/test_policy"生成测试报告:
adb shell "sepolicy-analyze /sys/fs/selinux/policy --html > report.html"
7. 从失败中学习:建立系统化的排错流程
经过多次实战后,我总结出一个高效的排查清单:
日志三重验证:
- 确认avc日志时间戳新鲜度
- 交叉比对
logcat/dmesg/audit.log - 检查是否有
dontaudit规则干扰
文件位置四步确认:
graph TD A[源码te文件位置] --> B[编译产物路径] B --> C[设备存储路径] C --> D[内存加载策略]权限依赖矩阵分析:
操作阶段 所需权限 常见遗漏点 路径查找 search 父目录类型 文件打开 open 设备类权限 数据读写 read/write 驱动ioctl 控制操作 ioctl 特定命令值 环境因素检查表:
- [ ] SELinux模式(enforcing/permissive)
- [ ] 设备厂商定制覆盖
- [ ] 系统属性覆盖
- [ ] 其他安全模块干扰(如SELinux MLS)
在实际项目中,最让我意外的一个案例是:某设备厂商在init.rc中硬编码了restorecon命令,导致每次重启都会恢复默认策略。最终通过以下命令发现:
adb shell "grep -r 'restorecon' /vendor/etc/init/"记住,SELinux排错就像破案——需要耐心收集证据、严谨分析线索,最后往往是最不起眼的细节成为突破口。当你再次遇到"改了te却不生效"的情况时,不妨按照这个系统化的清单逐步排查,相信一定能找到那个"隐藏的真相"。
