客製化SELinux

在整合基本層級的 SELinux 功能並徹底分析結果後,您可以新增自己的策略設定來覆寫 Android 作業系統的自訂。這些策略仍必須滿足Android 相容性計劃要求,且不得刪除預設的 SELinux 設定。

製造商不應刪除現有的 SELinux 政策。否則,他們將面臨破壞 Android SELinux 實現及其管理的應用程式的風險。這包括可能需要改進才能合規和運行的第三方應用程式。應用程式無需修改即可在支援 SELinux 的裝置上繼續運作。

當開始自訂 SELinux 時,請記住:

  • 為所有新守護程式編寫 SELinux 策略
  • 適當時使用預定義域
  • 將網域指派給任何作為init服務產生的進程
  • 在編寫策略之前熟悉宏
  • 向 AOSP 提交核心政策變更

並且記住不要:

  • 創建不相容的策略
  • 允許最終用戶策略定制
  • 允許 MDM 策略自訂
  • 用違反政策的行為嚇唬用戶
  • 添加後門

有關具體要求,請參閱Android 相容性定義文件核心安全功能部分。

SELinux 使用白名單方法,這意味著所有存取都必須在策略中明確允許才能被授予。由於 Android 的預設 SELinux 策略已經支援 Android 開源項目,因此您無需以任何方式修改 SELinux 設定。如果您確實自訂 SELinux 設置,請務必小心,不要破壞現有的應用程式。開始:

  1. 使用最新的Android核心
  2. 採用最小特權原則
  3. 僅解決您自己對 Android 的新增。預設策略自動與Android 開源專案程式碼庫配合使用。
  4. 將軟體元件劃分為執行單一任務的模組。
  5. 建立 SELinux 策略,將這些任務與不相關的功能隔離。
  6. 將這些策略放入/device/ manufacturer / device-name /sepolicy目錄中的*.te檔案(SELinux 策略來源檔案的副檔名)中,並使用BOARD_SEPOLICY變數將它們包含在您的建置中。
  7. 最初允許新域。這是透過在網域的.te檔案中使用授權聲明來完成的。
  8. 分析結果並完善您的網域定義。
  9. 當 userdebug 版本中不再出現進一步的拒絕時,刪除授權聲明。

整合 SELinux 策略變更後,請在開發工作流程中新增步驟,以確保未來的 SELinux 相容性。在理想的軟體開發過程中,SELinux 策略僅在軟體模型發生變化時發生變化,而不是實際實現發生變化。

當您開始自訂 SELinux 時,請先審核您對 Android 的新增內容。如果您新增了執行新功能的元件,請在開啟強制模式之前確保元件符合 Android 的安全性策略以及 OEM 制定的任何相關策略。

為了防止不必要的問題,最好是過於寬泛和過度相容,而不是過於限制和不相容,從而導致設備功能損壞。相反,如果您的變更將使其他人受益,您應該將對預設 SELinux 策略的修改作為補丁提交。如果修補程式已套用至預設安全性策略,則無需在每個新的 Android 版本中進行此變更。

政策聲明範例

SELinux 是基於M4電腦語言,因此支援各種巨集以節省時間。

在下列範例中,所有網域都被授予讀取或寫入/dev/null以及讀取/dev/zero存取權限。

# Allow read / write access to /dev/null
allow domain null_device:chr_file { getattr open read ioctl lock append write};

# Allow read-only access to /dev/zero
allow domain zero_device:chr_file { getattr open read ioctl lock };

可以使用 SELinux *_file_perms宏(簡寫)編寫相同的語句:

# Allow read / write access to /dev/null
allow domain null_device:chr_file rw_file_perms;

# Allow read-only access to /dev/zero
allow domain zero_device:chr_file r_file_perms;

政策範例

以下是 DHCP 策略的完整範例,我們將在下面進行研究:

type dhcp, domain;
permissive dhcp;
type dhcp_exec, exec_type, file_type;
type dhcp_data_file, file_type, data_file_type;

init_daemon_domain(dhcp)
net_domain(dhcp)

allow dhcp self:capability { setgid setuid net_admin net_raw net_bind_service
};
allow dhcp self:packet_socket create_socket_perms;
allow dhcp self:netlink_route_socket { create_socket_perms nlmsg_write };
allow dhcp shell_exec:file rx_file_perms;
allow dhcp system_file:file rx_file_perms;
# For /proc/sys/net/ipv4/conf/*/promote_secondaries
allow dhcp proc_net:file write;
allow dhcp system_prop:property_service set ;
unix_socket_connect(dhcp, property, init)

type_transition dhcp system_data_file:{ dir file } dhcp_data_file;
allow dhcp dhcp_data_file:dir create_dir_perms;
allow dhcp dhcp_data_file:file create_file_perms;

allow dhcp netd:fd use;
allow dhcp netd:fifo_file rw_file_perms;
allow dhcp netd:{ dgram_socket_class_set unix_stream_socket } { read write };
allow dhcp netd:{ netlink_kobject_uevent_socket netlink_route_socket
netlink_nflog_socket } { read write };

讓我們來剖析一下這個例子:

在第一行,類型宣告中,DHCP 守護程式繼承自基本安全性原則( domain )。從前面的語句範例中,DHCP 可以讀取和寫入/dev/null

在第二行中,DHCP 被識別為授權域。

init_daemon_domain(dhcp)行中,政策宣告 DHCP 由init產生並允許與其通訊。

net_domain(dhcp)行中,此政策允許 DHCP 使用net網域中的常見網路功能,例如讀取和寫入 TCP 封包、透過套接字進行通訊以及執行 DNS 請求。

allow dhcp proc_net:file write;此策略規定 DHCP 可以寫入/proc中的特定檔案。這一行示範了 SELinux 的細粒度文件標記。它使用proc_net標籤來限制僅對/proc/sys/net下的檔案進行寫入存取。

該範例的最後一個區塊以allow dhcp netd:fd use;描述如何允許應用程式彼此互動。此策略規定 DHCP 和 netd 可以透過檔案描述符、FIFO 檔案、資料封包套接字和 UNIX 流套接字相互通訊。 DHCP 只能讀取和寫入資料封包套接字和 UNIX 流套接字,而不能建立或開啟它們。

可用的控件

班級允許
文件
ioctl read write create getattr setattr lock relabelfrom relabelto append
unlink link rename execute swapon quotaon mounton
目錄
add_name remove_name reparent search rmdir open audit_access execmod
插座
ioctl read write create getattr setattr lock relabelfrom relabelto append bind
connect listen accept getopt setopt shutdown recvfrom sendto recv_msg send_msg
name_bind
檔案系統
mount remount unmount getattr relabelfrom relabelto transition associate
quotamod quotaget
過程
fork transition sigchld sigkill sigstop signull signal ptrace getsched setsched
getsession getpgid setpgid getcap setcap share getattr setexec setfscreate
noatsecure siginh setrlimit rlimitinh dyntransition setcurrent execmem
execstack execheap setkeycreate setsockcreate
安全
compute_av compute_create compute_member check_context load_policy
compute_relabel compute_user setenforce setbool setsecparam setcheckreqprot
read_policy
能力
chown dac_override dac_read_search fowner fsetid kill setgid setuid setpcap
linux_immutable net_bind_service net_broadcast net_admin net_raw ipc_lock
ipc_owner sys_module sys_rawio sys_chroot sys_ptrace sys_pacct sys_admin
sys_boot sys_nice sys_resource sys_time sys_tty_config mknod lease audit_write
audit_control setfcap

更多的

和更多

絕不允許規則

SELinux neverallow規則禁止不應該發生的行為。透過相容性測試,SELinux neverallow規則現在可以跨裝置強制執行。

以下指南旨在幫助製造商在定製過程中避免與neverallow規則相關的錯誤。此處使用的規則編號對應於 Android 5.1,並且可能會因版本而異。

規則 48: neverallow { domain -debuggerd -vold -dumpstate -system_server } self:capability sys_ptrace;
請參閱ptrace的手冊頁。 sys_ptrace功能授予對任何進程進行ptrace能力,這允許對其他進程進行大量控制,並且應該只屬於規則中概述的指定係統元件。對此功能的需求通常表示存在不適合面向使用者的建置或不必要的功能。刪除不需要的組件。

規則76: neverallow { domain -appdomain -dumpstate -shell -system_server -zygote } { file_type -system_file -exec_type }:file execute;
此規則旨在防止在系統上執行任意程式碼。具體來說,它斷言僅執行/system上的程式碼,這透過驗證啟動等機制提供了安全保證。通常,當遇到此neverallow規則的問題時,最佳解決方案是將有問題的程式碼移至/system分區。

在 Android 8.0+ 中自訂 SEPolicy

本部分提供 Android 8.0 及更高版本中供應商 SELinux 策略的指南,包括有關 Android 開源專案 (AOSP) SEPolicy 和 SEPolicy 擴充功能的詳細資訊。有關 SELinux 策略如何跨分區和 Android 版本保持兼容的更多信息,請參閱兼容性

政策投放

在 Android 7.0 及更早版本中,裝置製造商可以向BOARD_SEPOLICY_DIRS添加策略,包括旨在跨不同裝置類型增強 AOSP 策略的策略。在 Android 8.0 及更高版本中,將策略新增至BOARD_SEPOLICY_DIRS只會將該策略放置在供應商映像中。

在 Android 8.0 及更高版本中,策略存在於 AOSP 中的以下位置:

  • 系統/sepolicy/public 。包括導出用於特定於供應商的策略的策略。一切都融入 Android 8.0相容性基礎架構中。公共政策旨在跨版本持續存在,因此您可以在自訂政策中包含任何/public 。因此,可以放置在/public中的策略類型受到更多限制。考慮平台的匯出策略 API:任何處理/system/vendor之間介面的內容都屬於這裡。
  • 系統/sepolicy/私有。包括系統映像運作所必需的策略,但供應商映像策略不應了解這些策略。
  • 系統/sepolicy/供應商。包括進入/vendor但存在於核心平台樹(不是特定於設備的目錄)中的元件的策略。這是建構系統區分設備和全域組件的產物;從概念上講,這是下面描述的設備特定策略的一部分。
  • 設備/ manufacturer / device-name /sepolicy 。包括特定於設備的策略。還包括對策略的裝置自訂,這在 Android 8.0 及更高版本中對應於供應商映像上元件的策略。

在 Android 11 及更高版本中,system_ext 和產品分區還可以包含特定於分區的策略。 system_ext和產品策略也分為公有和私有,供應商可以使用system_ext和產品的公共策略,就像系統策略一樣。

  • SYSTEM_EXT_PUBLIC_SEPOLICY_DIRS 。包括導出用於特定於供應商的策略的策略。安裝到system_ext分區。
  • SYSTEM_EXT_PRIVATE_SEPOLICY_DIRS 。包括 system_ext 映像運行所需的策略,但供應商映像策略不應了解這些策略。安裝到system_ext分區。
  • PRODUCT_PUBLIC_SEPOLICY_DIRS 。包括導出用於特定於供應商的策略的策略。安裝到產品分割區。
  • PRODUCT_PRIVATE_SEPOLICY_DIRS 。包括產品映像運作所必需的策略,但供應商映像策略不應了解這些策略。安裝到產品分割區。
注意:使用GSI時,OEM的system_ext和產品分區將不會被掛載。使用 OEM 的 system_ext 和產品公共政策的供應商 sepolicy 中的規則將變為 NOP,因為缺少 OEM 特定的類型定義。
注意:使用 system_ext 和產品公共策略時要格外小心。公共策略充當 system_ext/product 和供應商之間的導出 API。合作夥伴應該自行管理相容性問題。

支持的政策場景

在搭載 Android 8.0 及更高版本的裝置上,供應商映像必須與 OEM 系統映像和 Google 提供的參考 AOSP 系統映像搭配使用(並在此參考映像上傳遞 CTS)。這些要求確保框架和供應商代碼之間的清晰分離。此類設備支援以下場景。

僅供應商圖像擴展

範例:從供應商映像向vndservicemanager新增服務,以支援供應商映像中的進程。

與使用先前的 Android 版本啟動的裝置一樣,請在device/ manufacturer / device-name /sepolicy中新增裝置特定的自訂。管理供應商元件如何(僅)與其他供應商元件互動的新策略應涉及僅在device/ manufacturer / device-name /sepolicy中存在的類型。此處編寫的策略允許供應商上的程式碼運行,不會作為僅框架 OTA 的一部分進行更新,並且將出現在具有參考 AOSP 系統映像的裝置上的組合策略中。

與 AOSP 搭配使用的供應商映像支持

範例:新增一個實作 AOSP 定義的 HAL 的新進程(從供應商映像註冊到hwservicemanager )。

與使用先前的 Android 版本啟動的裝置一樣,在device/ manufacturer / device-name /sepolicy中執行裝置特定的自訂。作為system/sepolicy/public/的一部分導出的策略可供使用,並作為供應商策略的一部分提供。公共策略中的類型和屬性可以用在新規則中,規定與新供應商特定位的交互,但須遵守所提供的neverallow限制。與僅供應商的情況一樣,此處的新策略不會作為僅框架 OTA 的一部分進行更新,並將出現在具有參考 AOSP 系統映像的裝置上的組合策略中。

僅系統映像擴充

範例:新增一個新服務(在 servicemanager 中註冊),該服務只能由系統映像中的其他進程存取。

將此原則新增至system/sepolicy/private 。您可以新增額外的進程或物件來啟用合作夥伴系統映像中的功能,前提是這些新位元不需要與供應商映像上的新元件互動(具體來說,此類進程或物件必須在沒有供應商映像策略的情況下完全運行) 。由system/sepolicy/public匯出的政策可在此使用,就像僅適用於供應商映像擴充功能一樣。此策略是系統映像的一部分,可以在僅框架 OTA 中更新,但在使用參考 AOSP 系統映像時不會出現。

為擴展 AOSP 組件提供服務的供應商映像擴展

範例:一個新的非 AOSP HAL,供 AOSP 系統映像中也存在的擴充客戶端(例如擴充的 system_server)使用。

系統和供應商之間的互動策略必須包含在供應商分區上提供的device/ manufacturer / device-name /sepolicy目錄中。這與上述新增供應商映像支援以使用參考 AOSP 映像的情況類似,但修改後的 AOSP 元件可能還需要額外的策略才能與系統分割區的其餘部分正確操作(只要它們仍然存在,就可以了)有公共AOSP 類型標籤)。

公用 AOSP 元件與僅有系統映像擴充的互動策略應位於system/sepolicy/private

僅存取 AOSP 介面的系統映像擴展

範例:新的非 AOSP 系統進程必須存取 AOSP 所依賴的 HAL。

這與僅系統映像擴充範例類似,只是新的系統元件可以跨system/vendor介面進行互動。新系統元件的政策必須放入system/sepolicy/private中,只要它是透過 AOSP 已在system/sepolicy/public中建立的介面(即功能所需的類型和屬性都在那裡),這是可以接受的。雖然策略可以包含在特定於裝置的策略中,但由於僅框架更新,它將無法使用其他system/sepolicy/private類型或變更(以任何影響策略的方式)。該策略可能會在僅限框架的 OTA 中更改,但在使用 AOSP 系統映像(也不會具有新的系統元件)時不會出現。

為新系統元件提供服務的供應商映像擴展

範例:新增一個新的非 AOSP HAL,供沒有 AOSP 類似物的客戶端進程使用(因此需要自己的網域)。

AOSP 擴充範例類似,系統和供應商之間的互動策略必須位於供應商分區上附帶的device/ manufacturer / device-name /sepolicy目錄中(以確保系統策略不了解供應商特定的詳細資訊)。您可以新增的公用類型來擴充system/sepolicy/public中的策略;這只能在現有 AOSP 政策的基礎上進行,即不要刪除 AOSP 公共政策。然後,新的公共類型可用於system/sepolicy/privatedevice/ manufacturer / device-name /sepolicy中的政策。

請記住,對system/sepolicy/public的每個新增功能都增加了複雜性,因為它暴露了必須在映射檔案中追蹤的新相容性保證,並且受到其他限制。 system/sepolicy/public中只能新增新的類型和對應的允許規則;不支援屬性和其他策略聲明。此外,新的公共類型不能用於直接標記/vendor策略中的物件。

不支持的政策情景

搭載 Android 8.0 及更高版本的裝置不支援以下策略場景和範例。

在僅框架 OTA 之後需要對新供應商映像組件進行許可的系統映像的其他擴展

範例:在下一個 Android 版本中新增了一個新的非 AOSP 系統進程,需要自己的網域,並且需要存取新的非 AOSP HAL。

新的(非 AOSP)系統和供應商組件互動類似,不同之處在於新的系統類型是在純框架 OTA 中引入的。儘管可以將新類型新增至system/sepolicy/public中的策略中,但現有供應商策略不了解新類型,因為它僅追蹤 Android 8.0 系統公共策略。 AOSP 透過透過屬性(例如hal_foo屬性)公開供應商提供的資源來處理此問題,但由於system/sepolicy/public不支援屬性合作夥伴擴展,因此供應商策略無法使用此方法。訪問必須由先前存在的公共類型提供。

範例:對系統進程(AOSP 或非 AOSP)的變更必須改變它與新的非 AOSP 供應商元件的互動方式。

系統映像上的策略必須在不了解特定供應商自訂的情況下編寫。因此,有關 AOSP 中特定介面的策略透過 system/sepolicy/public 中的屬性公開,以便供應商策略可以選擇加入使用這些屬性的未來系統策略。但是,不支援system/sepolicy/public中的屬性擴展,因此規定係統組件如何與新供應商組件互動的所有策略(並且不由 AOSP system/sepolicy/public中已有的屬性處理)必須位於device/ manufacturer / device-name /sepolicy 。這意味著系統類型無法變更作為純框架 OTA 一部分的供應商類型所允許的存取權限。