Формат файла АПЕКС

Формат контейнера 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 и выглядит следующим образом.

  1. Файл APEX загружается через приложение для установки пакетов, ADB или другой источник.
  2. Менеджер пакетов запускает процедуру установки. После распознавания того, что файл является APEX, диспетчер пакетов передает управление диспетчеру APEX.
  3. Менеджер APEX проверяет файл APEX.
  4. Если файл APEX проверен, внутренняя база данных диспетчера APEX обновляется, чтобы отразить активацию файла APEX при следующей загрузке.
  5. Запросчик установки получает широковещательную рассылку после успешной проверки пакета.
  6. Для продолжения установки систему необходимо перезагрузить.
  7. При следующей загрузке диспетчер APEX запускается, считывает внутреннюю базу данных и выполняет следующие действия для каждого указанного файла APEX:

    1. Проверяет файл APEX.
    2. Создает петлевое устройство из файла APEX.
    3. Создает блочное устройство сопоставления устройств поверх петлевого устройства.
    4. Подключает блочное устройство сопоставления устройств к уникальному пути (например, /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 pair
openssl genrsa -out foo.pem 4096

# extract the public key from the key pair
avbtool extract_public_key --key foo.pem --output foo.avbpubkey

# in Android.bp
apex_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 обычно используются следующим образом:

  1. OEM или ODM предварительно загружают APEX в /system/apex при поставке устройства.
  2. Доступ к файлам в APEX осуществляется по пути /apex/<apex_name>/ .
  3. Когда обновленная версия APEX установлена ​​в /data/apex , после перезагрузки путь указывает на новый APEX.

Обновление службы с помощью APEX

Чтобы обновить службу с помощью APEX:

  1. Отметьте службу в системном разделе как обновляемую. Добавьте updatable параметр в определение службы.

    /system/etc/init/myservice.rc:
    
    service myservice /system/bin/myservice
        class core
        user system
        ...
        updatable
    
  2. Создайте новый файл .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.

Diagram shows the format of a compressed APEX file

Рисунок 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.

  1. Файл original_apex внутри /system/apex/com.android.foo.capex распаковывается в /data/apex/decompressed/com.android.foo@37.apex .
  2. restorecon /data/apex/decompressed/com.android.foo@37.apex выполняется для проверки правильности метки SELinux.
  3. Проверки выполняются на /data/apex/decompressed/com.android.foo@37.apex , чтобы гарантировать его действительность: apexd проверяет открытый ключ, связанный в /data/apex/decompressed/com.android.foo@37.apex , на убедитесь, что он равен пакету в /system/apex/com.android.foo.capex .
  4. Файл /data/apex/decompressed/com.android.foo@37.apex жестко связан с /data/apex/active/com.android.foo@37.apex .
  5. Обычная логика активации для несжатых файлов 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, который реализует функции. В таких случаях эти приложения не перенаправляются.