Google is committed to advancing racial equity for Black communities. See how.
本頁面由 Cloud Translation API 翻譯而成。
Switch to English

自由訪問控制(DAC)

添加到構建中的文件系統對象和服務通常需要單獨的唯一ID,稱為Android ID(AID)。當前,諸如文件和服務之類的許多資源不必要地使用核心(Android定義的)AID。在許多情況下,您可以改用OEM(OEM定義的)AID。

Android的早期版本(Android 7.x和更低版本)使用設備特定的android_filesystem_config.h文件擴展了AID機制,以指定文件系統功能和/或自定義OEM AID。但是,此系統不直觀,因為它不支持為OEM AID使用好聽的名稱,要求您為用戶和組字段指定原始數字,而無法將友好名稱與數字AID關聯。

較新版本的Android(Android 8.0及更高版本)支持擴展文件系統功能的新方法。此新方法支持以下功能:

  • 配置文件的多個源位置(啟用可擴展的構建配置)。
  • OEM AID值的構建時完整性檢查。
  • 生成自定義OEM AID標頭,可根據需要在源文件中使用該標頭。
  • 友好名稱與實際OEM AID值的關聯。支持用戶和組的非數字字符串參數,即“ foo”而不是“ 2901”。

其他改進包括從system/core/libcutils/include/private/android_filesystem_config.h刪除android_ids[]數組。該數組現在作為完全私有生成的數組存在於Bionic中,並通過getpwnam()getgrnam() 。 (這具有在修改核心AID時產生穩定二進製文件的副作用。)有關工具和具有更多詳細信息的README文件,請參閱build/make/tools/fs_config

添加Android ID(AID)

Android 8.0從Android開放源代碼項目(AOSP)中刪除了android_ids[]數組。當生成仿生android_ids[]數組時,所有AID友好名稱都是從system/core/libcutils/include/private/android_filesystem_config.h頭文件生成的。工具將拾取任何與AID_*匹配的define ,並且*變為小寫名稱。

例如,在private/android_filesystem_config.h

#define AID_SYSTEM 1000

成為:

  • 友好名稱:系統
  • uid:1000
  • gid:1000

要添加新的AOSP核心AID,只需將#define添加到android_filesystem_config.h頭文件中。 AID將在構建時生成,並可供使用用戶和組參數的接口使用。該工具將驗證新的AID是否不在APP或OEM範圍內;它還尊重對這些範圍的更改,並應根據更改或新的OEM保留範圍自動重新配置。

配置AID

要啟用新的AID機制,請在BoardConfig.mk文件中設置TARGET_FS_CONFIG_GEN 。此變量保存配置文件列表,使您可以根據需要附加文件。

按照約定,配置文件使用名稱config.fs ,但實際上您可以使用任何名稱。 config.fs文件採用Python ConfigParser ini格式,並包括一個大寫部分(用於配置文件系統功能)和一個AIDs部分(用於配置OEM AID)。

配置大寫部分

caps部分支持在構建中的文件系統對像上設置文件系統功能 (文件系統本身也必須支持此功能)。

由於在Android中以root用戶身份運行穩定的服務會導致兼容性測試套件(CTS)失敗,因此,在運行進程或服務時保留功能的先前要求涉及設置功能,然後使用setuid / setgid來運行適當的AID。使用大寫,您可以跳過這些要求,讓內核為您完成。將控制權交給main() ,您的進程已經具有所需的功能,因此您的服務可以使用非root用戶和組(這是啟動特權服務的首選方式)。

caps部分使用以下語法:

部分定義
[path] 要配置的文件系統路徑。以/結尾的路徑被視為目錄,否則為文件。

在不同文件中指定具有相同[path]多個節是錯誤的。在<= 3.2的Python版本中,同一文件可能包含覆蓋前一部分的部分;在Python 3.2中,它設置為嚴格模式。
mode 八進製文件模式有效的八進製文件模式,至少3位數字。如果指定3,則其前綴為0,否則按原樣使用mode。
user AID_ <用戶> C define有效的AID或友好名稱(例如AID_RADIOradio均可接受)。要定義自定義AID,請參閱“ 配置AID”部分
group AID_ <組> 與用戶相同。
caps 帽* bionic/libc/kernel/uapi/linux/capability.h聲明的名稱,不帶前導CAP_ 。允許混合大小寫。上限也可以是原始的:
  • 二進制(0b0101)
  • 八進制(0455)
  • 整數(42)
  • 十六進制(0xFF)
使用空格分隔多個大寫字母。

有關用法示例,請參閱使用文件系統功能

配置AID部分

AID部分包含OEM AID,並使用以下語法:

部分定義
[AID_<name>] <name>可以包含設置為大寫字母,數字和下劃線的字符。小寫版本用作友好名稱。生成的用於代碼包含的頭文件使用精確的AID_<name>

指定具有相同AID_<name>多個節是錯誤的(不區分大小寫,並且具有與[path]相同的約束)。

<name>必須以分區名稱開頭,以確保它不與其他源衝突。
value <編號> 有效的C樣式數字字符串(十六進制,八進制,二進制和十進制)。

用相同的值選項指定多個節是錯誤的。

必須在與<name>使用的分區相對應的範圍內指定值選項。有效分區及其對應範圍的列表在system/core/libcutils/include/private/android_filesystem_config.h 。選項包括:
  • 供應商分區
    • AID_OEM_RESERVED_START(2900)-AID_OEM_RESERVED_END(2999)
    • AID_OEM_RESERVED_2_START(5000)-AID_OEM_RESERVED_2_END(5999)
  • 系統分區
    • AID_SYSTEM_RESERVED_START(6000)-AID_SYSTEM_RESERVED_END(6499)
  • ODM分區
    • AID_ODM_RESERVED_START(6500)-AID_ODM_RESERVED_END(6999)
  • 產品分區
    • AID_PRODUCT_RESERVED_START(7000)-AID_PRODUCT_RESERVED_END(7499)
  • System_ext分區
    • AID_SYSTEM_EXT_RESERVED_START(7500)-AID_SYSTEM_EXT_RESERVED_END(7999)

有關使用示例,請參閱定義OEM AID名稱使用OEM AID

用法示例

以下示例詳細說明瞭如何定義和使用OEM AID以及如何啟用文件系統功能。 OEM AID名稱( [AID_ name ] )必須以分區名稱開頭,例如“ vendor_ ”,以確保它們不與將來的AOSP名稱或其他分區衝突。

定義OEM AID名稱

要定義OEM AID,請創建config.fs文件並設置AID值。例如,在device/x/y/config.fs ,設置以下內容:

[AID_VENDOR_FOO]
value: 2900

創建文件後,設置TARGET_FS_CONFIG_GEN變量並在BoardConfig.mk指向它。例如,在device/x/y/BoardConfig.mk ,設置以下內容:

TARGET_FS_CONFIG_GEN += device/x/y/config.fs

您的自定義AID現在可以在新版本中被整個系統使用。

使用OEM AID

要使用OEM AID,請在您的C代碼中,將oemaids_headers包含在關聯的Makefile中,並添加#include "generated_oem_aid.h" ,然後開始使用聲明的標識符。例如,在my_file.c ,添加以下內容:

#include "generated_oem_aid.h"
…

If (ipc->uid == AID_VENDOR_FOO) {
  // Do something
...

在關聯的Android.bp文件中,添加以下內容:

header_libs: ["oemaids_headers"],

如果您使用的是Android.mk文件,請添加以下內容:

LOCAL_HEADER_LIBRARIES := oemaids_headers

使用友好的名字

在Android 9中,您可以對任何支持AID名稱的接口使用友好名稱。例如:

  • some/init.rcchown命令中:
    chown vendor_foo /vendor/some/vendor_foo/file
    
  • some/init.rcservice中:
    service vendor_foo /vendor/bin/foo_service
        user vendor_foo
        group vendor_foo
    

因為從友好名稱到uid的內部映射是由/vendor/etc/passwd/vendor/etc/group ,所以必須安裝供應商分區。

關聯友好名稱

Android 9支持將友好名稱與實際OEM AID值相關聯。您可以為用戶和組使用非數字字符串參數,即“ vendor_ foo”而不是“ 2901”。

從AID轉換為友好名稱

對於OEM AID ,Android 8.x要求使用帶有getpwnam和類似功能的oem_####以及在通過getpwnam處理查找的getpwnam (例如init腳本)。在Android 9中,您可以使用Bionic中的getpwnamgetgrnam朋友將Android ID(AID)轉換為友好名稱,反之亦然。

使用文件系統功能

要啟用文件系統功能,請在config.fs文件中創建一個caps部分。例如,在device/x/y/config.fs ,添加以下部分:

[system/bin/foo_service]
mode: 0555
user: AID_VENDOR_FOO
group: AID_SYSTEM
caps: SYS_ADMIN | SYS_NICE

創建文件後,在BoardConfig.mk TARGET_FS_CONFIG_GEN設置為指向該文件。例如,在device/x/y/BoardConfig.mk ,設置以下內容:

TARGET_FS_CONFIG_GEN += device/x/y/config.fs

執行服務vendor_ foo ,它將以功能CAP_SYS_ADMINCAP_SYS_NICE開始,而不會調用setuidsetgid 。此外, vendor_ foo服務的SELinux策略不再需要功能setuidsetgid ,可以將其刪除。

配置替代(Android 6.x-7.x)

Android 6.0將fs_config和相關的結構定義( system/core/include/private/android_filesystem_config.h )移到了system/core/libcutils/fs_config.c中,可以通過/system/etc/fs_config_dirs/system/etc/fs_config_files 。對目錄和文件使用單獨的匹配和解析規則(可以使用其他glob表達式)使Android能夠處理兩個不同表中的目錄和文件。 system/core/libcutils/fs_config.c結構定義不僅允許運行時讀取目錄和文件,而且主機可以在構建期間使用相同的文件來構建文件系統映像,例如${OUT}/system/etc/fs_config_dirs${OUT}/system/etc/fs_config_files

雖然擴展文件系統的替代方法已被Android 8.0中引入的模塊化配置系統所取代,但如果需要,您仍然可以使用舊方法。以下各節詳細介紹瞭如何生成和包括替代文件以及配置文件系統。

生成替代文件

您可以生成對齊的二進制文件/system/etc/fs_config_dirs/system/etc/fs_config_files使用fs_config_generate在工具build/tools/fs_config 。該工具使用libcutils庫函數( fs_config_generate() )將DAC需求管理到緩衝區中,並為包含文件定義規則,以使DAC規則制度化。

要使用該文件,請在device/ vendor / device /android_filesystem_config.h中創建一個包含文件,以作為覆蓋文件。該文件必須使用在system/core/include/private/android_filesystem_config.h定義的structure fs_path_config格式,並對目錄和文件符號使用以下結構初始化:

  • 對於目錄,請使用android _device _dirs[]
  • 對於文件,請使用android _device _files[]

當不使用android_device_dirs[]android_device_files[] ,您可以定義NO_ANDROID_FILESYSTEM_CONFIG_DEVICE_DIRSNO_ANDROID_FILESYSTEM_CONFIG_DEVICE_FILES (請參見下面的示例 )。您還可以在板配置中使用TARGET_ANDROID_FILESYSTEM_CONFIG_H指定替代文件,其基本名稱為android_filesystem_config.h

包括替代文件

要包含文件,請確保PRODUCT_PACKAGES包含fs_config_dirs和/或fs_config_files以便它可以將它們分別安裝到/system/etc/fs_config_dirs/system/etc/fs_config_files 。構建系統會在存在BoardConfig.mk $(TARGET_DEVICE_DIR)搜索自定義android_filesystem_config.h 。如果此文件在其他位置,請將板配置變量TARGET_ANDROID_FILESYSTEM_CONFIG_H指向該位置。

配置文件系統

要在Android 6.0及更高版本中配置文件系統,請執行以下操作:

  1. 創建$(TARGET_DEVICE_DIR)/android_filesystem_config.h文件。
  2. fs_config_dirs和/或fs_config_files添加到板配置文件(例如$(TARGET_DEVICE_DIR)/device.mk )中的PRODUCT_PACKAGES中。

替代示例

此示例顯示了一個補丁,用於覆蓋system/bin/glgps守護程序,以在device/ vendor / device目錄中添加喚醒鎖支持。請記住以下幾點:

  • 每個結構條目都是模式,uid,gid,功能和名稱。 system/core/include/private/android_filesystem_config.h會自動system/core/include/private/android_filesystem_config.h以提供清單AID_ROOTAID_ROOTAID_SHELLCAP_BLOCK_SUSPEND )。
  • android_device_files[]部分包含一個操作, system/etc/fs_config_dirs在未指定時禁止訪問system/etc/fs_config_dirs ,該操作可作為缺少目錄覆蓋內容的附加DAC保護。但是,這是薄弱的保護;如果某人可以控制/system ,那麼他們通常可以做他們想做的任何事情。
diff --git a/android_filesystem_config.h b/android_filesystem_config.h
new file mode 100644
index 0000000..874195f
--- /dev/null
+++ b/android_filesystem_config.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+/* This file is used to define the properties of the filesystem
+** images generated by build tools (eg: mkbootfs) and
+** by the device side of adb.
+*/
+
+#define NO_ANDROID_FILESYSTEM_CONFIG_DEVICE_DIRS
+/* static const struct fs_path_config android_device_dirs[] = { }; */
+
+/* Rules for files.
+** These rules are applied based on "first match", so they
+** should start with the most specific path and work their
+** way up to the root. Prefixes ending in * denotes wildcard
+** and will allow partial matches.
+*/
+static const struct fs_path_config android_device_files[] = {
+  { 00755, AID_ROOT, AID_SHELL, (1ULL << CAP_BLOCK_SUSPEND),
"system/bin/glgps" },
+#ifdef NO_ANDROID_FILESYSTEM_CONFIG_DEVICE_DIRS
+  { 00000, AID_ROOT, AID_ROOT, 0, "system/etc/fs_config_dirs" },
+#endif
+};


diff --git a/device.mk b/device.mk
index 0c71d21..235c1a7 100644
--- a/device.mk
+++ b/device.mk
@@ -18,7 +18,8 @@ PRODUCT_PACKAGES := \
     libwpa_client \
     hostapd \
     wpa_supplicant \
-    wpa_supplicant.conf
+    wpa_supplicant.conf \
+    fs_config_files

 ifeq ($(TARGET_PREBUILT_KERNEL),)
 ifeq ($(USE_SVELTE_KERNEL), true)

從早期版本遷移文件系統

從Android 5.x和更早版本遷移文件系統時,請記住,Android 6.x

  • 刪除一些包含,結構和內聯定義。
  • 需要引用libcutils而不是直接從system/core/include/private/android_filesystem_config.h 。依賴於system/code/include/private_filesystem_config.h的文件或目錄結構或fs_config設備製造商專用可執行文件必須添加libcutils庫依賴項。
  • 需要設備製造商的system/core/include/private/android_filesystem_config.h私有分支副本以及現有目標上的額外內容,才能移動到device/ vendor / device /android_filesystem_config.h
  • 保留將SELinux強制訪問控制(MAC)應用於目標系統上的配置文件的權利,使用fs_config()包含自定義目標可執行文件的實現必須確保訪問權限。