Формат контейнера Android Pony EXpress (APEX) был представлен в Android 10 и используется в процессе установки системных модулей более низкого уровня. Этот формат упрощает обновление системных компонентов, которые не вписываются в стандартную модель приложений Android. Некоторыми примерами компонентов являются собственные службы и библиотеки, уровни аппаратной абстракции ( HAL ), среда выполнения ( ART ) и библиотеки классов.
Термин «APEX» также может относиться к файлу APEX.
Фон
Хотя Android поддерживает обновления модулей, которые соответствуют стандартной модели приложений (например, службы, действия) через приложения-установщики пакетов (например, приложение Google Play Store), использование аналогичной модели для компонентов ОС более низкого уровня имеет следующие недостатки:
- Модули на основе APK нельзя использовать в начале последовательности загрузки. Диспетчер пакетов является центральным хранилищем информации о приложениях и может быть запущен только из диспетчера действий, который становится готовым на более позднем этапе процедуры загрузки.
- Формат APK (в частности, манифест) предназначен для приложений Android, а системные модули не всегда подходят.
Дизайн
В этом разделе описывается общий дизайн формата файлов 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.
Файл 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 (или 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: драйвер обратной связи и 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.
- ВВЕРХ: цикл: добавить ioctl для изменения размера логического блока ( 4.4 )
- BACKPORT: блок/цикл: установить hw_sectors ( 4.4 )
- Upstream: цикл: добавить LOOP_SET_BLOCK_SIZE в compat ioctl ( 4.4 )
- ANDROID: mnt: исправить next_descendent ( 4.4 )
- ANDROID: 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
, две библиотеки включаются, когда в libFoo
указана только native_shared_libs
.
Обработка нескольких 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 : Соответствует
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 с помощью открытого ключа с тем же идентификатором на устройстве.
ZIP-подпись
Подпишите APEX так же, как вы подписываете APK. Подпишите APEX дважды; один раз для файловой системы mini (файл 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
Использование АПЕКС
После перезагрузки 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, который реализует функции. В таких случаях эти приложения не перенаправляются.