Формат контейнера Android Pony EXpress (APEX) был представлен в Android 10 и используется в процессе установки низкоуровневых системных модулей. Этот формат упрощает обновление системных компонентов, не вписывающихся в стандартную модель приложений Android. Примерами таких компонентов являются собственные службы и библиотеки, уровни аппаратной абстракции ( HAL ), среда выполнения ( ART ) и библиотеки классов.
Термин «APEX» может также относиться к файлу APEX.
Фон
Хотя Android поддерживает обновления модулей, соответствующих стандартной модели приложения (например, сервисов, действий), через приложения-установщики пакетов (такие как приложение Google Play Store), использование аналогичной модели для низкоуровневых компонентов ОС имеет следующие недостатки:
- Модули на основе APK нельзя использовать на ранних этапах загрузки. Менеджер пакетов — это центральное хранилище информации о приложениях, и его можно запустить только из менеджера активности, который становится готовым к работе на более позднем этапе загрузки.
- Формат APK (в частности, манифест) разработан для приложений Android, а системные модули не всегда хорошо подходят.
Дизайн
В этом разделе описывается высокоуровневая структура формата файла APEX и менеджера APEX, представляющего собой службу, управляющую файлами APEX.
Дополнительную информацию о том, почему был выбран именно этот проект для APEX, см. в разделе Альтернативы, рассмотренные при разработке APEX .
Формат APEX
Это формат файла APEX.
Рисунок 1. Формат файла APEX
На верхнем уровне файл APEX представляет собой zip-файл, в котором файлы хранятся в несжатом виде и располагаются на границах 4 КБ.
Четыре файла в файле APEX:
-
apex_manifest.json
-
AndroidManifest.xml
-
apex_payload.img
-
apex_pubkey
Файл apex_manifest.json
содержит имя и версию пакета, которые идентифицируют файл APEX. Это буфер протокола ApexManifest
в формате JSON.
Файл AndroidManifest.xml
позволяет файлу APEX использовать инструменты и инфраструктуру, связанные с APK, такие как ADB, PackageManager и приложения для установки пакетов (например, Play Store). Например, файл APEX может использовать существующий инструмент, такой как aapt
, для проверки основных метаданных файла. Файл содержит информацию об имени и версии пакета. Эта информация, как правило, также доступна в apex_manifest.json
.
Для нового кода и систем, работающих с APEX, рекомендуется использовать apex_manifest.json
вместо AndroidManifest.xml
. AndroidManifest.xml
может содержать дополнительную информацию о таргетинге, которую можно использовать в существующих инструментах публикации приложений.
apex_payload.img
— это образ файловой системы ext4, поддерживаемый dm-verity. Образ монтируется во время выполнения через устройство обратной связи. В частности, хеш-дерево и блок метаданных создаются с помощью библиотеки libavb
. Полезная нагрузка файловой системы не анализируется (поскольку образ должен быть монтируемым на месте). Обычные файлы включены в файл apex_payload.img
.
apex_pubkey
— открытый ключ, используемый для подписи образа файловой системы. Во время выполнения этот ключ гарантирует, что загруженный APEX подписан тем же лицом, которое подписывает тот же APEX во встроенных разделах.
Правила именования APEX
Чтобы предотвратить конфликты имен между новыми APEX по мере развития платформы, используйте следующие правила именования:
-
com.android.*
- Зарезервировано для APEX-ов AOSP. Не является уникальным для какой-либо компании или устройства.
-
com.<companyname>.*
- Зарезервировано для компании. Потенциально может использоваться несколькими устройствами этой компании.
-
com.<companyname>.<devicename>.*
- Зарезервировано для APEX, уникальных для конкретного устройства (или подмножества устройств).
Менеджер APEX
Менеджер APEX (или apexd
) — это автономный нативный процесс, отвечающий за проверку, установку и удаление файлов APEX. Этот процесс запускается и готов к работе на ранних этапах загрузки. Файлы APEX обычно предустановлены на устройстве в каталоге /system/apex
. Менеджер APEX по умолчанию использует эти пакеты, если обновления недоступны.
Последовательность обновления APEX использует класс PackageManager и выглядит следующим образом.
- Файл APEX загружается через приложение-установщик пакетов, ADB или другой источник.
- Менеджер пакетов запускает процедуру установки. Определив, что файл является APEX, менеджер пакетов передаёт управление менеджеру APEX.
- Менеджер APEX проверяет файл APEX.
- Если файл APEX проверен, внутренняя база данных менеджера APEX обновляется, чтобы отразить, что файл APEX активируется при следующей загрузке.
- Запросчик установки получает широковещательное сообщение об успешной проверке пакета.
- Для продолжения установки необходимо перезагрузить систему.
При следующей загрузке запустится менеджер APEX, прочитает внутреннюю базу данных и выполнит следующие действия для каждого указанного файла APEX:
- Проверяет файл APEX.
- Создает петлевое устройство из файла APEX.
- Создает блочное устройство сопоставления устройств поверх петлевого устройства.
- Монтирует блочное устройство сопоставления устройств по уникальному пути (например,
/apex/ name @ ver
).
После монтирования всех файлов APEX, перечисленных во внутренней базе данных, менеджер APEX предоставляет другим системным компонентам службу связывания для запроса информации об установленных файлах APEX. Например, другие системные компоненты могут запросить список файлов APEX, установленных на устройстве, или точный путь к месту монтирования конкретного APEX, чтобы обеспечить доступ к этим файлам.
Файлы APEX — это файлы APK
Файлы APEX являются допустимыми APK-файлами, поскольку представляют собой подписанные ZIP-архивы (с использованием схемы подписи APK), содержащие файл AndroidManifest.xml
. Это позволяет файлам APEX использовать инфраструктуру для APK-файлов, такую как приложение-установщик пакетов, утилиту подписи и менеджер пакетов.
Файл AndroidManifest.xml
внутри файла APEX минимален и содержит name
пакета, versionCode
и необязательные targetSdkVersion
, minSdkVersion
и maxSdkVersion
для точного определения целевой версии. Эта информация позволяет доставлять файлы APEX по существующим каналам, таким как приложения-установщики пакетов и ADB.
Поддерживаемые типы файлов
Формат APEX поддерживает следующие типы файлов:
- Собственные общие библиотеки
- Собственные исполняемые файлы
- JAR-файлы
- Файлы данных
- Файлы конфигурации
Это не означает, что APEX может обновлять все эти типы файлов. Возможность обновления типа файла зависит от платформы и стабильности определений интерфейсов для этих типов файлов.
Варианты подписания
Файлы APEX подписываются двумя способами. Сначала файл apex_payload.img
(а именно, дескриптор vbmeta, добавленный к apex_payload.img
) подписывается ключом. Затем весь APEX подписывается с использованием схемы подписи APK v3 . При этом используются два разных ключа.
На стороне устройства устанавливается открытый ключ, соответствующий закрытому ключу, используемому для подписи дескриптора vbmeta. Менеджер APEX использует открытый ключ для проверки APEX, запрашиваемых для установки. Каждый APEX должен быть подписан разными ключами, что обеспечивается как во время сборки, так и во время выполнения.
APEX во встроенных перегородках
Файлы APEX могут располагаться во встроенных разделах, например, /system
. Раздел уже находится на dm-verity, поэтому файлы APEX монтируются непосредственно на петлевое устройство.
Если APEX присутствует во встроенном разделе, его можно обновить, предоставив пакет APEX с тем же именем и кодом версии, большим или равным указанному. Новый APEX хранится в каталоге /data
, и, подобно APK, вновь установленная версия заменяет версию, уже присутствующую во встроенном разделе. Но, в отличие от APK, вновь установленная версия APEX активируется только после перезагрузки.
Требования к ядру
Для поддержки основных модулей APEX на устройстве Android требуются следующие компоненты ядра Linux: драйвер loopback и dm-verity. Драйвер loopback монтирует образ файловой системы в модуль APEX, а dm-verity проверяет этот модуль.
Производительность драйвера обратной связи и dm-verity важна для достижения хорошей производительности системы при использовании модулей APEX.
Поддерживаемые версии ядра
Основные модули APEX поддерживаются на устройствах с ядром версии 4.4 и выше. Новые устройства с Android 10 и выше должны использовать ядро версии 4.9 и выше для поддержки модулей APEX.
Необходимые исправления ядра
Необходимые патчи ядра для поддержки модулей APEX включены в общее дерево Android. Чтобы получить патчи для поддержки APEX, используйте последнюю версию общего дерева Android.
Версия ядра 4.4
Эта версия поддерживается только для устройств, обновлённых с Android 9 до Android 10, на которых требуется поддержка модулей APEX. Для получения необходимых патчей настоятельно рекомендуется выполнить слияние с ветки android-4.4
. Ниже приведён список необходимых отдельных патчей для ядра версии 4.4.
- UPSTREAM: цикл: добавить ioctl для изменения размера логического блока ( 4.4 )
- ОБРАТНЫЙ ПОРТ: блок/цикл: установить hw_sectors ( 4.4 )
- UPSTREAM: цикл: добавить LOOP_SET_BLOCK_SIZE в совместимый ioctl ( 4.4 )
- ANDROID: mnt: Исправление next_descendent ( 4.4 )
- ANDROID: mnt: перемонтирование должно распространяться на подчиненные устройства подчиненных устройств ( 4.4 )
- ANDROID: mnt: Распространить перемонтирование правильно ( 4.4 )
- Откат «ANDROID: dm verity: добавить минимальный размер предварительной выборки» ( 4.4 )
- UPSTREAM: цикл: удаление кэшей, если смещение или block_size изменены ( 4.4 )
Версии ядра 4.9/4.14/4.19
Чтобы получить необходимые исправления для версий ядра 4.9/4.14/4.19, выполните слияние с ветки android-common
.
Необходимые параметры конфигурации ядра
В следующем списке показаны базовые требования к конфигурации для поддержки модулей APEX, которые были представлены в Android 10. Элементы, отмеченные звездочкой (*), представляют собой существующие требования Android 9 и более ранних версий.
(*) CONFIG_AIO=Y # AIO support (for direct I/O on loop devices)
CONFIG_BLK_DEV_LOOP=Y # for loop device support
CONFIG_BLK_DEV_LOOP_MIN_COUNT=16 # pre-create 16 loop devices
(*) CONFIG_CRYPTO_SHA1=Y # SHA1 hash for DM-verity
(*) CONFIG_CRYPTO_SHA256=Y # SHA256 hash for DM-verity
CONFIG_DM_VERITY=Y # DM-verity support
Требования к параметрам командной строки ядра
Для поддержки APEX убедитесь, что параметры командной строки ядра соответствуют следующим требованиям:
-
loop.max_loop
НЕ ДОЛЖЕН быть установлен -
loop.max_part
должен быть <= 8
Построить APEX
В этом разделе описывается сборка APEX с использованием системы сборки Android. Ниже приведён пример Android.bp
для APEX с именем apex.test
.
apex {
name: "apex.test",
manifest: "apex_manifest.json",
file_contexts: "file_contexts",
// libc.so and libcutils.so are included in the apex
native_shared_libs: ["libc", "libcutils"],
binaries: ["vold"],
java_libs: ["core-all"],
prebuilts: ["my_prebuilt"],
compile_multilib: "both",
key: "apex.test.key",
certificate: "platform",
}
Пример apex_manifest.json
:
{
"name": "com.android.example.apex",
"version": 1
}
пример file_contexts
:
(/.*)? u:object_r:system_file:s0
/sub(/.*)? u:object_r:sub_file:s0
/sub/file3 u:object_r:file3_file:s0
Типы файлов и их расположение в APEX
Тип файла | Расположение в APEX |
---|---|
Общие библиотеки | /lib и /lib64 ( /lib/arm для переведенной arm в x86) |
Исполняемые файлы | /bin |
Java-библиотеки | /javalib |
Готовые изделия | /etc |
Транзитивные зависимости
Файлы APEX автоматически включают транзитивные зависимости собственных общих библиотек или исполняемых файлов. Например, если libFoo
зависит от libBar
, то обе библиотеки будут включены, если в свойстве native_shared_libs
указана только libFoo
.
Обработка нескольких ABI
Установите свойство native_shared_libs
для основного и дополнительного двоичных интерфейсов приложений (ABI) устройства. Если APEX предназначен для устройств с одним ABI (то есть только 32-разрядным или только 64-разрядным), будут установлены только библиотеки с соответствующим ABI.
Установите свойство binaries
только для основного ABI устройства, как описано ниже:
- Если устройство 32-разрядное, то устанавливается только 32-разрядный вариант двоичного файла.
- Если устройство 64-битное, то устанавливается только 64-битный вариант двоичного файла.
Чтобы добавить детальный контроль над ABI собственных библиотек и двоичных файлов, используйте свойства multilib.[first|lib32|lib64|prefer32|both].[native_shared_libs|binaries]
.
-
first
: соответствует основному ABI устройства. Это значение по умолчанию для двоичных файлов. -
lib32
: Соответствует 32-битному ABI устройства, если поддерживается. -
lib64
: Соответствует 64-битному ABI поддерживаемого устройства. -
prefer32
: соответствует 32-битному ABI устройства, если поддерживается. Если 32-битный ABI не поддерживается, соответствует 64-битному ABI. -
both
: соответствует обоим ABI. Это значение по умолчанию дляnative_shared_libraries
.
Свойства java
, libraries
и prebuilts
не зависят от ABI.
Этот пример предназначен для устройства, которое поддерживает 32/64 и не предпочитает 32:
apex {
// other properties are omitted
native_shared_libs: ["libFoo"], // installed for 32 and 64
binaries: ["exec1"], // installed for 64, but not for 32
multilib: {
first: {
native_shared_libs: ["libBar"], // installed for 64, but not for 32
binaries: ["exec2"], // same as binaries without multilib.first
},
both: {
native_shared_libs: ["libBaz"], // same as native_shared_libs without multilib
binaries: ["exec3"], // installed for 32 and 64
},
prefer32: {
native_shared_libs: ["libX"], // installed for 32, but not for 64
},
lib64: {
native_shared_libs: ["libY"], // installed for 64, but not for 32
},
},
}
подписание vbmeta
Подпишите каждый APEX разными ключами. При необходимости создайте пару открытого и закрытого ключей и модуль apex_key
. Используйте свойство key
для подписи APEX этим ключом. Открытый ключ автоматически добавляется в APEX под именем avb_pubkey
.
# create an rsa key pairopenssl genrsa -out foo.pem 4096
# extract the public key from the key pairavbtool extract_public_key --key foo.pem --output foo.avbpubkey
# in Android.bpapex_key { name: "apex.test.key", public_key: "foo.avbpubkey", private_key: "foo.pem", }
В приведённом выше примере имя открытого ключа ( foo
) становится идентификатором ключа. Идентификатор ключа, используемого для подписи APEX, записывается в APEX. Во время выполнения apexd
проверяет APEX, используя открытый ключ с тем же идентификатором на устройстве.
Подписание APEX
Подписывайте APEX-файлы так же, как и APK-файлы. Подписывайте APEX-файлы дважды: один раз для мини-файловой системы (файла apex_payload.img
) и один раз для всего файла.
Чтобы подписать APEX на уровне файла, задайте свойство certificate
одним из следующих трех способов:
- Не установлено: если значение не задано, APEX подписывается сертификатом, расположенным в
PRODUCT_DEFAULT_DEV_CERTIFICATE
. Если флаг не установлен, путь по умолчанию —build/target/product/security/testkey
. -
<name>
: APEX подписан сертификатом<name>
в том же каталоге, что иPRODUCT_DEFAULT_DEV_CERTIFICATE
. -
:<name>
: APEX подписан сертификатом, который определён модулем Soong с именем<name>
. Модуль сертификата можно определить следующим образом.
android_app_certificate {
name: "my_key_name",
certificate: "dir/cert",
// this will use dir/cert.x509.pem (the cert) and dir/cert.pk8 (the private key)
}
Установить APEX
Для установки APEX используйте ADB.
adb install apex_file_name
adb reboot
Если в apex_manifest.json
supportsRebootlessUpdate
имеет значение true
, а текущий установленный APEX не используется (например, все содержащиеся в нем службы были остановлены), то новый APEX можно установить без перезагрузки с помощью флага --force-non-staged
.
adb install --force-non-staged apex_file_name
Используйте APEX
После перезагрузки APEX монтируется в каталог /apex/<apex_name>@<version>
. Одновременно можно монтировать несколько версий одного и того же APEX. Среди путей монтирования тот, который соответствует последней версии, монтируется с помощью bind-mount в /apex/<apex_name>
.
Клиенты могут использовать привязанный путь для чтения или выполнения файлов из APEX.
APEX обычно используются следующим образом:
- OEM или ODM-производитель предварительно загружает APEX в папку
/system/apex
при отправке устройства. - Доступ к файлам в APEX осуществляется по пути
/apex/<apex_name>/
. - Если обновленная версия APEX установлена в
/data/apex
, после перезагрузки путь указывает на новую версию APEX.
Обновление сервиса с помощью APEX
Чтобы обновить службу с помощью APEX:
Отметьте службу в системном разделе как обновляемую. Добавьте опцию
updatable
к определению службы./system/etc/init/myservice.rc: service myservice /system/bin/myservice class core user system ... updatable
Создайте новый
.rc
файл для обновлённой службы. Используйте опциюoverride
, чтобы переопределить существующую службу./apex/my.apex/etc/init.rc: service myservice /apex/my.apex/bin/myservice class core user system ... override
Определения служб можно задать только в .rc
файле APEX. Триггеры действий в APEX не поддерживаются.
Если служба, помеченная как обновляемая, запускается до активации APEX, запуск откладывается до завершения активации APEX.
Настройте систему для поддержки обновлений APEX
Установите следующее системное свойство в true
для поддержки обновлений файлов APEX.
<device.mk>:
PRODUCT_PROPERTY_OVERRIDES += ro.apex.updatable=true
BoardConfig.mk:
TARGET_FLATTEN_APEX := false
или просто
<device.mk>:
$(call inherit-product, $(SRC_TARGET_DIR)/product/updatable_apex.mk)
Уплощенная верхушка
Для устаревших устройств иногда невозможно или нецелесообразно обновить старое ядро для полной поддержки APEX. Например, ядро могло быть собрано без CONFIG_BLK_DEV_LOOP=Y
, который критически важен для монтирования образа файловой системы внутри APEX.
Flattened APEX — это специально созданный APEX, который можно активировать на устройствах с устаревшим ядром. Файлы в flattened APEX устанавливаются непосредственно в каталог во встроенном разделе. Например, lib/libFoo.so
в flattened APEX my.apex
устанавливается в /system/apex/my.apex/lib/libFoo.so
.
Активация плоских APEX не требует использования петлевого устройства. Весь каталог /system/apex/my.apex
напрямую монтируется к /apex/name@ver
.
Обновить APEX-файлы, упорядоченные по формату, путём загрузки обновлённых версий из сети невозможно, поскольку загруженные APEX-файлы не могут быть преобразованы в формат. Обновить APEX-файлы, упорядоченные по формату, можно только через обычное беспроводное обновление (OTA).
Конфигурация по умолчанию — это уплощённый APEX. Это означает, что все APEX по умолчанию уплощены, если только вы явно не настроите устройство на создание неуплощённых APEX для поддержки обновлений APEX (как описано выше).
Смешивание APEX с уплощёнными и неуплощёнными версиями на устройстве НЕ поддерживается. Все APEX на устройстве должны быть либо неуплощёнными, либо уплощёнными. Это особенно важно при поставке предварительно подписанных сборок APEX для таких проектов, как Mainline. APEX, которые не были предварительно подписаны (то есть собраны из исходного кода), также должны быть неуплощёнными и подписаны соответствующими ключами. Устройство должно наследовать от updatable_apex.mk
, как описано в разделе «Обновление службы с помощью APEX» .
Сжатые APEX-файлы
В Android 12 и более поздних версиях реализовано сжатие данных APEX для уменьшения влияния обновляемых пакетов APEX на объём хранилища. После установки обновления APEX, хотя предустановленная версия больше не используется, она по-прежнему занимает тот же объём памяти. Занятое пространство остаётся недоступным.
Сжатие APEX минимизирует воздействие на хранилище, используя сильно сжатый набор файлов APEX на разделах, доступных только для чтения (например, в разделе /system
). В Android 12 и более поздних версиях используется алгоритм сжатия zip DEFLATE.
Сжатие не обеспечивает оптимизацию следующего:
Bootstrap APEX, которые необходимо монтировать на самом раннем этапе последовательности загрузки.
Необновляемые APEX. Сжатие имеет смысл только в том случае, если в разделе
/data
установлена обновлённая версия APEX. Полный список обновляемых APEX доступен на странице «Компоненты модульной системы» .Динамические общие библиотеки APEX. Поскольку
apexd
всегда активирует обе версии таких APEX (предустановленную и обновлённую), их сжатие не добавляет смысла.
Сжатый формат файла APEX
Это формат сжатого файла APEX.
Рисунок 2. Сжатый формат файла APEX
На верхнем уровне сжатый файл APEX представляет собой zip-файл, содержащий исходный файл APEX в сжатом виде со степенью сжатия 9, а также другие файлы, хранящиеся в несжатом виде.
Файл APEX состоит из четырех файлов:
-
original_apex
: сжатый со степенью сжатия 9 Это оригинальный, несжатый файл APEX . -
apex_manifest.pb
: только сохранено -
AndroidManifest.xml
: только сохраненный -
apex_pubkey
: только сохранено
Файлы apex_manifest.pb
, AndroidManifest.xml
и apex_pubkey
являются копиями соответствующих файлов в original_apex
.
Сборка сжатого APEX
Сжатый APEX можно создать с помощью инструмента apex_compression_tool.py
расположенного в system/apex/tools
.
В системе сборки доступно несколько параметров, связанных со сжатием APEX.
В Android.bp
сжимаемость файла APEX контролируется свойством compressible
:
apex {
name: "apex.test",
manifest: "apex_manifest.json",
file_contexts: "file_contexts",
compressible: true,
}
Флаг продукта PRODUCT_COMPRESSED_APEX
определяет, должен ли образ системы, созданный из источника, содержать сжатые файлы APEX.
Для локальных экспериментов вы можете принудительно сжать APEX-файлы, установив OVERRIDE_PRODUCT_COMPRESSED_APEX=
в true
.
Сжатые файлы APEX, создаваемые системой сборки, имеют расширение .capex
. Это расширение упрощает различение сжатых и несжатых версий файла APEX.
Поддерживаемые алгоритмы сжатия
Android 12 поддерживает только сжатие deflate-zip.
Активировать сжатый файл APEX во время загрузки
Перед активацией сжатого APEX original_apex
файл APEX распаковывается в каталог /data/apex/decompressed
. Полученный распакованный файл APEX жёстко связан с каталогом /data/apex/active
.
Рассмотрим следующий пример как иллюстрацию описанного выше процесса.
Рассмотрим /system/apex/com.android.foo.capex
как сжатый активируемый APEX с versionCode 37.
-
original_apex
файл apex внутри/system/apex/com.android.foo.capex
распаковывается в/data/apex/decompressed/com.android.foo@37.apex
. -
restorecon /data/apex/decompressed/com.android.foo@37.apex
выполняется для проверки наличия у него правильной метки SELinux. - Проверки выполняются для
/data/apex/decompressed/com.android.foo@37.apex
, чтобы убедиться в его действительности:apexd
проверяет открытый ключ, упакованный в/data/apex/decompressed/com.android.foo@37.apex
, чтобы убедиться, что он равен ключу, упакованному в/system/apex/com.android.foo.capex
. - Файл
/data/apex/decompressed/com.android.foo@37.apex
жестко связан с каталогом/data/apex/active/com.android.foo@37.apex
. - Обычная логика активации для несжатых файлов APEX выполняется на
/data/apex/active/com.android.foo@37.apex
.
Взаимодействие с ОТА
Сжатые файлы APEX влияют на доставку и применение OTA-обновлений. Поскольку OTA-обновление может содержать сжатый файл APEX с более высокой версией, чем активная версия на устройстве, перед перезагрузкой устройства для применения OTA-обновления необходимо зарезервировать определённый объём свободного места.
Для поддержки системы OTA apexd
предоставляет следующие два API-интерфейса:
-
calculateSizeForCompressedApex
— вычисляет размер, необходимый для распаковки файлов APEX из OTA-пакета. Это можно использовать для проверки наличия достаточного места на устройстве перед загрузкой OTA-пакета. -
reserveSpaceForCompressedApex
— резервирует место на диске для будущего использованияapexd
для распаковки сжатых файлов APEX внутри пакета OTA.
В случае A/B-обновления OTA apexd
пытается выполнить распаковку в фоновом режиме в рамках процедуры OTA после установки. Если распаковка не удаётся, apexd
выполняет распаковку во время загрузки, применяющей обновление OTA.
Альтернативы, рассмотренные при разработке APEX
Ниже приведены некоторые параметры, которые AOSP рассматривала при разработке формата файла APEX, а также причины, по которым они были включены или исключены.
Регулярные системы управления пакетами
В дистрибутивах Linux используются мощные, зрелые и надёжные системы управления пакетами, такие как dpkg
и rpm
. Однако они не были адаптированы для APEX, поскольку не могут защитить пакеты после установки. Проверка выполняется только при установке пакетов. Злоумышленники могут незаметно нарушить целостность установленных пакетов. Это регресс для Android, где все компоненты системы хранились в файловых системах, доступных только для чтения, целостность которых защищалась dm-verity для каждого ввода-вывода. Любое вмешательство в работу системных компонентов должно быть либо запрещено, либо обнаруживаться, чтобы устройство могло отказаться загружаться в случае взлома.
dm-crypt для целостности
Файлы в контейнере APEX находятся во встроенных разделах (например, разделе /system
), защищённых dm-verity, где любые изменения файлов запрещены даже после монтирования разделов. Для обеспечения такого же уровня безопасности все файлы в контейнере APEX хранятся в образе файловой системы, связанном с хэш-деревом и дескриптором vbmeta. Без dm-verity контейнер APEX в разделе /data
уязвим к непреднамеренным изменениям, внесённым после его проверки и установки.
Фактически, раздел /data
также защищён слоями шифрования, такими как dm-crypt. Хотя это обеспечивает определённый уровень защиты от несанкционированного доступа, его основная цель — конфиденциальность, а не целостность. Когда злоумышленник получает доступ к разделу /data
, дальнейшая защита становится невозможной, и это, опять же, регресс по сравнению с тем, когда все компоненты системы находились в разделе /system
. Хеш-дерево внутри файла APEX вместе с dm-verity обеспечивает тот же уровень защиты содержимого.
Перенаправить пути из /system в /apex
Файлы системных компонентов, упакованные в APEX, доступны по новым путям, например, /apex/<name>/lib/libfoo.so
. Когда эти файлы находились в разделе /system
, они были доступны по таким путям, как /system/lib/libfoo.so
. Клиент файла APEX (другие файлы APEX или платформа) должен использовать новые пути. В связи с изменением пути может потребоваться обновление существующего кода.
Хотя одним из способов избежать изменения пути является наложение содержимого файла APEX на раздел /system
, команда Android решила не накладывать файлы на раздел /system
поскольку это может повлиять на производительность, поскольку количество накладываемых файлов (возможно, даже расположенных один за другим) увеличится.
Другой вариант заключался в перехвате функций доступа к файлам, таких как open
, stat
и readlink
, чтобы пути, начинающиеся с /system
перенаправлялись на соответствующие пути в /apex
. Команда Android отказалась от этого варианта, поскольку невозможно изменить все функции, принимающие пути. Например, некоторые приложения статически подключают Bionic, который реализует эти функции. В таких случаях перенаправление для этих приложений не происходит.