本文轉載自:Android系統SELinux詳解
前言
??SELinux是一種加強文件安全的一種策略,可以更好地保護我們的Android系統, 比如限制系統服務的訪問權限、控制應用對數據和系統日志的訪問等措施,這樣就降低了惡意軟件的影響,并且可以防止因代碼存在的缺陷而產生的對系統安全的影響。
??從系統安全方面考慮,SELinux是保護神,但是從軟件開發方面,SELinux就是一道牽絆,這是一把雙刃劍。SELinux默認開啟,即使獲得了該系統的root權限,也只能向相關策略中指定的設備寫入數據,從而更好地保護和限制系統服務,保障系統和數據的安全。
1.環境
硬件平臺:Google Pixel2
操作系統:Android 10.0
2.selinux有兩種工作模式
名稱 | 作用 |
---|---|
permissive | 所有操作都被允許(即沒有MAC),但是如果有違反權限的話,會記錄日志 |
enforcing | 所有操作都會進行權限檢查 |
3.標簽、規則和域
??SELinux依靠標簽來匹配操作和策略。標簽用于決定允許的事項。套接字、文件和進程在SELinux中都有標簽。SELinux在做決定時需參照兩點:一是為這些對象分配的標簽,二是定義這些對象如何交互的策略。
??在SELinux中,標簽采用以下形式:user:role:type:mls_level,其中type是訪問決定的主要組成部分,可通過構成標簽的其他組成部分進行修改。對象會映射到類,對每個類的不同訪問類型由權限表示。
??策略規則采用以下形式:allow domains types:classes permissions;,其中:
名稱 | 作用 |
---|---|
domain | 一個進程或一組進程的標簽。也稱為域類型,因為它只是指進程的類型。 |
type | 一個對象(例如,文件、套接字)或一組對象的標簽。 |
class | 要訪問的對象(例如,文件、套接字)的類型。 |
Permission | 要執行的操作(例如,讀取、寫入)。 |
4.策略配置源文件
- external/sepolicy
??這是獨立于設備的配置,一般不能針對設備進行修改;
- device/sepolicy
??這是特定于設備的配置,基于BOARD_SEPOLICY_*變量來選擇對應平臺的策略配置。
5.Type Enforcement (TE) 配置文件
??.te文件中保存了對應對象的域和類型定義、規則。通常每個域一個.te文件,例如installd.te。在device.te、file.te 中聲明了設備和文件類型。在某些文件(例如domain.te、app.te)中則存儲著共享規則。
6.標簽配置文件
file_contexts:文件安全上下文;
property_contexts:屬性安全上下文。
7.SEAndroid app分類
??SELinux(或SEAndroid)將app劃分為主要三種類型(根據user不同,也有其他的domain類型):
名稱 | 作用 |
---|---|
untrusted_app | 第三方app,沒有Android平臺簽名,沒有system權限 |
platform_app | 有android平臺簽名,沒有system權限 |
system_app | 有android平臺簽名和system權限 |
從上面劃分,權限等級,理論上:untrusted_app < platform_app < system_app
8.user
??user可以理解為UID。android的UID和linux的UID根本是兩回事,Linux的UID是用于針對多用戶操作系統中用于區分用戶的,而Android中的UID是用于系統進行權限管理的。
9.seinfo
??不同簽名會創建對應的selinux上下文。
// Android.mk
LOCAL_CERTIFICATE := platform
有platform簽名,所以seinfo是platform。
10.自定義安全策略
??以上面兩個運行的app來說,我們為這兩個APP添加額外的權限,對應的TE配置文件分別就是system_app.te、untrusted_app.te,對應路徑為:
$aosp/system/sepolicy/public/system_app.te
$aosp/system/sepolicy/public/untrusted_app.te
以longzhiye.example.app為例,我們為其添加can設備的執行權限:
longzhiye@longzhiye-laptop:~/mount/project/androidq$ vi system/sepolicy/public/system_app.te
......
allow system_app vendor_shell_exec:file { getattr open read execute execute_no_trans };
allow system_app shell_exec:file { getattr open read execute execute_no_trans };
allow system_app shell:file { getattr open read execute execute_no_trans };
......
以策略規則配置形式(allow domains types:classes permissions)
分析:
策略規則 | 示例 |
---|---|
domains | system_app |
types | vendor_shell_exec |
classes | file |
permissions | getattr open read execute execute_no_trans |
11.neverallow failures
??有時我們增加的權限,系統默認的配置是不允許的,比如我們上面給forlinx.example.app增加的執行腳本的權限,報錯如下:
libsepol.report_failure: neverallow on line 9 of system/sepolicy/private/system_app.te
(or line 41463 of policy.conf) violated by allow system_app shell:file { read open };
libsepol.report_failure: neverallow on line 22 of system/sepolicy/private/shell.te
(or line 40025 of policy.conf) violated by allow system_app shell:file { read open };
libsepol.check_assertions: 2 neverallow failures occurred
系統默認的安全策略的路徑為system/sepolicy/,根據報錯的提示,我們可以修改默認的配置,修改system/sepolicy/private/system_app.te和system/sepolicy/private/shell.te,從而完成權限的賦予。
12.安卓中快速編譯sepolicy并驗證(需要本地代碼整編過一次,已經生成out目錄)
$ mmm 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
13.如何應對neverallow? 繞過CTS認證
??在system/sepolicy/private/logpersist.te與system/sepolicy/prebuilts/api/29.0/private/logpersist.te中配置以下allow語句并編譯,會報neverallow的錯。如下聲明allow:
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:
- type log_data_file, file_type, data_file_type, core_data_file_type;
??在file_contexts中定義安全上下文:
- /data/syslog(/.*)? u:object_r:log_data_file:s0
??在logpersist.te將allow語句改為:
- allow logpersist log_data_file 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 };
14.如何新增domian域?(一般在平臺相關目錄下添加)
例子如下:
(1)在device/平臺名/system/private/file_contexts 文件添加
# tcontext=u:object_r:sysfs:s0
/sys/kernel/display/abcd u:object_r:wxl_abcd:s0 #wxl_abcd替換sysfs,wxl_abcd隨便取。
(2)在device/平臺名/system/public/file.te 中添加
type wxl_cabc, fs_type,sysfs_type;
(3)在 device/平臺名/system/private/system_server.te 文件中添加
allow system_server wxl_abcd:file { r_file_perms w_file_perms rw_file_perms };
添加write或者read的權限要注意open的權限,最后使用r_file_perms、w_file_perms、rw_file_perms。
15.添加設備文件節點權限(sysfs gpio管腳節點權限)?
/sys/class/leds/green/brightness //快捷方式
/sys/devices/soc.0/gpio-leds.66/leds/green/brightness //實際節點
操作LED燈的設備文件節點為APP層system app進程開放該節點訪問權限(讀或寫),權限配置主要修改(一般在/device/平臺/sepolicy/common)目錄下的file.te、file_contexts和system_app.te三個文件。
(1)file.te修改如下:
// GPIO accessed by system app
type sysfs_gpio, fs_type, sysfs_type;
(2)file_contexts修改如下:
/sys/devices/soc/1010000.pinctrl/gpio/gpio62/value u:object_r:sysfs_gpio:s0
/sys/devices/soc/1010000.pinctrl/gpio/gpio63/value u:object_r:sysfs_gpio:s0
(3)system_app.te修改如下:
allow system_app sysfs_gpio:file rw_file_perms;
如果通過以上添加SELinux之后,仍沒有權限讀寫sys或proc節點,需要到/system/core/rootdir/init.rc里面配置如下:
(1)修改設備節點用戶所有者和所屬用戶組,以及它們所對應的權限
chown system system 設備文件結點
chmod 777 設備文件結點
16.修改selinux沒有生效???
??將SELinux Policy文件存放在下面目錄
(1) Google 原生目錄 /system/sepolicy
(2) 廠商配置目錄 /device/廠商平臺/sepolicy/
android將SELinux Policy 文件存放的te一般都是在device/平臺/sepolicy 和 /system/sepolicy兩個目錄下。