添加到構建中的文件系統對象和服務經常需要單獨的唯一 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[]
數組。在生成 Bionic android_ids[]
數組時,所有 AID 友好名稱都是從system/core/libcutils/include/private/android_filesystem_config.h
頭文件生成的。任何與AID_*
匹配的define
都會被工具拾取,並且*成為小寫名稱。
例如,在private/android_filesystem_config.h
中:
#define AID_SYSTEM 1000
變成:
- 友好名稱:系統
- 用戶ID: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 格式,包括一個 caps 部分(用於配置文件系統功能)和一個 AIDs 部分(用於配置 OEM AID)。
配置大寫部分
caps 部分支持在構建中的文件系統對像上設置文件系統功能(文件系統本身也必須支持此功能)。
由於在 Android 中以 root 身份運行穩定服務會導致兼容性測試套件 (CTS)失敗,因此在運行進程或服務時保留功能的先前要求涉及設置功能,然後使用setuid
/ setgid
到適當的 AID 來運行。使用 caps,您可以跳過這些要求並讓內核為您完成。當控制權交給main()
時,您的進程已經具備了所需的功能,因此您的服務可以使用非 root 用戶和組(這是啟動特權服務的首選方式)。
大寫部分使用以下語法:
部分 | 價值 | 定義 |
---|---|---|
[path] | 要配置的文件系統路徑。以 / 結尾的路徑被認為是一個目錄,否則它是一個文件。 在不同的文件中指定具有相同 [path] 的多個部分是錯誤的。在 Python 版本 <= 3.2 中,同一文件可能包含覆蓋前一部分的部分;在 Python 3.2 中,它被設置為嚴格模式。 | |
mode | 八進製文件模式 | 至少 3 位的有效八進製文件模式。如果指定了 3,則以 0 為前綴,否則按原樣使用模式。 |
user | AID_<用戶> | C define 的有效AID 或友好名稱(例如AID_RADIO 和radio 都可接受)。要定義自定義 AID,請參閱配置 AID 部分。 |
group | AID_<組> | 與用戶相同。 |
caps | 帽* | 在bionic/libc/kernel/uapi/linux/capability.h 中聲明的名稱沒有前導CAP_ 。允許混合大小寫。大寫也可以是原始的:
|
有關使用示例,請參閱使用文件系統功能。
配置 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 中定義。選項包括:
|
有關使用示例,請參閱定義 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.rc
的chown
命令中:chown vendor_foo /vendor/some/vendor_foo/file
- 在
some/init.rc
的service
中:service vendor_foo /vendor/bin/foo_service user vendor_foo group vendor_foo
因為從友好名稱到 uid 的內部映射是由/vendor/etc/passwd
和/vendor/etc/group
執行的,所以必須掛載 vendor 分區。
關聯友好名稱
Android 9 支持將友好名稱與實際 OEM AID 值相關聯。您可以對用戶和組使用非數字字符串參數,即“ vendor_ foo”而不是“2901”。
從 AID 轉換為友好名稱
對於OEM AID ,Android 8.x 要求將oem_####
與getpwnam
和類似功能一起使用,以及在通過getpwnam
處理查找的地方(例如init
腳本)。在 Android 9 中,您可以使用 Bionic 中的getpwnam
和getgrnam
朋友將 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
創建文件後,將TARGET_FS_CONFIG_GEN
設置為指向BoardConfig.mk
中的該文件。例如,在device/x/y/BoardConfig.mk
中,設置以下內容:
TARGET_FS_CONFIG_GEN += device/x/y/config.fs
當 service vendor_ foo
被執行時,它以沒有setuid
和setgid
調用的能力CAP_SYS_ADMIN
和CAP_SYS_NICE
開始。此外, vendor_ foo
服務的 SELinux 策略不再需要能力setuid
和setgid
,可以刪除。
配置覆蓋 (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 中引入的模塊化配置系統所取代,但如果需要,您仍然可以使用舊方法。以下部分詳細介紹瞭如何生成和包含覆蓋文件以及配置文件系統。
生成覆蓋文件
您可以使用build/tools/fs_config
中的fs_config_generate
生成對齊的二進製文件/system/etc/fs_config_dirs
和/system/etc/fs_config_files
fs_config_files 。該工具使用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_DIRS
和NO_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
。構建系統在$(TARGET_DEVICE_DIR)
中搜索自定義android_filesystem_config.h
,其中BoardConfig.mk
存在。如果此文件存在於其他位置,請將板配置變量TARGET_ANDROID_FILESYSTEM_CONFIG_H
設置為指向該位置。
配置文件系統
在 Android 6.0 及更高版本中配置文件系統:
- 創建
$(TARGET_DEVICE_DIR)/android_filesystem_config.h
文件。 - 將
fs_config_dirs
和/或fs_config_files
添加到電路板配置文件中的PRODUCT_PACKAGES
(例如$(TARGET_DEVICE_DIR)/device.mk
)。
覆蓋示例
此示例顯示了用於覆蓋system/bin/glgps
守護程序以在device/ vendor / device
目錄中添加喚醒鎖支持的補丁。請記住以下幾點:
- 每個結構條目是模式、uid、gid、功能和名稱。
system/core/include/private/android_filesystem_config.h
被自動包含以提供清單#defines (AID_ROOT
,AID_SHELL
,CAP_BLOCK_SUSPEND
)。 -
android_device_files[]
部分包含一個在未指定時禁止訪問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()
的自定義目標可執行文件的實現必須確保訪問。