SELinux 預設為拒絕存取,也就是說,凡是核心中設有掛鉤的存取要求,都必須由政策明確允許。也就是說,政策檔案包含大量有關規則、類型、類別、權限等的資訊。本文件不會完整探討 SELinux,但現在推出新的 Android 裝置時,瞭解如何編寫政策規則至關重要。目前已有大量關於 SELinux 的資訊。如需建議資源,請參閱支援文件。
金鑰檔案
如要啟用 SELinux,請整合最新版 Android 核心,然後併入 system/sepolicy 目錄中的檔案。編譯後,這些檔案會組成 SELinux 核心安全政策,涵蓋上游 Android 作業系統。
一般來說,您不應直接修改 system/sepolicy
檔案。請改為在 /device/manufacturer/device-name/sepolicy
目錄中新增或編輯裝置專屬的政策檔案。在 Android 8.0 以上版本中,您對這些檔案所做的變更只會影響供應商目錄中的政策。如要進一步瞭解 Android 8.0 以上版本中公用 SEPolicy 的分離情形,請參閱「在 Android 8.0 以上版本中自訂 SEPolicy」。無論 Android 版本為何,您仍會修改下列檔案:
政策檔案
結尾為 *.te
的檔案是 SELinux 政策來源檔案,用於定義網域及其標籤。您可能需要在 /device/manufacturer/device-name/sepolicy
中建立新的政策檔案,但請盡可能更新現有檔案。
環境檔案
您可以在內容檔案中指定物件的標籤。
file_contexts
會將標籤指派給檔案,並由各種使用者空間元件使用。建立新政策時,請建立或更新這個檔案,為檔案指派新標籤。如要套用新的file_contexts
,請重建檔案系統映像檔,或對要重新標記的檔案執行restorecon
。升級時,系統會自動將file_contexts
的變更套用至系統和使用者資料分割區,做為升級程序的一部分。升級至其他分割區時,也可以自動套用變更,方法是在分割區以讀寫模式掛接後,將restorecon_recursive
呼叫新增至 init.board.rc 檔案。genfs_contexts
會將標籤指派給不支援擴充屬性的檔案系統,例如proc
或vfat
。這項設定會載入為核心政策的一部分,但變更可能不會對核心內 inode 生效,因此需要重新啟動,或是卸載並重新掛接檔案系統,才能完全套用變更。特定掛接點也可以指派特定標籤,例如使用context=mount
選項。vfat
property_contexts
會將標籤指派給 Android 系統屬性,藉此控管哪些程序可以設定這些屬性。啟動期間,init
程序會讀取這項設定。service_contexts
會將標籤指派給 Android 繫結器服務,藉此控管哪些程序可以新增 (註冊) 及尋找 (查閱) 服務的繫結器參照。啟動期間,servicemanager
程序會讀取這項設定。seapp_contexts
會將標籤指派給應用程式程序和/data/data
目錄。每次啟動應用程式時,zygote
程序都會讀取這項設定,installd
則會在啟動期間讀取這項設定。mac_permissions.xml
會根據應用程式的簽章 (以及套件名稱,如果有的話) 指派seinfo
標記。然後,您可以在seapp_contexts
檔案中將seinfo
標記做為鍵,為所有具有該seinfo
標記的應用程式指派特定標籤。啟動期間,system_server
會讀取這項設定。keystore2_key_contexts
將標籤指派給 Keystore 2 命名空間。 這些命名空間是由keystore2
精靈強制執行。Keystore 一直以來都提供以 UID/AID 為基礎的命名空間。此外,Keystore 2 還會強制執行 sepolicy 定義的命名空間。如要詳細瞭解這個檔案的格式和慣例,請參閱這篇文章。
BoardConfig.mk Makefile
編輯或新增政策和內容檔案後,請更新
/device/manufacturer/device-name/BoardConfig.mk
makefile,以參照 sepolicy
子目錄和每個新政策檔案。
如要進一步瞭解 BOARD_SEPOLICY
變數,請參閱
system/sepolicy/README
檔案。
BOARD_SEPOLICY_DIRS += \ <root>/device/manufacturer/device-name/sepolicy BOARD_SEPOLICY_UNION += \ genfs_contexts \ file_contexts \ sepolicy.te
重建完成後,裝置就會啟用 SELinux。現在您可以自訂 SELinux 政策,以配合您在 Android 作業系統中新增的項目 (如「自訂」一節所述),也可以驗證現有設定 (如「驗證」一節所述)。
新的政策檔案和 BoardConfig.mk 更新完成後,系統會自動將新的政策設定建構至最終核心政策檔案。如要進一步瞭解如何在裝置上建構 sepolicy,請參閱「建構 sepolicy」。
實作
如要開始使用 SELinux,請按照下列步驟操作:
- 在核心中啟用 SELinux:
CONFIG_SECURITY_SELINUX=y
- 變更 kernel_cmdline 或 bootconfig 參數,以便:
或BOARD_KERNEL_CMDLINE := androidboot.selinux=permissive
這項設定僅適用於裝置的初始政策開發。取得初始啟動程序政策後,請移除這個參數,確保裝置強制執行政策,否則 CTS 會失敗。BOARD_BOOTCONFIG := androidboot.selinux=permissive
- 以寬容模式啟動系統,並查看啟動時遇到的拒絕:
在 Ubuntu 14.04 以上版本: 在 Ubuntu 12.04 上:adb shell su -c dmesg | grep denied | audit2allow -p out/target/product/BOARD/root/sepolicy
adb pull /sys/fs/selinux/policy adb logcat -b all | audit2allow -p policy
- 評估輸出內容,找出類似
init: Warning! Service name needs a SELinux domain defined; please fix!
的警告。如需操作說明和工具,請參閱「驗證」。 - 找出需要標籤的裝置和其他新檔案。
- 為物件使用現有或新的標籤。查看
*_contexts
檔案,瞭解先前的標籤,並根據標籤的含義指派新標籤。理想情況下,這是符合政策的現有標籤,但有時需要新標籤,且需要該標籤的存取權規則。將標籤新增至適當的環境檔案。 - 找出應有專屬安全網域的網域/程序。
您可能需要為每個應用程式撰寫全新的政策。舉例來說,從
init
衍生的所有服務都應有自己的 下列指令可協助找出仍在執行的服務 (但所有服務都需要這類處理方式):adb shell su -c ps -Z | grep init
adb shell su -c dmesg | grep 'avc: '
- 查看
init.device.rc
,找出沒有網域類型的網域。在開發程序初期提供網域,避免在init
中新增規則,或以其他方式混淆init
存取權與自有政策中的存取權。 - 將
BOARD_CONFIG.mk
設為使用BOARD_SEPOLICY_*
變數。如要瞭解如何設定,請參閱system/sepolicy
中的 README。 - 檢查 init.device.rc 和 fstab.device 檔案,並確認每個
mount
都對應到正確標示的檔案系統,或已指定context= mount
選項。 - 逐一查看每個拒絕項目,並建立 SELinux 政策,妥善處理每個項目。請參閱「自訂」一文中的範例。
您應先從 AOSP 中的政策著手,然後根據自己的自訂項目建構政策。如要進一步瞭解政策策略,並深入瞭解其中一些步驟,請參閱「撰寫 SELinux 政策」。
用途
以下是設計軟體和相關聯 SELinux 政策時,應考量的具體攻擊範例:
符號連結:符號連結會顯示為檔案,因此經常會被讀取為檔案,可能導致遭到攻擊。舉例來說,部分具備特殊權限的元件 (例如 init
) 會變更特定檔案的權限,有時會過度開放。
攻擊者可能會將這些檔案替換為他們控制的程式碼符號連結,藉此覆寫任意檔案。但如果您知道應用程式絕不會遍歷符號連結,可以使用 SELinux 禁止應用程式執行這項操作。
系統檔案:請考慮系統檔案類別,這類檔案只能由系統伺服器修改。不過,由於 netd
、init
和 vold
會以根層級執行,因此可以存取這些系統檔案。因此,如果 netd
遭到入侵,可能會連帶影響這些檔案,甚至可能入侵系統伺服器。
有了 SELinux,您就能將這些檔案識別為系統伺服器資料檔案。因此,只有系統伺服器有權讀取/寫入這些檔案。即使 netd
遭到入侵,也無法將網域切換至系統伺服器網域,並存取這些系統檔案 (即使是以根身分執行)。
應用程式資料:另一個例子是必須以根身分執行的函式類別,但不應存取應用程式資料。這項功能非常實用,因為您可以做出各種斷言,例如禁止與應用程式資料無關的特定網域存取網際網路。
setattr:對於 chmod
和 chown
等指令,您可以找出相關聯網域可執行 setattr
的檔案集。即使是根層級,也可能無法透過這些變更存取該範圍以外的任何內容。因此,應用程式可能會針對標示為 app_data_files
的項目執行 chmod
和 chown
,但不會針對 shell_data_files
或 system_data_files
執行。