在 Android 的早期版本(Android 4.2 以前),應用與系統服務的安全隔離主要依靠:
這樣的設計雖能避免應用直接干擾他人,但仍有兩個問題:
於是 Google 在 Android 4.3 (2013) 開始導入 SELinux (Security-Enhanced Linux),並在 Android 5.0 (Lollipop) 之後全面啟用 「Enforcing 模式」。
SELinux 成為 Android 安全架構的關鍵基石,用以實現 Mandatory Access Control (MAC) —— 強制存取控制。
2.1 DAC 與 MAC 的差異
| 模型 | 名稱 | 控制權歸屬 | 特點 |
|---|---|---|---|
| DAC (Discretionary Access Control) | 任意存取控制 | 由檔案擁有者決定 | 如 Linux 傳統 chmod, chown |
| MAC (Mandatory Access Control) | 強制存取控制 | 由系統策略統一規範 | SELinux、AppArmor 等屬此類 |
在 Android 中,DAC 仍存在,但 SELinux 的 MAC 為「第二層強制規範」,無論 UID 權限如何,都必須通過 policy 驗證。
2.2 SELinux 的基本組成
+-----------------------------------------------------------+
| SELinux Policy Framework |
+-----------------------------------------------------------+
| policy.conf / sepolicy → compiled into sepolicy |
| type enforcement (TE) → 決定哪些 domain 能存取何資源 |
| file_contexts → 檔案與型別對應 |
| seapp_contexts → app 與 domain 對應 |
| service_contexts → 系統服務 domain 對應 |
+-----------------------------------------------------------+
| Kernel SELinux Module (AVC) |
| → Security Server 決策 + Access Vector Cache |
+-----------------------------------------------------------+
簡單來說:
圖 1:SELinux 在 Android 系統架構中的位置
+-----------------------------------------------------------+
| Application Framework 層 |
| (PermissionManagerService, ActivityManagerService...) |
+-----------------------------------------------------------+
| Native System Services 層 |
| (system_server, mediaserver, keystore, surfaceflinger) |
+-----------------------------------------------------------+
| Binder / HAL / JNI 層 |
| (libbinder.so, HIDL/AIDL IPC, HAL drivers) |
+-----------------------------------------------------------+
| Kernel & SELinux |
| (AVC, sepolicy, security_context enforcement) |
+-----------------------------------------------------------+
Android 的安全模型是 多層次防禦 (Defense-in-Depth):
在 init 階段,SELinux 的初始化流程如下:
u:r:system_server:s0
u:r:app_123:s0:c512,c768
u:object_r:system_data_file:s0
格式說明:user:role:type:level
user:通常是 u;
role:角色(在 Android 幾乎都固定);
type:最關鍵,定義該進程或物件的 domain;
level:多層安全等級(Android 目前主要用於 app sandbox)。
| 檔案名稱 | 功能 |
|---|---|
| sepolicy | 編譯後的策略檔,供 kernel 直接使用 |
| file_contexts | 對應系統檔案與 security label |
| seapp_contexts | 對應 App 與其 domain |
| service_contexts | 對應 system service 名稱與 domain |
| property_contexts | 對應 system property 的安全屬性 |
圖 2:策略關聯概念圖
App (UID) ─▶ seapp_contexts ─▶ app_domain
System Service ─▶ service_contexts ─▶ system_domain
File Path ─▶ file_contexts ─▶ object_type
假設惡意應用想讀取相機 buffer:
app_123 (u:r:untrusted_app:s0)
→ 嘗試讀取 /dev/camera
Kernel 查詢 policy:
allow untrusted_app camera_device:chr_file read;
若 policy 無此項 → AVC (Access Vector Cache) 拒絕,logcat 顯示:
avc: denied { read } for pid=1234 comm="MyApp"
path="/dev/camera" scontext=u:r:untrusted_app:s0
tcontext=u:object_r:camera_device:s0
tclass=chr_file permissive=0
即使該 App 有 CAMERA 權限,也無法直接存取底層裝置檔案,必須透過 framework API 間接操作。
mediaserver、surfaceflinger、keystore、system_server 各自有獨立 domain:
即使其中之一被攻擊,也無法隨意干擾其他系統服務。
例如:mediaserver 無法直接讀取 /data/system/ 內的使用者設定。
| 模式 | 說明 |
|---|---|
| Permissive | 僅記錄違規行為,不阻擋 |
| Enforcing | 實際阻擋違規操作(Android 預設) |
可透過 adb shell getenforce 查看當前狀態。
adb logcat -b all | grep avc
或dmesg | grep avc
輸出中可看到:
假設開發者自訂 HAL 服務 /vendor/bin/hw/myhal:
type myhal, domain;
type myhal_exec, exec_type, file_type;
init_daemon_domain(myhal)
/vendor/bin/hw/myhal u:object_r:myhal_exec:s0
allow myhal self:capability { net_bind_service };
allow myhal system_data_file:dir search;
mmm system/sepolicy
adb shell ps -Z | grep myhal
三層安全防護模型
+---------------------------------------+
| 應用層:Runtime Permission |
| (檢查使用者授權) |
+---------------------------------------+
| Framework 層:PermissionManagerService |
| (授權決策、AppOps 檢查) |
+---------------------------------------+
| Kernel 層:SELinux + UID sandbox |
| (強制阻擋底層資源存取) |
+---------------------------------------+
| 防護層級 | 功能 | 例子 |
|---|---|---|
| App sandbox (UID) | 防止應用交叉讀取資料 | App A 無法讀取 App B 的資料夾 |
| Permission System | 控制 API 存取 | 需要 CAMERA 權限才能開啟鏡頭 |
| SELinux Policy | 防止底層繞過 API | 阻擋對 /dev/camera 的直接存取 |
這三層共同構成 Android 的安全閉環。
| Android 版本 | SELinux 狀態 | 主要改進 |
|---|---|---|
| 4.3 | 初次導入 | 僅 Audit 模式 |
| 4.4 | 部分服務 Enforcing | system_server 仍 permissive |
| 5.0 | 全面 Enforcing | 所有 system domain 強制 |
| 8.0 | Treble 分區化 Policy | 分離 /system /vendor policy |
| 10 | Scoped storage + Policy modularization | 降低誤殺風險 |
| 12 | User-space SELinux | 支援 userdebug 擴展 |
| 14 | 精簡化 App domain | 加強沙箱一致性 |
SELinux 不僅是「額外安全層」,而是 Android 信任模型的核心之一。
它確保即使 應用或系統進程被攻擊,仍受限於 Policy 規則,無法任意操作系統資源。
對開發者而言,理解 SELinux 是設計安全 HAL、Native Daemon、Vendor Service 的必要條件。
SELinux 在 Android 安全體系中的角色
+-----------------------------------------------------------+
| 應用層 (Permissions) |
| 應用請求 API → Framework 驗證 |
+-----------------------------------------------------------+
| 系統層 (SELinux Policy / AppOps) |
| 驗證 domain / type / context,控制 IPC、file、socket |
+-----------------------------------------------------------+
| Kernel 層 (Sandbox + Capability) |
| UID/GID 隔離 + Kernel Security Modules |
+-----------------------------------------------------------+
一句話總結:
Permission 決定「誰能申請」;SELinux 決定「申請了之後能不能真的做」。