前言
SELinux(Security-Enhanced Linux)是一套强制性的安全审查机制(强制访问控制)。Android从5.0(L)开始启用SELinux Enforce模式,即既打印异常log也拒绝请求。增强了系统及进程的安全性,最明显的一点是限制了ROOT权限,之前ROOT就能获取所有权限的导致非常混乱的情况得到很大改善。
下面主要记录下,一般情况下 碰到这类权限问题是如何处理的。
问题
在开发中,可能会遇到这类权限问题,通常搜索“avc”即可,如下:
avc: denied { create } for pid=503 comm="idmap" name="overlays.list"
scontext=u:r:zygote:s0 tcontext=u:object_r:resource_cache_data_file:s0 tclass=file
确认问题
userdebug或eng软件,通过adb命令(adb shell setenforce 0)临时关闭SElinux(使进入Permissive模式) 使请求都能被执行,重启失效。
如果问题消失,这样就能确认是SELinux 权限导致的问题。如果问题依然在,则是其他原因而非SELinux权限导致。
SElinux模式:
- Enforce模式:打印异常log,拒绝请求。没有权限的请求被拒绝后 执行就会有问题。
- Permissive模式:打印异常log,不拒绝请求。请求没被拒绝,执行不会出现问题。
获取当前SELinux状态:
adb shell getenforce //5.0开始 默认是开启Enforce模式,即获取的值为:Enforcing
设置SELinux:
adb shell setenforce 0 //设置后即Permissive
adb shell setenforce 1 //设置后即Enforcing
分析
avc: denied { create } for pid=503 comm="idmap" name="overlays.list" scontext=u:r:zygote:s0 tcontext=u:object_r:resource_cache_data_file:s0 tclass=file
这一段log中,主要注意以下几个值(用不同颜色标记出来了):
- denied -> create //缺少什么权限
- scontext -> zygote //谁缺少权限
- tcontext -> resource_cache_data_file //对哪个文件缺少权限
- tclass -> file //什么类型的文件
上面log就是:zygote进程对resource_cache_data_file的file类型文件缺少create权限。
解决
权限拒绝,一般添加上需要的权限即可。
在scontext.te添加:allow scontext tcontext:tclass denied
如上log就是在zygote.te文件中添加:
allow zygote resource_cache_data_file:file {create };
MTK平台SELinux Policy文件一般存放在:
Google原生目录:system/sepolicy
MTK配置目录:device/mediatek/sepolicy 或者 device/mediatek/{platform}}/sepolicy
快速确认是否编译成功
selinux policy的汇总:用grep在 out/target/product/project/obj/ETC/sepolicy_intermediates中搜索即可。
AndroidQ上ioctl变化
Google在Android Q上增强了对ioctl的审查,除保持对ioctl的审查/授权之外,对具体的ioctlcmd也需要进一步地审查/授权。
/kernel/security/selinux/hooks.c
...
error = ioctl_has_perm(cred, file, FILE__IOCTL, (u16) cmd);
...
对于这样的一条avc log:
avc: denied { ioctl } for comm="BootAnimation" path="/proc/ged" dev="proc" ino=4026532249 ioctlcmd=0x6700 scontext=u:r:bootanim:s0 tcontext=u:object_r:proc_ged:s0 tclass=file permissive=0
在Android Q上,则需要:
allow bootanim proc_ged:file ioctl;
allowxperm bootanim proc_ged:file ioctl 0x6700;
0x6700 即log中的ioctlcmd。
0x6700这个值一般在sepolicy目录下的ioctl_defines文件中配置。所以在Q上,上述log最终:
ioctl_defines#
define(`GED_BRIDGE_IO_LOG_BUF_GET', `0x6700')
bootanim.te#
allow bootanim proc_ged:file ioctl;
allowxperm bootanim proc_ged:file ioctl GED_BRIDGE_IO_LOG_BUF_GET;