SELinux走過的坑

linux通過UID/GID機制對權(quán)限進行管理,將文件的權(quán)限劃分為讀、寫和執(zhí)行三種,分別用字母r、w和x表示。每一個文件有三組讀、寫和執(zhí)行權(quán)限,分別是針對“文件的所有者”、“文件所有者所屬的組”以及其它用戶。
在linux系統(tǒng)中,我們想完全操作某個文件,只需要執(zhí)行sudo chmod 777 filename 即可。這表示root用戶擁有無限大的權(quán)限,可以操作系統(tǒng)中的任何文件。
所以在安卓系統(tǒng)中,引入了SELinux用以提升系統(tǒng)安全性。

一、常用命令

SELinux模式有三種,Enforcing強制模式、Permissive寬容模式與Disabled完全禁用。
區(qū)別是Enforcing強制模式中,SELinux是起作用,而Permissive寬容模式SELinux不起作用,僅輸出權(quán)限拒絕日志。

查看SELinux模式命令:getenforce
更改SELinux模式命令:setenforce 1 設(shè)置為Enforcing
                  setenforce 0 設(shè)置為Permissive

安卓中快速編譯sepolicy并驗證,需要本地代碼整編過一次,已經(jīng)生成out目錄之后。(這里我遇到一個問題,這樣編過幾次之后,再去整編的時候就會報image out of space的錯誤,暫時不知道原因。)

$ mmma system/sepolicy/
$ adb push out/target/product/xxx/system/etc/selinux /system/etc/selinux
$ adb push out/target/product/xxx/vendor/etc/selinux /vendor/etc/selinux

也可單編systemimage,并刷機

$ make systemimage
$ adb reboot bootloader
$ fastboot flash system ./system.img
$ fastboot reboot

二、SELinux基本概念

1、如何配置SEpolicy

在分析安卓系統(tǒng)問題看日志時,會有同學好奇以下日志的含義:

05-25 18:51:22.421  7419  7419 W logcat  : type=1400 audit(0.0:1319): 
avc: denied { write } for name="syslog" 
dev="mmcblk0p87" ino=31476 scontext=u:r:logpersist:s0 
tcontext=u:object_r:system_data_file:s0 tclass=dir permissive=0

這是linux的審計信息,簡單的來說該日志可以理解為:logpersist想要訪問system_data_file的dir目錄,缺少了write寫權(quán)限。
這是因為SELinux權(quán)限限制了,通過配置sepolicy即可通過。
如果想要簡單配置sepolicy權(quán)限,則需要在logpersist.te文件下,設(shè)置以下allow:

allow  logpersist  system_data_file:dir  write;

但當加上“allow”語句之后,編譯會報錯,這是因為谷歌設(shè)置了neverallow,不允許我們針對“l(fā)ogpersist”與“system_data_file”添加allow語句。
為了解決這一問題,更加詳細的了解一下SELinux。

2、了解

SEAndroid安全機制中的安全策略就是在“安全上下文”的基礎(chǔ)上進行描述的, 它通過主體和客體的安全上下文,定義主體是否有權(quán)限訪問客體。
以上述日志舉例,主體 scontext就是u:r:logpersist:s0,客體tcontext是u:object_r:system_data_file:s0。該錯誤日志表示主體沒有對客體的write權(quán)限,其中tclass=dir表示客體的類型為文件夾。

  1. Domain:u:r:logpersist:s0是一個“域”,它是一個進程或一組進程的標簽。
  2. Type:u:object_r:system_data_file:s0是一個“對象標簽”,它是一個對象或一組對象的標簽。
  3. Class:dir 是客體的類型。(dir是文件夾,file是文件...)
  4. Permission:write 是缺少的權(quán)限。

以下語句表示,允許“l(fā)ogpersist進程”對所屬“system_data_file”的文件件類型為文件夾“dir”進行“write”操作。

allow  logpersist  system_data_file:dir  write;

3、安全上下文

安全上下文由“SELinux用戶”、“SELinux角色”、“類型”、“安全級別” 四部分組成,格式為“user:role:type:sensitivity”。
進程的安全上下文:用戶固定為 u,角色固定為 r。如:u:r:logpersist:s0
文件的安全上下文:用戶固定為 u,角色固定為 obejct_r。如:u:object_r:system_data_file:s0
安全級別:可以選擇啟用或者不啟用,通常在進程及文件的安全上下文中安全級別都設(shè)置為s0。

進程的安全上下文的類型稱為Domain,文件的安全上下文中的類型稱為Type。

三、如何應(yīng)對neverallow

在system/sepolicy/private/logpersist.te與system/sepolicy/prebuilts/api/29.0/private/logpersist.te中配置以下allow語句并編譯,會報neverallow的錯。

allow  logpersist  system_data_file:dir  write;

這表示谷歌不允許我們使用allow語句,解除限制的最暴力方法就是將報錯處的neverallow語句刪掉,這樣確實可行,但是會過不了cts。
由于我們要訪問的目錄path為/data/syslog,將該目錄定義成自己的Type
可以自定義Type,如下:
在file.te中自定義一個type為file_type,data_file_type,core_data_file_type:(應(yīng)該只需要定義為file_type即可,我沒有測試:)

type log_data_file, file_type, data_file_type, core_data_file_type;

在file_contexts中定義安全上下文:

/data/syslog(/.*)?            u:object_r:log_data_file:s0

將allow語句改為:

allow  logpersist  log_data_file to  write;

然后在logpersist.te中單獨將自定義的log_data_file減去即可。(這里最好的是自定義一個service代替logpersist,那就要新建一個te文件了,比較麻煩)

neverallow logpersist {
  file_type
  userdebug_or_eng(`-misc_logd_file -coredump_file')
  with_native_coverage(`-method_trace_data_file')
  -log_data_file
}:file { create write append };

四:參考文獻

1:https://blog.csdn.net/weixin_42082222/article/details/85239018
2:https://blog.csdn.net/ch853199769/article/details/82498725
3:https://blog.csdn.net/weixin_42082222/article/details/85239018

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容