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. Ten dokument opisuje sposób obsługi 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
    • 104s, użytkownik 8G, system 867 MB, typ systemu plików: F2FS: szyfrowanie=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 korzystać z systemu plików F2FS lub ext4. Podczas korzystania z F2FS należy uwzględnić wszystkie poprawki związane z F2FS, które są dostępne Wspólne jądro Androida.

Oprogramowanie DSU zostało opracowane i przetestowane z użyciem jądra systemu/common 4.9. Zalecane jest użycie jądro w wersji 4.9 lub nowszej.

Zachowanie dostawcy HAL

HAL Weaver

HAL Weaver zapewnia stałą liczbę przedziałów do przechowywania kluczy użytkownika. Organizacja DSU zużywa 2 dodatkowe przedziały na klucze. Jeśli producent OEM ma licencję HAL, musi mieć 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.

Sprawdzanie rozruchu

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)

Przywracanie

Jeśli używasz DSU, pobrany obraz systemu Android musi być nowszy niż aktualny obraz systemu urządzenia. Jest to możliwe dzięki porównaniu poprawki zabezpieczeń na różnych poziomach Weryfikacja podczas uruchamiania Androida (AVB) Deskryptor właściwości AVB obu obrazów systemowych: 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

Po uruchomieniu instancji DSU przydzielane są 2 pliki tymczasowe:

  • Partycja logiczna do przechowywania GSI.img (1~1,5 G)
  • Pusta partycja /data o pojemności 8 GB jako piaskownica do uruchamiania GSI

Przed uruchomieniem DSU zalecamy zarezerwowanie co najmniej 10 GB wolnego miejsca instancji. DSU obsługuje też przydział z karty SD. Gdy karta SD jest ma najwyższy priorytet dla alokacji. 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 wprowadzonych 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ą narzędzia 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 aplikacji:

  1. Pobierz listę obrazów i odpowiednie adresy URL ze schematem zdefiniowanym przez dostawcę.
  2. Dopasuj obrazy na liście do urządzenia i wyświetl je zgodne którą użytkownik ma wybrać.
  3. Wywołaj funkcję 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ć następujący 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

W Androidzie 11 wprowadziliśmy program ładujący DSU – jednym kliknięciem, to frontend w ustawieniach programisty.

Uruchamiam narzędzie ładujące DSU

Rysunek 1. Uruchamiam narzędzie ładujące 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 moduł ładujący DSU wczytuje deskryptor 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 dostępna w ramach flagi funkcji settings_dynamic_android. Przed przy użyciu DSU, sprawdź, czy jest włączona odpowiednia flaga funkcji.

Włączam flagę funkcji.

Rysunek 3. Włączanie flagi funkcji

Interfejs flag funkcji może być niedostępny na urządzeniu z kompilacją użytkownika. W w tym 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 do przechowywania obrazów systemu jest plik Google Zasobnik Compute Engine (GCE). Administrator wersji używa funkcji konsoli Cloud Storage w GCP dodać, usunąć lub zmienić opublikowany obraz systemu.

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

Dostęp publiczny w GCE

Rysunek 4. Dostęp publiczny w GCE

Procedura publicznego udostępniania elementu 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 partycji danych. 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 mają odpowiednią partycję na urządzeniu.

Proces DSU z wieloma partycjami

Rysunek 5. Proces DSU z wieloma partycjami

DSU podpisany 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. Przykład: załóżmy, że istnieje pakiet DSU zawierający 2 obrazy partycji, jak poniżej:

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ć parowanie klucz publiczny, na przykład /avb/*.avbpubkey. Jeśli urządzenie już zastosowało AVB, wystarczy istniejąca procedura podpisywania. Sekcje poniżej pokazują i wyróżnij miejsce docelowe klucza publikacyjnego AVB, który służy sprawdź obrazy 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, które zostały 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. Pozwala to uniknąć instalacji nierozpoznanej jednostki DSU np. instalując kod DSU podpisany przez OEM-A na urządzeniu wyprodukowanego przez OEM-B.

  • Opcjonalny atrybut tos wskazuje plik tekstowy z opisem warunki korzystania z 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 znaków opisujący architekturę urządzenia. Ten atrybut jest obowiązkowa i jest porównywana z właściwością systemową ro.product.cpu.abi. Ich wartości muszą być dokładnie takie same.

  • 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. Kiedy to został określony, musi on być równy lub większy niż ro.system.build.version.release właściwość systemową. Ta kontrola pozwala zapobiec uruchomieniu obrazu GSI Androida 10 na tym urządzeniu z Androidem 11. urządzenie dostawcy, które obecnie nie jest obsługiwane. Dozwolone jest uruchomienie obrazu GSI Androida 11 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.

Ze względów bezpieczeństwa unieważnianie kluczy DSU

W bardzo rzadkich przypadkach, gdy para kluczy RSA używana do podpisywania obrazów DSU jest został przejęty, należy jak najszybciej zaktualizować dysk ramdisk, aby usunąć przejętego klucza. Oprócz aktualizacji partycji rozruchowej możesz zablokować przejętych kluczy przy użyciu listy odwołanych kluczy DSU (czarnej listy kluczy) z protokołu HTTPS Adres URL.

Lista unieważnionych kluczy DSU zawiera listę unieważnionych kluczy publicznych AVB. Podczas instalacji DSU weryfikowane są klucze publiczne w obrazach DSU na liście unieważnień. 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 odwołanych kluczy powinien być adresem HTTPS siła i jest określona 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 zasobów może być nakładanie i dostosowywanie, dzięki czemu OEM, który wdroży funkcję DSU, może zapewnić tworzyć własną czarną listę kluczy. Dzięki temu OEM może zablokować określonych kluczy publicznych bez aktualizowania obrazu pamięci 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 unieważnienia klucza. Obecnie jedyny obsługiwana wartość to 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 jest przechowywany tylko w sprzętowy moduł zabezpieczeń (HSM). W takim przypadku po kluczu może być dostępny certyfikat klucza publicznego x509 i generowanie treści. 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

Pole oem_cert.avbpubkey musi być podane poniżej /avb/*.avbpubkey, aby można było zweryfikować podpisanego pakietu DSU. 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ć plik 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. Spraw, aby środowisko docelowe droidcore zależało od dodanego elementu 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 SHA-1 do zadbaj o jego czytelność przed umieszczeniem go 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 ponownie artefaktu utworzonego w ramach pierwotnego procesu podpisywania AVB, aby utworzyć pakiet DSU. Alternatywnym sposobem jest wyodrębnienie podpisanego już pliku z pakietu do publikacji, a następnie użyć wyodrębnionych obrazów do utworzenia pliku ZIP .

  • Metoda 2. Aby podpisać partycje DSU, użyj tych poleceń, jeśli prywatne 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 Korzystanie z narzędzia avbtool.

Weryfikacja pakietu DSU lokalnie

Zalecamy zweryfikowanie wszystkich lokalnych obrazów pod kątem sparowania klucza publicznego z te polecenia:


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

Oczekiwane dane wyjściowe wyglądają tak:

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

OEM może zastąpić listę, definiując persist.sys.fflag.override.settings_dynamic_system.list wskazujący własny deskryptor 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, tak jak to widać na rys. 7.

Łańcuch opublikowanych metadanych DSU

Rysunek 7. Łańcuch opublikowanych metadanych DSU