<devsite-heading text="政策兼容性" for="%E6%94%BF%E7%AD%96%E5%85%BC%E5%AE%B9%E6%80%A7" level="h1" class="devsite-page-title"># 政策兼容性</devsite-heading>
本文介紹 Android 如何處理與平臺 OTA 相關(guān)的政策兼容性問題,其中新平臺 SELinux 設(shè)置可能與舊供應(yīng)商 SELinux 設(shè)置有所不同。
基于 Treble 的 SELinux 政策設(shè)計會考慮平臺政策和供應(yīng)商政策之間的二進(jìn)制文件區(qū)別;如果供應(yīng)商分區(qū)生成依賴項(xiàng)(例如 platform < vendor < oem),則架構(gòu)會變得更加復(fù)雜。
在 Android 8.0 及更高版本中,SELinux 全局政策劃分為私有和公共組件。公共組件包含政策和相關(guān)基礎(chǔ)架構(gòu),保證可用于平臺版本。 此政策會向供應(yīng)商政策編寫者公開,讓供應(yīng)商編譯的供應(yīng)商政策文件在與平臺提供的政策結(jié)合使用時,可以為設(shè)備產(chǎn)生功能齊全的政策。
- 對于版本控制,導(dǎo)出的平臺公共政策將編寫為屬性。
- 為了便于編寫政策,導(dǎo)出的類型將在政策編譯流程中轉(zhuǎn)換為版本化屬性。公共類型也可以直接用于供應(yīng)商上下文文件提供的標(biāo)簽決策。
Android 可維護(hù)平臺政策中導(dǎo)出的具體類型與每個平臺版本的相應(yīng)版本化屬性之間的映射。這可確保在使用類型標(biāo)記對象時,不會破壞平臺公共政策在之前版本中所保證的行為。系統(tǒng)通過使每個平臺版本的映射文件保持最新來維護(hù)此映射,該映射文件會為公共政策中導(dǎo)出的每種類型保留屬性成員資格信息。
<devsite-heading text="對象所有權(quán)和標(biāo)簽" for="object-ownership-and-labeling" level="h2" link="" toc="" class="" back-to-top="">## 對象所有權(quán)和標(biāo)簽</devsite-heading>
<devsite-heading text="對象所有權(quán)和標(biāo)簽" for="object-ownership-and-labeling" level="h2" link="" toc="" class="" back-to-top=""></devsite-heading>
在 Android 8.0 及更高版本中自定義政策時,必須為每個對象明確定義所有權(quán),以使平臺和供應(yīng)商政策保持分離。例如,如果供應(yīng)商標(biāo)記 /dev/foo 而后平臺在后續(xù) OTA 中標(biāo)記 /dev/foo,則會出現(xiàn)未定義的行為。對于 SELinux,這表現(xiàn)為標(biāo)簽沖突。設(shè)備節(jié)點(diǎn)只能有一個標(biāo)簽,解析為最后應(yīng)用的標(biāo)簽。因此:
- 如果進(jìn)程需要訪問未成功應(yīng)用的標(biāo)簽,則會失去相應(yīng)資源的訪問權(quán)限。
- 由于創(chuàng)建了錯誤的設(shè)備節(jié)點(diǎn),因此已獲得文件訪問權(quán)限的進(jìn)程可能會被中斷。
系統(tǒng)屬性也有可能存在命名沖突,進(jìn)而導(dǎo)致系統(tǒng)上出現(xiàn)未定義行為(以及 SELinux 標(biāo)簽出現(xiàn)此行為)。具有 SELinux 標(biāo)簽的任何對象(包括屬性、服務(wù)、進(jìn)程、文件和套接字)都可能會出現(xiàn)平臺和供應(yīng)商標(biāo)簽沖突的情況。要避免此類問題,請明確定義這些對象的所有權(quán)。
除了標(biāo)簽沖突外,SELinux 類型/屬性名稱也可能出現(xiàn)沖突。 類型/屬性名稱沖突往往會導(dǎo)致政策編譯器錯誤。
<devsite-heading text="類型/屬性命名空間" for="type-attribute-namespacing" level="h3" link="" toc="" class="">### 類型/屬性命名空間</devsite-heading>
SELinux 不允許相同類型/屬性的多個聲明。具有重復(fù)聲明的政策將無法編譯。為避免類型和屬性名稱沖突,所有供應(yīng)商聲明都應(yīng)是以 np_ 開頭的命名空間。
<devsite-code><pre class="" is-upgraded="">type foo, domain; → type np_foo, domain;</pre></devsite-code> <devsite-heading text="系統(tǒng)屬性和進(jìn)程標(biāo)簽所有權(quán)" for="system-property-and-process-labeling-ownership" level="h3" link="" toc="" class="">### 系統(tǒng)屬性和進(jìn)程標(biāo)簽所有權(quán)</devsite-heading>
要避免標(biāo)簽沖突,最有效的解決方法是使用屬性命名空間。要在重命名或添加導(dǎo)出的平臺屬性時輕松識別平臺屬性并避免名稱沖突,請確保所有供應(yīng)商屬性都有各自的前綴:
| 屬性類型 | 可接受的前綴 |
| 可讀寫 | vendor.<wbr> |
| 只讀 | ro.<wbr>vendor.<wbr>
ro.<wbr>boot.<wbr>
ro.<wbr>hardware.<wbr> |
| 永久 | persist.<wbr>vendor.<wbr> |
供應(yīng)商可以繼續(xù)使用 ro.boot.*(來自內(nèi)核命令行)和 ro.hardware.*(明顯的硬件相關(guān)屬性)。
對于非系統(tǒng)分區(qū)的 init rc 文件中的服務(wù),init rc 文件中的所有供應(yīng)商服務(wù)都應(yīng)該包含 vendor.。類似的規(guī)則適用于供應(yīng)商屬性的 SELinux 標(biāo)簽(vendor_ 表示供應(yīng)商屬性)。
<devsite-heading text="文件所有權(quán)" for="file-ownership" level="h3" link="" toc="" class="">### 文件所有權(quán)</devsite-heading>
避免文件沖突是一項(xiàng)具有挑戰(zhàn)性的工作,因?yàn)槠脚_和供應(yīng)商政策通常都為所有文件系統(tǒng)提供標(biāo)簽。與類型命名不同,文件的命名空間并不實(shí)用,因?yàn)槠渲泻芏喽际怯蓛?nèi)核創(chuàng)建的。要避免此類沖突,請遵循本節(jié)中文件系統(tǒng)的命名指南。對于 Android 8.0,這些指南只是建議,并不要求在技術(shù)上強(qiáng)制執(zhí)行。將來,這些建議將由供應(yīng)商測試套件 (VTS) 強(qiáng)制執(zhí)行。
<devsite-heading text="系統(tǒng) (/system)" for="system" level="h4" link="" class="">#### 系統(tǒng) (/system)</devsite-heading>
只有系統(tǒng)映像必須通過 file_contexts、service_contexts 等為 /system 組件提供標(biāo)簽。如果在 /vendor 政策中添加了 /system 組件的標(biāo)簽,則可能會導(dǎo)致僅針對框架的 OTA 更新無法實(shí)現(xiàn)。
<devsite-heading text="供應(yīng)商 (/vendor)" for="vendor" level="h4" link="" class="">#### 供應(yīng)商 (/vendor)</devsite-heading>
AOSP SELinux 政策已經(jīng)為平臺與之交互的 vendor 分區(qū)部分添加標(biāo)簽,因此能夠?yàn)槠脚_進(jìn)程編寫 SELinux 規(guī)則,以便訪問 vendor 分區(qū)部分并/或與之通信。示例:
| /vendor 路徑 | 平臺提供的標(biāo)簽 | 取決于標(biāo)簽的平臺進(jìn)程 |
| /vendor(<wbr>/.<wbr>*****)? | vendor_file | 框架中的所有 HAL 客戶端、ueventd 等 |
| /vendor/framework(<wbr>/.<wbr>*****)? | vendor_framework_file | dex2oat、appdomain 等 |
| /vendor/app(<wbr>/.<wbr>*****)? | vendor_app_file | dex2oat、installd、idmap 等 |
| /vendor/overlay(<wbr>/.<wbr>*****) | vendor_overlay_file | system_server、zygote、idmap 等 |
*****有關(guān)更多示例,請參閱 system/sepolicy/private/file_contexts。
因此,您在 vendor 分區(qū)中標(biāo)記額外的文件時,必須遵循特定規(guī)則(通過 neverallows 強(qiáng)制執(zhí)行):
-
vendor_file必須是vendor分區(qū)中所有文件的默認(rèn)標(biāo)簽。平臺政策要求使用此標(biāo)簽來訪問直通式 HAL實(shí)現(xiàn)。 - 通過供應(yīng)商 SEPolicy 在
vendor分區(qū)中添加的所有新exec_types均必須具有vendor_file_type屬性。這一規(guī)則將通過 neverallows 強(qiáng)制執(zhí)行。 - 為了避免與將來的平臺/框架更新發(fā)生沖突,請避免在
exec_types分區(qū)中標(biāo)記除vendor之外的文件。 - AOSP 標(biāo)識的 Same-Process HAL 的所有庫依賴項(xiàng)均必須標(biāo)記為
same_process_hal_file.。
<devsite-heading text="Procfs (/proc)" for="procfs" level="h4" link="" class="">#### Procfs (/proc)</devsite-heading>
/proc 中的文件可以僅使用 genfscon 標(biāo)簽進(jìn)行標(biāo)記。在 Android 7.0 中,平臺政策和供應(yīng)商政策都使用 genfscon 來標(biāo)記 procfs 中的文件。
建議:只有平臺政策可以標(biāo)記 /proc。如果 vendor 進(jìn)程需要訪問 /proc 中當(dāng)前使用默認(rèn)標(biāo)簽 (proc) 標(biāo)記的文件,則供應(yīng)商政策不應(yīng)明確標(biāo)記它們,而應(yīng)使用常規(guī) proc 類型為供應(yīng)商域添加規(guī)則。這樣,平臺更新可以適應(yīng)通過 procfs 公開的未來內(nèi)核接口,并根據(jù)需要進(jìn)行明確標(biāo)記。
<devsite-heading text="Debugfs (/sys/kernel/debug)" for="debugfs" level="h4" link="" class="">#### Debugfs (/sys/kernel/debug)</devsite-heading>
Debugfs 可以在 file_contexts 和 genfscon 中進(jìn)行標(biāo)記。在 Android 7.0 中,平臺和供應(yīng)商都會標(biāo)記 debugfs。
建議:在短期內(nèi),只有供應(yīng)商政策可以標(biāo)記 debugfs。從長遠(yuǎn)來看,請移除 debugfs。
<devsite-heading text="Tracefs (/sys/kernel/debug/tracing)" for="tracefs" level="h4" link="" class="">#### Tracefs (/sys/kernel/debug/tracing)</devsite-heading>
Tracefs 可以在 file_contexts 和 genfscon 中進(jìn)行標(biāo)記。在 Android 7.0 中,只有平臺標(biāo)記 tracefs。
建議:只有平臺可以標(biāo)記 tracefs。
<devsite-heading text="Sysfs (/sys)" for="sysfs" level="h4" link="" class="">#### Sysfs (/sys)</devsite-heading>
/sys 中的文件可以使用 file_contexts 和 genfscon 進(jìn)行標(biāo)記。在 Android 7.0 中,平臺和供應(yīng)商都使用 file_contexts 和 genfscon 來標(biāo)記 sysfs 中的文件。
建議:平臺可以標(biāo)記不針對特定設(shè)備的 sysfs 節(jié)點(diǎn)。否則,只有供應(yīng)商可以標(biāo)記文件。
<devsite-heading text="tmpfs (/dev)" for="tmpfs" level="h4" link="" class="">#### tmpfs (/dev)</devsite-heading>
/dev 中的文件可以在 file_contexts 中進(jìn)行標(biāo)記。在 Android 7.0 中,平臺和供應(yīng)商標(biāo)簽文件都在這里。
建議:供應(yīng)商只能標(biāo)記 /dev/vendor 中的文件(例如 /dev/vendor/foo、/dev/vendor/socket/bar)。
<devsite-heading text="Rootfs (/)" for="rootfs" level="h4" link="" class="">#### Rootfs (/)</devsite-heading>
/ 中的文件可以在 file_contexts 中進(jìn)行標(biāo)記。在 Android 7.0 中,平臺和供應(yīng)商標(biāo)簽文件都在這里。
建議:只有系統(tǒng)可以標(biāo)記 / 中的文件。
<devsite-heading text="數(shù)據(jù) (/data)" for="data-data" level="h4" link="" class="">#### 數(shù)據(jù) (/data)</devsite-heading>
數(shù)據(jù)可以通過 file_contexts 和 seapp_contexts 組合進(jìn)行標(biāo)記。
建議:禁止供應(yīng)商在 /data/vendor 之外進(jìn)行標(biāo)記。只有平臺可以標(biāo)記 /data 的其他部分。
<devsite-heading text="兼容性屬性" for="compatibility-attributes" level="h2" link="" toc="" class="" back-to-top="">## 兼容性屬性</devsite-heading> <devsite-heading text="兼容性屬性" for="compatibility-attributes" level="h2" link="" toc="" class="" back-to-top=""></devsite-heading>
SELinux 政策是特定對象類和權(quán)限的源類型和目標(biāo)類型之間的交互。受 SELinux 政策影響的每個對象(進(jìn)程、文件等)可能只有一種類型,但該類型可能有多個屬性。
政策大多根據(jù)現(xiàn)有類型編寫:
<devsite-code><pre class="" is-upgraded="">allow source_type target_type:target_class permission(s);</pre></devsite-code>
這之所以有效,是因?yàn)檎呤窃诨趯λ蓄愋土私獾幕A(chǔ)上而編寫的。但是,如果供應(yīng)商政策和平臺政策使用特定類型,而特定對象的標(biāo)簽僅在其中一項(xiàng)政策中發(fā)生變化,則另一個所包含的政策可能會獲得或失去之前所依賴的訪問權(quán)限。例如:
<devsite-code><pre class="" is-upgraded="">File_contexts: /sys/A u:object_r:sysfs:s0 Platform: allow p_domain sysfs:class perm; Vendor: allow v_domain sysfs:class perm;</pre></devsite-code>
可以改為:
<devsite-code><pre class="" is-upgraded="">File_contexts: /sys/A u:object_r:sysfs_A:s0</pre></devsite-code>
盡管供應(yīng)商政策將保持不變,但由于缺少針對新 sysfs_A 類型的政策,v_domain 將失去訪問權(quán)限。
通過根據(jù)屬性定義政策,我們可以為底層對象提供一個類型,該類型具有與平臺和供應(yīng)商代碼的政策相對應(yīng)的屬性??梢葬槍λ蓄愋屯瓿纱瞬僮?,以便有效地創(chuàng)建一個其中從不使用具體類型的屬性政策。實(shí)際上,只需對平臺和供應(yīng)商之間重疊的政策部分執(zhí)行此操作,這些部分是作為平臺公共政策(作為供應(yīng)商政策的一部分進(jìn)行編譯)定義和提供的。
將公共政策定義為版本化屬性可實(shí)現(xiàn)以下兩個政策兼容性目標(biāo):
- 確保供應(yīng)商代碼在平臺更新后繼續(xù)有效。 通過向與供應(yīng)商代碼所依賴的對象相對應(yīng)的對象的具體類型添加屬性,保留訪問權(quán)限,可以做到這一點(diǎn)。
- 能夠棄用政策。通過將政策集明確地劃分到屬性(在與這些屬性對應(yīng)的版本不再受支持時,可以立即移除這些屬性)中,可以做到這一點(diǎn)。由于知道舊政策依然存在于供應(yīng)商政策中,并且會在升級時被自動移除,因此可以繼續(xù)在平臺中進(jìn)行開發(fā)。
<devsite-heading text="政策可寫性" for="policy-writability" level="h3" link="" toc="" class="">### 政策可寫性</devsite-heading>
為了實(shí)現(xiàn)無需了解具體版本變化即可制定政策的目標(biāo),Android 8.0 包含平臺公共政策類型與其屬性之間的映射。類型 foo 映射到屬性 foo_v*N*,其中 *N* 是目標(biāo)版本。vN 對應(yīng)于 PLATFORM_SEPOLICY_VERSION 編譯變量,格式為 MM.NN(其中 MM 對應(yīng)于平臺 SDK 編號,NN 是平臺 sepolicy 特定版本)。
公共政策中的屬性未采用版本編號,而是以 API 形式存在(可以在上面構(gòu)建平臺和供應(yīng)商政策,以使兩個分區(qū)之間的接口保持穩(wěn)定)。平臺和供應(yīng)商政策寫入程序都可以像當(dāng)前那樣繼續(xù)寫入政策。
以 allow source_foo target_bar:*class perm*; 形式導(dǎo)出的平臺公共政策包含在供應(yīng)商政策中。在編譯(包括相應(yīng)的版本)期間,它將轉(zhuǎn)換為將放入設(shè)備供應(yīng)商部分的政策(以轉(zhuǎn)換后的通用中間語言 (CIL) 顯示):
<devsite-code><pre class="" is-upgraded=""> (allow source_foo_vN target_bar_vN (class (perm)))</pre></devsite-code>
由于供應(yīng)商政策絕不會比平臺更早,因此不必須顧慮以前的版本。但是,平臺政策需要知道供應(yīng)商政策追溯到什么時候,將屬性添加到其所屬類型中,并設(shè)置與版本化屬性相對應(yīng)的政策。
<devsite-heading text="政策差異" for="policy-diffs" level="h3" link="" toc="" class="">### 政策差異</devsite-heading>
如果不在各版本差異中將屬性映射到類型,那么通過在每種類型的末尾添加 _v*N* 來自動創(chuàng)建屬性時,不會創(chuàng)建任何內(nèi)容。Android 維護(hù)著屬性版本之間的映射以及類型到這些屬性的映射。這是在前面提到的包含語句的映射文件(例如 (CIL))中完成的:
<devsite-code><pre class="" is-upgraded="">(typeattributeset foo_vN (foo))</pre></devsite-code> <devsite-heading text="平臺升級" for="platform-upgrades" level="h4" link="" class="">#### 平臺升級</devsite-heading>
以下部分詳細(xì)介紹了平臺升級的各種情況。
<devsite-heading text="相同的類型" for="same-types" level="h5" link="" class="">##### 相同的類型</devsite-heading>
當(dāng)對象未更改政策版本中的標(biāo)簽時,會出現(xiàn)這種情況。 源類型和目標(biāo)類型同樣會出現(xiàn)這種情況,可以通過 /dev/binder 查看,后者在所有版本中都帶有 binder_device 標(biāo)簽。它在轉(zhuǎn)換后的政策中表示為以下形式:
<devsite-code><pre class="" is-upgraded="">binder_device_v1 … binder_device_vN</pre></devsite-code>
從 v1 升級到 v2 時,平臺政策必須包含:
<devsite-code><pre class="" is-upgraded="">type binder_device; -> (type binder_device) (in CIL)</pre></devsite-code>
在 v1 映射文件 (CIL) 中:
<devsite-code><pre class="" is-upgraded="">(typeattributeset binder_device_v1 (binder_device))</pre></devsite-code>
在 v2 映射文件 (CIL) 中:
<devsite-code><pre class="" is-upgraded="">(typeattributeset binder_device_v2 (binder_device))</pre></devsite-code>
在 v1 供應(yīng)商政策 (CIL) 中:
<devsite-code><pre class="" is-upgraded="">(typeattribute binder_device_v1) (allow binder_device_v1 …)</pre></devsite-code>
在 v2 供應(yīng)商政策 (CIL) 中:
<devsite-code><pre class="" is-upgraded="">(typeattribute binder_device_v2) (allow binder_device_v2 …)</pre></devsite-code> <devsite-heading text="新類型" for="new-types" level="h5" link="" class="">##### 新類型</devsite-heading>
在添加新功能時或政策安全強(qiáng)化期間,平臺會添加新類型,此時便會出現(xiàn)這種情況。
- 新功能。當(dāng)該類型標(biāo)記以前不存在的對象(例如新服務(wù)進(jìn)程)時,供應(yīng)商代碼之前未與其直接交互,因此不存在相應(yīng)的政策。與該類型對應(yīng)的新屬性在以前的版本中沒有屬性,因此映射文件中不需要包含定位到該版本的條目。
-
政策安全強(qiáng)化。當(dāng)該類型表示政策安全強(qiáng)化時,新的類型屬性必須鏈接回與前一個類型對應(yīng)的屬性鏈(與上一個示例將
/sys/A從sysfs更改為sysfs_A類似)。供應(yīng)商代碼依賴于允許訪問sysfs的規(guī)則,并且需要將該規(guī)則添加為新類型的屬性。
從 v1 升級到 v2 時,平臺政策必須包含:
<devsite-code><pre class="" is-upgraded="">type sysfs_A; -> (type sysfs_A) (in CIL) type sysfs; (type sysfs) (in CIL)</pre></devsite-code>
在 v1 映射文件 (CIL) 中:
<devsite-code><pre class="" is-upgraded="">(typeattributeset sysfs_v1 (sysfs sysfs_A))</pre></devsite-code>
在 v2 映射文件 (CIL) 中:
<devsite-code><pre class="" is-upgraded="">(typeattributeset sysfs_v2 (sysfs)) (typeattributeset sysfs_A_v2 (sysfs_A))</pre></devsite-code>
在 v1 供應(yīng)商政策 (CIL) 中:
<devsite-code><pre class="" is-upgraded="">(typeattribute sysfs_v1) (allow … sysfs_v1 …)</pre></devsite-code>
在 v2 供應(yīng)商政策 (CIL) 中:
<devsite-code><pre class="" is-upgraded="">(typeattribute sysfs_A_v2) (allow … sysfs_A_v2 …) (typeattribute sysfs_v2) (allow … sysfs_v2 …)</pre></devsite-code> <devsite-heading text="移除的類型" for="removed-types" level="h5" link="" class="">##### 移除的類型</devsite-heading>
類型會在底層對象發(fā)生以下情形時遭到移除,此時便會出現(xiàn)這種(罕見)情況:
- 仍然存在但獲得不同的標(biāo)簽。
- 被平臺移除。
在政策放松期間,系統(tǒng)會移除某個類型,并為使用該類型標(biāo)記的對象提供其他已存在的標(biāo)簽。這表示屬性映射的合并:供應(yīng)商代碼必須仍然能夠通過底層對象曾經(jīng)擁有的屬性訪問該底層對象,但系統(tǒng)的其余部分現(xiàn)在必須能夠通過其新屬性訪問它。
如果它改用新屬性,則重新添加標(biāo)簽與在新類型中相同,不同之處在于:使用現(xiàn)有標(biāo)簽時,為新類型添加舊屬性將導(dǎo)致同樣使用此類型標(biāo)記的其他對象也變得可以訪問。這本質(zhì)上是由平臺完成的,并被視為一種為保持兼容性而可以接受的權(quán)衡。
<devsite-code><pre class="" is-upgraded="">(typeattribute sysfs_v1) (allow … sysfs_v1 …)</pre></devsite-code>
示例版本 1:合并類型(移除 sysfs_A)
從 v1 升級到 v2 時,平臺政策必須包含:
<devsite-code><pre class="" is-upgraded="">type sysfs; (type sysfs) (in CIL)</pre></devsite-code>
在 v1 映射文件 (CIL) 中:
<devsite-code><pre class="" is-upgraded="">(typeattributeset sysfs_v1 (sysfs)) (type sysfs_A) # in case vendors used the sysfs_A label on objects (typeattributeset sysfs_A_v1 (sysfs sysfs_A))</pre></devsite-code>
在 v2 映射文件 (CIL) 中:
<devsite-code><pre class="" is-upgraded="">(typeattributeset sysfs_v2 (sysfs))</pre></devsite-code>
在 v1 供應(yīng)商政策 (CIL) 中:
<devsite-code><pre class="" is-upgraded="">(typeattribute sysfs_A_v1) (allow … sysfs_A_v1 …) (typeattribute sysfs_v1) (allow … sysfs_v1 …)</pre></devsite-code>
在 v2 供應(yīng)商政策 (CIL) 中:
<devsite-code><pre class="" is-upgraded="">(typeattribute sysfs_v2) (allow … sysfs_v2 …)</pre></devsite-code>
示例版本 2:完全移除(foo 類型)
從 v1 升級到 v2 時,平臺政策必須包含:
<devsite-code><pre class="" is-upgraded=""># nothing - we got rid of the type</pre></devsite-code>
在 v1 映射文件 (CIL) 中:
<devsite-code><pre class="" is-upgraded="">(type foo) #needed in case vendors used the foo label on objects (typeattributeset foo_v1 (foo))</pre></devsite-code>
在 v2 映射文件 (CIL) 中:
<devsite-code><pre class="" is-upgraded=""># nothing - get rid of it</pre></devsite-code>
在 v1 供應(yīng)商政策 (CIL) 中:
<devsite-code><pre class="" is-upgraded="">(typeattribute foo_v1) (allow foo …) (typeattribute sysfs_v1) (allow sysfs_v1 …)</pre></devsite-code>
在 v2 供應(yīng)商政策 (CIL) 中:
<devsite-code><pre class="" is-upgraded="">(typeattribute sysfs_v2) (allow sysfs_v2 …)</pre></devsite-code> <devsite-heading text="新類/權(quán)限" for="new-class-permissions" level="h5" link="" class="">##### 新類/權(quán)限</devsite-heading>
當(dāng)平臺升級引入先前版本中不存在的新政策組件時,會出現(xiàn)這種情況。例如,當(dāng) Android 添加了創(chuàng)建添加、查找和列出權(quán)限的 servicemanager 對象管理器時,想要向 servicemanager 注冊的供應(yīng)商守護(hù)程序需要之前未提供的權(quán)限。在 Android 8.0 中,只有平臺政策可以添加新的類和權(quán)限。
要允許所有可能由供應(yīng)商政策創(chuàng)建或擴(kuò)展的域毫無阻礙地使用新類,平臺政策需要包含類似于下文的規(guī)則:
<devsite-code><pre class="" is-upgraded="">allow {domain -coredomain} *:new_class perm;</pre></devsite-code>
這甚至可能需要政策允許訪問所有接口(公共政策)類型,以確保供應(yīng)商映像獲得訪問權(quán)限。如果這會導(dǎo)致不可接受的安全政策(就像 servicemanager 更改可能會導(dǎo)致的結(jié)果一樣),則系統(tǒng)可能會強(qiáng)制進(jìn)行供應(yīng)商升級。
<devsite-heading text="移除的類/權(quán)限" for="removed-class-permissions" level="h5" link="" class="">##### 移除的類/權(quán)限</devsite-heading>
移除對象管理器(例如 ZygoteConnection 對象管理器)會出現(xiàn)這種情況,應(yīng)該不會導(dǎo)致出現(xiàn)問題。對象管理器類和權(quán)限可以一直在政策中保持已定義狀態(tài),直到供應(yīng)商版本不再使用它為止。通過在相應(yīng)的映射文件中添加定義,可以做到這一點(diǎn)。
<devsite-heading text="新類型/重新添加標(biāo)簽的類型的供應(yīng)商自定義" for="vendor-customization-for-new-relabeled-types" level="h4" link="" class="">#### 新類型/重新添加標(biāo)簽的類型的供應(yīng)商自定義</devsite-heading>
新供應(yīng)商類型是制定供應(yīng)商政策的核心,這是因?yàn)樾鹿?yīng)商類型是說明新進(jìn)程、二進(jìn)制文件、設(shè)備、子系統(tǒng)和存儲的數(shù)據(jù)所必需的。因此,必須允許創(chuàng)建供應(yīng)商定義的類型。
由于供應(yīng)商政策始終是設(shè)備上最舊的政策,因此無需自動將所有供應(yīng)商類型轉(zhuǎn)換為政策中的屬性。平臺不依賴于在供應(yīng)商政策中標(biāo)記的任何內(nèi)容,因?yàn)槠脚_并不知道它;但是,平臺將提供它與帶有這些類型標(biāo)記的對象(例如 domain、sysfs_type 等)進(jìn)行交互所用的屬性和公共類型。為使平臺繼續(xù)與這些對象正確交互,必須適當(dāng)?shù)貞?yīng)用這些屬性和類型,并且可能需要將特定規(guī)則添加到可自定義域(例如 init)中。
<devsite-heading text="Android 9 的屬性更改" for="attributes-p" level="h2" link="" toc="" class="" back-to-top="">## Android 9 的屬性更改</devsite-heading> <devsite-heading text="Android 9 的屬性更改" for="attributes-p" level="h2" link="" toc="" class="" back-to-top=""></devsite-heading>
升級到 Android 9 的設(shè)備可以使用以下屬性,但搭載 Android 9 的設(shè)備不必如此。
<devsite-heading text="違規(guī)者屬性" for="violator-attributes" level="h3" link="" toc="" class="">### 違規(guī)者屬性</devsite-heading>
Android 9 包含以下與域相關(guān)的屬性:
-
data_between_core_and_vendor_violators。 違反不得按vendor和coredomains之間的路徑共享文件這一要求的所有域的屬性。平臺和供應(yīng)商進(jìn)程不應(yīng)使用磁盤文件進(jìn)行通信(不穩(wěn)定的 ABI)。 建議:- 供應(yīng)商代碼應(yīng)使用
/data/vendor。 - 系統(tǒng)不應(yīng)使用
/data/vendor。
- 供應(yīng)商代碼應(yīng)使用
-
system_executes_vendor_violators。違反不執(zhí)行供應(yīng)商二進(jìn)制文件這一要求的所有系統(tǒng)域(init和shell domains除外)的屬性。供應(yīng)商二進(jìn)制文件的執(zhí)行具有不穩(wěn)定的 API。平臺不應(yīng)直接執(zhí)行供應(yīng)商二進(jìn)制文件。建議:-
供應(yīng)商二進(jìn)制文件中的此類平臺依賴項(xiàng)必須位于 HIDL HAL 之后。
或
需要訪問供應(yīng)商二進(jìn)制文件的
coredomains應(yīng)移至供應(yīng)商分區(qū),因此不再是coredomain。
-
<devsite-heading text="不受信任的屬性" for="untrusted-attributes" level="h3" link="" toc="" class="">### 不受信任的屬性</devsite-heading>
托管任意代碼的不受信任的應(yīng)用不應(yīng)具有 HwBinder 服務(wù)的訪問權(quán)限,但被視為足夠安全而可以通過此類應(yīng)用訪問的服務(wù)除外(請參閱下面的安全服務(wù))。這主要有以下兩個原因:
- HwBinder 服務(wù)器不會執(zhí)行客戶端身份驗(yàn)證,因?yàn)?HIDL 目前未公開調(diào)用方 UID 信息。即使 HIDL 確實(shí)公開了此類數(shù)據(jù),許多 HwBinder 服務(wù)也會在低于應(yīng)用的級別運(yùn)行(例如 HAL),或者不能依賴應(yīng)用身份進(jìn)行授權(quán)。因此,為了安全起見,默認(rèn)假設(shè)是每個 HwBinder 服務(wù)都將其所有客戶端視為具有可執(zhí)行該服務(wù)所提供操作的同等授權(quán)。
- HAL 服務(wù)器(HwBinder 服務(wù)的一個子集)包含安全問題選擇率高于
system/core組件的代碼,并且可以訪問堆棧的較低層級(一直到硬件),從而提升繞過 Android 安全模型的機(jī)率。
<devsite-heading text="安全服務(wù)" for="safe-services" level="h4" link="" class="">#### 安全服務(wù)</devsite-heading>
安全服務(wù)包括:
-
same_process_hwservice。這些服務(wù)(根據(jù)定義)在客戶端進(jìn)程中運(yùn)行,因此與運(yùn)行該進(jìn)程的客戶端域具有相同的訪問權(quán)限。 -
coredomain_hwservice。這些服務(wù)不會帶來與第 2 種原因相關(guān)的風(fēng)險。 -
hal_configstore_ISurfaceFlingerConfigs。此服務(wù)專供任何域使用。 -
hal_graphics_allocator_hwservice。surfaceflingerBinder 服務(wù)(應(yīng)用可以訪問該服務(wù))也提供這些操作。 -
hal_omx_hwservice。這是mediacodecBinder 服務(wù)(應(yīng)用可以訪問該服務(wù))的 HwBinder 版本。 -
hal_codec2_hwservice。這是較新版本的hal_omx_hwservice。
<devsite-heading text="可用的屬性" for="useable-attributes" level="h4" link="" class="">#### 可用的屬性</devsite-heading>
所有被認(rèn)為不安全的 hwservices 都具有 untrusted_app_visible_hwservice 屬性。相應(yīng)的 HAL 服務(wù)器具有 untrusted_app_visible_halserver 屬性。搭載 Android P 的設(shè)備絕不得使用 untrusted 屬性。
建議:
-
不受信任的應(yīng)用應(yīng)與系統(tǒng)服務(wù)進(jìn)行通信,系統(tǒng)服務(wù)再與供應(yīng)商 HIDL HAL 通信。例如,應(yīng)用可以與
[binderservicedomain](https://android.googlesource.com/platform/system/sepolicy/+/master/public/app.te#209)通信,然后mediaserver(屬于binderservicedomain)再與[hal_graphics_allocator](https://android.googlesource.com/platform/system/sepolicy/+/master/private/mediaserver.te#6)通信。或
需要直接訪問
vendorHAL 的應(yīng)用應(yīng)具有各自的供應(yīng)商定義的 sepolicy 域。
<devsite-heading text="文件屬性測試" for="file-attribute-tests" level="h3" link="" toc="" class="">### 文件屬性測試</devsite-heading>
Android 9 包含一些編譯時測試,旨在確保特定位置的所有文件都具有適當(dāng)?shù)膶傩裕ɡ纾?code>sysfs 中的所有文件都具有必需的 sysfs_type 屬性)。
<devsite-heading text="平臺公共政策" for="platform-public-policy" level="h2" link="" toc="" class="" back-to-top="">## 平臺公共政策</devsite-heading> <devsite-heading text="平臺公共政策" for="platform-public-policy" level="h2" link="" toc="" class="" back-to-top=""></devsite-heading>
平臺公共政策是遵循 Android 8.0 架構(gòu)模型的核心所在,而不是簡單地將 v1 和 v2 中的平臺政策結(jié)合起來。供應(yīng)商可以看到一部分平臺政策(包含可用類型和屬性以及關(guān)于這些類型和屬性的規(guī)則),這部分政策隨后會包含在供應(yīng)商政策中(即 vendor_sepolicy.cil)。
類型和規(guī)則會在供應(yīng)商生成的政策中自動轉(zhuǎn)換為 attribute_v*N*,以便所有由平臺提供的類型都是帶有版本編號的屬性(但屬性不帶版本編號)。平臺負(fù)責(zé)將其提供的具體類型映射到適當(dāng)?shù)膶傩?,以確保供應(yīng)商政策繼續(xù)有效,并將為特定版本提供的規(guī)則包括在內(nèi)。將平臺公共政策和供應(yīng)商政策相結(jié)合可滿足 Android 8.0 架構(gòu)模型目標(biāo),即允許獨(dú)立平臺和供應(yīng)商構(gòu)建。
<devsite-heading text="映射到屬性鏈" for="mapping-to-attribute-chains" level="h3" link="" toc="" class="">### 映射到屬性鏈</devsite-heading>
使用屬性映射到政策版本時,一個類型會映射到一個或多個屬性,確保使用該類型標(biāo)記的對象可通過與這些對象之前的類型對應(yīng)的屬性訪問。
達(dá)成向政策編寫器隱藏版本信息的目標(biāo)意味著自動生成版本化屬性并分配給適當(dāng)?shù)念愋?。對于常見的靜態(tài)類型,這很簡單:type_foo 映射到 type_foo_v1。
對于對象標(biāo)簽更改(例如 sysfs → sysfs_A 或 mediaserver → audioserver),創(chuàng)建此映射非常重要(如上面的示例中所述)。平臺政策維護(hù)者必須確定如何在對象的轉(zhuǎn)換點(diǎn)處創(chuàng)建映射,這需要了解對象及其所分配到的標(biāo)簽之間的關(guān)系并確定何時發(fā)生這種情況。為了實(shí)現(xiàn)向后兼容性,需要在平臺端(這是唯一可以升級的分區(qū))管理這種復(fù)雜性。
<devsite-heading text="版本升級" for="version-uprevs" level="h3" link="" toc="" class="">### 版本升級</devsite-heading>
為簡單起見,Android 平臺會在新版本分支發(fā)布后推出一個 sepolicy 版本。如上所述,版本號包含在 PLATFORM_SEPOLICY_VERSION 中,其格式為 MM.nn,其中 MM 對應(yīng)于 SDK 值,nn 是在 /platform/system/sepolicy. 中維護(hù)的不公開值。 例如,19.0 對應(yīng)于 Kitkat,21.0 對應(yīng)于 Lollipop,22.0 對應(yīng)于 Lollipop-MR1,23.0 對應(yīng)于 Marshmallow,24.0 對應(yīng)于 Nougat,25.0 對應(yīng)于 Nougat-MR1,26.0 對應(yīng)于 Oreo,27.0 對應(yīng)于 Oreo-MR1,28.0 對應(yīng)于 Android P。Uprevs 不一定總是整數(shù)。例如,如果因 MR 版本遞增而需要對 system/sepolicy/public 進(jìn)行不兼容的更改,但不是 API 遞增,則該 sepolicy 版本可以為 vN.1。開發(fā)分支中的版本是 10000.0,該版本絕不會用在搭載 Android 的設(shè)備中。
Android 可能會在升級時棄用最舊的版本。為了解何時棄用某個版本,Android 可能會根據(jù)供應(yīng)商政策收集運(yùn)行該 Android 版本且仍在接收主要平臺更新的設(shè)備數(shù)量。如果該數(shù)字小于特定閾值,則會棄用該版本。
<devsite-heading text="多個屬性的性能影響" for="performance-impact-of-multiple-attributes" level="h3" link="" toc="" class="">### 多個屬性的性能影響</devsite-heading>
如 https://github.com/SELinuxProject/cil/issues/9 中所述,分配給某種類型的大量屬性會在政策緩存未命中時導(dǎo)致性能問題。
這已被證實(shí)是 Android 中存在的問題,因此我們對 Android 8.0 進(jìn)行了更改,以移除政策編譯器添加到政策中的屬性,另外還移除了未使用的屬性。這些更改解決了性能降低問題。
<devsite-heading text="SELinux 上下文標(biāo)簽" for="selinux-contexts-labeling" level="h2" link="" toc="" class="" back-to-top="">## SELinux 上下文標(biāo)簽</devsite-heading> <devsite-heading text="SELinux 上下文標(biāo)簽" for="selinux-contexts-labeling" level="h2" link="" toc="" class="" back-to-top=""></devsite-heading>
為便于區(qū)別平臺和供應(yīng)商 sepolicy,系統(tǒng)以不同方式構(gòu)建 SELinux 上下文文件以使它們分離開來。
<devsite-heading text="文件上下文" for="file-contexts" level="h3" link="" toc="" class="">### 文件上下文</devsite-heading>
Android 8.0 為 file_contexts 引入了以下更改:
- 為避免啟動期間在設(shè)備上產(chǎn)生額外的編譯開銷,
file_contexts不再以二進(jìn)制文件形式存在,而是可讀的正則表達(dá)式文本文件,例如{property, service}_contexts(和 7.0 之前的版本一樣)。 -
file_contexts拆分為兩個文件:-
plat_file_contexts- 沒有任何設(shè)備特定標(biāo)簽的 Android 平臺
file_context(/vendor分區(qū)的標(biāo)簽部分除外,為確保 sepolicy 文件正常運(yùn)行必須為這些部分準(zhǔn)確添加標(biāo)簽)。 - 必須位于設(shè)備上
system分區(qū)中的/system/etc/selinux/plat_file_contexts下,并由init在啟動時加載(與供應(yīng)商file_context一起加載)。
- 沒有任何設(shè)備特定標(biāo)簽的 Android 平臺
-
vendor_file_contexts- 設(shè)備特定
file_context,通過合并file_contexts(位于設(shè)備的Boardconfig.mk文件中由BOARD_SEPOLICY_DIRS指向的目錄下)進(jìn)行編譯。 - 必須安裝在
vendor分區(qū)的/vendor/etc/selinux/vendor_file_contexts中,并在啟動時由init加載(與平臺file_context一起加載)。
- 設(shè)備特定
-
<devsite-heading text="屬性上下文" for="property-contexts" level="h3" link="" toc="" class="">### 屬性上下文</devsite-heading>
在 Android 8.0 中,property_contexts 拆分到兩個文件中:
-
plat_property_contexts- 沒有任何設(shè)備特定標(biāo)簽的 Android 平臺
property_context。 - 必須位于
system分區(qū)中的/system/etc/selinux/plat_property_contexts下,并由init在啟動時加載(與供應(yīng)商property_contexts一起加載)。
- 沒有任何設(shè)備特定標(biāo)簽的 Android 平臺
-
vendor_property_contexts- 設(shè)備特定
property_context,通過合并property_contexts(位于設(shè)備的Boardconfig.mk文件中由BOARD_SEPOLICY_DIRS指向的目錄下)進(jìn)行編譯。 - 必須位于
vendor分區(qū)中的/vendor/etc/selinux/vendor_property_contexts下,并由init在啟動時加載(與平臺property_context一起加載)。
- 設(shè)備特定
<devsite-heading text="服務(wù)上下文" for="service-contexts" level="h3" link="" toc="" class="">### 服務(wù)上下文</devsite-heading>
在 Android 8.0 中,service_contexts 拆分到以下兩個文件中:
-
plat_service_contexts-
servicemanager的 Android 平臺特定service_context。service_context沒有設(shè)備特定標(biāo)簽。 - 必須位于
system分區(qū)中的/system/etc/selinux/plat_service_contexts下,并由servicemanager在啟動時加載(與供應(yīng)商service_contexts一起加載)。
-
-
vendor_service_contexts- 設(shè)備特定
service_context,通過合并service_contexts(位于設(shè)備的Boardconfig.mk文件中由BOARD_SEPOLICY_DIRS指向的目錄下)進(jìn)行編譯。 - 必須位于
vendor分區(qū)中的/vendor/etc/selinux/vendor_service_contexts下,并由servicemanager在啟動時加載(與平臺service_contexts一起加載)。 - 雖然
servicemanager會在啟動時查找此文件,但對于完全兼容的TREBLE設(shè)備,vendor_service_contexts絕不能存在。這是因?yàn)?vendor和system進(jìn)程之間的所有交互都必須執(zhí)行hwservicemanager/hwbinder。
- 設(shè)備特定
-
plat_hwservice_contexts-
hwservicemanager的 Android 平臺hwservice_context(沒有任何設(shè)備特定標(biāo)簽)。 - 必須位于
system分區(qū)中的/system/etc/selinux/plat_hwservice_contexts下,并由hwservicemanager在啟動時加載(與vendor_hwservice_contexts一起加載)。
-
-
vendor_hwservice_contexts- 設(shè)備特定
hwservice_context,通過合并hwservice_contexts(位于設(shè)備的Boardconfig.mk文件中由BOARD_SEPOLICY_DIRS指向的目錄下)進(jìn)行編譯。 - 必須位于
vendor分區(qū)中的/vendor/etc/selinux/vendor_hwservice_contexts下,并由hwservicemanager在啟動時加載(與plat_service_contexts一起加載)。
- 設(shè)備特定
-
vndservice_contexts-
vndservicemanager的設(shè)備特定service_context,通過合并vndservice_contexts(位于設(shè)備的Boardconfig.mk文件中由BOARD_SEPOLICY_DIRS指向的目錄下)進(jìn)行編譯。 - 必須位于
vendor分區(qū)中的/vendor/etc/selinux/vndservice_contexts下,并由vndservicemanager在啟動時加載。
-
<devsite-heading text="Seapp 上下文" for="seapp-contexts" level="h3" link="" toc="" class="">### Seapp 上下文</devsite-heading>
在 Android 8.0 中,seapp_contexts 拆分到兩個文件中:
-
plat_seapp_contexts- 沒有設(shè)備特定更改的 Android 平臺
seapp_context。 - 必須位于
system分區(qū)中的/system/etc/selinux/plat_seapp_contexts.下。
- 沒有設(shè)備特定更改的 Android 平臺
-
vendor_seapp_contexts- 平臺
seapp_context的設(shè)備特定擴(kuò)展,通過合并seapp_contexts(位于設(shè)備的Boardconfig.mk文件中由BOARD_SEPOLICY_DIRS指向的目錄下)進(jìn)行編譯。 - 必須位于
vendor分區(qū)中的/vendor/etc/selinux/vendor_seapp_contexts下。
- 平臺
<devsite-heading text="MAC 權(quán)限" for="mac-permissions" level="h3" link="" toc="" class="">### MAC 權(quán)限</devsite-heading>
在 Android 8.0 中,mac_permissions.xml 拆分到兩個文件中:
- 平臺
mac_permissions.xml- 沒有設(shè)備特定更改的 Android 平臺
mac_permissions.xml。 - 必須位于
system分區(qū)中的/system/etc/selinux/.下。
- 沒有設(shè)備特定更改的 Android 平臺
- 非平臺
mac_permissions.xml- 平臺
mac_permissions.xml的設(shè)備特定擴(kuò)展,通過mac_permissions.xml(位于設(shè)備的Boardconfig.mk文件中由BOARD_SEPOLICY_DIRS指向的目錄下)進(jìn)行編譯。 - 必須位于
vendor分區(qū)中的/vendor/etc/selinux/.下。
- 平臺