Selinux 許可權問題
為了確定是否因為SELinux導致的問題,可先執行:
setenforce 0 (臨時禁用掉SELinux)
getenforce (得到結果為Permissive)
如果問題消失了,基本可以確認是SELinux造成的許可權問題,需要通過正規的方式來解決許可權問題。
android KK 4.4 版本後,Google 預設啟用了SELinux, 並會把SELinux 審查異常列印在kernel log 或者 android log(L 版本)中,對應的關鍵字是: “avc: denied” 或者”avc: denied”
案例1
audit(0.0:67): avc: denied { write |
分析過程:
缺少什麼許可權: { write }許可權,
誰缺少許可權: scontext=u:r:kernel
對哪個檔案缺少許可權:tcontext=u:object_r:block_device
什麼型別的檔案: tclass=blk_file
完整的意思: kernel程序對block_device型別的blk_file缺少write許可權。
解決方法:找到kernel.te這個檔案,加入以下內容:
allow kernel block_device:blk_file write; |
make install clean後重新編譯,刷boot.img
案例2
audit(0.0:53): avc: denied { execute } for path="/data/data/com.mofing/qt-reserved-files/plugins/platforms/libgnustl_shared.so" dev="nandl" ino=115502 scontext=u:r:platform_app:s0 tcontext=u:object_r:app_data_file:s0 tclass=file permissive=0 |
分析過程:
缺少什麼許可權: { execute}許可權,
誰缺少許可權: scontext = u:r:platform_app:s0
對哪個檔案缺少許可權:tcontext = u:object_r:app_data_file
什麼型別的檔案: tclass= file
完整的意思: platform_app程序對app_data_file型別的file缺少execute許可權。
解決方法:找到platform_app.te這個檔案,加入以下內容:
allow platform_app app_data_file:file execute; |
make install clean後重新編譯,刷boot.img才會生效。
案例3
audit(1444651438.800:8): avc: denied { search } for pid=158 comm="setmacaddr" name="/" dev="nandi" ino=1 scontext=u:r:engsetmacaddr:s0 tcontext=u:object_r:vfat:s0 tclass=dir permissive=0 |
解決方法 :engsetmacaddr.te
allow engsetmacaddr vfat:dir { search write add_name create }; 或者 allow engsetmacaddr vfat:dir create_dir_perms; |
(create_dir_perms包含search write add_name create可參考external/sepolicy/global_macros的定義宣告)
案例4
audit(1441759284.810:5): avc: denied { read } for pid=1494 comm="sdcard" name="0" dev="nandk" ino=245281 scontext=u:r:sdcardd:s0 tcontext=u:object_r:system_data_file:s0 tclass=dir permissive=0 |
解決方法 :sdcardd.te
allow sdcardd system_data_file:dir read; 或者 |
(rw_dir_perms包含read write,可參考external/sepolicy/global_macros的定義宣告)
要加入的許可權很多時,可以用中括號,比如:
allow engsetmacaddr vfat:dir { search write add_name create};
解決過的問題:
報錯:
avc: denied { set } for property=sys.powerctl scontext=u:r:init_shell:s0 tcontext=u:object_r:powerctl_prop:s0 tclass=property_service
解決辦法:
在sepolicy路徑下init_shell.te中新增許可權設定
6. 高階進階
以上基本是對已經存在的程序增加許可權,但對第三方程序改如何新增一個全新的te檔案並賦予許可權呢?
以寫mac地址的setmacaddr執行檔案為例(這個執行檔android原生不存在,自行新增的):
在init.xxx.rc中如下服務:
service engsetmacaddr /system/bin/setmacaddr /data/misc/wifi/wifimac.txt class main disabled oneshot |
1. 在device/softwinner/astar-common/sepolicy/file_contexts中,參考其他程序宣告一個scontext:
…… /system/bin/install-recovery.sh u:object_r:install_recovery_exec:s0 /system/bin/dex2oat u:object_r:dex2oat_exec:s0 /system/bin/patchoat u:object_r:dex2oat_exec:s0 /system/bin/setmacaddr u:object_r:engsetmacaddr_exec:s0 |
指定setmacaddr的路徑,並指定一個名字,一定要以service名+_exec結尾
2.參考其.te檔案在device/softwinner/astar-common/sepolicy/file_contexts 建立engsetmacaddr.te檔案,內容如下:
type engsetmacaddr, domain; type engsetmacaddr_exec, exec_type, file_type;
allow engsetmacaddr system_file:file { execute_no_trans}; |
以上賦予的許可權全部是根據avc denied的log缺什麼一步一步補什麼來的。
驅動建立了一個新的裝置節點,即使許可權是777,android層也是沒有訪問許可權的。
下面以一個/dev/wifi_bt節點為示範,讓此節點被使用者空間的system_server程序訪問。
1. 編輯devicesoftwinner/astar-common/sepolicy/device.te,仿照這個檔案裡的寫法,定義一個dev_type型別的wifi_bt_device裝置:
type misc_block_device, dev_type; type private_block_device, dev_type; …… type wf_bt_device, dev_type; |
2. 編輯file_contexts.te,將/dev/wf_bt節點宣告為第1步定義的wf_bt_device:
/dev/block/by-name/misc u:object_r:misc_block_device:s0 /dev/block/by-name/alog u:object_r:log_block_device:s0 /dev/block/by-name/private u:object_r:private_block_device:s0 # We add here /dev/wf_bt u:object_r:wf_bt_device:s0 |
3. 在system_server.te,根據dmesg | grep avc允許system_server對wf_bt_device這個節點可讀可寫:
# Read/Write to /proc/net/xt_qtaguid/ctrl and and /dev/xt_qtaguid. allow system_server qtaguid_proc:file rw_file_perms; allow system_server qtaguid_device:chr_file rw_file_perms; …… allow system_server wf_bt_device:chr_file rw_file_perms; |
其他程序如需訪問/dev/wf_bt節點,依樣畫葫蘆,增加對wf_bt_device的許可權即可。