本頁說明 Android 如何處理平台無線 (OTA) 更新的政策相容性問題,因為新的平台 SELinux 設定可能與舊的供應商 SELinux 設定不同。
物件擁有權和標籤
每個物件都必須明確定義擁有權,才能將平台和供應商政策分開。舉例來說,如果供應商政策標籤 /dev/foo 和平台政策標籤 /dev/foo 在後續的 OTA 中,有未定義的行為 (例如意外拒絕),或更嚴重的是啟動失敗,在 SELinux 中,這會顯示為標籤衝突。裝置節點只能有一個標籤,該標籤會解析為最後套用的標籤。因此:
- 需要存取未成功套用標籤的程序會失去資源存取權。
- 取得檔案存取權的程序可能會中斷,因為建立的裝置節點有誤。
凡是具有 SELinux 標籤的物件 (包括屬性、服務、程序、檔案和通訊端),都可能發生平台與供應商標籤之間的衝突。為避免發生這些問題,請清楚定義這些物件的擁有權。
型別/屬性命名空間
除了標籤衝突外,SELinux 類型和屬性名稱也可能發生衝突。SELinux 不允許重複宣告相同型別和屬性。如果政策含有重複的聲明,編譯就會失敗。為避免型別和屬性名稱發生衝突,強烈建議所有供應商宣告都以 vendor_ 前置半形字元開頭。舉例來說,供應商應使用 type vendor_foo, domain;,而非 type foo, domain;。
檔案擁有權
由於平台和供應商政策通常會為所有檔案系統提供標籤,因此要避免檔案發生衝突並不容易。與型別命名不同,檔案的命名空間並不實用,因為其中許多檔案都是由核心建立。為避免發生這類衝突,請按照本節的檔案系統命名指引操作。如果是 Android 8.0,這些是建議,並無技術上的強制規定。日後,供應商測試套件 (VTS) 將會強制執行這些建議。
系統 (/system)
只有系統映像檔必須透過 file_contexts、service_contexts 等為 /system 元件提供標籤。如果在供應商政策中加入 /system 元件的標籤,可能無法進行僅限架構的 OTA 更新。
供應商 (/vendor)
AOSP SELinux 政策已標記平台互動的 vendor 分區部分,因此可為平台程序編寫 SELinux 規則,以便與 vendor 分區部分通訊或存取這些部分。範例:
| /vendor path | 平台提供的標籤 | 平台程序 (視標籤而定) |
|---|---|---|
/vendor(/.*)?
|
vendor_file
|
架構中的所有 HAL 用戶端,例如 ueventd。
|
/vendor/framework(/.*)?
|
vendor_framework_file
|
dex2oat、appdomain 等。
|
/vendor/app(/.*)?
|
vendor_app_file
|
dex2oat、installd、idmap 等。
|
/vendor/overlay(/.*)
|
vendor_overlay_file
|
system_server、zygote、idmap 等。
|
因此,在 vendor 分區中標記其他檔案時,必須遵守特定規則 (透過 neverallows 強制執行):
vendor_file必須是vendor分區中所有檔案的預設標籤。平台政策規定必須這樣做,才能存取直通 HAL 實作項目。- 透過供應商政策在
vendor分區中新增的所有exec_types都必須具備vendor_file_type屬性。這項限制會透過 neverallow 強制執行。 - 為避免日後與平台/架構更新發生衝突,請勿在
vendor分區中標記exec_types以外的檔案。 - 針對 AOSP 識別的相同程序 HAL,所有程式庫依附元件都必須標示為
same_process_hal_file.
Procfs (/proc)
/proc 中的檔案只能使用 genfscon 標籤標示。在 Android 7.0 中,平台和供應商政策都使用 genfscon 為 procfs 中的檔案加上標籤。
建議:僅限平台政策標籤 /proc。
如果供應商程序需要存取 /proc 中的檔案,且這些檔案目前標示為預設標籤 (proc),供應商政策不應明確標示這些檔案,而應使用一般 proc 類型,為供應商網域新增規則。這樣一來,平台更新就能配合日後透過 procfs 公開的 Kernel 介面,並視需要明確標示。
Debugfs (/sys/kernel/debug)
Debugfs 可在 file_contexts 和 genfscon 中加上標籤。在 Android 7.0 至 Android 10 中,平台和供應商標籤都是 debugfs。
在 Android 11 中,debugfs 無法在正式版裝置上存取或掛接。裝置製造商應移除 debugfs。
Tracefs (/sys/kernel/debug/tracing)
Tracefs 可在 file_contexts 和 genfscon 中加上標籤。在 Android 7.0 中,只有平台標籤 tracefs。
建議:只有平台可以標示 tracefs。
Sysfs (/sys)
/sys 中的檔案可能會同時使用 file_contexts 和 genfscon 標示。在 Android 7.0 中,平台和供應商都會使用 genfscon 為 sysfs 中的檔案加上標籤。
建議:平台可能會標示非裝置專用的 sysfs 節點。否則只有供應商可以標記檔案。
tmpfs (/dev)
/dev 中的檔案可能會在 file_contexts 中加上標籤。在 Android 7.0 中,平台和供應商標籤檔案都位於此處。
最佳化建議:供應商只能標記 /dev/vendor 中的檔案 (例如 /dev/vendor/foo、/dev/vendor/socket/bar)。
Rootfs (/)
/ 中的檔案可能會在 file_contexts 中加上標籤。在 Android 7.0 中,平台和供應商標籤檔案都位於此處。
建議:只有系統可以在 / 中標示檔案。
資料 (/data)
資料標記方式是結合 file_contexts 和 seapp_contexts。
最佳化建議:禁止在外部使用供應商標籤。
/data/vendor只有平台可以標記 /data 的其他部分。
Genfs 標籤版本
從 2025 年 4 月的供應商 API 級別開始,使用 genfscon 在 system/sepolicy/compat/plat_sepolicy_genfs_ver.cil 中指派的較新 SELinux 標籤,對於舊版 vendor 分割區為選用項目。這樣一來,舊版 vendor 分區就能保留現有的 SEPolicy 實作項目。這項設定由 Makefile 變數 BOARD_GENFS_LABELS_VERSION 控制,該變數儲存在 /vendor/etc/selinux/genfs_labels_version.txt 中。
範例:
-
在供應商 API 級別 202404 中,
/sys/class/udc節點預設標示為sysfs。 -
從供應商 API 級別 202504 開始,
/sys/class/udc會標示為sysfs_udc。
不過,/sys/class/udc 可能會由使用 API 層級 202404 的vendor分區使用,無論是預設的 sysfs 標籤或供應商專屬標籤都可能。無條件將 /sys/class/udc 標示為 sysfs_udc 可能會導致與這些 vendor 分區不相容。勾選 BOARD_GENFS_LABELS_VERSION 後,平台會繼續使用舊版 vendor 分區的標籤和權限。
BOARD_GENFS_LABELS_VERSION 可以大於或等於供應商 API 級別。舉例來說,使用 API 級別 202404 的 vendor 分區可以將 BOARD_GENFS_LABELS_VERSION 設為 202504,採用 202504 推出的新標籤。請參閱
202504 專屬 genfs 標籤清單。
標記 genfscon 節點時,平台必須考量舊版 vendor 分區,並視需要導入相容性備援機制。平台可以使用平台專屬程式庫查詢 genfs 標籤版本。
-
在原生平台,請使用
libgenfslabelsversion。如需libgenfslabelsversion的標頭檔案,請參閱genfslabelsversion.h。 -
在 Java 中,請使用
android.os.SELinux.getGenfsLabelsVersion()。
平台公共政策
平台 SELinux 政策分為私有和公開。平台公開政策包含的類型和屬性一律適用於供應商 API 層級,可做為平台和供應商之間的 API。這項政策會提供給供應商政策撰寫者,讓供應商建構供應商政策檔案,並與平台專屬政策合併,為裝置產生完整運作的政策。平台公開政策定義於 system/sepolicy/public。
舉例來說,在供應商的環境中,代表初始化程序的 vendor_init 類型定義於 system/sepolicy/public/vendor_init.te 下方:
type vendor_init, domain;
供應商可以參考 vendor_init 型別,編寫自訂政策規則:
# Allow vendor_init to set vendor_audio_prop in vendor's init scripts
set_prop(vendor_init, vendor_audio_prop)相容性屬性
SELinux 政策是來源和目標類型之間,針對特定物件類別和權限的互動。受 SELinux 政策影響的每個物件 (例如程序、檔案) 只能有一種型別,但該型別可能有多個屬性。
這項政策主要以現有類型撰寫,這裡的 vendor_init 和 debugfs 都是型別:
allow vendor_init debugfs:dir { mounton };
這是因為政策是根據所有型別編寫而成。不過,如果供應商政策和平台政策使用特定類型,且特定物件的標籤只在其中一項政策中變更,另一項政策可能包含先前獲得或失去存取權的政策。舉例來說,假設平台政策將 sysfs 節點標示為 sysfs:
/sys(/.*)? u:object_r:sysfs:s0
供應商政策會授予 /sys/usb 的存取權,標示為:
sysfs:
allow vendor_init sysfs:chr_file rw_file_perms;
如果平台政策變更為將 /sys/usb 標示為 sysfs_usb,供應商政策會維持不變,但由於缺少新 sysfs_usb 類型的政策,vendor_init 會失去 /sys/usb 的存取權:
/sys/usb u:object_r:sysfs_usb:s0
為解決這個問題,Android 導入了版本化屬性的概念。在編譯期間,建構系統會自動將供應商政策中使用的平台公開型別,轉換為這些已加入版本的屬性。這項翻譯功能會透過對應檔案啟用,將已加上版本的屬性與平台的一或多個公開類型建立關聯。
舉例來說,假設 /sys/usb 標示為 sysfs,且 2025 年 4 月的供應商政策授予 vendor_init 存取 /sys/usb 的權限。在這種情況下:
-
供應商政策會寫入規則
allow vendor_init sysfs:chr_file rw_file_perms;,因為/sys/usb在 202504 平台政策中標示為sysfs。建構系統編譯供應商政策時,會自動將規則轉換為allow vendor_init_202504 sysfs_202504:chr_file rw_file_perms;。屬性vendor_init_202504和sysfs_202504分別對應至vendor_init和sysfs類型,這些是平台定義的類型。 -
建構系統會產生識別資訊對應檔
/system/etc/selinux/mapping/202504.cil。由於system和vendor分區都使用相同的202504版本,因此對應檔案包含從type_202504到type的身分對應。舉例來說,vendor_init_202504對應至vendor_init,sysfs_202504對應至sysfs:(typeattributeset sysfs_202504 (sysfs)) (typeattributeset vendor_init_202504 (vendor_init)) ...
當版本從 202504 升級至 202604 時,系統會在 system/sepolicy/private/compat/202504/202504.cil 下建立 202504 vendor 分區的新對應檔案,並安裝至 202604 或更新版本 system 分區的 /system/etc/selinux/mapping/202504.cil。如先前所述,這個對應檔案一開始會包含身分對應。如果 202604 平台政策新增 sysfs_usb
的標籤 /sys/usb,對應檔案會更新,將 sysfs_202504 對應至 sysfs_usb:
(typeattributeset sysfs_202504 (sysfs sysfs_usb)) (typeattributeset vendor_init_202504 (vendor_init)) ...
這項更新可讓轉換後的供應商政策規則 allow
vendor_init_202504 sysfs_202504:chr_file rw_file_perms; 自動授予新 sysfs_usb 類型的存取權 vendor_init。
為維持與舊版 vendor 分區的相容性,每當新增公開型別時,該型別必須對應至對應檔案 system/sepolicy/private/compat/ver/ver.cil 中的至少一個版本化屬性,或列於 system/sepolicy/private/compat/ver/ver.ignore.cil 下方,說明先前供應商版本中沒有相符的型別。
平台政策、供應商政策和對應檔案的組合,可讓系統在不更新供應商政策的情況下進行更新。此外,系統會自動將屬性轉換為版本化屬性,因此供應商政策不必處理版本化作業,可繼續使用公開型別。
system_ext 公開和產品公開政策
從 Android 11 開始,system_ext 和 product 分區可將指定公開型別匯出至 vendor 分區。與平台公開政策相同,供應商政策會使用自動轉換為版本化屬性的類型和規則,例如從 type 轉換為 type_ver,其中 ver 是 vendor 分區的供應商 API 層級。
如果 system_ext 和 product 分區是根據相同的平台版本 ver,建構系統會產生基本對應檔案至 system_ext/etc/selinux/mapping/ver.cil 和 product/etc/selinux/mapping/ver.cil,其中包含從 type 到 type_ver 的身分對應。供應商政策可透過版本化屬性 type_ver 存取 type。
如果只更新 system_ext 和 product 分區 (例如從 ver 更新至 ver+1 或更新版本),但 vendor 分區仍為 ver,供應商政策可能會失去 system_ext 和 product 分區的存取權。為避免中斷,system_ext 和 product 分區應提供從具體型別到 type_ver 屬性的對應檔案。如果合作夥伴支援 ver vendor 分區 (使用 ver+1 或更新版本 system_ext 和 product 分區),則須負責維護對應檔案。
如要將對應檔案安裝至 system_ext 和 product 分區,裝置實作人員或供應商應採取下列行動:
- 從 ver
system_ext和product分區 將產生的基本對應檔案複製到來源樹狀結構。 - 視需要修改對應檔案。
-
將對應檔案安裝至 ver+1 (或更新版本) 和
product分割區。system_ext
舉例來說,假設 202504 system_ext 分區有一個名為 foo_type 的公開型別。然後,202504 system_ext 分區中的 system_ext/etc/selinux/mapping/202504.cil 會如下所示:
(typeattributeset foo_type_202504 (foo_type)) (expandtypeattribute foo_type_202504 true) (typeattribute foo_type_202504)
如果 bar_type 已新增至 202604 system_ext,且 bar_type 應對應至 202504 foo_type 分區,則 202504.cil 可從 (typeattributeset foo_type_202504 (foo_type)) 更新至 (typeattributeset foo_type_202504 (foo_type bar_type)),然後安裝至 202604 system_ext 分區。vendor202504 vendor 分區可以繼續存取 202604 system_ext 的 foo_type 和 bar_type。
Android 9 的屬性變更
升級至 Android 9 的裝置可以使用下列屬性,但搭載 Android 9 的裝置不得使用。
違規者屬性
Android 9 包含下列網域相關屬性:
data_between_core_and_vendor_violators. 所有網域的屬性,這些網域違反不得在vendor和coredomains之間透過路徑共用檔案的規定。平台和供應商程序不應使用磁碟上的檔案進行通訊 (ABI 不穩定)。建議:- 供應商代碼應使用
/data/vendor。 - 系統不應使用
/data/vendor。
- 供應商代碼應使用
system_executes_vendor_violators。所有系統網域 (init和shell domains除外) 的屬性,都違反不得執行供應商二進位檔的規定。執行供應商二進位檔時,API 不穩定。平台不應直接執行供應商二進位檔。建議:- 這類對供應商二進位檔的平台依附元件必須位於 HIDL HAL 後方。
或
coredomains需要存取供應商二進位檔的vendor應移至coredomain分區,並停止成為coredomains。
- 這類對供應商二進位檔的平台依附元件必須位於 HIDL HAL 後方。
不受信任的屬性
代管任意程式碼的不受信任應用程式不應存取 HwBinder 服務,但可存取被視為足夠安全,可供這類應用程式存取的服務 (請參閱下方的安全服務)。主要原因有二:
- HwBinder 伺服器不會執行用戶端驗證,因為 HIDL 目前不會公開呼叫端 UID 資訊。即使 HIDL 確實公開這類資料,許多 HwBinder 服務不是在應用程式層級以下運作 (例如 HAL),就是不得依據應用程式 ID 進行授權。因此,為確保安全,預設假設是每個 HwBinder 服務都會將所有用戶端視為同樣有權執行服務提供的作業。
- HAL 伺服器 (HwBinder 服務的子集) 包含的程式碼,安全問題發生率高於
system/core元件,且可存取堆疊的較低層 (一路到硬體),因此增加規避 Android 安全性模型的機會。
安全服務
安全服務包括:
same_process_hwservice。這些服務 (依定義) 會在用戶端的程序中執行,因此與程序執行的用戶端網域具有相同的存取權。coredomain_hwservice。這些服務不會造成與原因 #2 相關的風險。hal_configstore_ISurfaceFlingerConfigs。這項服務專為任何網域設計。hal_graphics_allocator_hwservice。這些作業也由surfaceflingerBinder 服務提供,應用程式可存取這項服務。hal_omx_hwservice。這是mediacodecBinder 服務的 HwBinder 版本,應用程式可存取此服務。hal_codec2_hwservice。這是hal_omx_hwservice的新版本。
可用的屬性
所有不安全的 hwservices 都具有 untrusted_app_visible_hwservice 屬性。對應的 HAL 伺服器具有 untrusted_app_visible_halserver 屬性。搭載 Android 9 的裝置「不得」使用 untrusted 屬性。
建議:
- 不信任的應用程式應改為與系統服務通訊,再由系統服務與供應商 HIDL HAL 通訊。舉例來說,應用程式可以與
binderservicedomain對話,然後mediaserver(即binderservicedomain) 會與hal_graphics_allocator對話。或
- 需要直接存取
vendorHAL 的應用程式應有自己的供應商定義 sepolicy 網域。
檔案屬性測試
Android 9 包含建構時間測試,可確保特定位置的所有檔案都具有適當的屬性 (例如,sysfs 中的所有檔案都具有必要的 sysfs_type 屬性)。
SELinux 內容標籤
為支援平台和供應商 sepolicy 的區別,系統會以不同方式建構 SELinux 內容檔案,確保兩者分開。
檔案內容
Android 8.0 針對 file_contexts 導入下列變更:
- 為避免在啟動期間裝置上產生額外的編譯負擔,
file_contexts不會以二進位形式存在。而是可讀取的規則運算式文字檔,例如{property, service}_contexts(7.0 之前的版本就是如此)。 file_contexts分成兩個檔案:plat_file_contexts- Android 平台
file_context,除了/vendor分區的標籤必須精確標示,確保 sepolicy 檔案正常運作外,其他部分沒有裝置專屬標籤。 - 必須位於裝置的
system分割區/system/etc/selinux/plat_file_contexts,並在啟動時由init與供應商file_context一併載入。
- Android 平台
vendor_file_contexts- 裝置專屬
file_context是透過合併裝置Boardconfig.mk檔案中BOARD_SEPOLICY_DIRS所指向目錄中的file_contexts所建構。 - 必須安裝在
vendor分割區的/vendor/etc/selinux/vendor_file_contexts中,並在啟動時由init與平台file_context一併載入。
- 裝置專屬
房源背景資訊
在 Android 8.0 中,property_contexts 分成兩個檔案:
plat_property_contexts- Android 平台
property_context,沒有裝置專屬標籤。 - 必須位於
system分區的/system/etc/selinux/plat_property_contexts,並在啟動時由init與供應商property_contexts一併載入。
- Android 平台
vendor_property_contexts- 裝置專屬的
property_context是透過合併裝置Boardconfig.mk檔案中BOARD_SEPOLICY_DIRS所指向目錄中的property_contexts所建構。 - 必須位於
vendor分區的/vendor/etc/selinux/vendor_property_contexts,並在啟動時由init與平台property_context一併載入
- 裝置專屬的
服務環境
在 Android 8.0 中,service_contexts 會拆分成下列檔案:
plat_service_contexts- Android 平台專屬
service_context,適用於servicemanager。service_context沒有裝置專屬標籤。 - 必須位於
system分區的/system/etc/selinux/plat_service_contexts,並在啟動時由servicemanager與供應商service_contexts一併載入。
- Android 平台專屬
vendor_service_contexts- 裝置專屬
service_context是透過合併裝置Boardconfig.mk檔案中BOARD_SEPOLICY_DIRS所指向目錄中的service_contexts所建構。 - 必須位於
vendor分區的/vendor/etc/selinux/vendor_service_contexts,並在啟動時由servicemanager與平台service_contexts一併載入。 - 雖然
servicemanager會在啟動時尋找這個檔案,但如要讓TREBLE裝置完全符合規範,vendor_service_contexts「不得」存在。這是因為vendor和system程序之間的所有互動都必須經過hwservicemanager/hwbinder。
- 裝置專屬
plat_hwservice_contexts- Android 平台
hwservice_context,沒有裝置專屬標籤。hwservicemanager - 必須位於
system分區的/system/etc/selinux/plat_hwservice_contexts,並在啟動時與vendor_hwservice_contexts一併由hwservicemanager載入。
- Android 平台
vendor_hwservice_contexts- 裝置專屬
hwservice_context是透過合併裝置Boardconfig.mk檔案中BOARD_SEPOLICY_DIRS所指向目錄中的hwservice_contexts所建構。 - 必須位於
vendor分區的/vendor/etc/selinux/vendor_hwservice_contexts,並在啟動時由hwservicemanager與plat_service_contexts一併載入。
- 裝置專屬
vndservice_contexts- 裝置專屬
service_context,是透過合併在裝置Boardconfig.mk中BOARD_SEPOLICY_DIRS所指向目錄中找到的vndservice_contexts所建構。vndservicemanager - 這個檔案必須位於
vendor分區的/vendor/etc/selinux/vndservice_contexts,並在啟動時由vndservicemanager載入。
- 裝置專屬
Seapp 內容
在 Android 8.0 中,seapp_contexts 分成兩個檔案:
plat_seapp_contexts- Android 平台
seapp_context,且沒有裝置專屬變更。 - 必須位於
system分區,且位於/system/etc/selinux/plat_seapp_contexts.
- Android 平台
vendor_seapp_contexts- 平台
seapp_context的裝置專屬擴充功能,是透過合併裝置Boardconfig.mk檔案中BOARD_SEPOLICY_DIRS所指向目錄的seapp_contexts所建構。 - 必須位於
vendor分區的/vendor/etc/selinux/vendor_seapp_contexts。
- 平台
MAC 權限
在 Android 8.0 中,mac_permissions.xml 分成兩個檔案:
- 月台
mac_permissions.xml- Android 平台
mac_permissions.xml,且沒有特定裝置的變更。 - 必須位於
system分區,且位於/system/etc/selinux/.
- Android 平台
- 非平台
mac_permissions.xml- 平台專屬的裝置擴充功能,由裝置
Boardconfig.mk檔案中BOARD_SEPOLICY_DIRS所指向目錄的mac_permissions.xml建構而成。mac_permissions.xml - 必須位於
vendor分區,且位於/vendor/etc/selinux/.
- 平台專屬的裝置擴充功能,由裝置