SEPolicy 语言:
Linux中有两种东西,一种死的(Inactive),一种活的(Active)。死的东西就是文件(Linux哲学,万物皆文件。注意,万不可狭义解释为File),而活的东西就是进程。此处的 死 和 活 是一种比喻,映射到软件层面的意思是:进程能发起动作,例如它能打开文件并操作它。而文件只能被进程操作。
根据 SELinux 规范,完整的 Secure Context 字符串为:user:role:type[:range]
进程的 Secure Context:
在 SELinux 中,每种东西都会被赋予一个安全属性,官方说法叫做 Security Context,Security Context是一个字符串,主要由三个部分组成,例如 SEAndroid 中,进程的 Security Context 可通过 ps -Z 命令查看:
上面的最左边的一列就是进程的 Security Context,以第一个进程 wpa_supplicant 为例
u:r:hal_wifi_supplicant_default:s0
其中
- u 为 user 的意思,SEAndroid 中定义了一个 SELinux 用户,值为 u
- r 为 role 的意思,role 是角色之意,它是 SELinux 中一个比较高层次,更方便的权限管理思路。简单点说,一个 u 可以属于多个 role,不同的 role 具有不同的权限。
- hal_wifi_supplicant_default 代表该进程所属的 Domain 为 hal_wifi_supplicant_default。MAC(Mandatory Access Control)强制访问控制 的基础管理思路其实是 Type Enforcement Access Control(简称TEAC,一般用TE表示),对进程来说,Type 就是 Domain,比如 hal_wifi_supplicant_default 需要什么权限,都需要通过 allow 语句在 te 文件中进行说明。
- s0 是 SELinux 为了满足军用和教育行业而设计的 Multi-Level Security(MLS)机制有关。简单点说,MLS 将系统的进程和文件进行了分级,不同级别的资源需要对应级别的进程才能访问
文件的 Secure Context:
文件的 Secure Context 可以通过 ls -Z 来查看,如下
ls libOMX_Core.so -Z
u:object_r:vendor_file:s0 libOMX_Core.so
u:同样是 user 之意,它代表创建这个文件的 SELinux user
object_r:文件是死的东西,它没法扮演角色,所以在 SELinux 中,死的东西都用 object_r 来表示它的 role
vendor_file:type,和进程的 Domain 是一个意思,它表示 libOMX_Core.so 文件所属的 Type 是 vendor_file
s0:MLS 的等级
根据 SELinux 规范,完整的 SELinux 策略规则语句格式为:
allow domains types:classes permissions;
- Domain - 一个进程或一组进程的标签。也称为域类型,因为它只是指进程的类型。
- Type - 一个对象(例如,文件、套接字)或一组对象的标签。
- Class - 要访问的对象(例如,文件、套接字)的类型。
- Permission - 要执行的操作(例如,读取、写入)。
= allow : 允许主体对客体进行操作
= neverallow :拒绝主体对客体进行操作
= dontaudit : 表示不记录某条违反规则的决策信息
= auditallow :记录某项决策信息,通常 SElinux 只记录失败的信息,应用这条规则后会记录成功的决策信息。
使用政策规则时将遵循的结构示例:
语句:
allow appdomain app_data_file:file rw_file_perms;
这表示所有应用域都可以读取和写入带有 app_data_file 标签的文件
SELinux 权限不足 avc-denied 问题解决:
目前所有的 SELinux 权限检测失败,在 Kernel Log 或者 Android Log 中都有对应的 avc-denied Log 与之对应。反过来,有 avc-denied Log,并非就会直接失败,还需要确认当时 SELinux 的模式, 是 Enforcing 还是 Permissve。
如果是 Enforcing 模式,就要检测对应的进程访问权限资源是否正常?是否有必要添加? 如果有必要添加,可以找下面的方式生成需要的 sepolicy 规则并添加到对应 te 文件。
使用 audit2allow 简化方法
从 logcat 或串口中提取相应的 avc-denied log,下面的语句为提取所有的 avc- denied log
$ adb shell "cat /proc/kmsg | grep avc" > avc_log.txt
使用 audit2allow 工具生成对应的 policy 规则
// audio2allow 使用必须先 source build/envsetup.sh,导入环境变量
$ audit2allow -i avc_log.txt -p $OUT/vendor/etc/selinux/precompiled_sepolicy
将对应的policy 添加到 te 文件中
= 一般添加在 /device/<company>/common/sepolicy 或者 /device/<company>/$DEVICE/sepolicy 目录下
BOARD_SEPOLICY_DIRS += device/$SoC/common/sepolicy 通过这个命令添加厂家自定义的 sepolicy 规则
--------------------------------------------------------------------------------
file_contexts //系统中所有file_contexts安全上下文
seapp_contexts //app安全上下文
property_contexts //属性的安全上下文
service_contexts //service文件安全上下文
genfs_contexts //虚拟文件系统安全上下文
以上文件system/sepolicy中都有对应的内容
在Android8.0以上,SELinux策略分离成平台(platform)和非平台(non-platform)两部分,
而平台策略为了给非平台作者导出特定的类型和属性,又分为平台私有(platform private)和平台公有(platform public)部分。
1.平台公有策略(platform public seoplicy)平台共有策略全部定义在/system/sepolicy/public下,public下的type和attribute可以被non-platform中的策略所使用,也就是说,设备制造商的sepolicy作者在non-platform下可以对platform public sepolicy的策略进行扩展。
2.平台私有策略(platform private seoplicy)与公有策略相反,被声明为私有策略的type或attribute对non-platform的策略作者是不可见的。
-------------------------------------------------------------------------------
怎么抓取SELinux Log?
1.adb shell dmesg----抓kernel log
(特别说明:adb shell "cat /proc/kmsg | grep avc" > avc_log.txt 可以直接提出avc的log)
2.adb logcat –b events
关键字:
avc: denied
修改之后,怎么快速验证?
方法一:
mmm system/sepolicy
生成out目录下,注意有两个目录:
system/etc/sepolicy---Android 原生的,建议不动。如果修改,会影响CTS
vendor/etc/sepolicy---第三方厂家修改。
特别说明:system/sepolicy/Android.mk中定义了一些属性
BOARD_SEPOLICY_DIRS ##此宏涉及到的目录,会编译到vendor/etc/sepolicy下
PLAT_PUBLIC_POLICY ##此宏涉及到的目录,会当成system/sepolicy/public
PLAT_PRIVATE_POLICY##此宏涉及到的目录,会当成system/sepolicy/private
另外,单独编译后,会发现都会有对应的生成目录
/out/target/product/xxx/vendor/etc/selinux/
vendor_file_contexts
vendor_property_contexts
vendor_sepolicy.cli //allow语句会生成到这里面
方法二:
make sepolicy
怎么从log中提取有效信息?
举例1
<36>[ 103.972283] c0 484 type=1400 audit(1536907169.826:34): avc: denied { read } for pid=2591 comm="roid.qh_engmode" name="printk" dev="proc" ino=35544 scontext=u:r:radio:s0 tcontext=u:object_r:proc:s0 tclass=file permissive=0
普通提取:
allow radio proc:file read;
关键字:
avc: denied { read } scontext=u:r:radio:s0 tcontext=u:object_r:proc:s0 tclass=file
格式:allow scontext tcontext:tclass {read}
深入提取:
1.观察原生:
#参考资料:
https://www.jianshu.com/p/e95cd0c17adc
解决avc-denied之设置SELinux策略
https://blog.csdn.net/eliot_shao/article/details/51859083
1). 简化方法
1.1 提取所有的avc LOG. 如 adb shell “cat /proc/kmsg | grep avc” > avc_log.txt
1.2 使用 audit2allow tool 直接生成policy. audit2allow -i avc_log.txt 即可自动输出生成的policy
1.3 将对应的policy 添加到selinux policy 规则中,对应MTK Solution, 您可以将它们添加在KK: mediatek/custom/common/sepolicy, L: device/mediatek/common/sepolicy 下面,如
allow zygote resource_cache_data_file:dir rw_dir_perms;
allow zygote resource_cache_data_file:file create_file_perms;
===> mediatek/custom/common/sepolicy/zygote.te (KK)
===> device/mediatek/common/sepolicy/zygote.te (L)
注意audit2allow 它自动机械的帮您将LOG 转换成policy, 而无法知道你操作的真实意图,有可能出现权限放大问题,经常出现policy 无法编译通过的情况。