快速閱讀
框架
SELinux介紹
看Android怎么寫?
如何確認是SELinux 約束引起?
怎么抓取SELinux Log?
修改之后,怎么快速驗證?
怎么從log中提取有效信息?
如何設置SELinux模式?
重點介紹
參考文檔
架構
從上層到驅動層的調用流程,但是我們重點關注sContext:
注:
file_contexts //系統中所有file_contexts安全上下文
seapp_contexts //app安全上下文
property_contexts //屬性的安全上下文
service_contexts? ? //service文件安全上下文
genfs_contexts //虛擬文件系統安全上下文
以上文件system/sepolicy中都有對應的內容
例如:通過adb shell ls –Z指令查看文本的sContext
通過adb shell ps -Z指令可以查看進程的sContext
SELinux介紹
SELinux的背景
1.SELinux則是由美國NSA(國安局)和一些公司(RedHat、Tresys)設計的一個針對Linux的安全加強系統
2.SELinux 按照默認拒絕的原則運行:任何未經明確允許的行為都會被拒絕
3.SELinux的兩種模式。
寬容模式:權限拒絕事件會被記錄下來,但不會被強制執行。
強制模式:權限拒絕事件會被記錄下來并強制執行。
4.Android 4.3(寬容模式)和 Android 4.4(部分強制模式),之后就全面強制執行SELinux
SeLinux作用
提高Android安全性。非法操作會被阻止,并且嘗試進行的所有違規行為都會被內核記錄到 dmesg 和 logcat 中。例如,app訪問文件:/proc/sys/kernel/printk,app設置屬性:persist.qiku.log.level等
看Android怎么寫?
具體源碼路徑:
system/sepolicy
注:
1)system/sepolicy/public/te_macros----這是定義方法的地方。eg:init_daemon_domain(adbd)
2)system/sepolicy/Android.mk中有對private、public、vendor目錄的說明,具體如下:
詳細說明:
在Android8.0以上,SELinux策略分離成平臺(platform)和非平臺(non-platform)兩部分,而平臺策略為了給非平臺作者導出特定的類型和屬性,又分為平臺私有(platform private)和平臺公有(platform public)部分。
1.平臺公有策略(platform public seoplicy)
平臺共有策略全部定義在/system/sepolicy/public下,public下的type和attribute可以被non-platform中的策略所使用,也就是說,設備制造商的sepolicy作者在non-platform下可以對platform public sepolicy的策略進行擴展。
2.平臺私有策略(platform private seoplicy)
與公有策略相反,被聲明為私有策略的type或attribute對non-platform的策略作者是不可見的。
舉例,以8.0版本的aosp源代碼中的/system/sepolicy/private/目錄下的atrace.te文件為例。
1)system/sepolicy/private/file_contexts有定義“/system/bin/atrace? ? u:object_r:atrace_exec:s0”
2)system/sepolicy/private/atrace.te有定義atrace相關的規則
3)我們在device/qcom/sepolicy/common目錄下新增一個atrace.te文件,并添加規則 "allow atrace sdcardfs:file read;"
當我們make sepolicy進行編譯時會在校驗的時候失敗,提示我們“device/qcom/sepolicy/common/atrace.te:2:ERROR 'unknown type atrace' at token ';' on line 23355”,那么也就是說private策略中的type和attribute對我們是不可見的。
注:
自我認知說明,scontext只有平臺和非平臺之分,也就是說,定義在平臺private下面file_contexts屬性,public和非平臺的也可以共享它。
如何確認是Selinux 約束引起?
userdebug版本:
adb root
adb shell setenforce 0
eng版本:
adb shell setenforce 0
詳細介紹:
adb shell setenforce 0
0--代表Permissive
1--代表Enforcing
adb shell getenforce---查看狀態
如果設置成permissive mode 后問題依舊,說明還有其他的權限問題約束,否則就是SELinux 方面的問題
怎么抓取SELinux Log?
1.adb shell dmesg----抓kernel log
(特別說明:adb shell "cat /proc/kmsg | grep avc" > avc_log.txt? 可以直接提出avc的log)
2.adb logcat –b events
關鍵字:
avc: denied
修改之后,怎么快速驗證?
方法一:
mmm system/sepolicy
生成out目錄下,注意有兩個目錄:
system/etc/sepolicy---Android 原生的,建議不動。如果修改,會影響CTS
vendor/etc/sepolicy---第三方廠家修改。
特別說明:
system/sepolicy/Android.mk中定義了一些屬性
BOARD_SEPOLICY_DIRS? ##此宏涉及到的目錄,會編譯到vendor/etc/sepolicy下
PLAT_PUBLIC_POLICY ##此宏涉及到的目錄,會當成system/sepolicy/public
PLAT_PRIVATE_POLICY##此宏涉及到的目錄,會當成system/sepolicy/private
另外,單獨編譯后,會發現都會有對應的生成目錄
方法二:
make sepolicy
怎么從log中提取有效信息?
舉例1
<36>[? 103.972283] c0? ? 484 type=1400 audit(1536907169.826:34): avc: denied { read } for pid=2591 comm="roid.qh_engmode" name="printk" dev="proc" ino=35544 scontext=u:r:radio:s0 tcontext=u:object_r:proc:s0 tclass=file permissive=0
普通提取:
allow radio proc:file read;
關鍵字:
avc: denied { read }? scontext=u:r:radio:s0 tcontext=u:object_r:proc:s0? tclass=file
格式:
allow scontext tcontext:tclass {read}
深入提取:
1.觀察原生:
2.自建:
1)定義路徑
新建文件
genfscon_contexts
輸入
genfscon proc /sys/kernel/printk u:object_r:proc_printk:s0
注:proc_printk是自定義的名字
2)定義type
type proc_printk, fs_type, proc_type;
注:
可以新建一個proc_printk.te,或者直接在file.te中導入
3)重新封裝
allow radio proc_printk:file read;
目的:
防止與原生中的neverallow發生沖突
舉例2
14: 09-03 12:21:04.673? 2325? 2325 I sh? ? ? : type=1400 audit(0.0:12): avc: denied { open } for path="/data/misc/qiku" dev="sda35" ino=508404 scontext=u:r:shell:s0 tcontext=u:object_r:system_data_file:s0 tclass=dir permissive=0
普通提取
allow shell system_data_file:dir open;
深入提取
1.觀察原生:
2.自建:
1)定義路徑
新建文件
file_contexts
輸入:
/data/misc/qiku(/.*)?? u:object_r:qiku_data_file:s0
2)定義type
type qiku_data_file, file_type, data_file_type;
注:
可以新建一個qiku_data_file.te,或者直接在file.te中導入
3)重新封裝
allow shell qiku_data_file:dir open;
如何設置SELinux模式?
兩種方案:
方案一:修改system/core/init/Android.mk
ifneq (,$(filter userdebug eng,$(TARGET_BUILD_VARIANT)))
init_options += \
? ? -DALLOW_LOCAL_PROP_OVERRIDE=1 \
? ? -DALLOW_PERMISSIVE_SELINUX=1 \
? ? -DREBOOT_BOOTLOADER_ON_PANIC=1 \
? ? -DWORLD_WRITABLE_KMSG=1 \
? ? -DDUMP_ON_UMOUNT_FAILURE=1
else
修改為
ifneq (,$(filter user userdebug eng,$(TARGET_BUILD_VARIANT)))
方案二:直接簡單粗暴的修改代碼system/core/init/selinux.cpp
bool IsEnforcing() {
return false; //force set selinux permissive.
if (ALLOW_PERMISSIVE_SELINUX) {
return StatusFromCmdline() == SELINUX_ENFORCING;
}
return true;
}
重點介紹
1)Android權限必須顯示聲明,沒有聲明的話默認就沒有權限。
2)neverallow語句的作用
在生成安全策略文件時進行檢查,判斷是否有違反neverallow語句。也就是說編譯過程中,發現neverallow中有注明不能allow的權限,而你又allow了一條,就會編譯不過。
參考文檔
https://blog.csdn.net/Innost/article/details/19299937
https://blog.csdn.net/Innost/article/details/19641487
https://blog.csdn.net/Innost/article/details/19767621
https://blog.csdn.net/huangyabin001/article/details/79290382
https://source.android.com/security/selinux/device-policy#label_new_services_and_address_denials
https://source.android.com/devices/architecture/configuration/add-system-properties?hl=zh-cn