新增至建構作業的檔案系統物件和服務通常需要個別的專屬 ID,也就是 Android ID (AID)。目前,許多資源 (例如檔案和服務) 都會不必要地使用核心 (Android 定義) AID;在許多情況下,您可以使用 OEM (OEM 定義) AID。
舊版 Android (Android 7.x 以下) 使用裝置專屬的 android_filesystem_config.h
檔案指定檔案系統功能和/或自訂 OEM AID,擴充了 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
標頭檔案產生。工具會擷取任何define
相符AID_*
項目,並將「*」轉換為小寫名稱。
例如,在 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 格式,並包含 caps 區段 (用於設定檔案系統功能) 和 AID 區段 (用於設定 OEM AID)。
設定上限專區
caps 區段支援在建構中的檔案系統物件上設定檔案系統功能 (檔案系統本身也必須支援這項功能)。
由於在 Android 中以根身分執行穩定服務會導致 Compatibility Test Suite (CTS) 失敗,因此先前的要求是在執行程序或服務時保留功能,然後設定功能,再使用 setuid
/setgid
執行適當的 AID。有了上限,您就可以略過這些需求,讓核心為您執行。控制權移交給 main()
時,您的程序已具備所需功能,因此服務可以使用非根使用者和群組 (這是啟動具備權限服務的首選方式)。
上限部分使用下列語法:
小節 | 值 | 定義 |
---|---|---|
[path] |
要設定的檔案系統路徑。以「/」結尾的路徑會視為目錄,否則為檔案。 如果在不同檔案中指定多個具有相同 [path] 的區段,就會發生錯誤。在 Python 3.2 之前的版本中,同一個檔案可能包含會覆寫前一個區段的區段;在 Python 3.2 中,則會設為嚴格模式。 |
|
mode |
八進位檔案模式 | 至少 3 位數的有效八進位檔案模式。如果指定 3,則會加上前置 0,否則會直接使用模式。 |
user |
AID_<user> | 有效 AID 的 C define 或易記名稱 (例如 AID_RADIO 和 radio 都是可接受的值)。如要定義自訂 AID,請參閱「設定 AID」一節。 |
group |
AID_<group> | 與使用者相同。 |
caps |
cap* | 如 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,請在相關聯的 Makefile 中加入 oemaids_headers
,並新增 #include "generated_oem_aid.h"
,然後開始使用宣告的 ID。例如,在 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
執行,因此必須掛接供應商分割區。
關聯好記的名稱
Android 9 支援將好記的名稱與實際的 OEM AID 值建立關聯。您可以為使用者和群組使用非數字字串引數,也就是「vendor_foo」,而非「2901」。
將 AID 轉換為好記的名稱
對於 OEM AID,Android 8.x 必須搭配 getpwnam
和類似函式使用 oem_####
,以及在處理 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
建立檔案後,請在 BoardConfig.mk
中將 TARGET_FS_CONFIG_GEN
設為指向該檔案。舉例來說,在 device/x/y/BoardConfig.mk
中設定以下內容:
TARGET_FS_CONFIG_GEN += device/x/y/config.fs
執行服務 vendor_foo
時,會以功能 CAP_SYS_ADMIN
和 CAP_SYS_NICE
啟動,不會呼叫 setuid
和 setgid
。此外,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
。這項工具會使用 libcutils
程式庫函式 (fs_config_generate()
) 將 DAC 需求項目管理到緩衝區,並定義包含檔案的規則,以建立 DAC 規則。
如要使用,請在 device/vendor/device/android_filesystem_config.h
中建立包含檔案,做為覆寫檔案。檔案必須使用 structure fs_path_config
格式 (如 system/core/include/private/android_filesystem_config.h
中所定義),並為目錄和檔案符號進行下列結構初始化:
- 如果是目錄,請使用
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
) 中的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 file system +** 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()
的自訂目標可執行檔,則必須確保存取權。