Android SELinux avc dennied許可權問題解決方法
1. 概述
SELinux是Google從android 5.0開始,強制引入的一套非常嚴格的許可權管理機制,主要用於增強系統的安全性。
然而,在開發中,我們經常會遇到由於SELinux造成的各種許可權不足,即使擁有“萬能的root許可權”,也不能獲取全部的許可權。本文旨在結合具體案例,講解如何根據log來快速解決90%的SELinux許可權問題。
2. 除錯確認SELinux問題
為了澄清是否因為SELinux導致的問題,可先執行:
setenforce 0 (臨時禁用掉SELinux)
getenforce (得到結果為Permissive)
如果問題消失了,基本可以確認是SELinux造成的許可權問題,需要通過正規的方式來解決許可權問題。
遇到許可權問題,在logcat或者kernel的log中一定會列印avc denied提示缺少什麼許可權,可以通過命令過濾出所有的avc denied,再根據這些log各個擊破:
cat /proc/kmsg | grep avc
或
dmesg | grep avc
例如:
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
可以看到有avc denied,且最後有permissive=0,表示不允許。
3. 具體案例分析
解決原則是:缺什麼許可權補什麼,一步一步補到沒有avc denied為止。
解決許可權問題需要修改的許可權檔案如下位置,以.te結尾
A:Android/devicesoftwinner/astar-common/sepolicy/*.te
B:Android/external/sepolicy/*.te
其中,A是對B的overlay(覆蓋),能在A修改的儘量在A修改,儘量避免修改B,修改B可能會導致CTS fail問題,修改A不會影響CTS測試。
(如果不需要深入瞭解,請直接跳到萬能公式這一章閱讀更簡潔)
下面給出四個案例:
案例1
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 |
分析過程:
缺少什麼許可權: { write }許可權,
誰缺少許可權: scontext=u:r:kernel:s0
對哪個檔案缺少許可權:tcontext=u:object_r:block_device
什麼型別的檔案: tclass=blk_file
完整的意思: kernel程式對block_device型別的blk_file缺少write許可權。
解決方法:在上文A位置,找到kernel.te這個檔案,加入以下內容:
allow kernel block_device:blk_file write; |
make installclean後重新編譯,刷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許可權。
解決方法:在上文A位置,找到platform_app.te這個檔案,加入以下內容:
allow platform_app app_data_file:file execute; |
make installclean後重新編譯,刷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的定義宣告)
4. 萬能公式
通過這四個案例,我們可以總結出一般規律,
以第案例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 |
某個scontext對某個tclass型別的tcontext缺乏某個許可權,我們需要允許這個許可權:
我們的log重新排列一下,
scontext = u:r:sdcardd
tcontex t= u:object_r:system_data_file:s0
tclass = dir
avc: denied { read }
得到萬能套用公式如下:
在scontext所指的.te檔案(例如sdcardd.te)中加入類似如下allowe內容:
5. TIPS
1. 以上以.te為字尾的檔案都在以下位置:
A:Android/devicesoftwinner/astar-common/sepolicy/*.te
B:Android/external/sepolicy/*.te
其中,A是對B的overlay(覆蓋),能在A修改的儘量在A修改,修改B可能會導致CTS fail問題,修改A不會影響CTS測試。修改之後,為了節約驗證時間,只重刷boot.img即可看效果;
2. 有時候avc denied的log不是一次性暴露所有許可權問題,要等解決一個許可權問題之後,才會暴露另外一個許可權問題。比如提示缺少某個目錄的read許可權,加入read之後,才顯示缺少write許可權,要一次次一次試,一次一次加,時間成本極大。
針對dir缺少的任何許可權,建議賦予create_dir_perms,基本涵蓋對dir的所有許可權,比如:
{ open search write read rename create rmdir getattr }等等。
針對file缺少的任何許可權,建議賦予rwx_file_perms,基本涵蓋對file的所有許可權,比如:
包含{ open read write open execute getattr create ioctl }等等。
更多內容請參考external/sepolicy/global_macros來了解更多許可權宣告。
3. 要加入的許可權很多時,可以用中括號,比如:
allow engsetmacaddr vfat:dir { search write add_name create};
4. 修改A位置的.te檔案遇到編譯錯誤怎麼辦?
(首先請排除拼寫錯誤)說明此項許可權是SELinux明確禁止的,也是Google CTS禁止的,如果產品不需要過CTS,可以修改。一般來說,編譯出錯的log會提示相關哪個檔案哪一行出錯,檔案位置一定會在B裡的.te檔案。比如B規定了以下neverallow,
neverallow system_server sdcard_type:dir { open read write };
那麼system_server是不能擁有這些許可權的,如果賦予這些許可權就編譯報錯,解決方法是根據編譯錯誤提示的行號,把這一句註釋掉即可。
6. 高階進階
6.1. 新建.te安全策略檔案方法
以上基本是對已經存在的程式增加許可權,但對第三方程式改如何新增一個全新的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缺什麼一步一步補什麼來的。
6.2. 新裝置節點增加訪問許可權
驅動建立了一個新的裝置節點,即使許可權是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的許可權即可。
相關文章
- android AVC錯誤修改許可權方法Android
- Android SELinux許可權AndroidLinux
- vue許可權問題解決方案Vue
- 用無程式碼解決CRM角色許可權問題
- Android6.0動態許可權最簡單的解決方法Android
- MySQL許可權問題MySql
- 採坑之Android手機訪問相簿許可權問題Android
- Centos sudo 許可權問題CentOS
- 更新完 zsh 說我目錄許可權問題的解決
- Android 通知許可權Android
- 許可權的級聯問題
- Ubuntu 下 Composer 許可權問題Ubuntu
- android動態許可權到自定義許可權框架Android框架
- win10 儲存excel報錯 許可權問題怎麼解決Win10Excel
- android 許可權庫EasyPermissionsAndroid
- Mysql資料庫許可權問題MySql資料庫
- hdfs檔案本地許可權問題
- Laravel Daily 日誌許可權問題LaravelAI
- jenkins 容器內的許可權問題Jenkins
- sqlserver 賦予許可權的問題SQLServer
- 記一個 Android 14 適配引發的Android 儲存許可權問題Android
- Android部分手機“後臺彈出介面許可權”解決方案Android
- WPF + Winform 解決管理員許可權下無法拖放檔案的問題ORM
- [求助] mac macaca doctor 報錯,好像是許可權問題,怎麼解決Mac
- win10許可權不能打勾怎麼辦 win10管理員許可權不能打勾解決方法Win10
- Android6.0------許可權申請管理(單個許可權和多個許可權申請)Android
- Laravel 框架的日誌許可權問題Laravel框架
- MaxCompute/DataWorks許可權問題排查建議
- Grafana9的dashboard許可權問題Grafana
- Laravel 日誌檔案許可權問題Laravel
- android 許可權元件設計Android元件
- 解決Python虛擬環境virtualenv下不能使用sudo提升許可權問題Python
- 解決在Windows10下沒有許可權修改hosts檔案的問題Windows
- Ubuntu共享資料夾訪問許可權問題Ubuntu訪問許可權
- 記一次 Laravel日誌許可權許可權問題(定時器導致)Laravel定時器
- 這也許是Android一句話許可權適配的更優解決方案Android
- 不同使用者python path 許可權問題Python
- 上傳APP到Google Play許可權問題APPGo