一、SELinux/SEAndroid簡(jiǎn)介
安全增強(qiáng)型 Linux(Security-Enhanced Linux)簡(jiǎn)稱 SELinux,它是一個(gè) Linux 內(nèi)核模塊,也是 Linux 的一個(gè)安全子系統(tǒng)。2.6 及以上版本的 Linux 內(nèi)核都已經(jīng)集成了 SELinux 模塊。
Android底層是基于linux架構(gòu)的,SEAndroid是Google在Android 4.4上正式推出的一套以SELinux為基礎(chǔ)于核心的系統(tǒng)安全機(jī)制。
二、設(shè)計(jì)目的
最大限度地減小系統(tǒng)中服務(wù)進(jìn)程可訪問(wèn)的資源(最小權(quán)限原則)。
三.安全模型介紹
DAC(Discretionary Access Control):自主訪問(wèn)控制。在沒(méi)有使用 SELinux 的操作系統(tǒng)中,決定一個(gè)資源是否能被訪問(wèn)的因素是:某個(gè)資源是否擁有對(duì)應(yīng)用戶的權(quán)限(讀、寫(xiě)、執(zhí)行)。只要訪問(wèn)這個(gè)資源的進(jìn)程符合以上的條件就可以被訪問(wèn)。而最致命問(wèn)題是,root 用戶不受任何管制,系統(tǒng)上任何資源都可以無(wú)限制地訪問(wèn)。這種權(quán)限管理機(jī)制的主體是用戶。
MAC(Mandatory Access Control): 強(qiáng)制訪問(wèn)控制。在使用了 SELinux 的操作系統(tǒng)中,決定一個(gè)資源是否能被訪問(wèn)的因素除了上述因素之外,還需要判斷每一類進(jìn)程是否擁有對(duì)某一類資源的訪問(wèn)權(quán)限。這樣一來(lái),即使進(jìn)程是以 root 身份運(yùn)行的,也需要判斷這個(gè)進(jìn)程的類型以及允許訪問(wèn)的資源類型才能決定是否允許訪問(wèn)某個(gè)資源。進(jìn)程的活動(dòng)空間也可以被壓縮到最小。即使是以 root 身份運(yùn)行的服務(wù)進(jìn)程,一般也只能訪問(wèn)到它所需要的資源。即使程序出了漏洞,影響范圍也只有在其允許訪問(wèn)的資源范圍內(nèi)。安全性大大增加。這種權(quán)限管理機(jī)制的主體是進(jìn)程。

可以看到,在 DAC 模式下,只要相應(yīng)目錄有相應(yīng)用戶的權(quán)限,就可以被訪問(wèn)。而在 MAC 模式下,還要受進(jìn)程允許訪問(wèn)目錄范圍的限制。
SELinux帶給Linux的主要價(jià)值是:提供了一個(gè)靈活的,可配置的MAC機(jī)制。
四、基本概念
SELinux 是通過(guò) MAC 的方式來(lái)控管程序,他控制的主體是程序(進(jìn)程), 而目標(biāo)則是該程序能否讀取的文件資源。
主體 (Subject):進(jìn)程
目標(biāo) (Object):被訪問(wèn)的資源(可以是文件、目錄、端口、設(shè)備等)。
政策 (Policy):訪問(wèn)限制條件
- targeted:針對(duì)網(wǎng)絡(luò)服務(wù)限制較多,針對(duì)本機(jī)限制較少,是默認(rèn)的政策;
- strict:完整的 SELinux 限制,限制方面較為嚴(yán)格。
- 其他策略
一般使用默認(rèn)的 targeted 政策即可。
安全上下文 (Security Context):
主體能不能存取目標(biāo)除了政策指定之外,主體與目標(biāo)的安全性本文必須一致才能夠順利存取。
SELinux驗(yàn)證整體流程:

DAC MAC的驗(yàn)證順序是:

Linux系統(tǒng)先做DAC檢查,如果沒(méi)有通過(guò)直接失敗,如果通過(guò)了,再做MAC權(quán)限檢查。
五、SELinux 工作模式
SELinux 有三種工作模式,分別是:
1. enforcing:強(qiáng)制模式。違反 SELinux 規(guī)則的行為將被阻止并記錄到日志中。
2. permissive:寬容模式。違反 SELinux 規(guī)則的行為只會(huì)記錄到日志中。一般為調(diào)試用。
3. disabled:關(guān)閉 SELinux。
adb shell getenforce 查看模式。
adb shell setenforce 0|1 分別對(duì)應(yīng)切換 permissve | enforcing 模式
三種工作模式的驗(yàn)證過(guò)程:

六、Security Context詳解
SELinux中,每種東西都賦予一個(gè)安全屬性,官方叫:Security Context 直譯就是安全上下文。它是一個(gè)字符串。
Scontext分為:進(jìn)程的scontext 和 文件的tcontext。兩者匹配時(shí),才會(huì)允許進(jìn)程訪問(wèn)文件,若不匹配時(shí)則不被允許。
Security Context用冒號(hào)分為四個(gè)字段: user : role : type : level
| 字段 | 說(shuō)明 |
|---|---|
| 用戶(User) | root:表示 root 的帳號(hào)身份。 system_u:表示系統(tǒng)程序方面的識(shí)別,通常就是程序。 user_u:代表的是一般使用者帳號(hào)相關(guān)的身份。 或者直接一個(gè) u 表示用戶 |
| 角色(Role) | object_r:代表的是文件或目錄等文件資源,這應(yīng)該是最常見(jiàn)的。system_r/r:代表程序,但一般使用者也會(huì)被指定成為 system_r/r 。 |
| 類型(Type) | type:在文件資源 (Object) 上面稱為類型 (Type)。 domain:在主體程序 (Subject) 則稱為領(lǐng)域 (domain) 。 domain 需要與 type 搭配,則該程序才能夠順利的讀取文件資源 |
| 級(jí)別(Level) | MSL安全級(jí)別 |
SEAndroid下舉例:
查看文件的tcontext: adb shell ls -Z
dr-xr-xr-x 69 root root u:object_r:cgroup:s0 0 1971-03-14 07:23 acct
查看進(jìn)程的scontext: adb shell ps -Z
u:r:init:s0 root 1 0 16204 1284 SyS_epoll_ 00004c7df8 S /init
七、安全策略-TE介紹
安全策略是在安全上下文的基礎(chǔ)上進(jìn)行描述的,也就是說(shuō),它通過(guò)主體和客體的安全上下文,定義主體是否有權(quán)限訪問(wèn)客體。SEAndroid安全機(jī)制主要是使用對(duì)象安全上下文中的類型來(lái)定義安全策略,這種安全策略就稱Type Enforcement,簡(jiǎn)稱TE。所有以.te為后綴的文件經(jīng)過(guò)編譯之后,就會(huì)生成一個(gè)sepolicy文件。這個(gè)sepolicy文件會(huì)打包在ROM中,并且保存在設(shè)備上。
根據(jù)SELinux規(guī)范,完整的allow相關(guān)的語(yǔ)句格式為:
rule_name source_type target_type : class perm_set
source_type 和 target_type 都是查看進(jìn)程和文件對(duì)應(yīng)的安全上下文得來(lái)的。
具體字段說(shuō)明如下:
| 字段 | 描述 |
|---|---|
| rule_name(訪問(wèn)控制規(guī)則) | allow : 允許主體對(duì)客體進(jìn)行操作 neverallow :拒絕主體對(duì)客體進(jìn)行操作 dontaudit : 表示不記錄某條違反規(guī)則的決策信息 auditallow :記錄某項(xiàng)決策信息,通常SElinux只記錄失敗的信息,應(yīng)用這條規(guī)則后會(huì)記錄成功的決策信息。 |
| source_type(訪問(wèn)者類型) | 進(jìn)程 ,屬性為domain類型,代表主體。 |
| target_type(目標(biāo)類型) | 資源,(文件、目錄、端口等)屬性為type類型,代表客體,目標(biāo)類型可以指定多個(gè)。 |
| class (客體類別) | 允許訪問(wèn)的客體類別,是對(duì)目標(biāo)類型的限制。常見(jiàn)類別: class filesystem class file 普通文件 class dir 目錄 class fd 文件描述 class lnk_file 鏈接文件 class chr_file 字符設(shè)備文件 ... |
| perm_set(權(quán)限) | 指定主體可以對(duì)客體進(jìn)行操作的種類。常見(jiàn)權(quán)限操作如下: ioctl、read、write、create、getattr、setattr、lock、relabelfrom、relabelto、append、link、rename、execute、swapon、quotaon、mounton |
另外對(duì)SEAndroid app分類稍微做下總結(jié):
platform_app.te(具有android platform簽名,沒(méi)有system權(quán)限的app)
system_app.te(具有android platform簽名與system權(quán)限的app)
untrusted_app.te(第三方app, 不具有android platform簽名和system權(quán)限)
看看allow語(yǔ)句的例子:
1.允許zygote domain中的進(jìn)程向init type的進(jìn)程(Object Class為process)發(fā)送sigchld信號(hào)
allow zygote init:process sigchld;
2.允許zygote域中的進(jìn)程search或getattr類型為appdomain的目錄。注意,多個(gè)perm_set, 可用{}括起來(lái)
allow zygote appdomain:dir { getattr search };
當(dāng)然語(yǔ)法還有很多,這部分可以自行去系統(tǒng)學(xué)習(xí),本文只是介紹基本的。
八、實(shí)戰(zhàn)演習(xí)
例如一個(gè)需求:在AMS 中寫(xiě) /d/rtmm/reclaim/objectfile 文件
- 首先要滿足DAC驗(yàn)證:首先確認(rèn)system system是否有objectfile文件的寫(xiě)權(quán)限,如果沒(méi)有,修改.rc文件。具體對(duì)應(yīng)是哪個(gè)文件,得去看mk了
假設(shè)system沒(méi)權(quán)限,那修改owner 和 group:
on boot
chown system system /d/rtmm/reclaim/objectfile
- 然后走M(jìn)AC驗(yàn)證:
首先AMS是在system_server進(jìn)程,看看system_server的安全上下文:
mido:/d/rtmm/reclaim # ps -Z | grep "system_server"
u:r:system_server:s0 system 1533 719 2717140 357292 SyS_epoll_ 7fb57e5540 S system_server
再看看目標(biāo)文件objectfile的安全上下文:
mido:/d/rtmm/reclaim # ls -Z
-rw-rw---- 1 system system u:object_r:debugfs_rtmm:s0 0 2018-10-25 18:19 objectfile
找到對(duì)應(yīng)的te文件:system_server.te
allow system_server debugfs:file w_file_perms;
w_file_perms 是定義的一個(gè)宏,比純write要好,包括了后續(xù)一些寫(xiě)完的收尾處理工作。
九、錯(cuò)誤分析和解決
很多情況下,我碰到的問(wèn)題是通過(guò)報(bào)錯(cuò)來(lái)看缺少什么權(quán)限,原則是"缺什么補(bǔ)什么". 看兩個(gè)案例:
案例一:
audit(0.0:67):avc: denied {write } forpath="/dev/block/vold/93:96" dev="tmpfs" ino=1263scontext=u:r:kernel:s0tcontext=u:object_r:block_device:s0tclass=blk_filepermissive=0
分析過(guò)程:
缺少什么權(quán)限: { write }權(quán)限,
誰(shuí)缺少權(quán)限: scontext=u:r:kernel:s0,
對(duì)哪個(gè)文件缺少權(quán)限:tcontext=u:object_r:block_device
什么類型的文件: tclass=blk_file
解決方法:kernel.te
allow kernel block_device:blk_file write;
案例二:
03-23 10:15:40.290 1422 1422 W Pipe_Write_Hand:type=1400 audit(0.0:79): avc: denied { ioctl } forpath="socket:[19308]" dev="sockfs" ino=19308scontext=u:r:system_app:s0 tcontext=u:r:bluetooth:s0 tclass=unix_stream_socketpermissive=0
03-23 10:15:40.301 1280 1422 W System.err: Java.io.IOException: Permission denie
解決方法:
在system_app.te里添加 bluetooth_domain(system_app)
原因: bluetooth.te中對(duì)bluetooth_domain屬性賦予了權(quán)限
allow bluetoothdomain bluetooth:unix_stream_socket { getopt setopt getattr read write ioctl shutdown};
參考:
https://blog.csdn.net/innost/article/details/19299937#comments
https://blog.csdn.net/ztguang/article/details/62834072?utm_source=blogxgwz0
https://blog.csdn.net/hanmengaidudu/article/details/60766591
http://cn.linux.vbird.org/linux_basic/0440processcontrol_5.php