目錄
一、SELinux 是什么?
二、SELinux 的兩種模式
如何查看當前 SELinux 狀態?
三、SELinux 在 Android 中的作用
四、為什么Root之后很多設備是 Permissive?
五、開發與調試場景
總結
🧩 一、什么是 SELinux 策略?
🗂? 二、SELinux 策略的組成
📄 三、一個簡單的策略例子(.te 文件)
解讀:
📁 四、文件上下文(.fc)
🛠? 五、策略編寫流程(開發者視角)
🔍 六、常用allow語法
🧪 七、開發時如何調試策略?
? 總結
一、SELinux 是什么?
SELinux 全稱是 Security-Enhanced Linux,是由美國國家安全局(NSA)和Red Hat開發的一種強制訪問控制(MAC)機制,被集成到了Linux內核中。
在Android中,SELinux 從 Android 4.3 開始引入,并從 Android 5.0(Lollipop)起默認啟用為強制模式(enforcing),是系統安全的核心。
二、SELinux 的兩種模式
SELinux 有兩個主要的運行狀態:
狀態 | 名稱 | 說明 |
---|---|---|
Permissive | 寬容模式 | 只記錄違規行為,不阻止操作;常用于調試或開發。 |
Enforcing | 強制模式 | 嚴格執行策略,阻止不合法的行為(如非法訪問系統資源)。 |
如何查看當前 SELinux 狀態?
在 Android 終端或 ADB shell 中輸入:
getenforce
-
返回
Enforcing
表示SELinux正在強制執行策略。 -
返回
Permissive
表示只是記錄日志,不真正限制訪問。 -
也可以使用
sestatus
命令(在某些Linux系統上)查看詳細信息。
三、SELinux 在 Android 中的作用
-
限制App權限越界
即使一個應用有root權限,如果違反SELinux策略(比如訪問系統核心資源),它的操作依然會被阻止。 -
防止惡意軟件提權
限制后臺服務或惡意模塊在未經授權的情況下獲取系統控制權。 -
分區不同安全域(context)
每個進程、文件都有一個安全上下文,像u:object_r:system_file:s0
,用于判斷它是否有權執行某操作。
四、為什么Root之后很多設備是 Permissive?
-
Root工具(如Magisk)經常會將SELinux設置為 Permissive,這樣方便修改系統文件或執行本不被允許的操作。
-
例如,某些模塊(如Xposed)需要插樁系統服務,如果SELinux是 Enforcing,這類操作會被阻止。
-
但 Permissive 模式存在安全風險,因為系統不會阻止任何行為,只記錄了日志。
五、開發與調試場景
-
在開發調試定制ROM、修改系統行為時,為了方便調試,會把SELinux設為Permissive。
-
發布正式ROM或上架Play商店時,Google強制要求為Enforcing模式。
總結
問題 | 解釋 |
---|---|
SELinux能提高安全性嗎? | 是的,它為Android添加了一道重要的系統級防線。 |
為什么root后會修改SELinux狀態? | 為了獲得更高權限訪問系統資源,繞開限制。 |
可以手動切換狀態嗎? | 在root環境下可以通過命令如 setenforce 0/1 進行切換,但需謹慎。 |
🧩 一、什么是 SELinux 策略?
SELinux 策略(policy) 是定義系統中哪些主體(subjects)可以訪問哪些客體(objects)以及如何訪問的規則集合。
在 Android 或 Linux 中:
-
主體一般是進程(如
system_server
、vold
)。 -
客體一般是文件、目錄、socket、屬性等資源。
策略是以 "類型強制訪問控制(TE – Type Enforcement)" 的形式存在。
🗂? 二、SELinux 策略的組成
SELinux策略由多種類型的文件構成:
文件 | 說明 |
---|---|
*.te | Type Enforcement 文件,定義主體和客體的訪問規則(核心策略文件) |
*.fc | 文件上下文文件,定義哪些文件路徑屬于哪種類型 |
*.if | 接口文件,模塊之間共享的抽象接口 |
*.pp | 編譯后的策略模塊文件(policy package) |
*.cil | 高級策略中使用的中間語言文件 |
📄 三、一個簡單的策略例子(.te 文件)
我們看一個簡單的策略例子,假設我們創建了一個名為 myapp
的進程:
# myapp.te# 聲明類型
type myapp, domain;
type myapp_exec, exec_type, file_type;# myapp 允許以 myapp_exec 類型啟動
init_daemon_domain(myapp)# myapp 允許讀取 log 文件
allow myapp logd:unix_stream_socket connectto;# 允許 myapp 讀取某個配置文件
allow myapp myconfig_file:file { read open getattr };
解讀:
-
type myapp, domain;
:定義了一個名為myapp
的安全上下文(安全域)。 -
type myapp_exec, exec_type, file_type;
:定義了myapp
的可執行文件類型。 -
init_daemon_domain(myapp)
:允許它作為一個守護進程啟動(使用宏簡化配置)。 -
allow ...
是核心規則,定義主體如何訪問客體。
📁 四、文件上下文(.fc)
這個文件指定哪些路徑屬于哪種類型(用于掛載策略到文件系統):
# myapp.fc/system/bin/myapp u:object_r:myapp_exec:s0
/data/myapp/config.xml u:object_r:myconfig_file:s0
🛠? 五、策略編寫流程(開發者視角)
-
創建類型定義文件(如
myapp.te
) -
指定文件上下文(
myapp.fc
) -
構建并安裝模塊
-
使用
checkmodule
、semodule_package
工具將.te
文件編譯成.pp
模塊
-
-
加載策略模塊
semodule -i myapp.pp
Android使用自己的策略編譯系統(Android.bp +
sepolicy
),而不是手動運行這些命令。
🔍 六、常用allow語法
allow <subject> <object>:<class> <permissions>;
示例:
allow myapp sysfs:file { read open };
allow myapp system_file:dir { search };
allow myapp shell_exec:file { execute };
元素 | 含義 |
---|---|
subject | 進程類型(誰在訪問) |
object | 被訪問的資源類型 |
class | 資源的類別,如 file、dir、socket 等 |
permissions | 允許的操作,如 read 、write 、open 、execute 等 |
🧪 七、開發時如何調試策略?
當 SELinux 阻止某項操作時,它會寫入 dmesg
或 /var/log/audit.log
(Android用logcat也能看到)。
日志格式大概如下:
avc: denied { read } for pid=1234 comm="myapp" name="config.xml" dev="sda1" ino=12345 scontext=u:r:myapp:s0 tcontext=u:object_r:myconfig_file:s0 tclass=file
avc: denied { read } for pid=1234 comm="myapp" name="config.xml" dev="sda1" ino=12345 scontext=u:r:myapp:s0 tcontext=u:object_r:myconfig_file:s0 tclass=file
?你可以用 audit2allow
工具自動生成建議的策略:
dmesg | audit2allow -m myapp
? 總結
內容 | 要點 |
---|---|
策略寫在 .te 文件 | 用 allow 聲明訪問權限 |
每個文件/進程都有 context | type 定義類型,.fc 綁定路徑 |
Android 使用宏(如 init_daemon_domain ) | 簡化復雜的策略編寫 |
日志審計是調試關鍵 |