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 एपीआई का सबसेट (Android के libc और Bionic को लागू करने के लिए सभी एपीआई उपलब्ध कराए जाते हैं)
- डीबग करने की सुविधाएं, जैसे कि 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
- इसमें पुष्टि किए गए बूट मेटाडेटा शामिल हैं.
पार्टीशन इमेज, वर्चुअलाइज़ेशन APEX में शिप की जाती हैं और VirtualizationService
के ज़रिए एक कंपोजिट डिस्क इमेज में पैकेज की जाती हैं. मुख्य ऑपरेटिंग सिस्टम कॉम्पोज़िट डिस्क इमेज के अलावा, VirtualizationService
इन अन्य पार्टीशन को बनाने के लिए ज़िम्मेदार है:
payload
- Android के APEX और APKs के बैकअप वाले पार्टीशन का एक सेट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
करते हैं. वे क्लाइंट APK और अनुरोध किए गए APEX को माउंट करते समय, इस जानकारी का इस्तेमाल करते हैं.Microdroid मैनेजर सेवा
apexd
से शुरू होगी.apexd
,/apex/<name>
डायरेक्ट्री में APEX को माउंट करता है. Android और Microdroid, दोनों में APEX फ़ाइलों को माउंट करने का तरीका एक जैसा है. हालांकि, Microdroid में APEX फ़ाइलें, सामान्य फ़ाइलों (/system/apex/*.apex
) से नहीं, बल्कि वर्चुअल ब्लॉक डिवाइसों (/dev/vdc1
, …) से आती हैं.zipfuse
, Microdroid का FUSE फ़ाइल सिस्टम है.zipfuse
, क्लाइंट APK को माउंट करता है. यह फ़ाइल सिस्टम के तौर पर एक Zip फ़ाइल होती है. इसके बाद, APK फ़ाइल को APEX की तरह ही, dm-verity की मदद से pVM के ज़रिए वर्चुअल ब्लॉक डिवाइस के तौर पर पास किया जाता है. APK में एक कॉन्फ़िगरेशन फ़ाइल होती है. इसमें उन APEX की सूची होती है जिनका अनुरोध ऐप्लिकेशन डेवलपर ने इस pVM इंस्टेंस के लिए किया है.apexd
, APEX को चालू करते समय इस सूची का इस्तेमाल करता है.बूट फ़्लो, Microdroid मैनेजर सेवा पर वापस आ जाता है. इसके बाद, मैनेजर सेवा, Binder RPC का इस्तेमाल करके Android के
VirtualizationService
के साथ संपर्क करती है, ताकि वह क्रैश या शटडाउन जैसे अहम इवेंट की रिपोर्ट कर सके. साथ ही, pVM को बंद करने जैसे अनुरोध स्वीकार कर सके. मैनेजर सेवा, APK की कॉन्फ़िगरेशन फ़ाइल से मुख्य बाइनरी की जगह पढ़ती है और उसे लागू करती है.
फ़ाइल एक्सचेंज (AuthFS)
आम तौर पर, Android कॉम्पोनेंट इनपुट, आउटपुट, और स्टेटस के लिए फ़ाइलों का इस्तेमाल करते हैं. साथ ही, इन्हें फ़ाइल डिस्क्रिप्टर (ParcelFileDescriptor
टाइप इन
AIDL) के तौर पर पास करते हैं. इनका ऐक्सेस, Android kernel कंट्रोल करता है. AuthFS, pVM की सीमाओं के बीच, एक-दूसरे पर भरोसा न करने वाले एंडपॉइंट के बीच फ़ाइलें शेयर करने के लिए, मिलती-जुलती सुविधा देता है.
मूल रूप से, AuthFS एक रिमोट फ़ाइल सिस्टम है. इसमें fs-verity
की तरह, अलग-अलग ऐक्सेस ऑपरेशन पर पारदर्शी तरीके से पूरी सुरक्षा की जांच की जाती है. इन जांचों की मदद से, frontend को यह पता चलता है कि भरोसेमंद नहीं होने वाले बैकएंड, जैसे कि Android ने फ़ाइल के कॉन्टेंट में छेड़छाड़ की है या नहीं. frontend में, pVM में चलने वाला फ़ाइल पढ़ने वाला प्रोग्राम शामिल है.
फ़ाइलों को एक्सचेंज करने के लिए, हर फ़ाइल के लिए कॉन्फ़िगरेशन के साथ बैकएंड (fd\_server
) शुरू किया जाता है. इससे यह तय होता है कि फ़ाइल को इनपुट (रीड-ओनली) के तौर पर इस्तेमाल करना है या आउटपुट (रीड-राइट) के तौर पर. इनपुट के लिए, फ़्रंटएंड यह पक्का करता है कि कॉन्टेंट, ऐक्सेस करते समय पुष्टि करने के लिए, मेर्कल ट्री के ऊपर मौजूद किसी जाने-पहचाने हैश से मेल खाता हो. आउटपुट के लिए, AuthFS, लिखने के ऑपरेशन से मिले कॉन्टेंट का हैश ट्री अंदरूनी तौर पर बनाए रखता है. साथ ही, डेटा को फिर से पढ़ने पर, डेटा की अखंडता को लागू कर सकता है.
फ़िलहाल, ट्रांसपोर्ट प्रोटोकॉल Binder RPC पर आधारित है. हालांकि, आने वाले समय में परफ़ॉर्मेंस को ऑप्टिमाइज़ करने के लिए, इसमें बदलाव हो सकता है.
कुंजी मैनेजमेंट
pVM को एक ऐसी सीलिंग पासकोड दी जाती है जो हमेशा मौजूद रहने वाले डेटा को सुरक्षित रखने के लिए सही होती है. साथ ही, एक ऐसी पुष्टि करने वाली पासकोड दी जाती है जो ऐसे हस्ताक्षर बनाने के लिए सही होती है जिनकी पुष्टि pVM से की जा सकती है.
Binder RPC
Android के ज़्यादातर इंटरफ़ेस, AIDL में दिखाए जाते हैं. इसे Binder Linux kernel driver के ऊपर बनाया गया है. pVMs के बीच इंटरफ़ेस के साथ काम करने के लिए, Binder प्रोटोकॉल को फिर से लिखा गया है, ताकि यह pVMs के मामले में, सोकेट और vsock के साथ काम कर सके. सॉकेट पर काम करने की सुविधा की मदद से, Android के मौजूदा AIDL इंटरफ़ेस का इस्तेमाल इस नए एनवायरमेंट में किया जा सकता है.
कनेक्शन सेट अप करने के लिए, pVM पेलोड जैसा कोई एक एंडपॉइंट, RpcServer
ऑब्जेक्ट बनाता है, रूट ऑब्जेक्ट को रजिस्टर करता है, और नए कनेक्शन के लिए सुनना शुरू करता है. क्लाइंट, RpcSession
ऑब्जेक्ट का इस्तेमाल करके इस सर्वर से कनेक्ट कर सकते हैं,
Binder
ऑब्जेक्ट पा सकते हैं, और इसका इस्तेमाल ठीक उसी तरह कर सकते हैं जिस तरह Binder
ऑब्जेक्ट का इस्तेमाल, kernel Binder ड्राइवर के साथ किया जाता है.