עדכוני מערכת דינמיים (DSU) מאפשרים לך ליצור תמונת מערכת אנדרואיד שמשתמשים יכולים להוריד מהאינטרנט ולנסות ללא סיכון של השחתת תמונת המערכת הנוכחית. מסמך זה מתאר כיצד לתמוך ב-DSU.
דרישות הליבה
ראה הטמעת מחיצות דינמיות לדרישות הליבה.
בנוסף, DSU מסתמך על תכונת ליבת ה-device-mapper-verity (dm-verity) כדי לאמת את תמונת מערכת אנדרואיד. אז עליך להפעיל את תצורות הליבה הבאות:
-
CONFIG_DM_VERITY=y
-
CONFIG_DM_VERITY_FEC=y
דרישות החלוקה
החל ב-Android 11, DSU מחייב את מחיצת /data
כדי להשתמש במערכת הקבצים F2FS או ext4. F2FS נותן ביצועים טובים יותר ומומלץ, אבל ההבדל אמור להיות לא משמעותי.
הנה כמה דוגמאות לכמה זמן לוקח עדכון מערכת דינמי עם מכשיר Pixel:
- באמצעות F2FS:
- 109s, משתמש 8G, מערכת 867M, סוג מערכת קבצים: F2FS: encryption=aes-256-xts:aes-256-cts
- 104s, משתמש 8G, מערכת 867M, סוג מערכת קבצים: F2FS: הצפנה=קרח
- באמצעות ext4:
- 135s, משתמש 8G, מערכת 867M, סוג מערכת קבצים: ext4: encryption=aes-256-xts:aes-256-cts
אם זה לוקח הרבה יותר זמן בפלטפורמה שלך, אולי תרצה לבדוק אם דגל ההרכבה מכיל דגל כלשהו שגורם לכתוב "סינכרון", או שאתה יכול לציין דגל "אסינכרון" במפורש כדי לקבל ביצועים טובים יותר.
מחיצת metadata
(16 MB ומעלה) נדרשת לאחסון נתונים הקשורים לתמונות המותקנות. יש להרכיב אותו במהלך ההרכבה בשלב הראשון.
מחיצת userdata
חייבת להשתמש במערכת הקבצים F2FS או ext4. בעת שימוש ב-F2FS, כלול את כל התיקונים הקשורים ל-F2FS הזמינים בקרנל הנפוץ של אנדרואיד .
DSU פותח ונבדק עם kernel/common 4.9. מומלץ להשתמש בגרעין 4.9 ומעלה עבור תכונה זו.
התנהגות HAL של הספק
וויבר HAL
ה-Weaver HAL מספק מספר קבוע של חריצים לאחסון מפתחות משתמש. ה-DSU צורך שני חריצי מפתח נוספים. אם ל-OEM יש HAL אורג, הוא צריך שיהיו לו מספיק חריצים עבור תמונת מערכת גנרית (GSI) ותמונת מארח.
שומר סף HAL
ה- Gatekeeper HAL צריך לתמוך בערכי USER_ID
גדולים, מכיוון שה-GSI מקזז את ה-UIDs ל-HAL ב-+1000000.
ודא אתחול
אם ברצונך לתמוך באתחול של תמונות GSI של מפתחים במצב נעול מבלי לבטל אתחול מאומת, כלול מפתחות GSI למפתחים על ידי הוספת השורה הבאה להתקן הקובץ device/<device_name>/device.mk
:
$(call inherit-product, $(SRC_TARGET_DIR)/product/developer_gsi_keys.mk)
הגנה לאחור
בעת שימוש ב-DSU, תמונת מערכת האנדרואיד שהורדת חייבת להיות חדשה יותר מתמונת המערכת הנוכחית במכשיר. זה נעשה על ידי השוואת רמות תיקון האבטחה במתאר ה-AVB של Android Verified Boot (AVB) של שתי תמונות המערכת: Prop: com.android.build.system.security_patch -> '2019-04-05'
.
עבור מכשירים שאינם משתמשים ב-AVB, הכנס את רמת תיקון האבטחה של תמונת המערכת הנוכחית לתוך הליבה cmdline או bootconfig עם טוען האתחול: androidboot.system.security_patch=2019-04-05
.
דרישות חומרה
כאשר אתה מפעיל מופע DSU, שני קבצים זמניים מוקצים:
- מחיצה לוגית לאחסון
GSI.img
(1~1.5 G) - מחיצת
/data
ריקה בנפח 8 GB כארגז החול להפעלת ה-GSI
אנו ממליצים לשמור לפחות 10 GB של מקום פנוי לפני השקת מופע DSU. DSU תומך גם בהקצאה מכרטיס SD. כאשר קיים כרטיס SD, יש לו את העדיפות הגבוהה ביותר להקצאה. תמיכה בכרטיסי SD היא קריטית עבור מכשירים בעלי הספק נמוך שאולי אין להם מספיק אחסון פנימי. כאשר קיים כרטיס SD, ודא שהוא לא מאומץ. DSU אינו תומך בכרטיסי SD מאומצים .
חזיתות זמינות
אתה יכול להפעיל את DSU באמצעות adb
, אפליקציית OEM או מטעין DSU בלחיצה אחת (באנדרואיד 11 ומעלה).
הפעל את DSU באמצעות adb
כדי להפעיל את DSU באמצעות adb, הזן את הפקודות הבאות:
$ 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
הפעל את DSU באמצעות אפליקציה
נקודת הכניסה העיקרית ל-DSU היא ה-API של android.os.image.DynamicSystemClient.java
:
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);
}
עליך לאגד/להתקין מראש את האפליקציה הזו במכשיר. מכיוון ש- DynamicSystemClient
הוא ממשק API של מערכת, אינך יכול לבנות את האפליקציה עם ה-API הרגיל של SDK ואי אפשר לפרסם אותה ב-Google Play. מטרת האפליקציה הזו היא:
- אחזר רשימת תמונות ואת כתובת האתר המתאימה עם סכימה המוגדרת על ידי הספק.
- התאם את התמונות ברשימה למכשיר והצג תמונות תואמות לבחירת המשתמש.
הפעל את
DynamicSystemClient.start
כך:DynamicSystemClient aot = new DynamicSystemClient(...) aot.start( ...URL of the selected image..., ...uncompressed size of the selected image...);
כתובת ה-URL מצביעה על קובץ תמונת מערכת ב-gzip, לא דל, שתוכל ליצור באמצעות הפקודות הבאות:
$ simg2img ${OUT}/system.img ${OUT}/system.raw
$ gzip ${OUT}/system.raw
$ ls ${OUT}/system.raw.gz
שם הקובץ צריך להיות בפורמט הזה:
<android version>.<lunch name>.<user defined title>.raw.gz
דוגמאות:
-
o.aosp_taimen-userdebug.2018dev.raw.gz
-
p.aosp_taimen-userdebug.2018dev.raw.gz
מטעין DSU בלחיצה אחת
אנדרואיד 11 מציגה את מטעין DSU בלחיצה אחת, המהווה חזית בהגדרות המפתחים.
איור 1. הפעלת מטעין ה-DSU
כאשר המפתח לוחץ על הלחצן DSU Loader , הוא מביא מתאר DSU JSON מוגדר מראש מהאינטרנט ומציג את כל התמונות הרלוונטיות בתפריט הצף. בחר תמונה כדי להתחיל את התקנת ה-DSU, וההתקדמות מוצגת בסרגל ההתראות.
איור 2. התקדמות התקנת תמונת DSU
כברירת מחדל, טוען ה-DSU טוען מתאר JSON המכיל את תמונות ה-GSI. הסעיפים הבאים מדגימים כיצד ליצור חבילות DSU חתומות על ידי OEM ולטעון אותן ממטען ה-DSU.
דגל תכונה
תכונת ה-DSU נמצאת תחת דגל התכונה settings_dynamic_android
. לפני השימוש ב-DSU, ודא שדגל התכונה המתאים מופעל.
איור 3. הפעלת דגל התכונה
ייתכן שממשק המשתמש של דגל התכונה אינו זמין במכשיר המריץ בניית משתמש. במקרה זה, השתמש בפקודה adb
במקום זאת:
$ adb shell setprop persist.sys.fflag.override.settings_dynamic_system 1
תמונות מערכת מארח ספק ב-GCE (אופציונלי)
אחד ממיקומי האחסון האפשריים לתמונות המערכת הוא דלי Google Compute Engine (GCE). מנהל ההפצה משתמש במסוף האחסון של GCP כדי להוסיף/למחוק/לשנות את תמונת המערכת שפורסמה.
התמונות חייבות להיות גישה לציבור, כפי שמוצג כאן:
איור 4. גישה לציבור ב-GCE
ההליך להפיכת פריט לציבורי זמין בתיעוד של Google Cloud .
DSU עם מספר מחיצות בקובץ ZIP
החל מאנדרואיד 11, ל-DSU יכולה להיות יותר ממחיצה אחת. לדוגמה, הוא יכול להכיל את product.img
בנוסף ל- system.img
. כאשר המכשיר מאתחל, השלב הראשון init
מזהה את מחיצות ה-DSU המותקנות ומחליף את המחיצה במכשיר באופן זמני, כאשר ה-DSU המותקן מופעל. חבילת DSU עשויה להכיל מחיצה שאין לה מחיצה מתאימה במכשיר.
איור 5. תהליך DSU עם מחיצות מרובות
DSU חתום על ידי OEM
כדי לוודא שכל התמונות הפועלות במכשיר מאושרות על ידי יצרן המכשיר, יש לחתום על כל התמונות בחבילת DSU. לדוגמה, נניח שיש חבילת DSU המכילה שתי תמונות מחיצה כמו להלן:
dsu.zip {
- system.img
- product.img
}
הן system.img
והן product.img
חייבים להיות חתומים על ידי מפתח OEM לפני הכנסתם לקובץ ה-ZIP. הנוהג המקובל הוא להשתמש באלגוריתם א-סימטרי, למשל, RSA, שבו המפתח הסודי משמש לחתימה על החבילה והמפתח הציבורי משמש לאימותה. ה-ramdisk של השלב הראשון חייב לכלול את המפתח הציבורי לקישור, לדוגמה, /avb/*.avbpubkey
. אם המכשיר כבר אימץ את AVB, נוהל החתימה הקיים יספיק. הסעיפים הבאים ממחישים את תהליך החתימה ומדגישים את המיקום של AVB pubkey המשמש לאימות התמונות בחבילת DSU.
מתאר DSU JSON
מתאר DSU JSON מתאר חבילות DSU. זה תומך בשני פרימיטיבים. ראשית, ה- include
primitive כולל מתארי JSON נוספים או מפנה מחדש את מטעין ה-DSU למיקום חדש. לדוגמה:
{
"include": ["https://.../gsi-release/gsi-src.json"]
}
שנית, פרימיטיבי image
משמש לתיאור חבילות DSU שפורסמו. בתוך פרימיטיבי התמונה יש כמה תכונות:
תכונות
name
details
הן מחרוזות המוצגות בתיבת הדו-שיח לבחירת המשתמש.התכונות
cpu_api
,vndk
ו-os_version
משמשות לבדיקות תאימות, המתוארות בסעיף הבא.תכונת
pubkey
האופציונלית מתארת את המפתח הציבורי שמתאים למפתח הסודי המשמש לחתימה על חבילת ה-DSU. כאשר זה מצוין, שירות DSU יכול לבדוק אם למכשיר יש את המפתח המשמש לאימות חבילת ה-DSU. כך נמנע התקנת חבילת DSU לא מזוהה, למשל התקנת DSU חתום על ידי OEM-A למכשיר מתוצרת OEM-B.התכונה האופציונלית
tos
מצביעה על קובץ טקסט המתאר את תנאי השירות עבור חבילת ה-DSU המתאימה. כאשר מפתח בוחר חבילת DSU עם תכונת תנאי השירות שצוינה, תיבת הדו-שיח המוצגת באיור 6 נפתחת, ומבקשת מהמפתח לקבל את תנאי השירות לפני התקנת חבילת DSU.איור 6. תיבת הדו-שיח תנאי השירות
לעיון, הנה מתאר DSU JSON עבור 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"
}
]
}
ניהול תאימות
מספר מאפיינים משמשים לציון התאימות בין חבילת DSU למכשיר המקומי:
cpu_api
היא מחרוזת המתארת את ארכיטקטורת המכשיר. תכונה זו היא חובה והיא מושווה למאפיין המערכתro.product.cpu.abi
. הערכים שלהם חייבים להתאים בדיוק.os_version
הוא מספר שלם אופציונלי המציין גרסת אנדרואיד. לדוגמה, עבור Android 10,os_version
הוא10
ועבור Android 11,os_version
הוא11
. כאשר תכונה זו מצוינת, היא חייבת להיות שווה למאפיין המערכתro.system.build.version.release
או גדול ממנו. הסימון הזה משמש למניעת אתחול תמונת Android 10 GSI במכשיר של ספק אנדרואיד 11, שאינו נתמך כרגע. אתחול תמונת Android 11 GSI במכשיר Android 10 מותר.vndk
הוא מערך אופציונלי המציין את כל ה-VNDK הכלולים בחבילת DSU. כאשר זה מצוין, טוען DSU בודק אם המספר שחולץ ממאפיין המערכתro.vndk.version
כלול.
שלל מפתחות DSU לצורך אבטחה
במקרה הנדיר ביותר כאשר צמד מפתחות ה-RSA המשמשים לחתימה על תמונות ה-DSU נפגע, יש לעדכן את ה-ramdisk בהקדם האפשרי כדי להסיר את המפתח שנפרץ. בנוסף לעדכון מחיצת האתחול, אתה יכול לחסום מפתחות שנפרצו באמצעות רשימת ביטול מפתחות DSU (רשימה שחורה של מפתחות) מכתובת URL של HTTPS.
רשימת ביטול מפתחות DSU מכילה רשימה של מפתחות ציבוריים של AVB שבוטלו. במהלך התקנת DSU, המפתחות הציבוריים בתוך תמונות ה-DSU מאומתים עם רשימת הביטולים. אם נמצא שהתמונות מכילות מפתח ציבורי שבוטל, תהליך ההתקנה של DSU נעצר.
כתובת ה-URL של רשימת ביטולי המפתח צריכה להיות כתובת URL של HTTPS כדי להבטיח את עוצמת האבטחה, והיא מצוינת במחרוזת משאבים:
frameworks/base/packages/DynamicSystemInstallationService/res/values/strings.xml@key_revocation_list_url
ערך המחרוזת הוא https://dl.google.com/developers/android/gsi/gsi-keyblacklist.json
, שהיא רשימת ביטולים עבור מפתחות GSI שפורסמו ב-Google. מחרוזת משאבים זו ניתנת לכיסוי ולהתאים אישית, כך שיצרני OEM שמאמצים את תכונת ה-DSU יכולים לספק ולתחזק רשימה שחורה של מפתחות משלהם. זה מספק דרך ל-OEM לחסום מפתחות ציבוריים מסוימים מבלי לעדכן את תמונת ramdisk של ההתקן.
הפורמט של רשימת הביטולים הוא:
{
"entries":[
{
"public_key":"bf14e439d1acf231095c4109f94f00fc473148e6",
"status":"REVOKED",
"reason":"Key revocation test key"
},
{
"public_key":"d199b2f29f3dc224cca778a7544ea89470cbef46",
"status":"REVOKED",
"reason":"Key revocation test key"
}
]
}
-
public_key
הוא תקציר SHA-1 של המפתח שבוטל, בפורמט המתואר בקטע יצירת ה-AVB pubkey . -
status
מציין את מצב ביטול המפתח. נכון לעכשיו, הערך הנתמך היחיד הואREVOKED
. -
reason
היא מחרוזת אופציונלית המתארת את הסיבה לביטול.
נהלי DSU
סעיף זה מתאר כיצד לבצע מספר הליכי תצורת DSU.
צור זוג מפתחות חדש
השתמש בפקודה openssl
כדי ליצור זוג מפתחות RSA פרטי/ציבורי בפורמט .pem
(לדוגמה, בגודל 2048 סיביות):
$ openssl genrsa -out oem_cert_pri.pem 2048
$ openssl rsa -in oem_cert_pri.pem -pubout -out oem_cert_pub.pem
ייתכן שהמפתח הפרטי אינו נגיש והוא נשמר רק במודול אבטחת חומרה (HSM) . במקרה זה, ייתכן שיהיה אישור מפתח ציבורי x509 זמין לאחר יצירת המפתח. עיין בסעיף הוספת מפתח הצימוד ל-ramdisk לקבלת הוראות ליצירת המפתח הציבורי של AVB מתעודת x509.
כדי להמיר אישור x509 לפורמט PEM:
$ openssl x509 -pubkey -noout -in oem_cert_pub.x509.pem > oem_cert_pub.pem
דלג על שלב זה אם האישור כבר קובץ PEM.
הוסף את מפתח הצימוד ל-ramdisk
יש לשים את ה- oem_cert.avbpubkey
תחת /avb/*.avbpubkey
כדי לאמת את חבילת ה-DSU החתומה. ראשית, המר את המפתח הציבורי בפורמט PEM לפורמט מפתח ציבורי AVB:
$ avbtool extract_public_key --key oem_cert_pub.pem --output oem_cert.avbpubkey
לאחר מכן כלול את המפתח הציבורי בשלב הראשון ramdisk עם השלבים הבאים.
הוסף מודול בנוי מראש כדי להעתיק את
avbpubkey
. לדוגמה, הוסףdevice/<company>/<board>/oem_cert.avbpubkey
ו-device/<company>/<board>/avb/Android.mk
עם תוכן כזה: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)
הפוך את יעד ה-droidcore תלוי ב-
oem_cert.avbpubkey
שנוסף:droidcore: oem_cert.avbpubkey
צור את התכונה AVB pubkey במתאר JSON
ה- oem_cert.avbpubkey
הוא בפורמט הבינארי של המפתח הציבורי AVB. השתמש ב-SHA-1 כדי להפוך אותו לקריאה לפני הכנסתו ל-JSON מתאר:
$ sha1sum oem_cert.avbpubkey | cut -f1 -d ' '
3e62f2be9d9d813ef5........866ac72a51fd20
זה יהיה התוכן של תכונת pubkey
של מתאר JSON.
"images":[
{
...
"pubkey":"3e62f2be9d9d813ef5........866ac72a51fd20",
...
},
חתום על חבילת DSU
השתמש באחת מהשיטות הבאות כדי לחתום על חבילת DSU:
שיטה 1: השתמש מחדש בחפץ שנוצר בתהליך החתימה המקורי של AVB כדי ליצור חבילת DSU. גישה חלופית היא לחלץ את התמונות שכבר חתומות מחבילת השחרור ולהשתמש בתמונות שחולצו כדי ליצור את קובץ ה-ZIP ישירות.
שיטה 2: השתמש בפקודות הבאות כדי לחתום על מחיצות DSU אם המפתח הפרטי זמין. כל
img
בתוך חבילת DSU (קובץ ה-ZIP) חתום בנפרד:$ 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
למידע נוסף על הוספת add_hashtree_footer
באמצעות avbtool
, ראה שימוש ב-avbtool .
אמת את חבילת ה-DSU באופן מקומי
מומלץ לאמת את כל התמונות המקומיות מול המפתח הציבורי להתאמה באמצעות הפקודות הבאות:
for partition in system product; do
avbtool verify_image --image ${OUT}/${partition}.img --key oem_cert_pub.pem
done
הפלט הצפוי נראה כך:
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
הכינו חבילת DSU
הדוגמה הבאה מייצרת חבילת DSU המכילה system.img
ו- product.img
:
dsu.zip {
- system.img
- product.img
}
לאחר חתימת שתי התמונות, השתמש בפקודה הבאה כדי ליצור את קובץ ה-ZIP:
$ mkdir -p dsu
$ cp ${OUT}/system.img dsu
$ cp ${OUT}/product.img dsu
$ cd dsu && zip ../dsu.zip *.img && cd -
התאם אישית את ה-DSU בלחיצה אחת
כברירת מחדל, טוען ה-DSU מצביע על מטא נתונים של תמונות GSI שהם https://...google.com/.../gsi-src.json
.
יצרני OEM יכולים להחליף את הרשימה על ידי הגדרת המאפיין persist.sys.fflag.override.settings_dynamic_system.list
שמצביע על מתאר JSON משלהם. לדוגמה, יצרן OEM עשוי לספק מטא נתונים של JSON הכוללים GSI וכן תמונות קנייניות של OEM כמו זה:
{
"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"
},
}
זה אפשרי עבור יצרן OEM לשרשר מטא נתונים של DSU שפורסמו כפי שמוצג באיור 7.
איור 7. שרשרת מטא נתונים של DSU שפורסמו