Microdroid هو نظام تشغيل Android مصغّر يعمل في آلة افتراضية محمية. لست مضطرًا إلى استخدام Microdroid، بل يمكنك بدء تشغيل جهاز افتراضي باستخدام أي نظام تشغيل. ومع ذلك، فإنّ حالات الاستخدام الأساسية لآلات pVM الافتراضية لا تتضمّن تشغيل نظام تشغيل مستقل، بل توفير بيئة تنفيذ معزولة لتشغيل جزء من تطبيق مع ضمانات أقوى للسرية والسلامة مقارنةً بما يمكن أن يوفّره نظام Android.
في أنظمة التشغيل التقليدية، يتطلب توفير مستوى عالٍ من السرية والسلامة بذل قدر كبير من الجهد (غالبًا ما يكون مكررًا) لأنّ أنظمة التشغيل التقليدية لا تتوافق مع بنية Android الأساسية. على سبيل المثال، باستخدام بنية Android العادية، على المطوّرين توفير وسيلة لتحميل جزء من تطبيقاتهم وتنفيذه بشكل آمن في الجهاز الظاهري المحمي، ويتم إنشاء الحمولة باستخدام glibc. يستخدم تطبيق Android مكتبة Bionic، ويتطلّب الاتصال بروتوكولاً مخصّصًا عبر vsock، كما أنّ تصحيح الأخطاء باستخدام adb يمثّل تحديًا.
يساعد Microdroid في سدّ هذه الثغرات من خلال توفير نسخة نظام تشغيل جاهزة مصمّمة لتتطلّب أقل قدر من الجهد من المطوّرين لتخفيف الحِمل عن جزء من تطبيقاتهم إلى آلة افتراضية محمية. يتم إنشاء الرمز البرمجي الأصلي باستخدام Bionic، ويتم التواصل عبر Binder، كما يتيح استيراد حِزم APEX من نظام Android المضيف وعرض مجموعة فرعية من واجهة برمجة تطبيقات Android، مثل "خدمة تخزين المفاتيح" لإجراء عمليات التشفير باستخدام المفاتيح المحمية بواسطة الأجهزة. بشكل عام، سيجد المطوّرون أنّ Microdroid بيئة مألوفة تتضمّن الأدوات التي اعتادوا استخدامها في نظام التشغيل Android الكامل.
الميزات
Microdroid هو إصدار مبسط من Android يتضمّن بعض المكوّنات الإضافية الخاصة بالأجهزة الافتراضية المحمية. تتيح Microdroid ما يلي:
- مجموعة فرعية من واجهات برمجة التطبيقات في NDK (يتم توفير جميع واجهات برمجة التطبيقات لتنفيذ Android لـ libc وBionic)
- ميزات تصحيح الأخطاء، مثل adb وlogcat وtombstone وgdb
- التشغيل المتحقَّق منه وSELinux
- تحميل وتنفيذ ملف ثنائي، بالإضافة إلى المكتبات المشترَكة، المضمّنة في حزمة APK
- استخدام Binder RPC عبر vsock وتبادل الملفات مع عمليات التحقّق الضمنية من السلامة
- تحميل حِزم APEX
لا يتيح Microdroid ما يلي:
واجهات برمجة تطبيقات Java لنظام التشغيل Android في حِزم
android.\*SystemServer وZygote
رسومات/ واجهة المستخدم
HALs
بنية Microdroid
تشبه Microdroid Cuttlefish في أنّ كلتيهما تتضمّنان بنية مشابهة لنظام Android العادي. يتألف Microdroid من صور الأقسام التالية المجمّعة معًا في صورة قرص مركّبة:
-
bootloader: يتحقّق من النواة ويبدأها. boot.img- يحتوي على النواة ومساحة التخزين المؤقت للذاكرة العشوائية (ramdisk) الأولية.-
vendor_boot.img: يحتوي على وحدات نواة خاصة بالجهاز الظاهري، مثل virtio. -
super.img: يتألف من أقسام منطقية للنظام والمورِّد. -
vbmeta.img: يحتوي على البيانات الوصفية لعملية "التشغيل المتحقَّق منه".
يتم شحن صور الأقسام في حزمة Virtualization APEX وتعبئتها في صورة قرص مركّبة بواسطة VirtualizationService. بالإضافة إلى نسخة قرص نظام التشغيل الأساسي، يكون VirtualizationService مسؤولاً عن إنشاء الأقسام الأخرى التالية:
-
payload: مجموعة من الأقسام التي تدعمها حِزم APEX وحِزم APK في نظام التشغيل Android -
instance: قسم مشفّر لتخزين بيانات التشغيل المتحقّق منه لكل مثيل، مثل قيمة التشفير لكل مثيل ومفاتيح APEX العامة الموثوق بها وعدادات الرجوع إلى الإصدار السابق
تسلسل التشغيل
يحدث تسلسل بدء تشغيل Microdroid بعد بدء تشغيل الجهاز. تمت مناقشة عملية تشغيل الجهاز في قسم البرامج الثابتة الخاصة بآلة pVM ضمن مستند البنية. تعرض "الشكل 1" الخطوات التي تحدث أثناء تسلسل بدء تشغيل Microdroid:
في ما يلي شرح للخطوات:
يتم تحميل برنامج الإقلاع في الذاكرة بواسطة crosvm، ويبدأ pvmfw في التنفيذ. قبل الانتقال إلى برنامج bootloader، ينفّذ pvmfw مهمتَين:
- يتحقّق من برنامج الإقلاع للتأكّد من أنّه صادر من مصدر موثوق به (Google أو أحد مصنّعي المعدات الأصلية).
- يضمن استخدام برنامج الإقلاع نفسه بشكل متّسق في عمليات تشغيل متعددة لآلة افتراضية محمية (pVM) نفسها من خلال استخدام صورة المثيل. على وجه التحديد، يتم تشغيل الجهاز الظاهري الخاص (pVM) في البداية باستخدام صورة فارغة للجهاز. يخزّن برنامج pvmfw هوية برنامج الإقلاع في صورة الجهاز ويشفّرها. وبالتالي، في المرة التالية التي يتم فيها تشغيل الجهاز الظاهري المحمي باستخدام صورة الجهاز الظاهري نفسها، يفك pvmfw تشفير الهوية المحفوظة من صورة الجهاز الظاهري ويتأكّد من أنّها هي نفسها التي تم حفظها سابقًا. وإذا كانت الهويات مختلفة، يرفض pvmfw بدء التشغيل.
بعد ذلك، يشغّل برنامج الإقلاع Microdroid.
يصل برنامج الإقلاع إلى قرص الآلة الافتراضية. على غرار pvmfw، يحتوي برنامج إقلاع على قرص آلة افتراضية يتضمّن معلومات حول صور الأقسام المستخدَمة في هذه الآلة الافتراضية أثناء عمليات التشغيل السابقة، بما في ذلك المفتاح العام.
يتحقّق برنامج الإقلاع من ملف vbmeta والأقسام المرتبطة، مثل
bootوsuper، وفي حال نجاح ذلك، يستخلص أسرار pVM في المرحلة التالية. بعد ذلك، يسلّم Microdroid التحكّم إلى النواة.بما أنّ قسم super تم التحقّق منه مسبقًا بواسطة برنامج الإقلاع (الخطوة 3)، يركّب النواة قسم super بدون شروط. وكما هو الحال مع نظام Android الكامل، يتألف القسم الفائق من أقسام منطقية متعددة يتم تركيبها باستخدام dm-verity. بعد ذلك، يتم نقل عنصر التحكّم إلى عملية
initالتي تبدأ تشغيل خدمات أصلية مختلفة. يشبه النص البرمجيinit.rcالنص البرمجي لنظام Android الكامل، ولكنّه مصمَّم خصيصًا لتلبية احتياجات Microdroid.تبدأ عملية
initتشغيل مدير Microdroid الذي يصل إلى صورة الجهاز الافتراضي. تزيل خدمة "مدير Microdroid" تشفير الصورة باستخدام المفتاح الذي تم تمريره من المرحلة السابقة، وتقرأ المفاتيح العامة وعدادات الرجوع إلى الإصدارات السابقة لحِزم APK وAPEX الخاصة بالعميل والتي تثق بها الآلة الافتراضية المحمية. تستخدمzipfuseوapexdهذه المعلومات لاحقًا عند تحميل حِزم APK للعميل وحِزم APEX المطلوبة، على التوالي.تبدأ خدمة مدير Microdroid في
apexd.apexdيركّب حِزم APEX في أدلة/apex/<name>. والفرق الوحيد بين طريقة تركيب حِزم APEX في Android وMicrodroid هو أنّ ملفات APEX في Microdroid تأتي من أجهزة حظر افتراضية (/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، ما يتيح لها إرسال تقارير عن الأحداث المهمة، مثل الأعطال أو عمليات الإيقاف، وقبول الطلبات، مثل إنهاء الجهاز الظاهري المحمي. تقرأ خدمة المدير موقع الملف الثنائي الرئيسي من ملف إعداد APK وتنفّذه.
تبادل الملفات (AuthFS)
من الشائع أن تستخدم مكوّنات Android الملفات للإدخال والإخراج والحالة، وأن يتم تمريرها كواصفات ملفات (النوع ParcelFileDescriptor في AIDL) مع التحكّم في الوصول إليها من خلال نواة Android. تسهّل AuthFS وظائف مشابهة لتبادل الملفات بين نقاط نهاية لا تثق ببعضها البعض عبر حدود pVM.
بشكل أساسي، AuthFS هو نظام ملفات بعيد يتضمّن عمليات تحقّق شفافة من السلامة
في عمليات الوصول الفردية، على غرار fs-verity. تسمح عمليات التحقّق للواجهة الأمامية، مثل برنامج قراءة الملفات الذي يتم تشغيله في آلة افتراضية محمية، برصد ما إذا كانت الواجهة الخلفية غير الموثوق بها، والتي تكون عادةً نظام التشغيل Android، قد تلاعبت بمحتوى الملف.
لتبادل الملفات، يتم بدء عملية الخلفية (fd\_server) باستخدام إعدادات لكل ملف تحدد ما إذا كان مخصّصًا للإدخال (للقراءة فقط) أو الإخراج (للقراءة والكتابة). بالنسبة إلى الإدخال، يفرض الواجهة الأمامية أن يتطابق المحتوى مع قيمة تجزئة معروفة، بالإضافة إلى شجرة Merkle لإجراء عملية التحقّق عند الوصول. بالنسبة إلى الإخراج، تحتفظ AuthFS داخليًا بشجرة تجزئة للمحتوى كما تم رصده من عمليات الكتابة، ويمكنها فرض السلامة عند إعادة قراءة البيانات.
تستند عملية النقل الأساسية حاليًا إلى Binder RPC، ولكن قد يتغيّر ذلك في المستقبل لتحسين الأداء.
إدارة المفاتيح
يتم تزويد الأجهزة الافتراضية المحمية (pVM) بمفتاح إغلاق ثابت ومناسب لحماية البيانات الدائمة، ومفتاح إثبات صحة مناسب لإنشاء توقيعات يمكن التحقّق من أنّها صادرة عن الجهاز الافتراضي المحمي.
Binder RPC
يتم التعبير عن معظم واجهات Android باستخدام AIDL، والتي تم إنشاؤها استنادًا إلى برنامج تشغيل نواة Linux Binder. لإتاحة التوافق بين الأجهزة الافتراضية المحمية، تمت إعادة كتابة بروتوكول Binder ليعمل عبر مآخذ التوصيل، وتحديدًا مآخذ التوصيل الافتراضية في حالة الأجهزة الافتراضية المحمية. يتيح التشغيل عبر المقابس استخدام واجهات AIDL الحالية في Android في هذه البيئة الجديدة.
لإعداد الاتصال، تنشئ إحدى نقاط النهاية، مثل حمولة pVM، عنصر RpcServer، وتسجّل عنصرًا جذريًا، وتبدأ في الاستماع إلى الاتصالات الجديدة. يمكن للعملاء الربط بهذا الخادم باستخدام عنصر RpcSession، والحصول على عنصر Binder، واستخدامه تمامًا كما يتم استخدام عنصر Binder مع برنامج تشغيل Binder في النواة.