前言
SELinux(Security-Enhanced Linux)是一套強制性的安全審查機制(強制訪問控制)。Android從5.0(L)開始啟用SELinux Enforce模式,即既打印異常log也拒絕請求。增強了系統及進程的安全性,最明顯的一點是限制了ROOT權限,之前ROOT就能獲取所有權限的導致非常混亂的情況得到很大改善。
下面主要記錄下,一般情況下 碰到這類權限問題是如何處理的。
問題
在開發中,可能會遇到這類權限問題,通常搜索“avc”即可,如下:
avc: denied { create } for pid=503 comm="idmap" name="overlays.list"
scontext=u:r:zygote:s0 tcontext=u:object_r:resource_cache_data_file:s0 tclass=file
確認問題
userdebug或eng軟件,通過adb命令(adb shell setenforce 0)臨時關閉SElinux(使進入Permissive模式) 使請求都能被執行,重啟失效。
如果問題消失,這樣就能確認是SELinux 權限導致的問題。如果問題依然在,則是其他原因而非SELinux權限導致。
SElinux模式:
- Enforce模式:打印異常log,拒絕請求。沒有權限的請求被拒絕后 執行就會有問題。
- Permissive模式:打印異常log,不拒絕請求。請求沒被拒絕,執行不會出現問題。
獲取當前SELinux狀態:
adb shell getenforce //5.0開始 默認是開啟Enforce模式,即獲取的值為:Enforcing
設置SELinux:
adb shell setenforce 0 //設置后即Permissive
adb shell setenforce 1 //設置后即Enforcing
分析
avc: denied { create } for pid=503 comm="idmap" name="overlays.list" scontext=u:r:zygote:s0 tcontext=u:object_r:resource_cache_data_file:s0 tclass=file
這一段log中,主要注意以下幾個值(用不同顏色標記出來了):
- denied -> create //缺少什么權限
- scontext -> zygote //誰缺少權限
- tcontext -> resource_cache_data_file //對哪個文件缺少權限
- tclass -> file //什么類型的文件
上面log就是:zygote進程對resource_cache_data_file的file類型文件缺少create權限。
解決
權限拒絕,一般添加上需要的權限即可。
在scontext.te添加:allow scontext tcontext:tclass denied
如上log就是在zygote.te文件中添加:
allow zygote resource_cache_data_file:file {create };
MTK平台SELinux Policy文件一般存放在:
Google原生目錄:system/sepolicy
MTK配置目錄:device/mediatek/sepolicy 或者 device/mediatek/{platform}}/sepolicy
快速確認是否編譯成功
selinux policy的匯總:用grep在 out/target/product/project/obj/ETC/sepolicy_intermediates中搜索即可。
AndroidQ上ioctl變化
Google在Android Q上增強了對ioctl的審查,除保持對ioctl的審查/授權之外,對具體的ioctlcmd也需要進一步地審查/授權。
/kernel/security/selinux/hooks.c
...
error = ioctl_has_perm(cred, file, FILE__IOCTL, (u16) cmd);
...
對於這樣的一條avc log:
avc: denied { ioctl } for comm="BootAnimation" path="/proc/ged" dev="proc" ino=4026532249 ioctlcmd=0x6700 scontext=u:r:bootanim:s0 tcontext=u:object_r:proc_ged:s0 tclass=file permissive=0
在Android Q上,則需要:
allow bootanim proc_ged:file ioctl;
allowxperm bootanim proc_ged:file ioctl 0x6700;
0x6700 即log中的ioctlcmd。
0x6700這個值一般在sepolicy目錄下的ioctl_defines文件中配置。所以在Q上,上述log最終:
ioctl_defines#
define(`GED_BRIDGE_IO_LOG_BUF_GET', `0x6700')
bootanim.te#
allow bootanim proc_ged:file ioctl;
allowxperm bootanim proc_ged:file ioctl GED_BRIDGE_IO_LOG_BUF_GET;