Microdroid היא מערכת הפעלה של Android בגרסת מיני שפועלת ב-pVM. אתם לא חייבים להשתמש ב-Microdroid, אפשר להפעיל מכונה וירטואלית עם כל מערכת הפעלה. עם זאת, התרחישים העיקריים לדוגמה לשימוש ב-pVMs לא כוללים הפעלה של מערכת הפעלה עצמאית, אלא סביבה מבודדת להרצה של חלק מאפליקציה עם ערבויות חזקות יותר של סודיות ושלמות מאשר Android יכול לספק.
במערכות הפעלה מסורתיות, כדי לספק סודיות ואימות חזקים נדרשת כמות עבודה רבה (לרוב כפולה), כי מערכות הפעלה מסורתיות לא מתאימות לארכיטקטורה הכוללת של Android. לדוגמה, בארכיטקטורה הרגילה של Android, המפתחים צריכים להטמיע דרך לטעון ולבצע באופן מאובטח חלק מהאפליקציה ב-pVM, ועומס העבודה נבנה מול glibc. באפליקציית Android נעשה שימוש ב-Bionic, התקשורת דורשת פרוטוקול מותאם אישית דרך vsock ותיקון באגים באמצעות adb הוא מאתגר.
Microdroid ממלא את הפערים האלה על ידי מתן קובץ אימג' של מערכת הפעלה מוכנה לשימוש, שנועד לדרוש מהמפתחים את המאמץ המינימלי כדי להעביר חלק מהאפליקציה שלהם ל-pVM. הקוד המקומי נבנה על Bionic, התקשורת מתבצעת דרך Binder, הוא מאפשר לייבא קובצי APEX מ-Android המארח ומציג קבוצת משנה של Android API, כמו מאגר מפתחות לפעולות קריפטוגרפיות עם מפתחות שמגובים בחומרה. באופן כללי, המפתחים אמורים למצוא ב-Microdroid סביבה מוכרת עם הכלים שהם התרגלו אליהם ב-Android OS המלא.
תכונות
Microdroid היא גרסה פשוטה של Android עם כמה רכיבים נוספים שספציפיים ל-pVM. Microdroid תומך ב:
- קבוצת משנה של ממשקי ה-API של NDK (כל ממשקי ה-API להטמעה של Android ב-libc וב-Bionic)
- תכונות ניפוי באגים, כמו adb, logcat, tombstone ו-gdb
- אתחול מאומת ו-SELinux
- טעינת קובץ בינארי והרצה שלו, יחד עם ספריות משותפות שמוטמעות ב-APK
- RPC של Binder דרך vsock וחילופי קבצים עם בדיקות תקינות משתמעות
- טעינת מודולים של APEX
Microdroid לא תומך באפשרויות הבאות:
ממשקי API של Java ל-Android בחבילות
android.\*
SystemServer ו-Zygote
גרפיקה/ממשק משתמש
HAL
הארכיטקטורה של Microdroid
Microdroid דומה ל-Cuttlefish בכך שלשניהם יש ארכיטקטורה שדומה ל-Android רגיל. Microdroid מורכב מתמונות המחיצות הבאות שמקובצות יחד בתמונת דיסק מורכבת:
bootloader
– אימות והפעלה של הליבה.boot.img
– מכיל את הליבה ואת init ramdisk.vendor_boot.img
– מכיל מודולים של ליבה ספציפיים למכונות וירטואליות, כמו virtio.super.img
– מורכב ממחיצות לוגיות של מערכת ומחיצות לוגיות של ספק.vbmeta.img
– מכיל מטא-נתונים של אתחול מאומת.
קובצי האימג' של המחיצות נשלחים ב-Virtualization APEX ומארזים בתמונה מורכבת של דיסק על ידי VirtualizationService
. בנוסף לתמונת הדיסק המשולבת הראשית של מערכת ההפעלה, VirtualizationService
אחראי ליצירת המחיצות הבאות:
payload
– קבוצה של מחיצות שמגובות על ידי קובצי APEX ו-APK של Androidinstance
– מחיצה מוצפנת לנתוני אתחול מאומתים שנשמרים לכל מכונה, כמו מלח לכל מכונה, מפתחות ציבוריים מהימנים של APEX ומונים לביטול שינויים
רצף האתחול
רצף האתחול של Microdroid מתרחש אחרי הפעלת המכשיר. הטעינה של המכשיר מפורטת בקטע 'קושחת pVM' במסמך Architecture. באיור 1 מוצגים השלבים שמתרחשים במהלך רצף האתחול של Microdroid:
זהו הסבר על השלבים:
תוכנת האתחול נטענת בזיכרון על ידי crosvm ו-pvmfw מתחיל לפעול. לפני המעבר למחולל האתחול, pvmfw מבצע שתי משימות:
- אימות של תוכנת האתחול כדי לבדוק אם היא ממקור מהימן (Google או יצרן ציוד מקורי).
- מוודא שנעשה שימוש עקבי באותו מנהל אתחול במספר הפעלות של אותו pVM באמצעות שימוש בתמונת המכונה. באופן ספציפי, ה-pVM מופעל בהתחלה עם קובץ אימג' ריק של מכונה. ה-pvmfw מאחסן את הזהות של מנהל האתחול בקובץ האימג' של המכונה ומצפין אותו. כך, בפעם הבאה ש-pVM יופעל עם אותה תמונת מכונה, pvmfw יפענח את הזהות השמורה מתוך תמונת המכונה ויאמת שהיא זהה לזו שנשמרה בעבר. אם הזהויות שונות, pvmfw לא יידלק.
לאחר מכן, תוכנת האתחול תפעיל את Microdroid.
תוכנת האתחול ניגשת לדיסק של המכונה. בדומה ל-pvmfw, למחולל האתחול יש כונן דיסק של מכונה עם מידע על קובצי אימג' של מחיצות ששימשו במכונה הזו במהלך הפעלות קודמות, כולל המפתח הציבורי.
תוכנת האתחול מאמתת את vbmeta ואת המחיצות המקושרות, כמו
boot
ו-super
, ואם האימות מצליח, היא מייצרת את סודות ה-pVM בשלב הבא. לאחר מכן, Microdroid מעביר את השליטה לליבה.מכיוון שמחיצה העל כבר אומתה על ידי מנהל האתחול (שלב 3), הליבה מחברת את מחיצת העל ללא תנאים. בדומה ל-Android המלא, המחיצה העליונה מורכבת מכמה מחיצות לוגיות שממוטנות מעל dm-verity. לאחר מכן השליטה מועברת לתהליך
init
, שמפעיל שירותים מקומיים שונים. הסקריפטinit.rc
דומה לסקריפט של Android מלא, אבל מותאם לצרכים של Microdroid.התהליך
init
מפעיל את מנהל Microdroid, שמקבל גישה לתמונת המכונה. שירות הניהול של Microdroid מפענח את התמונה באמצעות המפתח שהוענק בשלב הקודם, וקורא את המפתחות הציבוריים ומספרי החזרה לאחור של חבילת ה-APK וה-APEX של הלקוח ש-pVM הזה סומך עליהם. המידע הזה ישמש אתzipfuse
ו-apexd
בהמשך, כשהם יטענו את קובץ ה-APK של הלקוח ואת קובצי ה-APEX המבוקשים, בהתאמה.שירות הניהול של Microdroid מתחיל ב-
apexd
.apexd
מחבר את ה-APEXes לספריות/apex/<name>
. ההבדל היחיד בין האופן שבו קבצים מסוג APEX מותקנים ב-Android וב-Microdroid הוא שב-Microdroid, קבצי ה-APEX מגיעים ממכשירי בלוק וירטואליים (/dev/vdc1
, …), ולא מקובצים רגילים (/system/apex/*.apex
).zipfuse
היא מערכת הקבצים של FUSE ב-Microdroid.zipfuse
מחבר את קובץ ה-APK של הלקוח, שהוא למעשה קובץ Zip, כמערכת קבצים. מתחת, קובץ ה-APK מועבר כמכשיר בלוק וירטואלי על ידי ה-pVM עם dm-verity, כמו ב-APEX. קובץ ה-APK מכיל קובץ תצורה עם רשימה של APEX שפותח האפליקציה ביקש למכונה הזו של ה-pVM. הרשימה משמשת אתapexd
כשמפעילים חשבונות APEX.תהליך האתחול חוזר לשירות הניהול של Microdroid. לאחר מכן, שירות הניהול מתקשר עם
VirtualizationService
של Android באמצעות Binder RPC כדי לדווח על אירועים חשובים כמו קריסה או כיבוי, ולקבל בקשות כמו סיום של ה-pVM. שירות הניהול קורא את המיקום של הקובץ הבינארי הראשי מקובץ התצורה של ה-APK ומריץ אותו.
החלפת קבצים (AuthFS)
רכיבים של Android משתמשים בדרך כלל בקבצים להזנה, לפלט ולמצב, ומעבירים אותם כמזהים של קבצים (ParcelFileDescriptor
type ב-AIDL) עם גישה שנשלטת על ידי הליבה של Android. AuthFS מאפשר פונקציונליות דומה לחילופי קבצים בין נקודות קצה שלא סומכות זו על זו מעבר לגבולות של pVM.
ביסודו, AuthFS היא מערכת קבצים מרוחקת עם בדיקות תקינות שקופות של פעולות גישה ספציפיות, בדומה ל-fs-verity
. הבדיקות מאפשרות לקצה הקדמי, כמו תוכנית לקריאת קבצים שפועלת ב-pVM, לזהות אם הקצה העורפי הלא מהימן, בדרך כלל Android, שינה את תוכן הקובץ.
כדי להחליף קבצים, הקצה העורפי (fd\_server
) מופעל עם הגדרה לכל קובץ שמציינת אם הוא מיועד לקלט (קריאה בלבד) או לפלט (קריאה וכתיבה). לגבי קלט, ממשק הקצה אוכף שהתוכן תואם ל-hash ידוע, מעל עץ Merkle לאימות בזמן הגישה. בפלט, AuthFS שומרת באופן פנימי עץ גיבוב של התוכן כפי שנצפה מפעולות הכתיבה, ויכולה לאכוף את תקינות הנתונים כשהם נקראים חזרה.
התעבורה הבסיסית מבוססת כרגע על Binder RPC, אבל יכול להיות שהיא תשתנה בעתיד כדי לבצע אופטימיזציה של הביצועים.
ניהול מפתחות
למכונות הווירטואליות הפסיביות יש מפתח חותמת יציב שמתאים להגנה על נתונים קבועים, ומפתח אימות שמתאים ליצירת חתימות שאפשר לאמת שהן נוצרו על ידי המכונה הווירטואלית הפסיבית.
RPC ב-Binder
רוב ממשקי Android מבוססים על AIDL, שנבנה על גבי מנהל הליבה של Binder Linux. כדי לתמוך בממשקים בין מכונות pVM, פרוטוקול Binder נכתב מחדש כך שיפעל דרך שקעים, vsock במקרה של מכונות pVM. הפעולה דרך שקעים מאפשרת להשתמש בממשקי ה-AIDL הקיימים של Android בסביבה החדשה הזו.
כדי להגדיר את החיבור, נקודת קצה אחת, כמו עומס העבודה של pVM, יוצרת אובייקט RpcServer
, רושמת אובייקט ברמה הבסיסית ומתחילה להאזין לחיבורים חדשים. לקוחות יכולים להתחבר לשרת הזה באמצעות אובייקט RpcSession
, לקבל את האובייקט Binder
ולהשתמש בו בדיוק כמו שמשתמשים באובייקט Binder
עם מנהל ה-Binder של הליבה.