作者 | 赵青窕
审校 | 孙淑娟
经过数日的分析,我才明白关闭权限仅仅是关闭安卓权限中的一部分而并非所有权限,最终通过修改文件属性后,我的服务才可以正常启动了。经历这件事情后,我立志要把我的经验总结出来并分享给志同道合的朋友们。
根据我个人的工作经验,我把安卓权限分为如下三部分:
- 设置文件的属性
- 采用allow语句配置某一个应用访问某一个文件的权限
- Linux系统原生的用户,用户组权限
第1点和第2点属于SELinux的范畴,这两部分是相辅相成的关系,通过设置文件属性来配置某一文件是不是可执行文件,紧接着我们可以采用allow语句来配置该可执行文件可以访问的文件资源及其对文件资源的操作权限;第3点属于Linux这一类系统的共同特性,于前面两点是完全不同的部分,用户和用户组及权限用来说明某一文件所属的用户和用户组,及其读写执行权限。接下来,让我们先认识SELinux,然后再详细地看上面三部分。
SELinux相关命令
- 关闭SELinux权限:setenforce 0,即设置SELinux 成为permissive模式,对违反Selinux规则的行为会进行记录,但不会阻止。
- 打开SELinux权限:setenforce 1,即设置SELinux 成为enforcing模式,对违反Selinux规则的行为会进行记录,且会进行阻止。
- 获取SELinux权限:getenforce
下图1是上面三个命令的执行情况,供大家参考。
图 1 :SELinux命令演示
- 查看SELinux权限:命令参数中增加-Z(注意此处是大写字母)选项。
如果是查看文件,则采用图2中红色方框内的方式。
图 2:查看文件权限
如果是查看进程的权限,则可以采用图2中所说的方式。图2中列出了不查看权限和查看权限的方式,方便大家比较。
图 3:查看进程对应的SELinux权限
下图4是查看属性(property)权限的命令。
图 4:查看property权限
配置SELinux权限
在此,我通过一个例子来说明如何配置。假如我们有一个可执行文件,我们用test_bin表示,该可执行文件需要访问我们的驱动节点/dev/test,针对这种情况,我们需要配置4处。
1.file_contexts中对文件/dev/test进行配置,配置方法如下(先假设test_dev_node和
test_bin_exec已经定义了,后面会进行说明):
est_bin_exec已经定义了,后面会进行说明):
/dev/test u:object_r:test_dev_node:s0
test_bin(此处需要使用test_bin的绝对路径) u:object_r:test_bin_exec:s0
该配置语句的意思就是把我们的设备节点/dev/test配置为test_dev_node类型,可执行文
件test_bin配置为test_bin_exec的类型,其余部分也有其具体含义,只是对于使用者来
说,暂时可以忽略。在具体项目配置时,替换上面配置文件中标出来的内容即可。
2.配置对应的te文件
type test_dev_node, dev_type;
type test_bin_exec, exec_type, vendor_file_type, file_type;
allow test_bin_exec test_dev_node:chr_file rw_file_prems;
上面三条语句主要完成两种工作,分别是类型定义和allow语句,这两部分都比较重要,
类型定义好后,我们才能对资源进行相应类型的配置,如上面对/dev/test和test_bin的配
置,而allow语句就是配置我们常说的权限问题,上面的allow语句就是设置类型为
test_bin_exec的可执行程序可以访问test_dev_node类型的文件。我把这个过程总结为定
义类型---配置类型----设置权限。
除了上面涉及到的内容外,安卓系统中还具有property_contexts,service_contexts,
seapp_contexts等类型。不管什么类型,我们套用三步骤定义类型---配置类型----设置权限即可,并结合需要处理的文件类型,就可以完成权限配置,如属性类文件,定义类型时,其语句格式是type xxx property_type,倘若还是不知道如何定义,可以参考安卓基线代码中的SELinux定义,因为基线中的权限定义已经包含了尽可能全的情况。
当遇到neverallow问题时,我们就把出现问题部分按照上面三步骤定义类型---配置类型----设置权限进行重新定义,重新定义后的类型名称不在系统的nerverallow范畴内,再次重新设置后就可规避nerverallow问题。
至此,我们已经简单了解了SElinux问题,接下来重新思考一下文章开始的时候说的三大部分。
1.设置文件的属性
此处就是指上面在file_contexts对文件/dev/test和test_bin进行了属性配置,当我们关闭SELinux权限时,并不能关闭系统对文件属性的判断,比如当我们没有对test_bin进行配置时,安卓系统会认为test_bin是一个普通文件。这种情况下,不管SELinux是否关闭,test_bin都无法正常运行。请记住,关闭SELinux时,安卓系统仍然会判断文件属性。
2.allow语句
当系统中没有配置适当的allow语句,但配置了适当的文件属性和用户组属性,读写权限时,此时关闭SELinux就可以正常工作。若出现这种现象,说明就是因为allow语句配置不恰当,这个时候应该赶紧抓取对应的日志,从对应的log中过滤出AVC的日志,如下是一种AVC错误:
avc: denied { read } for name="vendor" dev="tmpfs" ino=9241 scontext=u:r:dumpstate:s0 tcontext=u:object_r: test_dev_node:s0 tclass=chr_file permissive=0
分析如下:
- 上面日志中的中括号中表示缺少的权限,从日志看缺少read全校;
- scontext=u:r:dumpstate:s0用来表示缺少权限;
- tcontext=u:object_r: test_dev_node:s0用来表示访问哪类文件时出现了权限问题;
- tclass=chr_file表示要访问的文件类型。
我们把上面四部分按照下面组合即可添加对应的权限:
allow dumpstate test_dev_node:chr_file r read;
3.用户,用户组和读写权限
这类权限是Linux这一类系统中原生的内容,这类权限与SELinux完全不相关。当用户组配置有问题时,即使关闭SELinux权限,其问题会依然存在。
那在安卓系统中,我们如何来进行该类权限的配置呢?其实在安卓中,有一类init.rc文件(文件名可以是init.rc或者init.xxx.rc),rc文件除了可以同来启动服务等功能外,还可以在该类文件中配置用户和用户组读写权限,如下面的例子所示:
on init
chmod 0660 /dev/test
chown system system /dev/test
总结
本文先简单介绍了SELinux,然后进行三大部分的说明。这三部分有任何一部分异常,其对应功能都无法正常工作。在配置安卓权限时,需要从这三部分来考虑,缺一不可,最重要的一点是,关闭SELinux,仅仅能屏蔽allow语句对应的权限问题。
作者介绍
赵青窕,51CTO社区编辑,从事多年驱动开发。研究兴趣包含安全OS和网络安全领域,发表过网络相关专利。