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

Формат контейнера 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.

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

  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 монтируются непосредственно поверх устройства обратной связи.

Если 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 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, используя открытый ключ с тем же идентификатором на устройстве.

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

  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, который реализует функции. В таких случаях эти приложения не перенаправляются.