前言
记录一下Android Sepolicy规则等相关知识,记录一下方便自己查阅和学习。
正文
从android5.0开始,强制开启了SELinux,对系统属性的访问权限也由selinux进行限制。
SELinux非常繁杂,8.0开始的Treble Project后,为了实现system、vendor分区的隔离,selinux的机制变的更加繁琐。本文不打算全面讲解android上selinux,通过概览全貌和常见案例分析,让大家在”不求甚解”的情况下,能够处理系统定制中80%的selinux权限问题。
常用命令
临时关闭SELInux模式
adb shell setenforce 0
开启SELINUX模式
adb shell setenforce 1
PS:adb改变selinux权限只是临时的,重启就恢复默认。
源码
system/sepolicy: ├── private ├── public │ ├── property_contexts │ ├── property.te │ ├── file_contexts │ ├── file.te │ ├── su.te │ ├── system_app.te │ ├── system_server.te │ ├── untrusted_app.te │ ├── priv_app.te │ └── zygote.te └── vendor
编译sepolicy
方式一
当源码完整编译过一次后,可以通过下面快速变一下修改的
$ mmma system/sepolicy/
$ adb push out/target/product/xxx/system/etc/selinux /system/etc/selinux $ adb push out/target/product/xxx/vendor/etc/selinux /vendor/etc/selinux
方式二
也可单编systemimage,并刷机
$ make systemimage $ adb reboot bootloader $ fastboot flash system ./system.img $ fastboot reboot
SEpolicy配置规则
SELINUX报错标准格式
avc: denied { 操作权限 } for pid=26382 comm=“进程名” scontext=u:r:源类型:s0 tcontext=u:r:目标类型:s0 tclass=访问类型 permissive=0
举例例子
avc: denied { write } for path="/dev/block/vold/93:96" dev="tmpfs" ino=/1263 scontext=u:r:kernel:s0 tcontext=u:object_r:block_device:s0 tclass=blk_file permissive=0
下面针对日志进行拆开介绍。
操作权限
{ write }
也就是少了write权限。
源类型
scontext=u:r:kernel:s0
源类型为kernel
目标类型
tcontext=u:object_r:block_device:s0
目标类型为block_device
访问类型
tclass=blk_file
访问类型为blk_file
因此在kernel.te文件新增如下规则
allow kernel block_device:blk_file write;
写操作一般还伴随open、append等,所以一般使用w_file_perms宏替代单一的write,可改为如下:
allow kernel block_device:blk_file w_file_perms;
其他情景介绍。
案例一
avc: denied { find } for service=media.audio_flinger pid=665 uid=1003 scontext=u:r:bootanim:s0 tcontext=u:object_r:audioserver_service:s0 tclass=service_manager permissive=0
需要在bootanim.te
中加入
allow bootanim audioserver_service:service_manager find
案例二
avc: denied { write } for name="syslog" dev="mmcblk0p87" ino=31476 scontext=u:r:logpersist:s0 tcontext=u:object_r:system_data_file:s0 tclass=dir permissive=0
需要在logpersist.te
中加入
allow logpersist system_data_file:dir write;
案例三
avc: denied { dac_read_search } for capability=2 scontext=u:r:update_engine:s0 tcontext=u:r:update_engine:s0 tclass=capability permissive=0 avc: denied { dac_override } for capability=1 scontext=u:r:update_engine:s0 tcontext=u:r:update_engine:s0 tclass=capability permissive=0
update_engine.te中新增
allow update_engine self:capability { dac_read_search dac_override };
案例四
avc: denied { read } for name="version" dev="proc" ino=4026532065 scontext=u:r:hal_wifi_default:s0 tcontext=u:object_r:proc_version:s0 tclass=file permissive=0
hal_wifi_default.te中新增。
按照规则,会写成如下,
allow hal_wifi_default proc_version:file read
但是一般还涉及其他的,推荐改为
allow hal_wifi_default proc_version:file r_file_perms;
案例五
对于上面的公式也不是万能的。
05-16 12:41:23.390 W/BootAnimation( 114): type=1400 audit(0.0:6): avc: denied { call } for scontext=u:r:bootanim:s0 tcontext=u:r:mediaserver:s0 tclass=binder permissive=0
需要在bootanim.te
里加入
binder_call(bootanim, mediaserver)
对于binder_call不是很熟悉,未遇到。。。
案例六
avc: denied { execmod } for path="/system/app/education_student/lib/arm/libhpHandPends.so" dev="mmcblk0p24" ino=424 scontext=u:r:untrusted_app:s0:c512,c768 tcontext=u:object_r:system_file:s0 tclass=file permissive=0
按照万能公式可得如下策略语句
allow untrusted_app system_file:file execmod;
但这不是最优解,也可能违反Neverallow。
目前android加载so的策略是强制使用地址无关代码的模式,execmod的本质是由于so不支持地址无关导致加载失败。地址无关可以在多个进程间共享so的代码指令,无需拷贝重定位,节省内存。
目前的Android.mk、NDK都默认加有-fPIC,只有很早之前的编译的so存在此问题。因此最优解是重新编译so,GCC编译时加上-fPIC参数即可。
my_system_prop定义
加入自定义my_system_prop,下面需要修改如下几个地方
property.te:
type my_system_prop, property_type;
property_contexts:
persist.my. u:object_r:my_system_prop:s0
system_app.te:
set_prop(system_app, my_system_prop)
案例
参照上面my_system_prop的定义,如果对应APK没有声明get_prop的权限。
比如
persist.my.test u:object_r:my_system_prop:s0
com.biumall.myapp想要去读取这个属性,但读取不到,需要如下分析。
查看属性的安全上下文
getprop -Z persist.my.test
显示相关信息
[persist.my.test]: [u:object_r:my_system_prop:s0]
查看进程的安全上下文
ps -AZ | grep com.biumall.myapp
显示相关信息
u:r:platform_app:s0:c512,c768 com.android.myapp
给platform_app加权限,在platform_app.te中添加
可以看到,com.android.myapp是platform_app权限,但要读取persist.my.test是需要my_system_prop权限。
get_prop(platform_app, my_system_prop)
参考文章
《》
《》
《》
《》
《