前言

记录一下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

下面针对日志进行拆开介绍。

  1. 操作权限

{ write }

也就是少了write权限。

  1. 源类型

scontext=u:r:kernel:s0

源类型为kernel

  1. 目标类型

tcontext=u:object_r:block_device:s0

目标类型为block_device

  1. 访问类型

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,下面需要修改如下几个地方

  1. property.te:

type my_system_prop, property_type;
  1. property_contexts:

persist.my. u:object_r:my_system_prop:s0
  1. 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想要去读取这个属性,但读取不到,需要如下分析。

  1. 查看属性的安全上下文

getprop -Z persist.my.test

显示相关信息

[persist.my.test]: [u:object_r:my_system_prop:s0]
  1. 查看进程的安全上下文

ps -AZ | grep com.biumall.myapp

显示相关信息

u:r:platform_app:s0:c512,c768 com.android.myapp
  1. 给platform_app加权限,在platform_app.te中添加

可以看到,com.android.myapp是platform_app权限,但要读取persist.my.test是需要my_system_prop权限。

get_prop(platform_app, my_system_prop)

参考文章

  1. Android-Selinux

  2. Android – 深入浅出理解SeLinux

  3. 【安卓】SELinux走过的坑

  4. 属性问题展开的selinux权限介绍

  5. 属性问题展开的selinux权限介绍

相关文章

暂无评论

none
暂无评论...