自定義 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/公共。包括為在供應商特定策略中使用而導出的策略。一切都進入 Android 8.0兼容性基礎架構。公共策略旨在跨版本持續存在,因此您可以在自定義策略中包含任何/public內容。因此,可以放在/public中的策略類型受到更多限制。考慮這個平台的導出策略 API:任何處理/system/vendor之間的接口的東西都屬於這裡。
  • 系統/sepolicy/私有。包括系統映像運行所需的策略,但供應商映像策略不應該知道。
  • 系統/sepolicy/供應商。包括進入/vendor但存在於核心平台樹(不是特定於設備的目錄)中的組件的策略。這是構建系統區分設備和全局組件的產物;從概念上講,這是下面描述的特定於設備的策略的一部分。
  • 設備/ manufacturer / device-name /sepolicy 。包括特定於設備的策略。還包括對策略的設備自定義,在 Android 8.0 及更高版本中對應於供應商映像上的組件策略。

在 Android 11 及更高版本中,system_ext 和產品分區還可以包含特定於分區的策略。 system_ext 和 product 策略也分為 public 和 private,供應商可以使用 system_ext 和 product 的 public 策略,如係統策略。

  • 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 和 product 分區。使用 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導出的策略在此處可用,就像僅用於 vendor-image-only 擴展一樣。此策略是系統映像的一部分,可以在僅框架的 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 的一部分。