Формат контейнера 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_manifest.json
рекомендуется использовать вместо AndroidManifest.xml
для нового кода и систем, работающих с APEX. AndroidManifest.xml
может содержать дополнительную информацию о таргетинге, которую могут использовать существующие инструменты публикации приложений.
apex_payload.img
— это образ файловой системы ext4, поддерживаемый dm-verity. Образ монтируется во время выполнения через устройство обратной связи. В частности, хеш-дерево и блок метаданных создаются с использованием библиотеки libavb
. Полезная нагрузка файловой системы не анализируется (поскольку образ должен быть монтируемым на месте). Обычные файлы включены в файл apex_payload.img
.
apex_pubkey
— это открытый ключ, используемый для подписи образа файловой системы. Во время выполнения этот ключ гарантирует, что загруженный APEX подписан тем же объектом, который подписывает тот же APEX во встроенных разделах.
Рекомендации по присвоению имен APEX
Чтобы предотвратить конфликты имен между новыми APEX по мере развития платформы, используйте следующие рекомендации по именованию:
-
com.android.*
- Зарезервировано для AOSP APEX. Не уникально для какой-либо компании или устройства.
-
com.<companyname>.*
- Зарезервировано для компании. Потенциально используется несколькими устройствами этой компании.
-
com.<companyname>.<devicename>.*
- Зарезервировано для 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 с тем же именем пакета и кодом версии, большим или равным. Новый APEX хранится в /data
, и, как и в случае с APK, вновь установленная версия затеняет версию, уже присутствующую во встроенном разделе. Но в отличие от APK, новая установленная версия APEX активируется только после перезагрузки.
Требования ядра
Для поддержки основных модулей APEX на устройстве Android требуются следующие функции ядра Linux: драйвер обратной связи и dm-verity. Драйвер обратной связи монтирует образ файловой системы в модуль APEX, а dm-verity проверяет модуль APEX.
Производительность драйвера обратной связи и 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 )
- АНДРОИД: mnt: исправление next_descendent ( 4.4 )
- АНДРОИД: mnt: remount должно распространяться на подчиненные устройства подчиненных ( 4.4 )
- ANDROID: mnt: правильное распространение перемонтирования ( 4.4 )
- Вернуть «ANDROID: dm verity: добавить минимальный размер предварительной выборки» ( 4.4 )
- UPSTREAM: цикл: удалять кеши, если смещение или размер блока изменены ( 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 с помощью системы сборки 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
Тип файла | Расположение в АПЕКС |
---|---|
Общие библиотеки | /lib и /lib64 ( /lib/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, используйте ADB.
adb install apex_file_name
adb reboot
Если для supportsRebootlessUpdate
в apex_manifest.json
установлено значение true
и установленный в данный момент APEX не используется (например, все содержащиеся в нем службы остановлены), то новый APEX можно установить без перезагрузки с помощью флага --force-non-staged
.
adb install --force-non-staged apex_file_name
Используйте АПЕКС
После перезагрузки APEX монтируется в каталог /apex/<apex_name>@<version>
. Одновременно можно установить несколько версий одного и того же APEX. Среди путей монтирования тот, который соответствует последней версии, монтируется по привязке в /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, который можно активировать на устройствах с устаревшим ядром. Файлы в объединенном APEX устанавливаются непосредственно в каталог встроенного раздела. Например, lib/libFoo.so
в сведенном APEX my.apex
устанавливается в /system/apex/my.apex/lib/libFoo.so
.
Активация сглаженного APEX не задействует петлевое устройство. Весь каталог /system/apex/my.apex
напрямую привязывается к /apex/name@ver
.
Сведенные APEX нельзя обновить, загрузив обновленные версии 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.
Сжатие не обеспечивает оптимизацию следующего:
Начальные 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
внутри него распаковывается в каталог /data/apex/decompressed
. Полученный распакованный файл APEX жестко связан с каталогом /data/apex/active
.
Рассмотрим следующий пример как иллюстрацию описанного выше процесса.
Рассмотрим /system/apex/com.android.foo.capex
как активируемый сжатый APEX с кодом версии 37.
- Файл
original_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, который реализует функции. В таких случаях эти приложения не перенаправляются.