自定義 SELinux
集成這一基本級別的功能並全面分析結果後,您可以添加自己的政策設置,以便涵蓋自己對 Android 操作系統進行的自定義。當然,這些政策仍必須要滿足 Android 兼容性計劃的要求,並且不會移除默認的 SELinux 設置。
製造商不得移除現有的安全設置,否則可能會破壞 Android SELinux 實現及其管控的應用。這包括可能需要進行改進以符合政策並正常運行的第三方應用。應用必須無需進行任何修改即可繼續在啓用了 SELinux 的設備上正常運行。
當開始着手自定義 SELinux 時,製造商應記得做以下事情:
- 爲所有新的守護進程編寫 SELinux 政策
- 儘可能使用預定義的域
- 爲作爲
init
服務衍生的所有進程分配域 - 在編寫政策之前先熟悉相關的宏
- 向 AOSP 提交對核心政策進行的更改
不要做以下事情:
- 創建不兼容的政策
- 允許對最終用戶政策進行自定義
- 允許對 MDM 政策進行自定義
- 恐嚇違反政策的用戶
- 添加後門程序
如需查看具體要求,請參閱 Android 兼容性定義文檔中的“內核安全功能”部分。
SELinux 採用白名單方法,這意味着只能授予政策中明確允許的訪問權限。由於 Android 的默認 SELinux 政策已經支持 Android 開放源代碼項目,因此原始設備製造商 (OEM) 無需以任何方式修改 SELinux 設置。如果他們要自定義 SELinux 設置,則應格外謹慎,以免破壞現有應用。以下是我們建議的做法:
- 使用最新的 Android 內核。
- 採用最小權限原則。
- 僅針對您向 Android 添加的內容調整 SELinux 政策。默認政策能夠自動適用於 Android 開放源代碼項目代碼庫。
- 將各個軟件組件拆分成多個負責執行單項任務的模塊。
- 創建用於將這些任務與無關功能隔離開來的 SELinux 政策。
- 將這些政策放在
/device/manufacturer/device-name/sepolicy
目錄中的 *.te 文件(te 是 SELinux 政策源代碼文件使用的擴展名)內,然後使用BOARD_SEPOLICY
變量將它們納入到您的版本中。 - 先將新域設爲寬容域。通過在相應域的 .te 文件中使用寬容聲明,可以做到這一點。
- 分析結果並優化域定義。
- 當 userdebug 版本中不再出現拒絕事件時,移除寬容聲明。
集成工作完成後,原始設備製造商 (OEM) 的 Android 開發過程還應包含一個確保向前兼容 SELinux 的步驟。在理想的軟件開發過程中,僅當軟件模型發生變化時,SELinux 政策才需要進行更改,而當實際實現發生變化時,SELinux 政策將不需要進行更改。
當設備製造商開始自定義 SELinux 時,他們應首先審覈自己向 Android 添加的內容。如果他們添加了執行新功能的組件,在開啓強制模式之前,他們需要先確認該組件是否符合 Android 採用的安全政策,以及原始設備製造商 (OEM) 制定的所有相關政策。
爲了防止出現不必要的問題,過度寬泛和過度兼容要好於過度限制和不兼容,後者會導致設備功能損壞。不過,如果製造商進行的更改能夠惠及其他人,則應將這些更改作爲補丁程序提供給默認 SELinux 政策。如果相應補丁程序已應用於默認安全政策,製造商將不再需要針對每個新的 Android 版本進行此項更改。
政策聲明示例
首先請注意,SELinux 基於 M4 計算機語言,因此支持多種有助於節省時間的宏。
在以下示例中,所有域都被授予從 /dev/null
讀取數據或向其寫入數據的權限以及從 /dev/zero
讀取數據的權限。
可以使用 SELinux *_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
標籤來限定 DHCP 僅對 /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 |
更多 |
還有更多 |
neverallow 規則
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
分區。