赞
踩
前言
SELinux 是 Google 从android 5.0 开始,强制引入的一种非常严格的管理机制,主要用于增强系统的安全性。SELinux有以下两种模式:
- enforcing mode: 限制访问
-
- permissive mode: 只审查权限,不限制
在调试过程中遇到权限问题时,可以通过如下方法,确定是不是由于 SELinux 导致的问题:
通过串口或者adb使用如下命令,先将 selinux权限切换到审查模式:
- setenforce 0 (临时关闭 SELinux 的限制访问模式)
- getenforce (得到结果为Permissive)
一般情况下,user 版本的固件才会打开 SELinux 权限,会发生一些权限问题,此时可以用 debug 版本的固件,来进行测试,是否还会有上述的问题发生。因为 debug 版本的固件一般不会打开 SELinux,即此时的 SELinux是审查模式,只会出现警告,但是不会报错。(注:此方法要确定,debug版本的固件是否会打开 SELinux权限,如果debug版本也开启了 SELinux 权限,则这个方法不适用。)
如果看到如下的log信息,一定可以确定是确定某些 SELinux 的权限:
- avc: denied { read write } for pid=231 comm="eGTouchD" name="ttyS1" dev="tmpfs" ino=257 scontext=u:r:eGTouchD:s0 tcontext=u:object_r:serial_device:s0 tclass=chr_file permissive=0
- avc: denied { read write } for pid=231 comm="eGTouchD" name="ttyS2" dev="tmpfs" ino=292 scontext=u:r:eGTouchD:s0 tcontext=u:object_r:serial_device:s0 tclass=chr_file permissive=0
使用上述三种方法,可以确定是否是 SELinux 造成的问题。如果确定是 SELinux 权限造成的问题,可以通过下面的方法来解决SELinux 权限问题。
通过上面的方法已经确定是 SELinux 造成的问题了,那么接下来通过如下方法,来解决 SELinux 权限问题。
文件路径 device/rockchip/common/BoardConfig.mk
BOARD_SELINUX_ENFORCING ?= false
- 目录:
- ~/rk3399_android10/system/core$
- 修改:
- diff --git a/init/selinux.cpp b/init/selinux.cpp
- index 86238b430..8532dfa3c 100644
- --- a/init/selinux.cpp
- +++ b/init/selinux.cpp
- @@ -97,6 +97,7 @@ EnforcingStatus StatusFromCmdline() {
- }
-
- bool IsEnforcing() {
- + return false;
- if (ALLOW_PERMISSIVE_SELINUX) {
- return StatusFromCmdline() == SELINUX_ENFORCING;
- }
- bool kernel_enforcing = (security_getenforce() == 1);
- bool is_enforcing = selinux_is_enforcing();
- is_enforcing = 0;
- if (kernel_enforcing != is_enforcing) {
- --- a/arch/arm64/boot/dts/rockchip/px30-android.dtsi
- +++ b/arch/arm64/boot/dts/rockchip/px30-android.dtsi
- @@ -6,7 +6,7 @@
-
- / {
- chosen: chosen {
- - bootargs = "earlyprintk=uart8250,mmio32,0xff160000 swiotlb=1 console=ttyFIQ0 androidboot.baseband=N/A androidboot.veritymode=enforcing androidboot.hardware=rk30board androidboot.console=ttyFIQ0 init=/init kpti=0";
- + bootargs = "earlyprintk=uart8250,mmio32,0xff160000 swiotlb=1 console=ttyFIQ0 androidboot.baseband=N/A androidboot.selinux=permissive androidboot.veritymode=enforcing androidboot.hardware=rk30board androidboot.console=ttyFIQ0 init=/init kpti=0";
- };
-
- fiq-debugger {
修改LINUX/android/kernel/arch/arm64/configs/xxx_defconfig文件(xxx一般为手机产品名), 去掉CONFIG_SECURITY_SELINUX=y 的配置项
首使用adb命令,从众多log信息中拾取与SELinux 权限相关的log,命令如下:
- adb shell dmesg | grep avc > avc.txt #ubuntu使用这个命令
-
- adb shell dmesg | findstr avc > avc.txt #win使用这个命令
通过上述命令,我们已经得到了一个只包含 SELinux 权限的所以log信息,列举一条log进行解析。
avc: denied { set } for property=ro.ril.ecclist pid=1 uid=0 gid=0 scontext=u:r:vendor_init:s0 tcontext=u:object_r:radio_prop:s0 tclass=property_service permissive=0
根据log的固定格式,进行手动的一一解析,log格式如下:
- avc: denied { 操作权限 } for pid=7201 comm=“进程名” scontext=u:r:源类型:s0 tcontext=u:r:目标类型:s0 tclass=访问类型 permissive=0
-
- #============= 源类型 ==============
- allow 源类型 目标类型:访问类型 操作权限;
- 完整的意思是: "源类型"进程对"目标类型"的"访问类型"缺少 "操作权限"
根据上边的格式,手动撸出来应该是这样的:
- #============= vendor_init ==============
- allow vendor_init radio_prop:property_service set;
因为 SELinux 造成的权限问题会非常多,如果手动一条一条的解析,那可能会被恶心死,所以我们可以使用如下工具,直接解析生成的 avc.txt文本,会将 avc.txt 文本中所有的权限问题,全部解析出来,速度非常之快。
举个例子:
在实际的开发项目中,遇到了 SELinux 权限问题,使用如下方法解析系统报出的 avc 权限问题。
- 1.adb shell dmesg | grep avc > avc.txt #将kernel 中报出的所有权限问题,提取到avc.txt文件
- 2.audit2allow -i avc.txt #使用 audit2allow 工具解析avc.txt
- 3.解析出来如下图所示:
- android$ audit2allow -i avc.txt
- #============= eGTouchD ============== //对应的是 eGTouchD.te 文件。
- allow eGTouchD device:chr_file { read write };
- allow eGTouchD self:capability dac_override;
- allow eGTouchD serial_device:chr_file { read write };
- allow eGTouchD shell_exec:file execute;
- 4.上述步骤解析完了报出的权限问题,接下来需要把,这些权限添加到对应的 eGTouchD.te 文件中,直接将上述的四条 allow xxx 拷贝到 eGTouchD.te即可。
- 5.加入上述权限后,重新编译固件,如果编译时遇到一些类似这样的报错:neverallow xxxx, 根据提示去关闭相应的nerverallow 即可。
安装 audit2allow 工具:
- sudo apt-get install policycoreutils # 安装工具
- sudo apt-get install policycoreutils-python-utils
- sudo apt-get autoremove # 安装有问题时执行
如果使用 audit2allow 工具时有如下报错的话,可以通过下面的方法解决:
- 遇到如下错误时:
- dxq@dxq-x:~/log$
- dxq@dxq-x:~/log$ audit2allow -i log.txt
- ValueError: You must specify the -p option with the path to the policy file.
- The above exception was the direct cause of the following exception:
-
- Traceback (most recent call last):
- File "/usr/bin/audit2allow", line 370, in <module>
- app.main()
- File "/usr/bin/audit2allow", line 354, in main
- audit2why.init()
- SystemError: <built-in function init> returned a result with an error set
- dxq@dxq-x:~/log$
-
- 解决办法:
- sudo vim /usr/bin/audit2allow
- 注释掉如下4行代码,这个错误是因为执行audit2why.init()导致的,具体原因不详。
- def main(self):
- try:
- self.__parse_options()
- # if self.__options.policy:
- # audit2why.init(self.__options.policy)
- # else:
- # audit2why.init()

- #Google原生目录
- system/sepolicy
- #厂家目录,以rk为例
- device/rockchip/common/sepolicy
编译时,厂商的 .te 文件会覆盖 Google 中原生的.te 文件,一般情况下,能在厂商目录下修改,就在厂商目录下修改。因为修改 Google 目录下的 .te文件,可能会引起 CTS fail 问题,但是修改厂商目录下的 .te文件,则不会影响 CTS。修改完后,只需要单独编译 boot.img 固件就行。
比如:一个进程需要读、写和打开的权限,但是一般情况下,可能会先报其中一个权限缺失,等你加了这个权限后,才会报另一个权限缺失,以此类推。
此时可以通过下面两种方法处理:
如果固件是debug版本,一般不会打开 SELinux,所以在debug版本中,只会报 avc denied的警告,但是不会报错,可以在debug 版本上,把要运行的程序都运行一次,然后把所有 avc denied 相关的log 抓取来,一次性加完。
针对dir缺少的任何权限,建议赋予create_dir_perms,基本涵盖对dir的所有权限,比如:
{ open search write read rename create rmdir getattr }等等。
针对file缺少的任何权限,建议赋予rwx_file_perms,基本涵盖对file的所有权限,比如:
包含{ open read write open execute getattr create ioctl }等等。
如有错误,请大神不吝赐教,非常感谢!
参考链接:
https://blog.csdn.net/tung214/article/details/72734086
————————————————
版权声明:本文为CSDN博主「进阶牛牛」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/it_rensheng/article/details/121636651
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。