SEAndroid学习笔记

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)))
    <root>
    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策略就加完了。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,386评论 6 479
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,939评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,851评论 0 341
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,953评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,971评论 5 369
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,784评论 1 283
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,126评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,765评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,148评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,744评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,858评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,479评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,080评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,053评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,278评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,245评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,590评论 2 343

推荐阅读更多精彩内容