從android5.0開始,強制開啟了SELinux,對系統屬性的訪問權限也由selinux進行限制。
SELinux非常繁雜,8.0開始的Treble Project后,為了實現system、vendor分區的隔離,selinux的機制變的更加繁瑣。本文不打算全面講解android上selinux,通過概覽全貌和常見案例分析,讓大家在"不求甚解"的情況下,能夠處理系統定制中80%的selinux權限問題。
1.SELinux的基本介紹
-
框架:Kernel中,SELinux通過Linux Security Modules實現。
kernel/fs/read_write.c:
int rw_verify_area(int read_write, struct file *file, const loff_t *ppos, size_t count)
{
......
/* 基礎權限檢查 */
if (unlikely(!access_ok(VERIFY_READ, buf, count)))
return -EFAULT;
......
/* selinux權限檢查 */
retval = security_file_permission(file,
read_write == READ ? MAY_READ : MAY_WRITE);
......
}
- 語法:rule_name source_type target_type : class perm_set
allow system_app misc_user_data_file:file create_file_perms;
get_prop(system_app, system_prop) 其實是一個宏,展開如下:
allow system_app system_prop:file r_file_perms; #/dev/properties/system_prop
2.android上selinux相關文件
- 源碼:
system/sepolicy:
├── private
├── public
│ ├── property_contexts
│ ├── property.te
│ ├── file_contexts
│ ├── file.te
│ ├── su.te
│ ├── system_app.te
│ ├── system_server.te
│ ├── untrusted_app.te
│ ├── priv_app.te
│ └── zygote.te
└── vendor - ROM:
selinux編譯生成的策略文件sepolicy,8.0之前在boot.img中,8.0由於treble的原因,system和vendor分區各放置一部分,加載的時候會進行合並。8.0之后單刷userdebug版本的boot不再能獲取root權限,要刷userdebug版的system.img才行。
/system/etc/selinux:
plat_file_contexts
plat_property_contexts
plat_sepolicy.cil
/vendor/etc/selinux:
vendor_file_contexts
vendor_property_contexts
vendor_sepolicy.cil
3.my_system_prop定義
property.te:
type my_system_prop, property_type;
property_contexts:
persist.my. u:object_r:my_system_prop:s0
system_app.te:
set_prop(system_app, my_system_prop)
案例
模塊編譯selinux:make sepolicy
關閉selinux:setenforce 0
-
案例一:build.prop明明聲明了屬性,為什么通過APK和adb shell獲取不到?
屬性組成:- /default.prop
- /system/build.prop
- /vendor/default.prop
- /vendor/build.prop
- 由代碼通過set生成的屬性
首先,只要build.prop里聲明了,就會被加載到系統屬性中。屬性是有權限控制的,所以APK是不能獲取所有屬性的。
參照上文my_system_prop的定義,如果對應APK沒有聲明get_prop的權限,是獲取不到相關權限的。
例如:
persist.my.test u:object_r:my_system_prop:s0
com.android.myapp想要去讀取這個屬性,但是讀不到,如何分析呢?-
查看屬性的安全上下文:getprop -Z persist.my.test
-
查看進程的安全上下文:ps -AZ | grep com.android.myapp
u:r:platform_app:s0:c512,c768 com.android.myapp -
給platform_app加權限,在platform_app.te中添加:
get_prop(platform_app, my_system_prop)
adb shell對應的身份是shell,也是受限的,只有adb root后getprop獲取的屬性才是最全的。
-
案例二:新增allow xxx權限,編譯報錯Neverallow,如何處理?
- cts版本不能有任何neverallow,只能去掉添加的權限
- 國內版本可適當注釋掉原生相關neverallow進行規避
neverallow check failed at out/target/product/sailfish/obj/ETC/plat_sepolicy.cil_intermediates/plat_sepolicy.cil:6373 from system/sepolicy/public/domain.te:1133
(neverallow base_typeattr_144 file_type (file (execmod)))
<root>
allow at out/target/product/sailfish/obj/ETC/vendor_sepolicy.cil_intermediates/vendor_sepolicy.cil:1396
(allow platform_app_28_0 app_data_file_28_0 (file (execute execmod)))
如上看出,具體是public/domain.te:1133的限制影響了新加權限,找到對應行數觀察:
neverallow { domain -untrusted_app_all } file_type:file execmod;
解決方式:
- 直接注釋到該行
# neverallow { domain -untrusted_app_all } file_type:file execmod;
- 只規避受影響的platform_app
neverallow { domain -untrusted_app_all -platform_app } file_type:file execmod;
-
案例三:avc: denied { write }之類的缺少權限如何處理?
audit(0.0:67): avc: denied { write } for path="/dev/block/vold/93:96" dev="tmpfs" ino=/1263 scontext=u:r:kernel:s0 tcontext=u:object_r:block_device:s0 tclass=blk_file permissive=0
語法:rule_name source_type target_type : class perm_set**
萬能公式:
缺少什么權限:{ write }權限
誰缺少權限:scontext=u:r:kernel:s0
對誰缺少權限:tcontext=u:object_r:block_device:s0
什么類型:tclass=blk_filekernel.te:
allow kernel block_device:blk_file write;
寫操作一般還伴隨open、append等,所以一般使用w_file_perms宏替代單一的write -
案例四:avc: denied { execmod }如何處理?
audit(0.0:51): avc: denied { execmod } for path="/system/app/education_student/lib/arm/libhpHandPends.so" dev="mmcblk0p24" ino=424 scontext=u:r:untrusted_app:s0:c512,c768 tcontext=u:object_r:system_file:s0 tclass=file permissive=0
按照萬能公式可得如下策略語句,這是沒問題的。但這不是最優解,也可能違反Neverallow。
allow untrusted_app system_file:file execmod;
目前android加載so的策略是強制使用地址無關代碼的模式,execmod的本質是由於so不支持地址無關導致加載失敗。
地址無關可以在多個進程間共享so的代碼指令,無需拷貝重定位,節省內存。目前的Android.mk、NDK都默認加有-fPIC,只有很早之前的編譯的so存在此問題。
因此最優解是重新編譯so,GCC編譯時加上-fPIC參數即可。
鏈接:https://www.jianshu.com/p/88a92d101532
參考:https://blog.csdn.net/qq_34211365/article/details/106056873