Объектам и сервисам файловой системы, добавленным в сборку, часто требуются отдельные уникальные идентификаторы, известные как идентификаторы Android (AID). В настоящее время многие ресурсы, такие как файлы и сервисы, без необходимости используют основные идентификаторы AID (определенные Android). Во многих случаях вместо них можно использовать идентификаторы AID OEM (определенные OEM).
В более ранних версиях Android (Android 7.x и ниже) механизм AID был расширен за счет использования файла android_filesystem_config.h, который зависит от устройства и позволяет указывать возможности файловой системы и/или пользовательские AID OEM. Однако эта система была неинтуитивной, поскольку не поддерживала использование понятных названий для идентификаторов OEM AID, требуя указывать необработанные числовые значения для полей пользователя и группы без возможности связать понятное название с числовым идентификатором AID.
В более новых версиях Android (8.0 и выше) поддерживается новый метод расширения возможностей файловой системы. Этот новый метод поддерживает следующее:
- Несколько исходных местоположений для файлов конфигурации (позволяет расширять конфигурации сборки).
- Проверка значений AID OEM во время сборки.
- Создание специального заголовка AID OEM, который можно использовать в исходных файлах.
- Сопоставление понятного названия с фактическим значением AID OEM-производителя. Поддерживает нечисловые строковые аргументы для пользователя и группы, например "foo" вместо "2901".
Также мы удалили массив android_ids[] из system/core/libcutils/include/private/android_filesystem_config.h. Теперь этот массив существует в Bionic как полностью закрытый сгенерированный массив с методами доступа с getpwnam() и getgrnam(). (Это имеет побочный эффект в виде создания стабильных двоичных файлов, поскольку основные идентификаторы AID изменяются.) Инструменты и файл README с дополнительной информацией можно найти на странице build/make/tools/fs_config.
Как добавить идентификаторы Android (AID)
В Android 8.0 массив android_ids[] был удален из Android Open Source Project (AOSP). Все понятные названия AID генерируются из заголовочного файла system/core/libcutils/include/private/android_filesystem_config.h при создании массива Bionic android_ids[]. Любые символы, соответствующие define и AID_*, будут распознаны инструментом, и * будет преобразовано в название в нижнем регистре.
Например, в private/android_filesystem_config.h:
#define AID_SYSTEM 1000Становится:
- Понятное название: система
- uid: 1000
- gid: 1000
Чтобы добавить новый основной идентификатор приложения AOSP, просто добавьте #define в заголовочный файл android_filesystem_config.h. Идентификатор AID генерируется при сборке и доступен интерфейсам, которые используют аргументы пользователя и группы. Инструмент проверяет, не входит ли новый AID в диапазоны APP или OEM. Он также учитывает изменения в этих диапазонах и должен автоматически перенастраиваться при изменении или появлении новых диапазонов, зарезервированных OEM.
Как настроить идентификаторы устройств
Чтобы включить новый механизм идентификаторов рекламы, задайте значение TARGET_FS_CONFIG_GEN в файле BoardConfig.mk. Эта переменная содержит список файлов конфигурации, позволяющий добавлять файлы по мере необходимости.
По соглашению файлы конфигурации называются config.fs, но на практике можно использовать любое название. Файлы config.fs имеют формат INI ConfigParser Python и содержат раздел caps (для настройки возможностей файловой системы) и раздел AIDs (для настройки идентификаторов OEM).
Как настроить раздел ограничений
Раздел caps позволяет задавать возможности файловой системы для ее объектов в сборке (сама файловая система также должна поддерживать эту функцию).
Поскольку стабильная работа сервиса с правами root в Android приводит к сбою Compatibility Test Suite (CTS), предыдущие требования к сохранению возможности при запуске процесса или сервиса включали настройку возможностей, а затем использование setuid/setgid для правильного AID. С помощью caps вы можете пропустить эти требования и заставить ядро сделать это за вас. Когда управление передается main(), у вашего процесса уже есть необходимые возможности, поэтому ваш сервис может использовать пользователя и группу без прав root (это предпочтительный способ запуска сервисов с правами доступа).
В разделе caps используется следующий синтаксис:
| Раздел | Значение | Определение |
|---|---|---|
[path] |
Путь к файловой системе, которую нужно настроить. Путь, заканчивающийся на /, считается каталогом,
в противном случае – файлом.
Нельзя указывать несколько разделов с одинаковым значением [path] в разных файлах. В версиях Python до 3.2 включительно один и тот же файл может содержать разделы, которые переопределяют предыдущие разделы. В Python 3.2 установлен строгий режим. |
|
mode |
Восьмеричный режим файла | Действительный восьмеричный режим файла, состоящий как минимум из трех цифр. Если указано значение 3, перед ним добавляется 0, в противном случае режим используется как есть. |
user |
AID_<user> | C define для действительного идентификатора AID или понятное название (например, AID_RADIO и radio). Чтобы задать специальный идентификатор приложения, ознакомьтесь с разделом Настройка идентификатора приложения. |
group |
AID_<group> | Как у пользователя. |
caps |
cap* | Название, указанное в
bionic/libc/kernel/uapi/linux/capability.h
без символа CAP_ в начале. Допускается смешанный регистр. Также можно использовать необработанные данные:
|
Пример использования приведен в разделе Как использовать возможности файловой системы.
Как настроить раздел AID
Раздел AID содержит идентификаторы AID OEM и использует следующий синтаксис:
| Раздел | Значение | Определение |
|---|---|---|
[AID_<name>] |
<name> может содержать символы из следующего набора: прописные буквы, цифры и символы подчеркивания. Версия в нижнем регистре используется в качестве понятного названия. В сгенерированном заголовочном файле для включения кода используется точное значение AID_<name>.
Нельзя указывать несколько разделов с одинаковым значением AID_<name> (без учета регистра и с теми же ограничениями, что и для [path]).
<name> должен начинаться с названия раздела, чтобы не было конфликтов с другими источниками. |
|
value |
<номер> | Допустимая строка чисел в стиле C (шестнадцатеричная, восьмеричная, двоичная и десятичная).
Нельзя указывать несколько разделов с одинаковым значением параметра. Варианты значений должны быть указаны в диапазоне, соответствующем разделу, используемому в <name>. Список допустимых разделов и соответствующих им диапазонов определен в system/core/libcutils/include/private/android_filesystem_config.h.
Доступны следующие варианты:
|
Примеры использования приведены в разделах Как задавать названия AID OEM и Как использовать AID OEM.
Примеры использования
В примерах ниже показано, как определить и использовать идентификатор AID от OEM-производителя и как включить функции файловой системы. Названия AID, созданных производителем оборудования ([AID_name]), должны начинаться с названия раздела, например vendor_, чтобы избежать конфликтов с названиями AOSP или других разделов.
Как задать названия идентификаторов OEM
Чтобы определить AID OEM-производителя, создайте файл 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, добавьте в код 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. Пример:
- В команде
chownвsome/init.rc:chown vendor_foo /vendor/some/vendor_foo/file
- В
serviceвsome/init.rc:service vendor_foo /vendor/bin/foo_service user vendor_foo group vendor_foo
Поскольку внутреннее сопоставление понятного имени с UID выполняется с помощью /vendor/etc/passwd и /vendor/etc/group, раздел поставщика должен быть смонтирован.
Как связать понятные названия
В Android 9 поддерживается возможность связывать понятное название с фактическим значением AID OEM. В качестве аргументов для пользователя и группы можно использовать нечисловые строки, например "vendor_foo" вместо "2901".
Как преобразовать идентификаторы устройств в понятные названия
Для идентификаторов OEM в Android 8.x требовалось использовать oem_#### с getpwnam и аналогичными функциями, а также в местах, где выполняется поиск с помощью getpwnam (например, в скриптах init). В Android 9 вы можете использовать getpwnam и getgrnam в Bionic для преобразования идентификаторов Android (AID) в понятные имена и наоборот.
Использовать возможности файловой системы
Чтобы включить возможности файловой системы, создайте раздел caps в файле config.fs. Например, в 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
Когда выполняется служба vendor_foo, она запускается с возможностями CAP_SYS_ADMIN и CAP_SYS_NICE без вызовов setuid и setgid. Кроме того, правилу SELinux сервиса vendor_foo больше не нужны возможности 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, вы по-прежнему можете использовать старый метод, если хотите. В следующих разделах рассказывается, как создать и добавить файлы переопределения и настроить файловую систему.
Создать файлы переопределения
Вы можете создать выровненные двоичные файлы /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 файл включения, который будет действовать как переопределение. Файл должен быть в формате 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 соответственно. Система сборки ищет пользовательские android_filesystem_config.h в $(TARGET_DEVICE_DIR), где есть 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 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. - Оставляет за собой право применять принудительный контроль доступа (MAC) SELinux к файлам конфигурации в целевой системе. Реализации, включающие пользовательские целевые исполняемые файлы, использующие
fs_config(), должны обеспечивать доступ.