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:
- Pobierz listę obrazów i odpowiednie adresy URL ze schematem zdefiniowanym przez dostawcę.
- Dopasuj obrazy na liście do urządzenia i wyświetl je zgodne którą użytkownik ma wybrać.
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.
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ń.
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.
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:
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.
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
idetails
to ciągi tekstowe, które są wyświetlane w okno, które użytkownik może wybrać.Atrybuty
cpu_api
,vndk
ios_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.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 10os_version
to10
, a dla Androida 11,os_version
to11
. Gdy 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 systemowejro.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ść toREVOKED
.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.
Dodaj gotowy moduł, aby skopiować plik
avbpubkey
. Na przykład dodajdevice/<company>/<board>/oem_cert.avbpubkey
idevice/<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)
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 powinny wyglądać 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.
Rysunek 7. Łańcuch opublikowanych metadanych DSU