SEAndroid学习笔记

您所在的位置:网站首页 service定义了哪些对service的操作访问方法 SEAndroid学习笔记

SEAndroid学习笔记

2023-03-11 22:54| 来源: 网络整理| 查看: 265

SELinux概念

以一个例子来记录下学习SEAndroid的笔记。

需求:很简单,一个system进程要往ServiceManager中添加服务。 没写对应的SELinux策略时遇到的错误:

02-21 10:37:25.662 484 484 E SELinux : avc: denied { add } for service=car_model_service pid=10283 uid=1000 scontext=u:r:system_app:s0 tcontext=u:object_r:default_android_service:s0 tclass=service_manager permissive=0

这个错误是说啥呢

denied 拒绝

{ add } 是指被拒绝的权限,或者叫被拒绝的动作

service=car_model_service 是指服务名称,这里就是要add到ServiceManager中的那个字符串"car_model_service"

pid = 10283 是指这个进程的操作被拒绝了

uid = 1000 这个进程的uid,1000就是Android中的system user

scontext=u:r:system_app:s0 这个是重点1,scontext是指源标签,就是发起操作的进程的标签,这个标签就是SELinux中用来判断权限的重要依据(SELinux是一个基于标签的系统,这个文章解释了这个标签是怎么给进程和文件打上的)

tcontext=u:object_r:default_android_service:s0 tcontext是指目的标签,object_r这个是标签中的角色部分,Android中r角色表示进程,是活的,能发起动作的角色,object_r这个角色,是死的,只能被人操作、访问,一般是文件、设备、属性等,这里是服务,更精确点说,是服务名:car_model_service,但是这个标签里是default_android_service这个类型,或者叫域,因为我们还没有在SELinux策略里明确定义car_model_service这个服务定义所属的域,所以selinux给他一个default_android_service域。

tclass=service_manager 这个是说,要操作的具体对象的类别,在这里是指要操作一个default_android_service下的service_manager对象,tclass常见的类别还有file、device等。

所以,总结以上,那条log的意思就是:uid 是system的进程10283 (SELinux标签是u:r:system_app:s0 )想要把标签是 u:object_r:default_android_service:s0 (car_model_service的标签)的对象对service_manager这个类型的对象做 { add } 操作,(就是要把car_model_service 加到 service_manager中),由于不符合现有的SELinux Policy的策略定义,被拒绝了。

注:标签u:r:system_app:s0中有4个部分分别是user:role:type:sec_level 其中SEAndroid中user都是u,role为r表示进程,role为object_r表示除进程外的其他可被进程操作的对象如file、device等,sec_level表示一个安全级别,Android中都是s0,为同一级别。所以SEAndroid大部分其实用到的只有type这部分即SELinux的子集,这篇介绍了SELinux中的三种强制执行模型,Android中主要是第一种基于类型的强制执行模型,有少部分用到了MCS(多类别安全模型)。 。

所以,我们要增加策略,那就是允许system_app域(或类型)的进程把default_android_service域中(或类型)的service add 到 service_manager中,可以试下自动将拒绝log转换成 SELinux策略的工具 audit2allow(自行搜索用法,这东西只能参考,大部分不好使)给出的策略:

#============= system_app ============== allow system_app default_android_service:service_manager add;

输出的这个的意思是,可以把这句加到system_app.te(system_app.te是什么?)文件中 试试。 但是,如果真这么加起作用,那就坏了,因为策略中没有定义的service名,系统都给打上了u:object_r:default_android_service:s0 标签(这个标签怎么来的),上面那句真起作用,那不就很容易破坏了SELinux的保护了吗?显然SELinux没有这么脆弱,上面那句规则会违反neverallow 规则,编译是无法通过的。

编译错误提示 neverallow check failed at out/target/product/PRODUCT_NAME/obj/ETC/treble_sepolicy_tests_intermediates/built_plat_sepolicy:4273 from system/sepolicy/public/domain.te:432 (neverallow base_typeattr_9 default_android_service (service_manager (add))) allow at out/target/product/PRODUCT_NAME/obj/ETC/treble_sepolicy_tests_intermediates/built_plat_sepolicy:11897 (allow system_app default_android_service (service_manager (add))) Failed to generate binary Failed to build policydb

根据错误提示可以找到对应的neverallow策略:

android/system/sepolicy/public/domain.te

# Do not allow service_manager add for default service labels. # Instead domains should use a more specific type such as # system_app_service rather than the generic type. # New service_types are defined in {,hw,vnd}service.te and new mappings # from service name to service_type are defined in {,hw,vnd}service_contexts. neverallow * default_android_service:service_manager add;

这个策略的意思是,不允许 任何 进程将类型为default_android_service的service 对service_manager 做 add操作(service_manager.c中的add service 函数中会根据selinux策略来检查),显然上面的audit2allow输出的策略和这条neverallow策略冲突。

所以需要修改策略。

根据neverallow策略,要add的service,不能被打上u:object_r:default_android_service:s0 标签,不然天王老子(比如root进程)都不能add到ServiceManager中去,先看看这个标签怎么来的:

android/system/sepolicy/private/service_contexts

我们随便找一个可以添加到ServiceManager的服务看看是怎么定义的,例如SurfaceFlinger的标签定义:

SurfaceFlinger u:object_r:surfaceflinger_service:s0

其他所有Android系统中由ServiceManager管理的服务都在这里做了定义,其中有一条规则是这样的:

* u:object_r:default_android_service:s0

可以看到service名字为 * 被打上了u:object_r:default_android_service:s0 标签,是指没有在service_contexts定义的,都是这个标签,所以我们要自己给要添加的service写一条规则定义其标签。

上面这个文件中定义了android系统默认的service的标签,根据不同项目需要自定义的service标签最好在项目文件目录中定义:

android/device/qcom/sepolicy/private/service_contexts

Android中所有service 对应的selinux标签都由该文件定义,该文件可以有多份,编译时合并。所以我们在这个文件中定义要add的service 标签:

car_model_service u:object_r:my_car_model_service:s0

当然 my_car_model_service这个域(或类型)也得定义,不然selinux不认识啊,service相关的域,或者叫类型的定义在如下文件(android默认肯定也有一个service.te的文件,定义所有Android原生的service域):

android/device/qcom/sepolicy/common/service.te

type my_car_model_service, service_manager_type;

这句话意思是,定义一个域(或类型)my_car_model_service,并且把它关联到service_manager_type,这个service_manager_type叫attribute,其实叫域的集合更好,这样关联后,有关service_manager_type的规则,同样也适用于my_car_model_service。 照猫画虎的参考其他service,我们还发现,还需要修改system_app.te,因为我们的进程是属于system_app域的,有关system_app域的进程的访问权限都定义在此文件中(当然这个文件也可以有多份)。

android/vendor/myvendor/sepolicy/system_app.te

add_service(system_app, my_car_model_service)

这里又出现一个概念,就是宏,就是可以展开的定义,add_service就是个宏,selinux宏的定义一般都在后缀为macros的文件中(system/sepolicy/中定义了大部分android默认的policy政策以及宏和其他的定义):

android/system/sepolicy/public/te_macros

########################################### # add_service(domain, service) # Ability for domain to add a service to service_manager # and find it. It also creates a neverallow preventing # others from adding it. define(`add_service', ` allow $1 $2:service_manager { add find }; neverallow { domain -$1 } $2:service_manager add; ')

所以上面system_app.te中的:

add_service(system_app, my_car_model_service)

编译后就变成了

allow system_app my_car_model_service:service_manager { add find }; neverallow { domain -system_app } my_car_model_service:service_manager add;

意思就是允许 system_app 域(或类型)的进程,就是打了标签 u:r:system_app:s0的进程,把my_car_model_service类型的服务对service_manager做 add 和 find 操作。就是能加进去,也能取出来用。 下面为了安全,还又加了一个neverallow策略,不允许除了system_app以外的 domain域(或类型)的进程往service_manager里加my_car_model_service。Android中所有的进程都关联到了domain上了。可以随意查看一个.te文件,开头都会定义type ***, domain; 就是说,所有对domain策略,对关联了domain的域都起作用。如果你定义一个进程的域没有关联domain域,那么所有进程相关的操作,都得自己重写。domain.te中定义了允许所有进程进行的操作的规则。毕竟selinux上任何进程对任何资源要操作,都要定义对应的策略。

稍等:

type my_car_model_service, service_manager_type;

这句有啥用呢?刚才说了type 的作用是把要定义的域关联到后面的属性(attribute)或域上,这样所有对于后面属性的策略都可以对新定义的域起作用,这句定义完成后,所有有关service_manager_type的规则,都可以对我们新的服务起作用,比如:

android/system/sepolicy/public/shell.te

allow shell { service_manager_type -gatekeeper_service -incident_service -installd_service -netd_service -virtual_touchpad_service -vr_hwc_service }:service_manager find;

这样你不用去配置,shell域的进程就可以取service_manager中去查找服务,例如dumpsys就是shell域的进程,否则,你得单独去允许my_car_model_service被shell查询。

到这里,解决这个简单问题的se策略就加完了。



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3