Microdroid, Android OS का एक छोटा वर्शन है. यह pVM में चलता है. आपको Microdroid का इस्तेमाल करने की ज़रूरत नहीं है. किसी भी ओएस के साथ वीएम शुरू किया जा सकता है. हालांकि, pVMs का मुख्य इस्तेमाल, स्टैंडअलोन ओएस को चलाने के लिए नहीं किया जाता. इसके बजाय, इनका इस्तेमाल ऐप्लिकेशन के किसी हिस्से को चलाने के लिए, अलग से एक्ज़ीक्यूशन एनवायरमेंट उपलब्ध कराने के लिए किया जाता है. इसमें Android की तुलना में, ज़्यादा भरोसेमंद तरीके से गोपनीयता और सुरक्षा की गारंटी दी जाती है.
पारंपरिक ऑपरेटिंग सिस्टम में, डेटा को सुरक्षित रखने और उसकी अखंडता बनाए रखने के लिए, काफ़ी काम करना पड़ता है. ऐसा इसलिए, क्योंकि पारंपरिक ऑपरेटिंग सिस्टम, Android के मुख्य आर्किटेक्चर के साथ काम नहीं करते. उदाहरण के लिए, स्टैंडर्ड Android आर्किटेक्चर में डेवलपर को, अपने ऐप्लिकेशन के कुछ हिस्से को pVM में सुरक्षित तरीके से लोड और एक्ज़ीक्यूट करने का तरीका लागू करना होता है. साथ ही, पेलोड को glibc के हिसाब से बनाया जाता है. Android ऐप्लिकेशन, Bionic का इस्तेमाल करता है. साथ ही, कम्यूनिकेशन के लिए vsock पर कस्टम प्रोटोकॉल की ज़रूरत होती है. इसके अलावा, adb का इस्तेमाल करके डीबग करना मुश्किल होता है.
Microdroid, इन कमियों को पूरा करता है. यह एक ओएस इमेज उपलब्ध कराता है. इसे इस तरह से डिज़ाइन किया गया है कि डेवलपर को अपने ऐप्लिकेशन के कुछ हिस्से को pVM में ऑफ़लोड करने के लिए, कम से कम मेहनत करनी पड़े. नेटिव कोड को Bionic के हिसाब से बनाया गया है. कम्यूनिकेशन, बाइंडर के ज़रिए होता है. साथ ही, यह होस्ट Android से APEX इंपोर्ट करने की अनुमति देता है. यह Android API का सबसेट दिखाता है. जैसे, हार्डवेयर की मदद से सुरक्षित की गई कुंजियों के साथ क्रिप्टोग्राफ़िक कार्रवाइयों के लिए कीस्टोर. कुल मिलाकर, डेवलपर को Microdroid एक जाना-पहचाना एनवायरमेंट लगेगा. इसमें वे टूल भी मिलेंगे जिनका इस्तेमाल वे Android OS में करते हैं.
सुविधाएं
Microdroid, Android का एक छोटा वर्शन है. इसमें pVM के लिए कुछ अतिरिक्त कॉम्पोनेंट शामिल हैं. Microdroid इनके साथ काम करता है:
- NDK एपीआई का सबसेट (libc और Bionic को Android में लागू करने के लिए सभी एपीआई उपलब्ध कराए जाते हैं)
- डीबग करने की सुविधाएं, जैसे कि adb, logcat, tombstone, और gdb
- वेरिफ़ाइड बूट और SELinux
- किसी APK में एम्बेड की गई शेयर की गई लाइब्रेरी के साथ-साथ, बाइनरी को लोड और एक्ज़ीक्यूट करना
- vsock पर Binder RPC और फ़ाइलों का आदान-प्रदान, जिसमें अपने-आप इंटिग्रिटी की जांच होती है
- APEX लोड हो रहे हैं
Microdroid इन पर काम नहीं करता:
android.\*
पैकेज में Android Java APISystemServer और Zygote
ग्राफ़िक्स/यूज़र इंटरफ़ेस (यूआई)
एचएएल
Microdroid आर्किटेक्चर
Microdroid, Cuttlefish की तरह ही है. दोनों का आर्किटेक्चर, स्टैंडर्ड Android जैसा है. Microdroid में ये पार्टीशन इमेज शामिल होती हैं. इन्हें कंपोज़िट डिस्क इमेज में एक साथ ग्रुप किया जाता है:
bootloader
- इससे कर्नल की पुष्टि होती है और वह शुरू हो जाता है.boot.img
- इसमें कर्नेल और init ramdisk होता है.vendor_boot.img
- इसमें वीएम के हिसाब से कर्नेल मॉड्यूल होते हैं, जैसे कि virtio.super.img
- इसमें सिस्टम और वेंडर के लॉजिकल पार्टिशन शामिल होते हैं.vbmeta.img
- इसमें वेरिफ़ाइड बूट मेटाडेटा होता है.
पार्टिशन इमेज, वर्चुअलाइज़ेशन एपेक्स में शिप की जाती हैं. इन्हें VirtualizationService
कंपोज़िट डिस्क इमेज में पैकेज करता है. मुख्य ओएस कंपोज़िट डिस्क इमेज के अलावा, VirtualizationService
इन अन्य पार्टीशन को बनाने के लिए ज़िम्मेदार है:
payload
- Android के APEX और APK की मदद से बनाए गए पार्टीशन का सेटinstance
- एन्क्रिप्ट (सुरक्षित) किया गया एक ऐसा पार्टीशन जिसमें हर इंस्टेंस के लिए वेरिफ़ाइड बूट डेटा सेव किया जाता है. जैसे, हर इंस्टेंस के लिए साल्ट, भरोसेमंद APEX की सार्वजनिक कुंजियां, और रोलबैक काउंटर
बूट सीक्वेंस
Microdroid बूट सीक्वेंस, डिवाइस बूट के बाद होता है. डिवाइस बूट करने के बारे में, आर्किटेक्चर दस्तावेज़ के pVM फ़र्मवेयर सेक्शन में बताया गया है. पहली इमेज में, Microdroid बूट सीक्वेंस के दौरान होने वाले चरण दिखाए गए हैं:
यहां इस प्रोसेस के बारे में बताया गया है:
crosvm, बूटलोडर को मेमोरी में लोड करता है और pvmfw काम करना शुरू कर देता है. बूटलोडर पर जाने से पहले, pvmfw दो काम करता है:
- यह बूटलोडर की पुष्टि करता है, ताकि यह पता चल सके कि यह किसी भरोसेमंद सोर्स (Google या OEM) से है या नहीं.
- यह कुकी यह पक्का करती है कि इंस्टेंस इमेज का इस्तेमाल करके, एक ही pVM के कई बूट में एक ही बूटलोडर का इस्तेमाल किया जाए. खास तौर पर, pVM को शुरू में एक खाली इंस्टेंस इमेज के साथ बूट किया जाता है. pvmfw, इंस्टेंस इमेज में बूटलोडर की पहचान को सेव करता है और उसे एन्क्रिप्ट (सुरक्षित) करता है. इसलिए, अगली बार जब pVM को उसी इंस्टेंस इमेज के साथ बूट किया जाता है, तो pvmfw इंस्टेंस इमेज से सेव की गई पहचान को डिक्रिप्ट करता है. साथ ही, यह पुष्टि करता है कि यह वही पहचान है जिसे पहले सेव किया गया था. अगर आइडेंटिटी अलग-अलग हैं, तो pvmfw बूट करने से मना कर देता है.
इसके बाद, बूटलोडर Microdroid को बूट करता है.
बूटलोडर, इंस्टेंस डिस्क को ऐक्सेस करता है. pvmfw की तरह, बूटलोडर में इंस्टेंस डिस्क ड्राइव होती है. इसमें पिछले बूट के दौरान इस इंस्टेंस में इस्तेमाल की गई पार्टीशन इमेज के बारे में जानकारी होती है. इसमें सार्वजनिक पासकोड भी शामिल होता है.
बूटलोडर, vbmeta और चेन वाले पार्टीशन की पुष्टि करता है. जैसे,
boot
औरsuper
. अगर पुष्टि हो जाती है, तो बूटलोडर अगले चरण के pVM सीक्रेट का पता लगाता है. इसके बाद, Microdroid, कर्नल को कंट्रोल सौंप देता है.बूटलोडर (तीसरा चरण) पहले ही सुपर पार्टीशन की पुष्टि कर चुका है. इसलिए, कर्नल बिना किसी शर्त के सुपर पार्टीशन को माउंट करता है. फ़ुल Android की तरह ही, सुपर पार्टिशन में कई लॉजिकल पार्टिशन होते हैं. इन्हें dm-verity पर माउंट किया जाता है. इसके बाद, कंट्रोल को
init
प्रोसेस में पास कर दिया जाता है. यह प्रोसेस, कई नेटिव सेवाओं को शुरू करती है.init.rc
स्क्रिप्ट, फ़ुल Android की स्क्रिप्ट की तरह ही होती है. हालांकि, इसे Microdroid की ज़रूरतों के हिसाब से तैयार किया जाता है.init
प्रोसेस, Microdroid मैनेजर को शुरू करती है. यह इंस्टेंस इमेज को ऐक्सेस करता है. Microdroid मैनेजर सेवा, पिछली स्टेज से पास की गई कुंजी का इस्तेमाल करके इमेज को डिक्रिप्ट करती है. साथ ही, उन क्लाइंट APK और APEX के सार्वजनिक पासकोड और रोलबैक काउंटर को पढ़ती है जिन पर यह pVM भरोसा करता है. इस जानकारी का इस्तेमाल बाद मेंzipfuse
औरapexd
करते हैं. ऐसा तब होता है, जब वे क्लाइंट एपीके और अनुरोध किए गए एपीईएक्स को माउंट करते हैं.Microdroid मैनेजर सेवा
apexd
से शुरू होती है.apexd
, APEX को/apex/<name>
डायरेक्ट्री में माउंट करता है. Android और Microdroid, दोनों में APEX को माउंट करने का तरीका एक जैसा है. हालांकि, Microdroid में APEX फ़ाइलें, वर्चुअल ब्लॉक डिवाइसों (/dev/vdc1
, …) से आती हैं, न कि सामान्य फ़ाइलों (/system/apex/*.apex
) से.zipfuse
, Microdroid का FUSE फ़ाइल सिस्टम है.zipfuse
क्लाइंट APK को माउंट करता है. यह फ़ाइल सिस्टम के तौर पर एक Zip फ़ाइल होती है. इसके बाद, APK फ़ाइल को pVM, dm-verity के साथ वर्चुअल ब्लॉक डिवाइस के तौर पर पास करता है. यह APEX की तरह ही होता है. इस APK में एक कॉन्फ़िगरेशन फ़ाइल होती है. इसमें उन APEX की सूची होती है जिनके लिए ऐप्लिकेशन डेवलपर ने इस pVM इंस्टेंस के लिए अनुरोध किया है. एपीईएक्स चालू करते समय,apexd
इस सूची का इस्तेमाल करता है.बूट फ़्लो, Microdroid मैनेजर सेवा पर वापस आ जाता है. इसके बाद, मैनेजर सेवा Android के
VirtualizationService
से कम्यूनिकेट करती है. इसके लिए, Binder RPC का इस्तेमाल किया जाता है, ताकि वह क्रैश या शटडाउन जैसे अहम इवेंट की रिपोर्ट कर सके. साथ ही, pVM को बंद करने जैसे अनुरोध स्वीकार कर सके. मैनेजर सर्विस, APK की कॉन्फ़िगरेशन फ़ाइल से मुख्य बाइनरी की जगह की जानकारी पढ़ती है और उसे लागू करती है.
फ़ाइल एक्सचेंज (AuthFS)
Android कॉम्पोनेंट, इनपुट, आउटपुट, और स्थिति के लिए फ़ाइलों का इस्तेमाल करते हैं. साथ ही, Android कर्नल से कंट्रोल किए गए ऐक्सेस के साथ, इन्हें फ़ाइल डिस्क्रिप्टर (AIDL में ParcelFileDescriptor
टाइप) के तौर पर पास करते हैं. AuthFS, pVM की सीमाओं के बीच, एक-दूसरे पर भरोसा न करने वाले एंडपॉइंट के बीच फ़ाइलों को शेयर करने की सुविधा देता है.
AuthFS, एक रिमोट फ़ाइल सिस्टम है. इसमें हर ऐक्सेस ऑपरेशन पर, पारदर्शी तरीके से इंटिग्रिटी की जांच की जाती है. यह fs-verity
की तरह ही काम करता है. इन जांचों की मदद से, फ़्रंटएंड यह पता लगा सकता है कि फ़ाइल के कॉन्टेंट में छेड़छाड़ की गई है या नहीं. फ़्रंटएंड, pVM में चलने वाला फ़ाइल-रीडिंग प्रोग्राम होता है. फ़ाइल के कॉन्टेंट में छेड़छाड़, आम तौर पर Android जैसे भरोसेमंद न होने वाले बैकएंड से की जाती है.
फ़ाइलों को ट्रांसफ़र करने के लिए, बैकएंड (fd\_server
) को हर फ़ाइल के हिसाब से कॉन्फ़िगर किया जाता है. इससे यह तय होता है कि फ़ाइल इनपुट (सिर्फ़ पढ़ने के लिए) के लिए है या आउटपुट (पढ़ने और लिखने के लिए). इनपुट के लिए, फ़्रंटएंड यह पक्का करता है कि कॉन्टेंट, जाने-पहचाने हैश से मेल खाता हो. साथ ही, ऐक्सेस के दौरान पुष्टि करने के लिए, मर्कल ट्री का इस्तेमाल किया जाता है. आउटपुट के लिए, AuthFS अंदरूनी तौर पर कॉन्टेंट का हैश ट्री बनाए रखता है. यह कॉन्टेंट, लिखने की कार्रवाइयों से मिलता है. साथ ही, डेटा को वापस पढ़ने पर, यह अखंडता लागू कर सकता है.
फ़िलहाल, ट्रांसपोर्ट की सुविधा Binder RPC पर आधारित है. हालांकि, परफ़ॉर्मेंस को ऑप्टिमाइज़ करने के लिए, आने वाले समय में इसमें बदलाव किया जा सकता है.
कुंजी मैनेजमेंट
pVM को एक स्टेबल सीलिंग कुंजी दी जाती है. यह कुंजी, लगातार बने रहने वाले डेटा को सुरक्षित रखने के लिए सही होती है. साथ ही, pVM को एक अटेस्टेशन कुंजी दी जाती है. यह कुंजी, ऐसे हस्ताक्षर बनाने के लिए सही होती है जिनकी पुष्टि की जा सकती है कि उन्हें pVM ने बनाया है.
Binder RPC
Android के ज़्यादातर इंटरफ़ेस, AIDL में दिखाए जाते हैं. यह Binder Linux कर्नेल ड्राइवर पर बनाया गया है. pVM के बीच इंटरफ़ेस को सपोर्ट करने के लिए, Binder प्रोटोकॉल को फिर से लिखा गया है, ताकि यह सॉकेट पर काम कर सके. pVM के मामले में, यह vsock पर काम करता है. सॉकेट पर काम करने की सुविधा की मदद से, Android के मौजूदा AIDL इंटरफ़ेस को इस नए एनवायरमेंट में इस्तेमाल किया जा सकता है.
कनेक्शन सेट अप करने के लिए, एक एंडपॉइंट, जैसे कि pVM पेलोड, RpcServer
ऑब्जेक्ट बनाता है, रूट ऑब्जेक्ट रजिस्टर करता है, और नए कनेक्शन के लिए सुनना शुरू करता है. क्लाइंट, RpcSession
ऑब्जेक्ट का इस्तेमाल करके इस सर्वर से कनेक्ट हो सकते हैं. साथ ही, Binder
ऑब्जेक्ट पा सकते हैं और इसका इस्तेमाल ठीक उसी तरह कर सकते हैं जिस तरह कर्नल बाइंडर ड्राइवर के साथ Binder
ऑब्जेक्ट का इस्तेमाल किया जाता है.