Dynamiczne aktualizacje systemu

Dynamiczne aktualizacje systemu (DSU) umożliwiają tworzenie obrazu systemu Android użytkownicy mogą pobierać z internetu i próbować bez ryzyka uszkodzenia urządzenia. do bieżącego obrazu systemu. Z tego dokumentu dowiesz się, jak obsługiwać DSU.

Wymagania jądra systemu

Zobacz Implementowanie partycji dynamicznych pod kątem wymagań jądra systemu operacyjnego.

Dodatkowo DSU korzysta z funkcji jądra systemu „device-mapper-verity” (dm-verity) aby zweryfikować obraz systemu Android. Musisz więc włączyć to jądro Konfiguracje:

  • CONFIG_DM_VERITY=y
  • CONFIG_DM_VERITY_FEC=y

Wymagania dotyczące partycji

Począwszy od Androida 11, DSU wymaga /data do używania systemu plików F2FS lub ext4. F2FS zapewnia lepszą wydajność jest zalecane, ale różnica powinna być nieistotna.

Oto kilka przykładów czasu trwania dynamicznej aktualizacji systemu na Pixelu urządzenie:

  • Korzystanie z F2FS:
    • 109s, użytkownik 8G, system 867M, typ systemu plików: F2FS: szyfrowanie=aes-256-xts:aes-256-cts
    • 104 s, użytkownik 8 G, system 867 M, typ systemu plików: F2FS: encryption=ice
  • Użycie ext4:
    • 135s, użytkownik 8G, system 867M, typ systemu plików: ext4: szyfrowanie=aes-256-xts:aes-256-cts

Jeśli na Twojej platformie potrzeba więcej czasu, sprawdź, czy uchwyt flaga zawiera dowolną flagę powodującą zapis „sync”, ale można też podać wartość „async” bezpośrednio, by zwiększyć skuteczność.

Partycja metadata (co najmniej 16 MB) jest wymagana do przechowywania danych związanych do zainstalowanych obrazów. Należy ją zamontować podczas pierwszego etapu podłączania.

Partycja userdata musi używać systemu plików F2FS lub ext4. Jeśli używasz F2FS, uwzględnij wszystkie poprawki związane z F2FS dostępne w ogólnym jądrze Androida.

DSU został opracowany i przetestowany z jądrem/common 4.9. Zalecane jest użycie jądro w wersji 4.9 lub nowszej.

Zachowanie interfejsu HAL dostawcy

Weaver HAL

HAL Weaver zapewnia stałą liczbę przedziałów do przechowywania kluczy użytkownika. Agencja DSU zużywa 2 dodatkowe przedziały na klucze. Jeśli OEM ma interfejs weaver HAL, musi mieć wystarczającą liczbę slotów na ogólny obraz systemu (GSI) i obraz hosta.

HAL bramkarz

HAL bramki musi: obsługuje duże wartości USER_ID, ponieważ GSI kompensuje identyfikatory UID do HAL o +1000000.

Weryfikacja podczas uruchamiania

Jeśli chcesz mieć możliwość uruchamiania obrazów GSI dla programistów w stanie ZABLOKOWANE bez wyłączania weryfikacja podczas uruchamiania, dołącz klucze GSI dewelopera, dodając następujący wiersz: do pliku device/<device_name>/device.mk:

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

Ochrona przed przywróceniem

Jeśli używasz DSU, pobrany obraz systemu Android musi być nowszy niż bieżącego obrazu systemu na urządzeniu. Polega to na porównaniu poziomów poprawek zabezpieczeń w weryfikacji podczas uruchamiania Androida (AVB)(descriptor właściwości AVB) obu obrazów systemu: Prop: com.android.build.system.security_patch -> '2019-04-05'.

W przypadku urządzeń, które nie korzystają z AVB, podaj poziom aktualizacji zabezpieczeń bieżącego systemu za pomocą polecenia cmdline jądra lub polecenia rozruchowego przy użyciu programu rozruchowego: androidboot.system.security_patch=2019-04-05

Wymagania sprzętowe

Gdy uruchomisz instancję DSU, przydzielone zostaną 2 pliki tymczasowe:

  • Partycja logiczna do przechowywania GSI.img (1~1,5 G)
  • pusty 8-gigabajtowy /data jako piaskownica do uruchamiania GSI;

Przed uruchomieniem DSU zalecamy zarezerwowanie co najmniej 10 GB wolnego miejsca instancji. DSU obsługuje też alokację z karty SD. Gdy karta SD jest obecna, ma najwyższy priorytet przy przydzielaniu. Obsługa karty SD jest kluczowe w przypadku urządzeń o mniejszej mocy, które mogą mieć za mało pamięci wewnętrznej. Jeśli masz kartę SD, upewnij się, że nie jest wykorzystywana. DSU nie obsługuje przyjętych kart SD.

Dostępne frontendy

Możesz uruchomić DSU za pomocą adb, aplikacji OEM lub narzędzia ładującego DSU jednym kliknięciem (w w Androidzie 11 lub nowszym).

Uruchamianie DSU za pomocą adb

Aby uruchomić DSU za pomocą narzędzia adb, wpisz te polecenia:

$ simg2img out/target/product/.../system.img system.raw
$ gzip -c system.raw > system.raw.gz
$ adb push system.raw.gz /storage/emulated/0/Download
$ adb shell am start-activity \
-n com.android.dynsystem/com.android.dynsystem.VerificationActivity  \
-a android.os.image.action.START_INSTALL    \
-d file:///storage/emulated/0/Download/system.raw.gz  \
--el KEY_SYSTEM_SIZE $(du -b system.raw|cut -f1)  \
--el KEY_USERDATA_SIZE 8589934592

Uruchamianie DSU za pomocą aplikacji

Głównym punktem wejścia do DSU jest android.os.image.DynamicSystemClient.java Interfejs API:

public class DynamicSystemClient {


...
...

     /**
     * Start installing DynamicSystem from URL with default userdata size.
     *
     * @param systemUrl A network URL or a file URL to system image.
     * @param systemSize size of system image.
     */
    public void start(String systemUrl, long systemSize) {
        start(systemUrl, systemSize, DEFAULT_USERDATA_SIZE);
    }

Musisz spakować tę aplikację lub wstępnie zainstalować ją na urządzeniu. Ponieważ DynamicSystemClient to systemowy interfejs API, nie można utworzyć aplikacji za pomocą zwykłego interfejsu API SDK API i nie możesz go opublikować w Google Play. Cel tej aplikacji:

  1. Pobieranie listy obrazów i odpowiadających im adresów URL za pomocą schematu określonego przez dostawcę.
  2. Dopasuj obrazy na liście do urządzenia i pokaż użytkownikowi kompatybilne obrazy.
  3. Wywołaj DynamicSystemClient.start w ten sposób:

    DynamicSystemClient aot = new DynamicSystemClient(...)
       aot.start(
            ...URL of the selected image...,
            ...uncompressed size of the selected image...);
    
    

Adres URL wskazuje skompresowany, nierozdzielony plik obrazu systemowego, za pomocą tych poleceń:

$ simg2img ${OUT}/system.img ${OUT}/system.raw
$ gzip ${OUT}/system.raw
$ ls ${OUT}/system.raw.gz

Nazwa pliku powinna mieć ten format:

<android version>.<lunch name>.<user defined title>.raw.gz

Przykłady:

  • o.aosp_taimen-userdebug.2018dev.raw.gz
  • p.aosp_taimen-userdebug.2018dev.raw.gz

Moduł ładujący DSU 1 kliknięciem

Android 11 wprowadza ładowarkę DSU jednym kliknięciem, która jest interfejsem w ustawieniach dewelopera.

Uruchamiam narzędzie ładujące DSU

Rysunek 1. Uruchamianie programu ładującego DSU

Gdy deweloper kliknie przycisk Moduł ładujący DS, pobierze wstępnie skonfigurowany z internetowego deskryptora JSON DSU oraz wyświetla wszystkie odpowiednie obrazy w pływającego menu. Wybierz obraz, aby rozpocząć instalację DSU i postępować pokazuje się na pasku powiadomień.

Postęp instalacji obrazu DSU

Rysunek 2. Postęp instalacji obrazu DSU

Domyślnie ładownik DSU wczytuje opis JSON zawierający obrazy GSI. W tych sekcjach dowiesz się, jak tworzyć i ładować pakiety DSU podpisane przez OEM je z programu ładującego DSU.

Flaga funkcji

Funkcja DSU jest obsługiwana przez flagę funkcji settings_dynamic_android. Przed przy użyciu DSU, sprawdź, czy jest włączona odpowiednia flaga funkcji.

Włączanie flagi funkcji.

Rysunek 3. Włączanie flagi funkcji

Interfejs flagi funkcji może być niedostępny na urządzeniu z wersją użytkową. W takim przypadku użyj polecenia adb:

$ adb shell setprop persist.sys.fflag.override.settings_dynamic_system 1

Obrazy systemu hosta dostawcy w GCE (opcjonalnie)

Jednym z możliwych miejsc przechowywania obrazów systemu jest zasobnik Google Compute Engine (GCE). Administrator wersji korzysta z konsoli miejsca na dane GCP, aby dodawać, usuwać i zmieniać opublikowany obraz systemu.

Obrazy muszą być dostępne publicznie, jak tutaj:

Dostęp publiczny w GCE

Rysunek 4. Dostęp publiczny w GCE

Procedura udostępniania elementów jest dostępna w dokumentacji Google Cloud.

Wielopartycjonalna jednostka DSU w pliku ZIP

Począwszy od Androida 11, DSU może mieć więcej niż 1 partycję. Na przykład może zawierać znak product.img, a dodatkowo system.img Po uruchomieniu urządzenia pierwszy etap init wykrywa zainstalowano partycje DSU i tymczasowo zastępuje partycję na urządzeniu, gdy czy zainstalowana aplikacja DSU jest włączona. Pakiet DSU może zawierać partycję, która nie ma odpowiadającej partycji na urządzeniu.

Proces DSU z wieloma partycjami

Rysunek 5. Proces DSU z wieloma partycjami

DSU podpisane przez OEM

Aby upewnić się, że wszystkie obrazy uruchomione na urządzeniu są autoryzowane przez urządzenie producenta, wszystkie obrazy w pakiecie DSU muszą być podpisane. Załóżmy, że mamy pakiet DSU zawierający 2 obrazy partycji:

dsu.zip {
    - system.img
    - product.img
}

Zarówno system.img, jak i product.img muszą być podpisane kluczem OEM do pliku ZIP. Zazwyczaj stosuje się metody asymetryczne (np. RSA), gdzie tajny klucz jest używany do podpisywania pakietu, a klucz jest używany do jego weryfikacji. Ramdysk pierwszego etapu musi zawierać klucz publiczny do parowania, na przykład /avb/*.avbpubkey. Jeśli urządzenie już zastosowało AVB, wystarczy istniejąca procedura podpisywania. W kolejnych sekcjach przedstawiono proces podpisywania oraz wyróżniono miejsce docelowe klucza publicznego AVB, który służy do weryfikacji obrazów w pakiecie DSU.

Deskryptor JSON DSU

Deskryptor JSON DSU opisuje pakiety DSU. Obsługuje 2 elementy podstawowe. Po pierwsze: element include zawiera dodatkowe deskryptory lub przekierowania JSON program ładujący DSU w nowe miejsce. Na przykład:

{
    "include": ["https://.../gsi-release/gsi-src.json"]
}

Po drugie: podstawowy image służy do opisywania udostępnionych pakietów DSU. Wewnątrz do obiektu graficznego jest kilka atrybutów:

  • Atrybuty name i details to ciągi tekstowe, które są wyświetlane w okno, które użytkownik może wybrać.

  • Atrybuty cpu_api, vndk i os_version są używane do sprawdzania zgodności, co jest opisane w następnej sekcji.

  • Opcjonalny atrybut pubkey opisuje publiczne który będzie parowany z tajnym kluczem używanym do podpisywania pakietu DSU. Gdy go podasz, usługa DSU może sprawdzić, czy urządzenie ma klucz użyte do zweryfikowania pakietu DSU. Zapobiega to instalacji niezidentyfikowanego pakietu DSU, na przykład zainstalowania pakietu DSU podpisanego przez OEM-A na urządzeniu wyprodukowanym przez OEM-B.

  • Opcjonalny atrybut tos wskazuje plik tekstowy, który opisuje warunki korzystania z usługi dla odpowiedniego pakietu DSU. Gdy deweloper wybiera pakiet DSU z określonym atrybutem warunków korzystania z usługi, otwiera się okno dialogowe widoczne na Rys. 6, z prośbą o zaakceptowanie warunków usługi przed zainstalowaniem pakietu DSU.

    Okno z Warunkami korzystania z usługi

    Rysunek 6. Okno z Warunkami korzystania z usługi

Oto deskryptor JSON DSU dla GSI:

{
   "images":[
      {
         "name":"GSI+GMS x86",
         "os_version":"10",
         "cpu_abi": "x86",
         "details":"exp-QP1A.190711.020.C4-5928301",
         "vndk":[
            27,
            28,
            29
         ],
         "pubkey":"",
         "tos": "https://dl.google.com/developers/android/gsi/gsi-tos.txt",
         "uri":"https://.../gsi/gsi_gms_x86-exp-QP1A.190711.020.C4-5928301.zip"
      },
      {
         "name":"GSI+GMS ARM64",
         "os_version":"10",
         "cpu_abi": "arm64-v8a",
         "details":"exp-QP1A.190711.020.C4-5928301",
         "vndk":[
            27,
            28,
            29
         ],
         "pubkey":"",
         "tos": "https://dl.google.com/developers/android/gsi/gsi-tos.txt",
         "uri":"https://.../gsi/gsi_gms_arm64-exp-QP1A.190711.020.C4-5928301.zip"
      },
      {
         "name":"GSI ARM64",
         "os_version":"10",
         "cpu_abi": "arm64-v8a",
         "details":"exp-QP1A.190711.020.C4-5928301",
         "vndk":[
            27,
            28,
            29
         ],
         "pubkey":"",
         "uri":"https://.../gsi/aosp_arm64-exp-QP1A.190711.020.C4-5928301.zip"
      },
      {
         "name":"GSI x86_64",
         "os_version":"10",
         "cpu_abi": "x86_64",
         "details":"exp-QP1A.190711.020.C4-5928301",
         "vndk":[
            27,
            28,
            29
         ],
         "pubkey":"",
         "uri":"https://.../gsi/aosp_x86_64-exp-QP1A.190711.020.C4-5928301.zip"
      }
   ]
}

Zarządzanie zgodnością

Do określenia zgodności pakietu DSU używa się kilku atrybutów oraz na urządzeniu lokalnym:

  • cpu_api to ciąg tekstowy opisujący architekturę urządzenia. Ten atrybut jest wymagany i jest porównywany z właściwością systemową ro.product.cpu.abi. Ich wartości muszą być identyczne.

  • os_version to opcjonalna liczba całkowita, która określa wersję Androida. Dla: na przykład w przypadku Androida 10 os_version to 10, a dla Androida 11, os_version to 11. Gdy to został określony, musi on być równy lub większy niż ro.system.build.version.release właściwość systemową. To sprawdzanie służy do zapobiegania uruchamianiu obrazu GSI Androida 10 na urządzeniu sprzedawcy z Androidem 11, które obecnie nie jest obsługiwane. Rozruchowy obraz GSI Androida 11 jest dozwolony na urządzeniu z Androidem 10.

  • vndk to opcjonalna tablica, która określa wszystkie zestawy VNDK zawarte w pakietu DSU. Gdy jest podany, moduł wczytujący DSU sprawdza, czy numer wyodrębnione z właściwości systemowej ro.vndk.version.

Unieważnianie kluczy DSU ze względów bezpieczeństwa

W bardzo rzadkich przypadkach, gdy klucz RSA używany do podpisywania obrazów DSU zostanie skompromitowany, należy jak najszybciej zaktualizować dysk RAM, aby usunąć skompromitowany klucz. Oprócz aktualizacji partycji rozruchowej możesz zablokować klucze zagrożone za pomocą listy wycofania kluczy DSU (lista kluczy na czarnej liście) z adresu URL HTTPS.

Lista kluczy odwołania DSU zawiera listę odwoływanych kluczy publicznych AVB. Podczas instalacji DSU klucze publiczne w obrazach DSU są weryfikowane za pomocą listy odwołanych certyfikatów. Jeśli okaże się, że zawierają one unieważnione zdjęcia publiczne spowoduje to zatrzymanie procesu instalacji DSU.

Aby zapewnić bezpieczeństwo, adres URL listy kluczy musi być adresem URL protokołu HTTPS. Jest on określony w ciągu zasobu:

frameworks/base/packages/DynamicSystemInstallationService/res/values/strings.xml@key_revocation_list_url

Wartość ciągu to https://dl.google.com/developers/android/gsi/gsi-keyblacklist.json, czyli listę unieważnień dla kluczy GSI udostępnionych przez Google. Ten ciąg znaków zasobu można nakładać i dostosowywać, aby producenci OEM, którzy korzystają z funkcji DSU, mogli udostępniać i utrzymywać własną listę kluczy zakazanych. Dzięki temu producent OEM może blokować niektóre klucze publiczne bez aktualizowania obrazu dysku RAM urządzenia.

Format listy odwołań:

{
   "entries":[
      {
         "public_key":"bf14e439d1acf231095c4109f94f00fc473148e6",
         "status":"REVOKED",
         "reason":"Key revocation test key"
      },
      {
         "public_key":"d199b2f29f3dc224cca778a7544ea89470cbef46",
         "status":"REVOKED",
         "reason":"Key revocation test key"
      }
   ]
}
  • public_key to skrót SHA-1 unieważnionego klucza w opisanym formacie podczas generowania klucza publikacyjnego AVB .
  • status wskazuje stan odwołania klucza. Obecnie jedyną obsługiwaną wartością jest REVOKED.
  • reason to opcjonalny ciąg znaków opisujący przyczynę unieważnienia.

Procedury DSU

W tej sekcji opisujemy, jak wykonać różne procedury konfiguracji DSU.

Generowanie nowej pary kluczy

Użyj polecenia openssl, aby wygenerować parę kluczy (prywatny/publiczny) RSA w .pem format (np. rozmiar 2048-bitowy):

$ openssl genrsa -out oem_cert_pri.pem 2048
$ openssl rsa -in oem_cert_pri.pem -pubout -out oem_cert_pub.pem

Klucz prywatny może być niedostępny i przechowywany tylko w sprzętowym module zabezpieczeń (HSM). W takim przypadku po wygenerowaniu klucza może być dostępny certyfikat klucza publicznego X.509. Patrz Dodawanie klucza publicznego parowania do pliku ramdisk. , aby uzyskać instrukcje generowania klucza publicznego AVB z certyfikatu x509.

Aby przekonwertować certyfikat x509 na format PEM:

$ openssl x509 -pubkey -noout -in oem_cert_pub.x509.pem > oem_cert_pub.pem

Pomiń ten krok, jeśli certyfikat jest już plikiem PEM.

Dodaj klucz publiczny parowania do dysku ramdy

Aby zweryfikować podpisany pakiet DSU, musisz umieścić oem_cert.avbpubkey w folderze /avb/*.avbpubkey. Najpierw przekonwertuj klucz publiczny w formacie PEM na publiczny AVB format klucza:

$ avbtool extract_public_key --key oem_cert_pub.pem --output oem_cert.avbpubkey

Następnie dołącz klucz publiczny do dysku RAM pierwszego etapu, wykonując czynności opisane poniżej.

  1. Dodaj gotowy moduł, aby skopiować avbpubkey. Na przykład dodaj device/<company>/<board>/oem_cert.avbpubkey i device/<company>/<board>/avb/Android.mk z takimi treściami:

    include $(CLEAR_VARS)
    
    LOCAL_MODULE := oem_cert.avbpubkey
    LOCAL_MODULE_CLASS := ETC
    LOCAL_SRC_FILES := $(LOCAL_MODULE)
    ifeq ($(BOARD_USES_RECOVERY_AS_BOOT),true)
    LOCAL_MODULE_PATH := $(TARGET_RECOVERY_ROOT_OUT)/first_stage_ramdisk/avb
    else
    LOCAL_MODULE_PATH := $(TARGET_RAMDISK_OUT)/avb
    endif
    
    include $(BUILD_PREBUILT)
    
  2. Ustaw zależność celu droidcore od dodanego oem_cert.avbpubkey:

    droidcore: oem_cert.avbpubkey
    

Generowanie atrybutu pubkey AVB w deskryptorze JSON

oem_cert.avbpubkey ma format binarny klucza publicznego AVB. Użyj funkcji SHA-1, aby uczynić go czytelnym przed umieszczeniem w deskryptorze JSON:

$ sha1sum oem_cert.avbpubkey | cut -f1 -d ' '
3e62f2be9d9d813ef5........866ac72a51fd20

To będzie zawartość atrybutu pubkey deskryptora JSON.

   "images":[
      {
         ...
         "pubkey":"3e62f2be9d9d813ef5........866ac72a51fd20",
         ...
      },

Podpisz pakiet DSU

Aby podpisać pakiet DSU, użyj jednej z tych metod:

  • Metoda 1. Użyj artefaktu utworzonego przez pierwotny proces podpisywania AVB, aby utworzyć pakiet DSU. Alternatywnym podejściem jest wyodrębnienie już podpisanych obrazów z opakowania wersji i użycie wyodrębnionych obrazów do bezpośredniego utworzenia pliku ZIP.

  • Metoda 2. Aby podpisać partycje DSU, użyj tych poleceń, jeśli prywatny jest dostępny. Każdy identyfikator img w pakiecie DSU (pliku ZIP) jest podpisany oddzielnie:

    $ key_len=$(openssl rsa -in oem_cert_pri.pem -text | grep Private-Key | sed -e 's/.*(\(.*\) bit.*/\1/')
    $ for partition in system product; do
        avbtool add_hashtree_footer \
            --image ${OUT}/${partition}.img \
            --partition_name ${partition} \
            --algorithm SHA256_RSA${key_len} \
            --key oem_cert_pri.pem
    done
    

Więcej informacji o dodawaniu add_hashtree_footer za pomocą avbtool znajdziesz w artykule Używanie narzędzia avbtool.

Weryfikacja pakietu DSU lokalnie

Zalecamy zweryfikowanie wszystkich lokalnych obrazów za pomocą parowania klucza publicznego za pomocą tych poleceń:


for partition in system product; do
    avbtool verify_image --image ${OUT}/${partition}.img  --key oem_cert_pub.pem
done

Oczekiwany wynik:

Verifying image dsu/system.img using key at oem_cert_pub.pem
vbmeta: Successfully verified footer and SHA256_RSA2048 vbmeta struct in dsu/system.img
: Successfully verified sha1 hashtree of dsu/system.img for image of 898494464 bytes

Verifying image dsu/product.img using key at oem_cert_pub.pem
vbmeta: Successfully verified footer and SHA256_RSA2048 vbmeta struct in dsu/product.img
: Successfully verified sha1 hashtree of dsu/product.img for image of 905830400 bytes

Tworzenie pakietu DSU

Ten przykład tworzy pakiet DSU zawierający system.img i product.img:

dsu.zip {
    - system.img
    - product.img
}

Po podpisaniu obu obrazów użyj tego polecenia, aby utworzyć plik ZIP:

$ mkdir -p dsu
$ cp ${OUT}/system.img dsu
$ cp ${OUT}/product.img dsu
$ cd dsu && zip ../dsu.zip *.img && cd -

Dostosowywanie usługi DSU jednym kliknięciem

Domyślnie moduł ładujący DSU wskazuje metadane obrazów GSI, które są https://...google.com/.../gsi-src.json

Producenci OEM mogą zastąpić tę listę, definiując właściwość persist.sys.fflag.override.settings_dynamic_system.list, która wskazuje na ich własny opis JSON. Na przykład OEM może podaj metadane JSON, które zawierają GSI, a także zastrzeżone obrazy OEM, jak na przykład:

{
    "include": ["https://dl.google.com/.../gsi-src.JSON"]
    "images":[
      {
         "name":"OEM image",
         "os_version":"10",
         "cpu_abi": "arm64-v8a",
         "details":"...",
         "vndk":[
            27,
            28,
            29
         ],
         "spl":"...",
         "pubkey":"",
         "uri":"https://.../....zip"
      },

}

Producent OEM może połączyć opublikowane metadane DSU, jak pokazano na rysunku 7.

Łańcuch opublikowanych metadanych DSU

Rysunek 7. Łańcuch opublikowanych metadanych DSU