Format pliku APEX

Format kontenera Android Pony EXpress (APEX) został wprowadzony w systemie Android 10 i jest używany w przepływie instalacji dla modułów systemowych niższego poziomu. Ten format ułatwia aktualizowanie składników systemu, które nie pasują do standardowego modelu aplikacji systemu Android. Niektóre elementy są przykładowe usługi natywne i biblioteki, warstwy abstrakcji sprzętu ( HALS ), uruchomieniowe ( ART ) oraz biblioteki klas.

Termin „APEX” może również odnosić się do pliku APEX.

Tło

Chociaż Android obsługuje aktualizacje modułów, które pasują do standardowego modelu aplikacji (na przykład usług, działań) za pośrednictwem aplikacji instalujących pakiety (takich jak aplikacja Sklep Google Play), używanie podobnego modelu dla komponentów systemu operacyjnego niższego poziomu ma następujące wady:

  • Modułów opartych na pakiecie APK nie można używać na początku sekwencji rozruchowej. Menedżer pakietów jest centralnym repozytorium informacji o aplikacjach i można go uruchomić tylko z menedżera aktywności, który jest gotowy na późniejszym etapie procedury rozruchu.
  • Format APK (w szczególności manifest) jest przeznaczony dla aplikacji na Androida, a moduły systemowe nie zawsze są odpowiednie.

Projekt

W tej sekcji opisano projekt wysokiego poziomu formatu pliku APEX i menedżera APEX, który jest usługą zarządzającą plikami APEX.

Aby uzyskać więcej informacji na temat tego, dlaczego został wybrany projekt dla APEX, zobacz Alternatywy uwzględnione przy opracowywaniu APEX .

Format APEX

To jest format pliku APEX.

Format pliku APEX

Format pliku Rysunek 1. APEX

Na najwyższym poziomie plik APEX to plik zip, w którym pliki są przechowywane w postaci nieskompresowanej i mieszczą się w granicach 4 KB.

Cztery pliki w pliku APEX to:

  • apex_manifest.json
  • AndroidManifest.xml
  • apex_payload.img
  • apex_pubkey

apex_manifest.json plik zawiera nazwę pakietu oraz wersję, która zidentyfikować plik APEX.

AndroidManifest.xml plików umożliwia plik APEX używać narzędzi APK-związane i infrastrukturalnych, takich jak ADB, PackageManager i aplikacjach pakietu Instalatora (takich jak Sklepie Play). Na przykład, plik APEX można użyć istniejącej funkcji, takich jak aapt do wglądu podstawowe metadane z pliku. Plik zawiera informacje o nazwie i wersji pakietu. Ta informacja jest ogólnie dostępny w apex_manifest.json .

apex_manifest.json zaleca się AndroidManifest.xml dla nowego kodu i systemów, które zajmują się APEX. AndroidManifest.xml może zawierać dodatkowe informacje kierowania, które mogą być wykorzystane przez dotychczasowych narzędzi aplikacji wydawniczych.

apex_payload.img jest system plików ext4 obraz poparte dm-Verity. Obraz jest montowany w czasie wykonywania za pomocą urządzenia pętli zwrotnej. Konkretnie, drzewo hash i metadane bloku są tworzone przy użyciu libavb bibliotekę. Ładunek systemu plików nie jest analizowany (ponieważ obraz powinien dać się zamontować na miejscu). Regularne pliki są zawarte wewnątrz apex_payload.img pliku.

apex_pubkey jest klucz publiczny używany do podpisania obraz systemu plików. W czasie wykonywania ten klucz zapewnia, że ​​pobrany APEX jest podpisany za pomocą tej samej jednostki, która podpisuje ten sam APEX na wbudowanych partycjach.

Menedżer APEX

Zarządca APEX (lub apexd ) jest rodowitym proces samodzielny odpowiedzialni za sprawdzanie, instalowanie i odinstalowywanie plików APEX. Ten proces jest uruchamiany i jest gotowy na wczesnym etapie sekwencji rozruchowej. Pliki APEX są zazwyczaj zainstalowane na urządzeniu pod /system/apex . Menedżer APEX domyślnie używa tych pakietów, jeśli nie są dostępne żadne aktualizacje.

Sekwencja aktualizacja wierzchołka wykorzystuje klasę PackageManager i przedstawia się następująco.

  1. Plik APEX jest pobierany za pośrednictwem aplikacji do instalacji pakietów, ADB lub innego źródła.
  2. Menedżer pakietów rozpoczyna procedurę instalacji. Po rozpoznaniu, że plik jest APEX, menedżer pakietów przekazuje kontrolę do menedżera APEX.
  3. Menedżer APEX weryfikuje plik APEX.
  4. Jeśli plik APEX zostanie zweryfikowany, wewnętrzna baza danych menedżera APEX zostanie zaktualizowana, aby odzwierciedlić, że plik APEX zostanie aktywowany przy następnym uruchomieniu.
  5. Żądający instalacji odbiera transmisję po pomyślnej weryfikacji pakietu.
  6. Aby kontynuować instalację, system musi zostać ponownie uruchomiony.
  7. Przy następnym uruchomieniu menedżer APEX uruchamia się, odczytuje wewnętrzną bazę danych i wykonuje następujące czynności dla każdego wymienionego pliku APEX:

    1. Weryfikuje plik APEX.
    2. Tworzy urządzenie pętli zwrotnej z pliku APEX.
    3. Tworzy urządzenie blokowe mapowania urządzeń na urządzeniu pętli zwrotnej.
    4. Mocowania urządzenia blokowego odwzorowujący urządzenie na unikalnym ścieżki (na przykład /apex/ name @ ver ).

Gdy wszystkie pliki APEX wymienione w wewnętrznej bazie danych są zamontowane, menedżer APEX udostępnia usługę spinacza dla innych komponentów systemu, aby przeszukiwać informacje o zainstalowanych plikach APEX. Na przykład inne komponenty systemu mogą wysyłać zapytania do listy plików APEX zainstalowanych w urządzeniu lub sprawdzać dokładną ścieżkę, w której zainstalowany jest określony APEX, aby można było uzyskać dostęp do plików.

Pliki APEX to pliki APK

Pliki APEX są ważne pliki APK, ponieważ są one podpisane ZIP (za pomocą schematu podpisu APK) zawierające AndroidManifest.xml pliku. Dzięki temu pliki APEX mogą korzystać z infrastruktury dla plików APK, takich jak aplikacja do instalacji pakietów, narzędzie do podpisywania i menedżer pakietów.

AndroidManifest.xml plików wewnątrz pliku APEX jest minimalne, składający się z pakietu name , versionCode i opcjonalnym targetSdkVersion , minSdkVersion i maxSdkVersion dla drobnoziarnisty kierowania. Informacje te umożliwiają dostarczanie plików APEX za pośrednictwem istniejących kanałów, takich jak aplikacje do instalacji pakietów i ADB.

Obsługiwane typy plików

Format APEX obsługuje następujące typy plików:

  • Natywne biblioteki współdzielone
  • Natywne pliki wykonywalne
  • Pliki JAR
  • Pliki danych
  • Pliki konfiguracyjne

Nie oznacza to, że APEX może aktualizować wszystkie te typy plików. Możliwość aktualizacji typu pliku zależy od platformy i stabilności definicji interfejsów dla typów plików.

Podpisywanie

Pliki APEX są podpisywane na dwa sposoby. Po pierwsze, apex_payload.img (konkretnie deskryptor vbmeta dołączane do apex_payload.img ) Plik jest podpisany za pomocą klucza. Następnie cała APEX jest podpisany przy użyciu v3 schematu podpisu APK . W tym procesie używane są dwa różne klucze.

Po stronie urządzenia instalowany jest klucz publiczny odpowiadający kluczowi prywatnemu używanemu do podpisywania deskryptora vbmeta. Menedżer APEX używa klucza publicznego do weryfikacji APEX, które są wymagane do zainstalowania. Każdy APEX musi być podpisany różnymi kluczami i jest wymuszany zarówno w czasie kompilacji, jak i w czasie wykonywania.

APEX w przegrodach do zabudowy

Pliki APEX mogą znajdować się w wybudowanym w partycjach, takich jak /system . Partycja jest już nad dm-verity, więc pliki APEX są montowane bezpośrednio nad urządzeniem loopback.

Jeśli APEX jest obecny we wbudowanej partycji, APEX można zaktualizować, dostarczając pakiet APEX o tej samej nazwie i kodzie wersji większym lub równym. Nowy APEX jest przechowywany w /data i, podobnie jak w APK, nowo zainstalowane cienie Version Wersja już obecne w wbudowanym partycji. Ale w przeciwieństwie do pakietów APK, nowo zainstalowana wersja APEX jest aktywowana dopiero po ponownym uruchomieniu.

Wymagania jądra

Aby obsługiwać moduły APEX mainline na urządzeniu z systemem Android, wymagane są następujące funkcje jądra Linux: sterownik pętli zwrotnej i dm-verity. Sterownik pętli zwrotnej montuje obraz systemu plików w module APEX, a dm-verity weryfikuje moduł APEX.

Wydajność sterownika pętli zwrotnej i dm-verity jest ważna dla osiągnięcia dobrej wydajności systemu podczas korzystania z modułów APEX.

Obsługiwane wersje jądra

Główne moduły APEX są obsługiwane na urządzeniach korzystających z jądra w wersji 4.4 lub wyższej. Nowe urządzenia uruchamiane z systemem Android 10 lub nowszym muszą używać jądra w wersji 4.9 lub nowszej, aby obsługiwać moduły APEX.

Wymagane poprawki jądra

Wymagane poprawki jądra do obsługi modułów APEX są zawarte we wspólnym drzewie Androida. Aby uzyskać łatki obsługujące APEX, użyj najnowszej wersji wspólnego drzewa Androida.

Wersja jądra 4.4

Ta wersja jest obsługiwana tylko dla urządzeń, które zostały zaktualizowane z Androida 9 do Androida 10 i chcą obsługiwać moduły APEX. Aby uzyskać wymaganych poprawek, w dół seryjnej z android-4.4 Zaleca się gałęzi. Poniżej znajduje się lista wymaganych pojedynczych łat dla wersji jądra 4.4.

  • UPSTREAM: pętla: dodaj ioctl do zmiany rozmiaru bloku logicznego ( 4,4 )
  • Backportu: blok / pętla: Zestaw hw_sectors ( 4,4 )
  • UPSTREAM: pętla: dodaj LOOP_SET_BLOCK_SIZE w compat ioctl ( 4,4 )
  • ANDROID: mnt: Fix next_descendent ( 4,4 )
  • ANDROID: mnt: Remount powinny propagować niewolników niewolników ( 4,4 )
  • ANDROID: mnt: Propagate zamontować prawidłowo ( 4,4 )
  • Przywrócić "ANDROID dm prawda: dodanie minimalnej wielkości preselekcji" ( 4.4 )
  • UPSTREAM: pętla: buforuje drop jeśli przesunięcie lub block_size są zmieniane ( 4.4 )

Wersje jądra 4.9/4.14/4.19

Aby uzyskać wymagane poprawki dla wersji jądra 4.9 / 4.14 / 4.19, w dół seryjnej z android-common oddział.

Wymagane opcje konfiguracji jądra

Poniższa lista przedstawia podstawowe wymagania konfiguracyjne dotyczące obsługi modułów APEX, które zostały wprowadzone w systemie Android 10. Elementy oznaczone gwiazdką (*) są istniejącymi wymaganiami z systemu Android 9 i niższych.

(*) 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

Wymagania dotyczące parametrów wiersza polecenia jądra

Aby obsługiwać APEX, upewnij się, że parametry wiersza poleceń jądra spełniają następujące wymagania:

  • loop.max_loop nie może być ustawiony
  • loop.max_part musi być <= 8

Budowanie APEX

W tej sekcji opisano, jak zbudować APEX przy użyciu systemu kompilacji Android. Poniżej znajduje się przykład Android.bp dla APEX nazwie 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 przykład:

{
  "name": "com.android.example.apex",
  "version": 1
}

file_contexts przykład:

(/.*)?           u:object_r:system_file:s0
/sub(/.*)?       u:object_r:sub_file:s0
/sub/file3       u:object_r:file3_file:s0

Typy plików i lokalizacje w APEX

Typ pliku Lokalizacja w APEX
Biblioteki udostępnione /lib i /lib64 ( /lib/arm tłumaczonych ramię w x86)
Pliki wykonywalne /bin
Biblioteki Java /javalib
Prefabrykowane /etc

Zależności przechodnie

Pliki APEX automatycznie zawierają przechodnie zależności natywnych bibliotek współdzielonych lub plików wykonywalnych. Na przykład, jeśli libFoo zależy libBar , dwa libs są włączone, gdy tylko libFoo figuruje w native_shared_libs nieruchomości.

Obsługa wielu ABI

Zainstalować native_shared_libs właściwości dla obu interfejsach binarnych stosowanie pierwotnych i wtórnych (ABI) urządzenia. Jeśli APEX jest przeznaczony dla urządzeń z pojedynczym ABI (czyli tylko 32-bitowym lub 64-bitowym), instalowane są tylko biblioteki z odpowiednim ABI.

Zainstalować binaries właściwość tylko dla głównego ABI urządzenia jak opisano poniżej:

  • Jeśli urządzenie jest tylko 32-bitowe, instalowany jest tylko 32-bitowy wariant pliku binarnego.
  • Jeśli urządzenie jest tylko 64-bitowe, instalowany jest tylko 64-bitowy wariant pliku binarnego.

Aby dodać kontrolę drobnoziarnisty przez ABI z natywnych bibliotek i plików binarnych, użyj multilib.[first|lib32|lib64|prefer32|both].[native_shared_libs|binaries] Właściwości.

  • first : Zapałki podstawowym ABI urządzenia. Jest to ustawienie domyślne dla plików binarnych.
  • lib32 : Zapałki 32- ABI urządzenia musi być obsługiwana.
  • lib64 : Odpowiada 64-bitowe ABI urządzenia, jest obsługiwany.
  • prefer32 : Odpowiada 32-bitowe ABI urządzenia musi być obsługiwana. Jeśli 32-bitowy ABI nie jest obsługiwany, odpowiada 64-bitowemu ABI.
  • both : Zapałki oba Abis. Jest to ustawienie domyślne dla native_shared_libraries .

W java , libraries i prebuilts właściwości są ABI-agnostykiem.

Ten przykład dotyczy urządzenia obsługującego 32/64 i nie preferującego 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
        },
    },
}

podpisywanie vbmeta

Podpisz każdy APEX za pomocą różnych kluczy. Kiedy potrzebny jest nowy klucz, należy utworzyć parę kluczy publiczny-prywatny i dokonać apex_key moduł. Użyj key własności do podpisania APEX przy użyciu klucza. Klucz publiczny jest automatycznie włączone w APEX z nazwą 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",
}

W powyższym przykładzie, nazwa klucza publicznego ( foo ) staje się identyfikator klucza. Identyfikator klucza użytego do podpisania APEX jest zapisany w APEX. W czasie wykonywania apexd weryfikuje APEX przy użyciu klucza publicznego z tym samym identyfikatorem w urządzeniu.

Podpisywanie ZIP

Podpisuj pliki APEX w taki sam sposób, jak podpisujesz pakiety APK. Dwukrotnie podpisuj APEX; raz na mini systemu plików ( apex_payload.img pliku) i raz dla całego pliku.

Podpisać APEX na poziomie plików, ustaw certificate własności w jednym z tych trzech sposobów:

  • Nie ustawiony: Jeśli wartość nie jest ustawiona, APEX jest podpisany certyfikatem znajdującej się PRODUCT_DEFAULT_DEV_CERTIFICATE . Jeśli nie flaga jest ustawiona, domyślnie ścieżka do build/target/product/security/testkey .
  • <name> : APEX jest podpisana z <name> certyfikatu w tym samym katalogu co PRODUCT_DEFAULT_DEV_CERTIFICATE .
  • :<name> : APEX jest podpisany certyfikatem, który jest zdefiniowany przez moduł Soong nazwie <name> . Moduł certyfikatu można zdefiniować w następujący sposób.
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)
}

Instalowanie APEX

Aby zainstalować APEX, użyj ADB.

adb install apex_file_name
adb reboot

Korzystanie z APEX

Po restarcie, APEX jest zamontowany w /apex/<apex_name>@<version> katalogu. Wiele wersji tego samego APEX-a może być montowanych w tym samym czasie. Wśród ścieżek obsada, ten, który odpowiada najnowszej wersji jest bind-zamontowany w /apex/<apex_name> .

Klienci mogą używać ścieżki montowanej przez powiązanie do odczytywania lub wykonywania plików z APEX.

APEX są zwykle używane w następujący sposób:

  1. OEM lub ODM wczytuje wierzchołek pod /system/apex , gdy urządzenie wysyła.
  2. Pliki w APEX są dostępne za pośrednictwem /apex/<apex_name>/ ścieżki.
  3. Gdy zaktualizowana wersja APEX jest instalowany w /data/apex , punkty droga do nowego APEX po restarcie.

Aktualizacja usługi za pomocą APEX

Aby zaktualizować usługę za pomocą APEX:

  1. Oznacz usługę na partycji systemowej jako zdatną do aktualizacji. Dodaj opcję updatable do definicji usługi.

    /system/etc/init/myservice.rc:
    
    service myservice /system/bin/myservice
        class core
        user system
        ...
        updatable
    
  2. Utwórz nowy .rc plik dla zaktualizowanej usługi. Użyj override opcję przedefiniować istniejące usługi.

    /apex/my.apex@1/etc/init.rc:
    
    service myservice /apex/my.apex@1/bin/myservice
        class core
        user system
        ...
        override
    

Definicje usług mogą być określone tylko w .rc akt wierzchołku. Wyzwalacze akcji nie są obsługiwane w APEX.

Jeżeli usługa oznaczona jako aktualizowalna rozpoczyna się przed aktywacją APEX-ów, start jest opóźniany do momentu zakończenia aktywacji APEX-ów.

Konfiguracja systemu do obsługi aktualizacji APEX

Ustaw następującą właściwość systemu, aby true wspierać aktualizacje plików APEX.

<device.mk>:

PRODUCT_PROPERTY_OVERRIDES += ro.apex.updatable=true

BoardConfig.mk:
TARGET_FLATTEN_APEX := false

Lub tylko

<device.mk>:

$(call inherit-product, $(SRC_TARGET_DIR)/product/updatable_apex.mk)

Spłaszczony APEX

W przypadku starszych urządzeń aktualizacja starego jądra do pełnej obsługi APEX jest czasami niemożliwa lub niewykonalna. Na przykład jądro może zostały zbudowane bez CONFIG_BLK_DEV_LOOP=Y , co jest kluczowe dla montowania obrazu systemu plików wewnątrz APEX.

Flattened APEX to specjalnie zbudowany APEX, który można aktywować na urządzeniach ze starszym jądrem. Pliki w spłaszczonym APEX są bezpośrednio instalowane w katalogu na wbudowanej partycji. Na przykład, lib/libFoo.so w spłaszczoną APEX my.apex jest zainstalowany /system/apex/my.apex/lib/libFoo.so .

Aktywacja spłaszczonego APEX nie obejmuje urządzenia pętli. Cały katalog /system/apex/my.apex jest bezpośrednio wiążą montowane do /apex/name@ver .

Spłaszczonych APEX-ów nie można zaktualizować, pobierając zaktualizowane wersje APEX-ów z sieci, ponieważ pobranych APEX-ów nie można spłaszczyć. Spłaszczone APEX mogą być aktualizowane tylko przez zwykłą OTA.

Spłaszczony APEX jest konfiguracją domyślną. Oznacza to, że wszystkie APEX są domyślnie spłaszczone, chyba że jawnie skonfigurujesz urządzenie do budowania niespłaszczonych APEX-ów do obsługi aktualizacji APEX (jak wyjaśniono powyżej).

Mieszanie spłaszczonych i niespłaszczonych APEX w urządzeniu NIE jest obsługiwane. Punkty APEX w urządzeniu muszą być albo niespłaszczone, albo wszystkie spłaszczone. Jest to szczególnie ważne w przypadku wysyłania wstępnie podpisanych prekompilacji APEX dla projektów takich jak Mainline. APEX, które nie są wstępnie podpisane (czyli zbudowane ze źródła), również powinny być niespłaszczone i podpisane odpowiednimi kluczami. Urządzenie powinno dziedziczyć updatable_apex.mk jak wyjaśniono w Aktualizowanie usługi wierzchołku .

Skompresowane APEX

Android 12 i nowsze obsługują kompresję APEX w celu zmniejszenia wpływu pamięci masowej aktualizowanych pakietów APEX. Po zainstalowaniu aktualizacji APEX, mimo że jej preinstalowana wersja nie jest już używana, nadal zajmuje tyle samo miejsca. Ta zajęta przestrzeń pozostaje niedostępna.

Kompresja APEX Minimalizuje to wpływ przechowywania za pomocą wysoko sprężonego zestaw plików APEX na partycje tylko do odczytu (takich jak /system partycji). Android 12 i nowsze używają algorytmu kompresji zip DEFLATE.

Kompresja nie zapewnia optymalizacji następujących elementów:

  • Bootstrap APEX, które należy zamontować na bardzo wczesnym etapie sekwencji rozruchu.

  • Nieaktualizowalne APEX. Kompresja jest korzystny tylko jeśli uaktualniona wersja wierzchołek jest zainstalowany na /data partycji. Pełną listę aktualizowalnych wierzchołkach jest dostępny na Modułowe komponenty systemu stronie.

  • Dynamiczne biblioteki współdzielone APEX. Od apexd zawsze aktywuje obie wersje takich wierzchołków (zainstalowany fabrycznie i zmodernizowane), ściskając im nie dodaje wartości.

Skompresowany format pliku APEX

To jest format skompresowanego pliku APEX.

Diagram shows the format of a compressed APEX file

Format pliku Rysunek 2. Sprężone APEX

Na najwyższym poziomie skompresowany plik APEX jest plikiem zip zawierającym oryginalny plik apex w nieskompresowanej formie z poziomem kompresji 9 oraz innymi plikami przechowywanymi w postaci nieskompresowanej.

Na plik APEX składają się cztery pliki:

  • original_apex : opróżniony z poziomu kompresji 9 Jest to oryginalny, nieskompresowany plik APEX .
  • apex_manifest.pb : przechowywane tylko
  • AndroidManifest.xml : przechowywane tylko
  • apex_pubkey : przechowywane tylko

apex_manifest.pb , AndroidManifest.xml i apex_pubkey pliki są kopiami ich odpowiednich plików w original_apex .

Budowanie skompresowanego APEX

Compressed APEX można zbudować przy użyciu apex_compression_tool.py narzędzia znajdującego się w system/apex/tools .

W systemie kompilacji dostępnych jest kilka parametrów związanych z kompresją APEX.

W Android.bp czy plik APEX jest ściśliwy jest kontrolowana przez compressible nieruchomości:

apex {
    name: "apex.test",
    manifest: "apex_manifest.json",
    file_contexts: "file_contexts",
    compressible: true,
}

PRODUCT_COMPRESSED_APEX kontrole flag produkt czy obraz systemu zbudowany ze źródła musi zawierać skompresowane pliki APEX.

Dla lokalnego eksperymentów można wymusić build skompresować wierzchołki ustawiając OVERRIDE_PRODUCT_COMPRESSED_APEX= się true .

Compressed APEX plików generowanych przez system kompilacji mają .capex rozszerzenie. Rozszerzenie ułatwia odróżnienie skompresowanych i nieskompresowanych wersji pliku APEX.

Obsługiwane algorytmy kompresji

Android 12 obsługuje tylko kompresję deflate-zip.

Aktywacja skompresowanego pliku APEX podczas rozruchu

Przed skompresowany APEX może być aktywowany, original_apex plik wewnątrz jest rozpakowane do /data/apex/decompressed katalogu. Powstały dekompresji plików APEX jest silnie powiązany z /data/apex/active katalogu.

Rozważmy następujący przykład jako ilustrację procesu opisanego powyżej.

Rozważmy /system/apex/com.android.foo.capex jako sprężony APEX aktywacji z versionCode 37.

  1. original_apex plik wewnątrz /system/apex/com.android.foo.capex rozpręża się /data/apex/decompressed/com.android.foo@37.apex .
  2. restorecon /data/apex/decompressed/com.android.foo@37.apex przeprowadza się w celu sprawdzenia, czy ma prawidłową etykietę SELinux.
  3. Weryfikacji kontrole są przeprowadzane na /data/apex/decompressed/com.android.foo@37.apex celu zapewnienia jego ważności: apexd sprawdza klucz publiczny spakowane w /data/apex/decompressed/com.android.foo@37.apex do upewnij się, że jest równa jednej dołączonego w /system/apex/com.android.foo.capex .
  4. /data/apex/decompressed/com.android.foo@37.apex plik jest silnie powiązany z /data/apex/active/com.android.foo@37.apex katalogu.
  5. Regularne logika aktywacji nieskompresowanych plików APEX jest wykonywana na /data/apex/active/com.android.foo@37.apex .

Interakcja z OTA

Skompresowane pliki APEX mają wpływ na dostarczanie i stosowanie OTA. Ponieważ aktualizacja OTA może zawierać skompresowany plik APEX z wersją wyższą niż ta, która jest aktywna na urządzeniu, pewna ilość wolnego miejsca musi zostać zarezerwowana przed ponownym uruchomieniem urządzenia w celu zastosowania aktualizacji OTA.

Na wsparcie systemu OTA, apexd naraża te dwa API Spoiwo:

  • calculateSizeForCompressedApex - oblicza wielkość potrzebnej do dekompresji plików APEX w pakiecie OTA. Można to wykorzystać do sprawdzenia, czy urządzenie ma wystarczającą ilość miejsca przed pobraniem OTA.
  • reserveSpaceForCompressedApex - rezerwy miejsca na dysku do wykorzystania w przyszłości przez apexd do dekompresji plików skompresowanych APEX wewnątrz opakowania OTA.

W przypadku aktualizacji A / B OTA, apexd próbach dekompresję w tle jako część postinstall OTA rutyny. Jeśli się nie powiedzie, dekompresja apexd dokonuje dekompresji podczas startu że zastosowanie aktualizacji OTA.

Alternatywy brane pod uwagę przy opracowywaniu APEX

Oto kilka opcji, które firma AOSP rozważyła podczas projektowania formatu pliku APEX, i dlaczego zostały one uwzględnione lub wykluczone.

Regularne systemy zarządzania pakietami

Dystrybucje Linuksa mają systemy zarządzania pakietami jak dpkg i rpm , które są silne, dojrzałe i wytrzymałe. Jednak nie zostały one zaadoptowane do APEX, ponieważ nie mogą chronić pakietów po instalacji. Weryfikacja jest przeprowadzana tylko wtedy, gdy pakiety są instalowane. Atakujący mogą niepostrzeżenie złamać integralność zainstalowanych pakietów. Jest to regresja dla Androida, w której wszystkie komponenty systemu były przechowywane w systemach plików tylko do odczytu, których integralność jest chroniona przez dm-verity dla każdego I/O. Wszelkie ingerencje w składniki systemu muszą być zabronione lub być wykrywalne, aby urządzenie mogło odmówić uruchomienia w przypadku naruszenia bezpieczeństwa.

dm-crypt dla integralności

Pliki w pojemniku APEX są z wbudowanych przegród (na przykład, /system przegroda), które są chronione przez DM-prawdzie, gdzie każda zmiana w plikach są zakazane nawet po działowe są zamontowane. Aby zapewnić ten sam poziom bezpieczeństwa plików, wszystkie pliki w APEX są przechowywane w obrazie systemu plików, który jest sparowany z drzewem mieszającym i deskryptorem vbmeta. Bez dm-Verity wierzchołku w /data partycji jest podatny do niezamierzonych zmian, które są wykonane po tym jak został zweryfikowany i zainstalowane.

W rzeczywistości, /data przegroda jest zabezpieczony przez warstwy szyfrowania, takie jak dm-Crypt. Chociaż zapewnia to pewien poziom ochrony przed manipulacją, jego głównym celem jest prywatność, a nie integralność. Kiedy osoba atakująca uzyska dostęp do /data partycji, nie może być dalej ochrona, a to znowu jest regres w stosunku do każdego elementu systemu będącego w /system partycji. Drzewo skrótów w pliku APEX wraz z dm-verity zapewnia ten sam poziom ochrony treści.

Przekierowywanie ścieżek z /system do /apex

Pliki składowe systemowe pakowane w APEX są dostępne za pośrednictwem nowych dróg jak /apex/<name>/lib/libfoo.so . Gdy pliki były częścią /system partycji, były one dostępne za pośrednictwem ścieżek takich jak /system/lib/libfoo.so . Klient pliku APEX (inne pliki APEX lub platforma) musi korzystać z nowych ścieżek. W wyniku zmiany ścieżki może być konieczna aktualizacja istniejącego kodu.

Chociaż jeden sposób, aby uniknąć zmiany ścieżki jest nakładanie zawartość pliku w pliku APEX na /system partycji, Android zespół nie zdecydował się plikami nakładki /system partycji, ponieważ może to wpłynąć na wydajność, ponieważ liczba plików jest nakładka ( być może nawet ułożone jeden po drugim) wzrosła.

Inną opcją było przejąć funkcje dostępu do plików, takich jak open , stat , a readlink , tak że ścieżki rozpoczynające się /system zostały przekierowane do odpowiadających im ścieżek pod /apex . Zespół Androida odrzucił tę opcję, ponieważ zmiana wszystkich funkcji akceptujących ścieżki jest niewykonalna. Na przykład niektóre aplikacje statycznie łączą Bionic, który implementuje funkcje. W takich przypadkach te aplikacje nie są przekierowywane.