Формат контейнера 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. Образ монтируется во время выполнения через устройство loopback. В частности, хэш-дерево и блок метаданных создаются с помощью библиотеки 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 монтируются непосредственно над устройством loopback.
Если APEX присутствует во встроенном разделе, APEX можно обновить, предоставив пакет APEX с тем же именем пакета и кодом версии, большим или равным. Новый APEX хранится в /data
и, подобно APK, вновь установленная версия заменяет версию, уже присутствующую во встроенном разделе. Но в отличие от APK, вновь установленная версия APEX активируется только после перезагрузки.
Требования к ядру
Для поддержки основных модулей APEX на устройстве Android требуются следующие функции ядра Linux: драйвер loopback и dm-verity. Драйвер loopback монтирует образ файловой системы в модуль APEX, а dm-verity проверяет модуль APEX.
Производительность драйвера обратной связи и dm-verity важна для достижения хорошей производительности системы при использовании модулей APEX.
Поддерживаемые версии ядра
Модули APEX mainline поддерживаются на устройствах с версиями ядра 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
Если supportsRebootlessUpdate
имеет значение true
в apex_manifest.json
и текущий установленный APEX не используется (например, все содержащиеся в нем службы были остановлены), то новый APEX можно установить без перезагрузки с помощью флага --force-non-staged
.
adb install --force-non-staged apex_file_name
Используйте APEX
После перезагрузки 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, который можно активировать на устройствах с устаревшим ядром. Файлы в flattened APEX устанавливаются непосредственно в каталог во встроенном разделе. Например, lib/libFoo.so
в flattened APEX my.apex
устанавливается в /system/apex/my.apex/lib/libFoo.so
.
Активация flattened APEX не задействует loop-устройство. Весь каталог /system/apex/my.apex
напрямую привязывается к /apex/name@ver
.
Flattened APEXes не может быть обновлен путем загрузки обновленных версий APEXes из сети, поскольку загруженные APEXes не могут быть flattened. Flattened APEXes может быть обновлен только через обычный OTA.
Flattened APEX — это конфигурация по умолчанию. Это означает, что все APEX по умолчанию flattened, если вы явно не настроите свое устройство на создание nonflattened 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. Сжатие полезно только в том случае, если обновленная версия APEX установлена на разделе
/data
. Полный список обновляемых 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 с versionCode 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, который реализует функции. В таких случаях эти приложения не перенаправляются.