selinux-實現

實現 SELinux

SELinux 設爲了“默認拒絕”模式,也就是說,對於在內核中存在鉤子的每一次訪問,都必須獲得政策的明確許可。這意味着政策文件中包含規則、類型、類、權限等方面的大量信息。關於 SELinux 的完整注意事項不在本文檔的討論範圍之內,現在您必須要瞭解的是在啓動新的 Android 設備時如何編寫政策規則。目前有大量關於 SELinux 的信息可供您參考。關於建議的資源,請參閱支持文檔

步驟總結

下面簡要總結了在 Android 設備上實現 SELinux 時需要執行的步驟:

  1. 在內核和配置中添加 SELinux 支持。
  2. 爲通過 init 啓動的每項服務(進程或守護進程)分配專用的域。
  3. 通過以下方式標識這些服務:
    • 查看 init.<device>.rc 文件並找到所有服務。
    • 檢查 dmesg 輸出中以下形式的警告:“init: Warning! Service name needs a SELinux domain defined; please fix!”(init:警告!服務名稱需要一個已定義的 SELinux 域;請更正!)。
    • 檢查 ps -Z | grep init 輸出,看看哪些服務正在 init 域中運行。
  4. 爲所有新進程、驅動程序、套接字等添加標籤。需要爲所有對象添加適當的標籤,以確保它們能夠與您應用的政策正確交互。請參閱 AOSP 中使用的標籤,以便在創建標籤名稱時參考。
  5. 制定全面涵蓋所有標籤的安全政策,並將權限限定到其絕對最低級別。

原始設備製造商 (OEM) 最好從 AOSP 中的政策入手,然後在這些政策的基礎上創建自己的自定義政策。

關鍵文件

SELinux for Android 隨附了立即啓用 SELinux 所需的一切。您只需集成最新的 Android 內核,然後整合 system/sepolicy目錄中的文件即可:

https://android.googlesource.com/kernel/common/

https://android.googlesource.com/platform/system/sepolicy/

這些文件在編譯後會包含 SELinux 內核安全政策,並涵蓋上游 Android 操作系統。您應該不需要直接修改 system/sepolicy 中的文件,而只需添加您自己的設備專用政策文件(位於 /device/manufacturer/device-name/sepolicy 目錄中)即可。

要實現 SELinux,您必須創建或修改以下文件:

  • 新的 SELinux 政策源代碼 (*.te) 文件 - 位於 /device/manufacturer/device-name/sepolicy 目錄中。這些文件用於定義域及其標籤。在編譯到單個 SELinux 內核政策文件時,新的政策文件會與現有的政策文件組合在一起。

    重要提示:請勿更改 Android 開放源代碼項目提供的 app.te 文件,否則可能會破壞所有第三方應用。

  • 更新後的 BoardConfig.mk Makefile - 位於包含 sepolicy 子目錄的目錄中。如果初始實現中沒有 sepolicy 子目錄,那麼在該子目錄創建之後,必須更新 BoardConfig.mk makefile,以引用該子目錄。
  • file_contexts - 位於 sepolicy 子目錄中。該文件用於爲文件分配標籤,並且可供多種用戶空間組件使用。在創建新政策時,請創建或更新該文件,以便爲文件分配新標籤。要應用新的 file_contexts,您必須重新構建文件系統映像,或對要重新添加標籤的文件運行 restorecon。在升級時,對 file_contexts 所做的更改會在升級過程中自動應用於系統和用戶數據分區。此外,還可以通過以下方式使這些更改在升級過程中自動應用於其他分區:在以允許讀寫的方式裝載相應分區後,將 restorecon_recursive 調用添加到 init.board.rc 文件中。
  • genfs_contexts - 位於 sepolicy 子目錄中。該文件用於爲不支持擴展屬性的文件系統(例如,proc 或 vfat)分配標籤。此配置會作爲內核政策的一部分進行加載,但更改可能對核心內 inode 無效。要全面應用更改,需要重新啓動設備,或卸載後重新裝載文件系統。此外,通過使用 context=mount 選項,還可以爲裝載的特定系統文件(例如 vfat)分配特定標籤。
  • property_contexts - 位於 sepolicy 子目錄中。該文件用於爲 Android 系統屬性分配標籤,以便控制哪些進程可以設置這些屬性。在啓動期間以及 selinux.reload_policy 屬性每次被設爲 1 時,init 進程都會讀取此配置。
  • service_contexts - 位於 sepolicy 子目錄中。該文件用於爲 Android Binder 服務分配標籤,以便控制哪些進行可以爲相應服務添加(註冊)和查找(查詢)Binder 引用。在啓動期間以及 selinux.reload_policy 屬性每次被設爲 1 時,servicemanager 進程都會讀取此配置。
  • seapp_contexts - 位於 sepolicy 子目錄中。該文件用於爲應用進程和 /data/data 目錄分配標籤。在每次應用啓動時,Zygote 進程都會讀取此配置;在啓動期間以及 selinux.reload_policy 屬性每次被設爲 1 時,installd 都會讀取此配置。
  • mac_permissions.xml - 位於 sepolicy 子目錄中。該文件用於根據應用簽名和應用軟件包名稱(後者可選)爲應用分配 seinfo 標記。然後,分配的 seinfo 標記可在 seapp_contexts 文件中用作密鑰,以便爲帶有該 seinfo 標記的所有應用分配特定標籤。在啓動期間,system_server 會讀取此配置。

接下來,只需在 sepolicy 子目錄和各個政策文件創建之後,更新 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

注意:從 M 版開始已不再需要 BOARD_SEPOLICY_UNION,因爲 BOARD_SEPOLICY_DIRS 變量中包含的任何目錄內的所有政策文件都會與基本政策自動合併。

設備在重新編譯後會啓用 SELinux。現在,您可以根據自己向 Android 操作系統添加的內容自定義自己的 SELinux 政策(如自定義中所述),也可以驗證您的現有設置(如驗證中所述)。

在新政策文件和 BoardConfig.mk 更新部署到位後,新政策設置會立即自動內置到最終的內核政策文件中。

用例

下面列舉了一些在開發軟件以及制定關聯的 SELinux 政策時需要注意的具體漏洞:

符號鏈接 - 由於符號鏈接以文件形式顯示,因此通常也是作爲文件被讀取。這可能會導致漏洞。例如,某些特權組件(例如 init)會更改某些文件的權限,有時會使之極度開放。

這樣一來,攻擊者便可以將這些文件替換成指向其控制的代碼的符號鏈接,從而重寫任意文件。但如果您知道自己的應用絕不會遍歷符號鏈接,則可以通過 SELinux 來禁止您的應用遍歷符號鏈接。

系統文件 - 以應該只有系統服務器可以修改的一系列系統文件爲例。由於 netd、init 和 vold 是以 Root 身份運行的,因此它們也可以訪問這些系統文件。這樣一來,如果 netd 遭到入侵,它將可以入侵這些文件,並可能會入侵系統服務器本身。

藉助 SELinux,您可以將這些文件標識爲系統服務器數據文件。這樣一來,系統服務器就是唯一對這些文件具有讀寫權限的域。即使 netd 遭到入侵,它也無法將域切換到系統服務器域並訪問這些系統文件,就算它是以 Root 身份運行的也是如此。

應用數據 - 另一個示例是必須以 Root 身份運行但不應獲得應用數據訪問權限的一系列函數。這非常有用,因爲可以做出廣泛的聲明,例如禁止與應用數據無關的特定域訪問互聯網。

setattr - 對於 chmod、chown 等命令,您可以標識關聯域可以在哪些文件中進行 setattr 操作。這樣一來,便可以禁止對這些文件之外的任何文件進行此類更改,即使以 Root 身份進行也不例外。因此,應用可以對帶 app_data_files 標籤的文件運行 chmod 和 chown 命令,但不能對帶 shell_data_files 或 system_data_files 標籤的文件運行這些命令。

詳細步驟

下面詳細介紹了 Android 建議您如何採用並自定義 SELinux 來保護設備:

  1. 在內核中啓用 SELinux: CONFIG_SECURITY_SELINUX=y
  2. 更改 kernel_cmdline 參數,以便:
    BOARD_KERNEL_CMDLINE := androidboot.selinux=permissive。 
    這僅適用於初始制定設備政策的情況。在擁有初始引導程序政策後,請移除此參數,以便將設備恢復強制模式,否則設備將無法通過 CTS 驗證。
  3. 以寬容模式啓動系統,看看在啓動時會遇到哪些拒絕事件:
    在 Ubuntu 14.04 或更高版本中:
    adb shell su -c dmesg | grep denied | audit2allow -p out/target/product/board/root/sepolicy 
    在 Ubuntu 12.04 中: adb shell su -c dmesg | grep denied | audit2allow
  4. 評估輸出。如需查看相關說明和工具,請參閱驗證
  5. 標識設備以及需要添加標籤的其他新文件。
  6. 爲您的對象使用現有標籤或新標籤。查看 *_contexts 文件,瞭解之前是如何爲內容添加標籤的,然後根據對標籤含義的瞭解分配一個新標籤。這最好是一個能夠融入到政策中的現有標籤,但有時需要使用新標籤,並且還需要關於訪問該標籤的規則。
  7. 標識應該擁有自己的安全域的域/進程。可能需要爲其中每個域/進程從頭開始編寫政策。例如,從 init 衍生的所有服務都應該有自己的安全域。可以通過以下命令查看保持運行的服務(不過所有服務都需要如此處理):
    $ adb shell su -c ps -Z | grep init
    $ adb shell su -c dmesg | grep 'avc: '
  8. 查看 init.<device>.rc,以找出所有沒有類型的服務。應提早爲此類服務提供域,以避免向 init 添加規則或將 init 訪問權限與其自身政策中的訪問權限混淆。
  9. 將 BOARD_CONFIG.mk 設爲使用 BOARD_SEPOLICY_* 變量。如需關於如何進行此項設置的詳細信息,請參閱 system/sepolicy 中的 README。
  10. 檢查 init.<device>.rc 和 fstab.<device> 文件,確保每一次使用“mount”都對應一個添加了適當標籤的文件系統,或者指定了 context= mount 選項。
  11. 查看每個拒絕事件,並創建 SELinux 政策來妥善處理每個拒絕事件。請參閱自定義中的示例。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章