Дискреционный контроль доступа (DAC)

Объектам и службам файловой системы, добавленным в сборку, часто требуются отдельные уникальные идентификаторы, известные как идентификаторы Android (AID). В настоящее время многие ресурсы, такие как файлы и службы, без необходимости используют базовые (определенные Android) AID; во многих случаях вместо этого можно использовать OEM (определенные OEM) AID.

Более ранние версии Android (Android 7.x и ниже) расширяли механизм AID, используя файл android_filesystem_config.h для конкретного устройства, чтобы указать возможности файловой системы и/или пользовательские OEM-AID. Однако эта система была неинтуитивной, поскольку она не поддерживала использование красивых имен для OEM-AID, требуя от вас указания необработанных числовых значений для полей пользователя и группы без возможности связать понятное имя с числовым AID.

Новые версии Android (Android 8.0 и выше) поддерживают новый метод расширения возможностей файловой системы. Этот новый метод поддерживает следующее:

  • Несколько исходных расположений для файлов конфигурации (обеспечивает расширяемые конфигурации сборки).
  • Проверка работоспособности значений OEM AID во время сборки.
  • Создание пользовательского заголовка OEM AID, который при необходимости можно использовать в исходных файлах.
  • Ассоциация понятного имени с фактическим значением OEM AID. Поддерживает нечисловые строковые аргументы для пользователя и группы, т.е. «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 с открытым исходным кодом (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

Становится:

  • Понятное имя: система
  • идентификатор: 1000
  • гид: 1000

Чтобы добавить новый основной AID AOSP, просто добавьте #define в заголовочный файл android_filesystem_config.h . AID будет сгенерирован при сборке и доступен для интерфейсов, использующих аргументы пользователя и группы. Инструменты подтверждают, что новый AID не соответствует диапазонам APP или OEM; он также учитывает изменения в этих диапазонах и должен автоматически перенастраиваться при изменениях или новых диапазонах, зарезервированных OEM.

Настройка AID

Чтобы включить новый механизм AID, установите TARGET_FS_CONFIG_GEN в файле BoardConfig.mk . Эта переменная содержит список файлов конфигурации, что позволяет добавлять файлы по мере необходимости.

По соглашению файлы конфигурации используют имя config.fs , но на практике вы можете использовать любое имя. Файлы config.fs имеют ini-формат Python ConfigParser и включают раздел caps (для настройки возможностей файловой системы) и раздел AID (для настройки OEM AID).

Настройка раздела caps

Раздел caps поддерживает настройку возможностей файловой системы для объектов файловой системы в сборке (сама файловая система также должна поддерживать эту функцию).

Поскольку запуск стабильной службы с правами root в Android приводит к сбою пакета тестов совместимости (CTS) , предыдущие требования для сохранения возможности во время запуска процесса или службы включали настройку возможностей, а затем использование setuid / setgid для правильного запуска AID. Используя ограничения, вы можете пропустить эти требования и позволить ядру сделать это за вас. Когда управление передается main() , ваш процесс уже имеет необходимые ему возможности, поэтому ваша служба может использовать пользователя и группу без полномочий root (это предпочтительный способ запуска привилегированных служб).

В разделе caps используется следующий синтаксис:

Раздел Ценить Определение
[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_ . Допускается смешанный случай. Шапки также могут быть сырыми:
  • двоичный (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)
  • ОДМ-раздел
    • 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-помощников

Чтобы использовать 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. Например:

  • В команде 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 включает поддержку связывания понятного имени с фактическим значением OEM AID. Вы можете использовать нечисловые строковые аргументы для пользователя и группы, например « vendor_ foo» вместо «2901».

Преобразование AID в понятные имена

Для OEM AID 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 и выше:

  1. Создайте файл $(TARGET_DEVICE_DIR)/android_filesystem_config.h .
  2. Добавьте файлы 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 .
  • Оставляет за собой право применять обязательный контроль доступа (MAC) SELinux к файлам конфигурации в целевой системе; реализации, включающие пользовательские целевые исполняемые файлы с использованием fs_config() должны обеспечивать доступ.