平台:intel---->sofia-3gr
Android 6.0
问题:项目中使用了串口要传送数据,所以需要检测串口的可操作性,在检测中使用了第三方的apk来检测串口,测试中偶尔会出现测试失败,log如下:
05-20 09:25:11.040 1546 1546 I auditd : type=1400 audit(0.0:13): avc: denied { read } for comm="medoctorstation" name="ttyS0" dev="tmpfs" ino=8685 scontext=u:r:untrusted_app:s0:c512,c768 tcontext=u:object_r:serial_device:s0 tclass=chr_file permissive=1
05-20 09:25:11.040 1546 1546 I medoctorstation: type=1400 audit(0.0:13): avc: denied { read } for name="ttyS0" dev="tmpfs" ino=8685 scontext=u:r:untrusted_app:s0:c512,c768 tcontext=u:object_r:serial_device:s0 tclass=chr_file permissive=1
05-20 09:25:11.040 1546 1546 I auditd : type=1400 audit(0.0:14): avc: denied { write } for comm="medoctorstation" name="ttyS0" dev="tmpfs" ino=8685 scontext=u:r:untrusted_app:s0:c512,c768 tcontext=u:object_r:serial_device:s0 tclass=chr_file permissive=1
05-20 09:25:11.040 1546 1546 I medoctorstation: type=1400 audit(0.0:14): avc: denied { write } for name="ttyS0" dev="tmpfs" ino=8685 scontext=u:r:untrusted_app:s0:c512,c768 tcontext=u:object_r:serial_device:s0 tclass=chr_file permissive=1
05-20 09:25:11.040 1546 1546 I auditd : type=1400 audit(0.0:15): avc: denied { open } for comm="medoctorstation" path="/dev/ttyS0" dev="tmpfs" ino=8685 scontext=u:r:untrusted_app:s0:c512,c768 tcontext=u:object_r:serial_device:s0 tclass=chr_file permissive=1
05-20 09:25:11.040 1546 1546 I medoctorstation: type=1400 audit(0.0:15): avc: denied { open } for path="/dev/ttyS0" dev="tmpfs" ino=8685 scontext=u:r:untrusted_app:s0:c512,c768 tcontext=u:object_r:serial_device:s0 tclass=chr_file permissive=1
05-20 09:25:11.040 1546 1546 I auditd : type=1400 audit(0.0:16): avc: denied { ioctl } for comm="medoctorstation" path="/dev/ttyS0" dev="tmpfs" ino=8685 ioctlcmd=5401 scontext=u:r:untrusted_app:s0:c512,c768 tcontext=u:object_r:serial_device:s0 tclass=chr_file permissive=1
05-20 09:25:11.040 1546 1546 I medoctorstation: type=1400 audit(0.0:16): avc: denied { ioctl } for path="/dev/ttyS0" dev="tmpfs" ino=8685 ioctlcmd=5401 scontext=u:r:untrusted_app:s0:c512,c768 tcontext=u:object_r:serial_device:s0 tclass=chr_file permissive=1
05-20 09:25:11.060 1546 1546 I auditd : type=1400 audit(0.0:17): avc: denied { getattr } for comm="medoctorstation" path="/dev/ttyS0" dev="tmpfs" ino=8685 scontext=u:r:untrusted_app:s0:c512,c768 tcontext=u:object_r:serial_device:s0 tclass=chr_file permissive=1
后来查了一下是由于selinux安全机制的影响,简单的说就是: 以前只要你有root权限就可以任意的操作系统内部所有文件(一切皆文件),比如,你以root的用户打开了记事本,这时候的由于你是root权限操作,这是记事本也就具有root权限去操作系统内部的所有文件,这种单方面的权限操作缺少严谨性,所以出现了selinux,若果说以前的机制是单方面出检测使用者的权限,而selinux就是从使用者和被操控者两个方面去检测权限的统一.
我查源码中以前的前辈是直接关闭了selinux,但是这样又会出现一个问题,系统无法去使用OTA差分包升级,这就导致了以后版本的更新太麻烦..所以,干!
selinux处于permissive :只会查询权限,但不会阻止操作,enforce:查询权限,并阻止相应的操作.
查询当前的selinux状态(getenforce): permissive(所谓的调试模式);
分析:
avc: denied { ioctl } for path="/dev/ttyS0" dev="tmpfs" ino=8685 ioctlcmd=5401 scontext=u:r:untrusted_app:s0:c512,c768 tcontext=u:object_r:serial_device:s0 tclass=chr_file permissive=1
缺操作权限: denied { ioctl }
操作者: scontext=u:r:untrusted_app:s0:c512,c768
被操作者: tcontext=u:object_r:serial_device:s0
被操作的类型: tclass=chr_file
这里遵循谁缺给谁加:
这里是untrusted_app缺了权限,那就给他添加,这里又有一个问题:
selinxu 是靠.te文件,来约束权限的,而这些权限文件在:
/device/xxx/xxx/common/sepolicy/*.te和extern/sepolicy/*.te都有,那么到底添加到那个文件呢?
笔者添加到/extern/sepolicy/*.te路径下,这里就添加在untrusted_app.te文件中,如下:
allow untrusted_app serial_device : chr_file ioctl;
如果多个权限的话如下:
allow untrusted_app serial_device : chr_file { read write open ioctl getattr };
添加:对proc下的节点
05-20 09:26:58.220 1929 1929 I auditd : type=1400 audit(0.0:22): avc: denied { write } for comm="sh" name="ylmk2_config" dev="proc" ino=4026543301 scontext=u:r:untrusted_app:s0:c512,c768 tcontext=u:object_r:proc:s0 tclass=file permissive=1
05-20 09:26:58.220 1929 1929 I sh : type=1400 audit(0.0:22): avc: denied { write } for name="ylmk2_config" dev="proc" ino=4026543301 scontext=u:r:untrusted_app:s0:c512,c768 tcontext=u:object_r:proc:s0 tclass=file permissive=1
这里的ylmk2_config是proc下的一个节点.
这里效仿的serial_device 来建立新的proc文件,此后编译不过的,是应为新旧的定义产生了冲突---屏蔽旧的定义即可
步骤:
先在extern/sepcify/下的file_contexts文件中添加
/proc/ylmk2_config u:object_r:proc:s0 //这里绑定了节点和设备
在同目录下的device.te文件中添加定义 //把你的节点申明为dev_type
type proc, dev_type;
然后在对应的te文件添加allow语句即可,如下:
allow untrusted_app proc : chr_file { write };
简单的说一下如何去判断你加载的语句生效了呢?这就要简单的说一下selinux机制的加载:
检测成功与否是根据te文件经过M4编译器,预编译生成的policy.config文件来判断的,policy.config文件会生成在out/target/product/obj/ETC目录下,定义的所有权限都会在。。。这个文件会经过checkpolicy检测从而生成sepolicy二进制文件,这个文件会在system/core/init/init.cpp中的selinux_initialize方法中判断系统定义的selinux状态,从而判断是否加载seplicy文件到系统的内核。 这里说的M4编译,可以在extern/sepolicy下的mk文件中有详细的编译顺序,checkpolicy是生成seploicy文件的检测工具,在extern/tool下有工具的源码。
android 提供了批量解决avc 权限问题:
操作:
1.
adb logcat -b all | grep "avc:" > avc.txt
执行缺少权限的操作
2.
源码目录执行
audit2allow -i avc.txt >xxx.txt
3.
将xxx.txt中用到的权限配置到android SElinux中去
audit2allow可执行文件位置:
./external/selinux/prebuilts/bin/audit2allow
audit2allow源码位置:./external/selinux/python/audit2allow