对于Android平台的工程师来说,selinux是一个比较常见的问题,经常会出现编写一些服务的时候出现权限问题导致服务结束的情况。而对于厂商来说,除非客户自己要求关闭selinux,否则都会遵循selinux的规则进行各种权限的添加
对于selinux的发家史这里就不进行介绍了,对于工程师而言,了解一个框架并且熟练的使用它才是最重要的事情。
selinux分为三种模式:disable(关闭)、permission(宽容)以及enforcing(强制)模式,在开发板上可以通过getenforce指令来得知当前系统的selinux模式,也可以通过setenforce指令来设置当前系统的selinux模式。
disable模式
想要设置为disable模式的话,只需要在system/core/init/selinux.cpp内,将IsEnforcing函数的返回值强制设置为返回false即可。
permission模式
permission模式最常见的场景为:
1.当前已经确定是selinux导致程序异常,希望一次性解决selinux相关的问题,那么就可以通过暂时设置selinux模式为permission,程序在运行过程中遇到权限相关的问题仍然会报错,但是仅仅是报错而已,并不会因此导致程序异常退出,也可以一次性将该进程出现的所有的selinux权限添加完毕后再进行功能验证。
2.程序异常但是无法排除是否除了selinux以外还有其他的问题导致异常,这种情况下同样可以选择将selinux模式设置为permission模式,如果此时selinux模式已经为permission了,但是程序仍然异常,那么就需要去看看除了selinux以外还有什么导致程序异常的。
3.当前模式下就是可以忽略掉selinux的影响,例如android下的recovery模式下系统升级,我们的需求很明了,在recovery模式下我什么业务也不执行,就只想完成系统升级,系统升级又涉及到分区的读写操作,这样去大量的添加selinux权限仅仅为了系统升级这么一个功能,有点得不偿失。因此可以尝试在这种场景下通过shell脚本等直接执行setenforce 0,可以节省大量开发时间
enforcing模式
enforcing模式就跟他的意思一样,就是强制执行,只要该进程出现selinux权限问题,那么此次操作就会被终止。厂家选择enforcing模式的目的也是为了系统安全,否则任何一个外来程序都能够在我们的系统上执行,安全风险太大并且维护成本太高,因此作为厂商,除非客户强烈要求默认为disable或者permission模式,否则都会选择enforcing模式。
下面就开始看看如何完成服务所需的selinux权限
-
分析avc报错原因,查看是哪个进程对哪个服务缺少什么样的权限
type=1400 audit(0.0:33378): avc: denied { open } for path="/dev/block/sdf2" dev="tmpfs" ino=496 scontext=u:r:test_:service:s0 tcontext=u:object_r:block_device:s0 tclass=blk_file permissive=1
根据avc报错,我们只需要关注4个地方:
1.1 缺少的权限:open
1.2 对应的服务(哪个服务缺少权限):test_sercice
1.3 test_service在对哪个上下文(block_device)进行open操作时缺少权限
1.4 block_device这个文件是什么类型(blk_file)
2.根据解析内容进行文件上下文的定义以及上下文的类型设置
这里指的文件上下文的定义是不希望大家在添加selinux权限的时候去破坏谷歌默认的nerverallow规则,建议一步到位,否则后续有CTS认证的需求的话,改动起来太麻烦。这里我们可以在vendor目录下,新建一个test_service文件夹,创建一个file_contexts文件
2.1 在file_contexts文件里面添加对应的上下文,假设希望对一个名为test_service的分区进行open操作,那么我的上下文就是
/dev/block/by-name/test_service u:object_r:test_service_partition:s0
2.2 新建一个test_service.te以及file.te文件,test.te用于声明我们的进程上下文以及的类型,test_service.te用于添加各种allow权限
#当前的上下文是针对设备节点的,因此类型应该为dev_type。如果是修改的文件的话,那么类型应该就是fs_type
type test_service_partition, dev_type;
添加对应的allow语句到test.te内
allow test_sercice test_service_partition:file { open };
如果是在其他的目录,不是在平台原生目录下进行添加selinux文件的话,还需要添加对应的打包语句。
如有错漏,麻烦各位大佬不吝赐教,谢谢