1. 什么是SELinux:
作為 Android 安全模型的一部分掘譬,Android 使用安全增強(qiáng)型 Linux (SELinux) 對(duì)所有進(jìn)程強(qiáng)制執(zhí)行強(qiáng)制訪問(wèn)控制 (MAC)驳遵,甚至包括以 Root/超級(jí)用戶權(quán)限運(yùn)行的進(jìn)程(Linux 功能)。很多公司和組織都為 Android 的 SELinux 實(shí)現(xiàn)做出了貢獻(xiàn)。借助 SELinux干像,Android 可以更好地保護(hù)和限制系統(tǒng)服務(wù)、控制對(duì)應(yīng)用數(shù)據(jù)和系統(tǒng)日志的訪問(wèn)、降低惡意軟件的影響割坠,并保護(hù)用戶免遭移動(dòng)設(shè)備上的代碼可能存在的缺陷的影響。
SELinux 按照默認(rèn)拒絕的原則運(yùn)行:任何未經(jīng)明確允許的行為都會(huì)被拒絕妒牙。SELinux 可按兩種全局模式運(yùn)行:
寬容模式(Permissive mode):權(quán)限拒絕事件會(huì)被記錄下來(lái)彼哼,但不會(huì)被強(qiáng)制執(zhí)行。
強(qiáng)制模式(Enforcing mode):權(quán)限拒絕事件會(huì)被記錄下來(lái)并強(qiáng)制執(zhí)行湘今。
Android 中包含 SELinux(處于強(qiáng)制模式)和默認(rèn)適用于整個(gè) AOSP 的相應(yīng)安全政策敢朱。在強(qiáng)制模式下,非法操作會(huì)被阻止摩瞎,并且嘗試進(jìn)行的所有違規(guī)行為都會(huì)被內(nèi)核記錄到 dmesg 和 logcat拴签。開發(fā)時(shí),您應(yīng)該先利用這些錯(cuò)誤信息對(duì)軟件和 SELinux 政策進(jìn)行優(yōu)化旗们,再對(duì)它們進(jìn)行強(qiáng)制執(zhí)行蚓哩。
此外,SELinux 還支持基于域的寬容模式上渴。在這種模式下岸梨,可將特定域(進(jìn)程)設(shè)為寬容模式,同時(shí)使系統(tǒng)的其余部分處于全局強(qiáng)制模式稠氮。簡(jiǎn)單來(lái)說(shuō)曹阔,域是安全政策中用于標(biāo)識(shí)一個(gè)進(jìn)程或一組進(jìn)程的標(biāo)簽,安全政策會(huì)以相同的方式處理所有具有相同域標(biāo)簽的進(jìn)程隔披。借助基于域的寬容模式赃份,可逐步將 SELinux 應(yīng)用于系統(tǒng)中越來(lái)越多的部分,還可以為新服務(wù)制定政策(同時(shí)確保系統(tǒng)的其余部分處于強(qiáng)制模式)奢米。
2. 設(shè)置SELinux模式:
對(duì)于受SELinux權(quán)限影響的功能驗(yàn)證抓韩,我們可以先將 SELinux 模式調(diào)整到 Permissive mode,然后再測(cè)試確認(rèn)是否與 SELinux約束相關(guān)。
在userdebug版本中:
adb root
adb shell setenforce 0
adb shell getenforce
注意恃慧,重啟后SELinux模式會(huì)恢復(fù)為enforcing园蝠,若有功能需要在啟動(dòng)時(shí)驗(yàn)證,則可以單獨(dú)重啟Android痢士。
3. 版本演變
低于安卓4.3 - 默認(rèn)不支持SELinux
安卓4.3 - 寬容模式
安卓4.4 - 部分強(qiáng)制模式(多數(shù)設(shè)備依然是寬容模式)
安卓5.1 - 默認(rèn)強(qiáng)制模式
高于安卓8.0 - 強(qiáng)制模式且Sepolicy規(guī)則被分成多個(gè)部分
4. 關(guān)鍵文件
通常情況下彪薛,不能直接修改 system/sepolicy 文件茂装,但可以添加或修改自己的設(shè)備專用政策文件(位于 /device/<manufacturer>/<device-name>/sepolicy 目錄中),比如qcom平臺(tái)項(xiàng)目就要修改 ”/device/qcom/sepolicy” 目錄下的文件善延。
要實(shí)現(xiàn) SELinux少态,必須創(chuàng)建或修改以下文件:
1.新的 SELinux 政策源代碼 (*.te) 文件 - 位于 /device/<manufacturer>/<device-name>/sepolicy 目錄中。這些文件用于定義域及其標(biāo)簽易遣。在編譯到單個(gè) SELinux 內(nèi)核政策文件時(shí)彼妻,新的政策文件會(huì)與現(xiàn)有的政策文件組合在一起。按官方的描述豆茫,可以在其中新增新的政策文件侨歉,但最好還是盡可能嘗試更新現(xiàn)有的文件。
請(qǐng)勿更改 Android 開放源代碼項(xiàng)目提供的 app.te 文件揩魂,否則可能會(huì)破壞所有第三方應(yīng)用幽邓。
2.file_contexts - 位于 sepolicy 子目錄中。該文件用于為文件分配標(biāo)簽火脉,并且可供多種用戶空間組件使用牵舵。在創(chuàng)建新政策時(shí),請(qǐng)創(chuàng)建或更新該文件倦挂,以便為文件分配新標(biāo)簽畸颅。
3.genfs_contexts - 位于 sepolicy 子目錄中。該文件用于為不支持?jǐn)U展屬性的文件系統(tǒng)(例如方援,proc 或 vfat)分配標(biāo)簽没炒。此配置會(huì)作為內(nèi)核政策的一部分進(jìn)行加載,但更改可能對(duì)核心內(nèi) inode 無(wú)效肯骇。要全面應(yīng)用更改窥浪,需要重新啟動(dòng)設(shè)備祖很,或卸載后重新裝載文件系統(tǒng)笛丙。此外,通過(guò)使用 context=mount 選項(xiàng)假颇,還可以為裝載的特定系統(tǒng)文件(例如 vfat)分配特定標(biāo)簽胚鸯。
4.property_contexts - 位于 sepolicy 子目錄中。該文件用于為 Android 系統(tǒng)屬性分配標(biāo)簽笨鸡,以便控制哪些進(jìn)程可以設(shè)置這些屬性姜钳。在啟動(dòng)期間,init 進(jìn)程會(huì)讀取此配置形耗。
5.service_contexts - 位于 sepolicy 子目錄中哥桥。該文件用于為 Android Binder 服務(wù)分配標(biāo)簽,以便控制哪些進(jìn)行可以為相應(yīng)服務(wù)添加(注冊(cè))和查找(查詢)Binder 引用激涤。在啟動(dòng)期間拟糕,servicemanager 進(jìn)程會(huì)讀取此配置。
6.seapp_contexts - 位于 sepolicy 子目錄中。該文件用于為應(yīng)用進(jìn)程和 /data/data 目錄分配標(biāo)簽送滞。在每次應(yīng)用啟動(dòng)時(shí)侠草,zygote 進(jìn)程都會(huì)讀取此配置;在啟動(dòng)期間犁嗅,installd 會(huì)讀取此配置边涕。
7.mac_permissions.xml - 位于 sepolicy 子目錄中。該文件用于根據(jù)應(yīng)用簽名和應(yīng)用軟件包名稱(后者可選)為應(yīng)用分配 seinfo 標(biāo)記褂微。然后功蜓,分配的 seinfo 標(biāo)記可在 seapp_contexts 文件中用作密鑰,以便為帶有該 seinfo 標(biāo)記的所有應(yīng)用分配特定標(biāo)簽宠蚂。在啟動(dòng)期間霞赫,system_server 會(huì)讀取此配置。
5. 規(guī)范
根據(jù)SELinux規(guī)范肥矢,完整的SContext字符串為:
user:role:type[:range]
以 “/build.prop u:object_r:rootfs:s0”為例:
u:為user的意思端衰,它代表創(chuàng)建這個(gè)文件的SELinux user
object_r:在SELinux中,文件類型都用object_r來(lái)表示它的role
rootfs:它表示該目錄或文件對(duì)應(yīng)的Type是rootfs甘改,type會(huì)在te文件中定義
s0:SELinux的Multi-Level Security(MLS)機(jī)制
根據(jù) SELinux 規(guī)范旅东,完整的 SELinux 策略規(guī)則語(yǔ)句格式為:
allow domains types:classes permissions
domain:一個(gè)進(jìn)程或一組進(jìn)程的標(biāo)簽,也稱為域類型
type:一個(gè)對(duì)象(文件十艾,套接字等)或一組對(duì)象的標(biāo)簽
class:要訪問(wèn)的對(duì)象的類型
permission:要執(zhí)行的操作抵代,例如讀寫等
示例:
allow appdomain app_data_file:file rw_file_perms
表示所有appdomain域都可以讀取和寫入帶有app_data_file標(biāo)簽的文件
6. 調(diào)試工具
一般使用 audit2allow 進(jìn)行權(quán)限的調(diào)試,audit2allow 工具可以獲取 dmesg 拒絕事件并將其轉(zhuǎn)換成相應(yīng)的 SELinux 政策聲明忘嫉。因此荤牍,該工具有助于大幅加快 SELinux 開發(fā)速度。但是該工具并不能完全調(diào)試 OK庆冕,還需要用戶自行根據(jù)需要修改康吵。
在 ubuntu 中安裝 policycoreutils:
sudo apt-get install policycoreutils
提取設(shè)備內(nèi)部的sepolicy規(guī)則文件:
adb pull /sys/fs/selinux/policy
用logcat抓取log后使用audit2allow工具解析:
adb logcat -b all -d | audit2allow -p policy
解析后會(huì)打印類似如下內(nèi)容:
#============= xxread ==============
allow xxread shell_exec:file map;
也可以通過(guò)log去自行解析,通過(guò)過(guò)濾“avc”相關(guān)的信息访递,比如:
12-28 02:26:50.659 3058 3058 W init.app.hibern: type=1400 audit(0.0:66): avc: denied { map } for path="/system/bin/sh" dev="overlay" ino=20087 scontext=u:r:xxread:s0 tcontext=u:object_r:shell_exec:s0 tclass=file permissive=0
同樣能得出上面那段內(nèi)容晦嵌,但是需要一定的解讀能力。
然后基于此內(nèi)容將對(duì)應(yīng)的allow權(quán)限添加至對(duì)應(yīng)的 .te 文件中即可(上面這段就要在xxread.te文件中添加)拷姿。
7. 編譯驗(yàn)證
對(duì)于SELinux策略修改的驗(yàn)證惭载,可以使用:
make selinux_policy
編譯之后,會(huì)在相應(yīng)的out目錄下生成新的文件
system(\vendor\system_ext)/etc/selinux/
把新生成的文件push到機(jī)器對(duì)應(yīng)的路徑下替換即可
8. 問(wèn)題案例
這個(gè)編譯問(wèn)題出在原本把新增的文件放在vendor目錄下响巢,由于文件中需要引用system下的可執(zhí)行文件描滔,所以根據(jù)audit2allow增加了訪問(wèn)system_file的allow規(guī)則,但是這樣一來(lái)編譯就會(huì)提示與系統(tǒng)默認(rèn)定義的neverallow規(guī)則沖突了踪古,我們是通過(guò)/vendor分區(qū)去執(zhí)行/system分區(qū)命令含长,這是由于Google啟動(dòng)的Treble計(jì)劃靶衍,為實(shí)現(xiàn)分區(qū)可獨(dú)立升級(jí),不允許進(jìn)行跨分區(qū)調(diào)用茎芋。
由于log中提示“neverallow on line 1024 of system/sepolicy/public/domain.te”颅眶,想嘗試在domain里面的那個(gè)neverallow中使用“-xxx”來(lái)去掉對(duì)該域的限制,后來(lái)編譯發(fā)現(xiàn)又報(bào)錯(cuò)了:
提示意思是domain.te是不允許被修改的田弥,編譯時(shí)會(huì)與默認(rèn)的api目錄下的domain.te進(jìn)行比對(duì)涛酗,一有差異就會(huì)中斷,這點(diǎn)在第4小節(jié)中已經(jīng)提到了偷厦,/system/sepolicy/ 目錄下的規(guī)則是不允許修改的商叹。
所以最后把此文件放在system目錄下,然后使用system分區(qū)的te規(guī)則文件只泼。
9. 思路總結(jié)
先確認(rèn)問(wèn)題是否與 Selinux 權(quán)限相關(guān)剖笙,關(guān)閉權(quán)限限制,先調(diào)試功能请唱,再調(diào)試權(quán)限弥咪。
小問(wèn)題可以使用 audit2allow 工具直接加。
Neverallow 問(wèn)題添加縮小域范圍十绑,自定義新的權(quán)限域進(jìn)行規(guī)避聚至。
添加權(quán)限盡量不修改系統(tǒng)定義域,以免其它進(jìn)程訪問(wèn)不到本橙,引起功能問(wèn)題扳躬。
多項(xiàng)目共基線修改,注意添加兼容問(wèn)題。防止不同項(xiàng)目編譯錯(cuò)誤甚亭。
不到萬(wàn)不得已不修改 system/sepolicy/下的文件贷币,防止 CTS 認(rèn)證失敗。