درهم مجهري

‫Microdroid هو نظام تشغيل Android مصغّر يعمل في جهاز افتراضي شخصي. لست مضطرًا إلى استخدام Microdroid، فيمكنك تشغيل جهاز افتراضي على أي نظام تشغيل. ومع ذلك، لا تعمل حالات الاستخدام الأساسية لأجهزة افتراضية شخصية على نظام تشغيل مستقل، بل تقدّم بيئة تنفيذ معزولة لتشغيل جزء من تطبيق مع ضمانات قوية للخصوصية والسلامة أكثر مما يمكن أن يوفّره Android.

في أنظمة التشغيل التقليدية، يتطلّب توفير السرية والتكامل التامَين قدرًا لا بأس به من العمل (غالبًا ما يكون مكرّرًا) لأنّ أنظمة التشغيل التقليدية لا تتوافق مع بنية Android العميقة. على سبيل المثال، باستخدام بنية Android العادية، يحتاج المطوّرون إلى تنفيذ وسيلة لتحميل جزء من تطبيقهم وتنفيذه بأمان في آلة افتراضية محمولة (pVM)، ويتم إنشاء الحمولة باستخدام glibc. يستخدم تطبيق Android Bionic، يتطلب الاتصال بروتوكولاً مخصصًا مقابل الاعتراض، كما أن تصحيح الأخطاء باستخدام adb أمر صعب.

يسدّ Microdroid هذه الفجوات من خلال توفير صورة نظام تشغيل جاهزة مصمّمة لتطلب من المطوّرين الحد الأدنى من الجهد لتفريغ جزء من تطبيقهم في جهاز افتراضي. يتم إنشاء الرمز البرمجي الأصلي باستخدام مكتبة Bionic، ويتم الاتصال من خلال Binder، ويسمح باستيراد حِزم APEX من نظام Android المضيف ويعرِض مجموعة فرعية من واجهة برمجة تطبيقات Android، مثل ملف تخزين المفاتيح للعمليات التشفيرية باستخدام مفاتيح مستندة إلى الأجهزة. بشكل عام، من المفترض أن يجد المطوّرون أنّ Microdroid هو بيئة مألوفة تتضمّن الأدوات التي اعتادوا عليها في نظام التشغيل Android الكامل.

الميزات

‫Microdroid هو إصدار مُبسَّط من Android مع بعض المكونات الإضافية الخاصة بأجهزة افتراضية شخصية. يتيح Microdroid ما يلي:

  • مجموعة فرعية من واجهات برمجة تطبيقات NDK (يتم توفير جميع واجهات برمجة التطبيقات لتنفيذ libc و Bionic في Android)
  • ميزات تصحيح الأخطاء، مثل 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: يحتوي على النواة ومساحة التخزين المؤقت لبدء التشغيل.
  • vendor_boot.img - يحتوي على وحدات نواة خاصة بأجهزة افتراضية، مثل virtio.
  • super.img - يتألّف من الأقسام المنطقية للنظام والمورّد.
  • vbmeta.img: يحتوي على بيانات وصفية لميزة "التمهيد التحقق منه".

يتم شحن صور الأقسام في Virtualization APEX ويتم حزمها في صورة قرص مركبة بواسطة VirtualizationService. بالإضافة إلى صورة القرص المركبة للنظام الأساسي، تتحمّل أداة VirtualizationService مسؤولية إنشاء الأقسام التالية:

  • payload: مجموعة من الأقسام التي تستند إلى حِزم APEX وحِزم APK من Android
  • instance - قسم مشفَّر للحفاظ على بيانات التشغيل التي تم التحقّق منها لكل مثيل، مثل الملح لكل مثيل والمفاتيح العامة الموثوق بها في APEX ومقاييس التراجع

تسلسل بدء التشغيل

يحدث تسلسل تشغيل Microdroid بعد تشغيل الجهاز. تتم مناقشة عملية تشغيل الجهاز في قسم البرامج الثابتة لنظام التشغيل pVM ضمن مستند البنية. يعرض الشكل 1 الخطوات التي تحدث أثناء تسلسل التمهيد في Microdroid:

عملية التمهيد الآمن مثيل microdroid

الشكل 1: عملية التمهيد الآمن لآلة microdroid الافتراضية

في ما يلي شرح للخطوات:

  1. يتم تحميل برنامج الإقلاع في الذاكرة بواسطة crosvm ويبدأ pvmfw في التنفيذ. قبل الانتقال إلى أداة تحميل البرامج، تُنفِّذ pvmfw مهمتَين:

    • التحقّق من برنامج الإقلاع للتأكّد من أنّه من مصدر موثوق به (Google أو أحد المصنّعين الأصليين للأجهزة)
    • تضمن هذه الميزة استخدام مشغّل الإقلاع نفسه بشكلٍ متسق في عمليات التمهيد المتعدّدة لنظام التشغيل الظاهري نفسه من خلال استخدام صورة المثيل. على وجه التحديد، يتم تشغيل pVM في البداية باستخدام صورة مثيل فارغة. ويخزِّن pvmfw هوية برنامج التمهيد في صورة المثيل ويشفّرها. وبالتالي، في المرة التالية التي يتم فيها التمهيد لوحدة pVM باستخدام صورة المثيل نفسها، يفكّ pvmfw تشفير هوية العميل المحفوظة من صورة المثيل ويتأكّد من أنّها هي نفسها التي تم حفظها سابقًا. إذا اختلفت الهويات، يرفض pvmfw التمهيد.

    بعد ذلك، يشغِّل برنامج الإقلاع نظام التشغيل Microdroid.

  2. يصل برنامج الإقلاع إلى قرص المثيل. على غرار pvmfw، يحتوي مُحمِّل الإقلاع على محرك أقراص مثيل يحتوي على معلومات عن صور الأقسام المستخدَمة في هذا المثيل أثناء عمليات الإقلاع السابقة، بما في ذلك المفتاح العام.

  3. يتحقّق برنامج الإقلاع من vbmeta والأقسام المرتبطة، مثل boot وsuper، وإذا نجحت عملية التحقّق، يحصل على أسرار مرحلة pVM التالية. بعد ذلك، ينقل Microdroid التحكّم إلى النواة.

  4. بما أنّه سبق أن تحقّق مشغّل الإقلاع من قسم Super (الخطوة 3)، يُثبِّت kernel القسم بدون قيد أو شرط. كما هو الحال مع نظام Android الكامل، يتكوّن القسم الفائق من أقسام منطقية متعددة تم تثبيتها على dm-verity. ويتم بعد ذلك تمرير التحكّم إلى عملية init التي تبدأ خدمات أساسية مختلفة. يتشابه نص init.rc البرمجي مع نص برمجي كامل Android، ولكنه مصمّم خصيصًا لتلبية احتياجات Microdroid.

  5. تبدأ عملية init مدير Microdroid الذي يصل إلى مثيل الصورة. تفكِّ خدمة مدير Microdroid تشفير الصورة باستخدام المفتاح الذي تم تمريره من المرحلة السابقة وتقرأ المفاتيح العامة ومقاييس التراجع لملف APK العميل وAPEXes التي يثق بها هذا الجهاز الظاهري للتشغيل. وتستخدم كلّ من zipfuse وapexd هذه المعلومات لاحقًا عند تثبيت حِزم APK الخاصة بالعملاء وحِزم APEX المطلوبة، على التوالي.

  6. تبدأ خدمة مدير Microdroid في ‎apexd.

  7. يُثبِّت apexd نطاقات APEX في الأدلة /apex/<name>. الفرق الوحيد بين كيفية تثبيت نظامَي التشغيل Android وMicrodroid لحِزم APEX هو أنّه في نظام التشغيل Microdroid، تأتي حِزم APEX من أجهزة الكتل الافتراضية (/dev/vdc1، …)، وليس من الملفات العادية (/system/apex/*.apex).

  8. zipfuse هو نظام ملفات FUSE في Microdroid. zipfuse يُثبّت حزمة APK الخاصة بالعميل، وهي في الأساس ملف Zip كنظام ملفات. في الأساس، يتم معالجة ملف APK كجهاز كتلة افتراضي من خلال آلة افتراضية محمولة (pVM) باستخدام dm-verity، تمامًا مثل APEX. يحتوي ملف APK على ملف إعدادات يحتوي على قائمة بتطبيقات APEX التي طلبها مطوّر التطبيقات لوحدة pVM هذه. يستخدم apexd القائمة عند تفعيل نقاط اتصال APEX.

  9. يعود تدفّق عملية التمهيد إلى خدمة مدير Microdroid. بعد ذلك، تتواصل خدمة التحكم مع VirtualizationService في Android باستخدام Binder RPC حتى تتمكّن من الإبلاغ عن الأحداث المهمة، مثل الأعطال أو عمليات الإيقاف، وقبول الطلبات، مثل إنهاء تشغيل جهاز افتراضي. تقرأ خدمة المدير موقع الملف الثنائي الرئيسي من ملف الإعدادات الخاص بملف APK وتنفذه.

تبادل الملفات (AuthFS)

من الشائع أن تستخدم مكوّنات Android الملفات للإدخال والإخراج والحالة وإرسالها كأوصاف ملفات (ParcelFileDescriptor نوع في AIDL) مع التحكّم في الوصول من خلال نواة Android. يسهّل AuthFS وظائف مماثلة لتبادل الملفات بين نقاط النهاية التي لا تثق ببعضها البعض على مستوى حدود pVM.

في الأساس، AuthFS هو نظام ملفات عن بُعد يتضمّن عمليات تحقّق شفافة من السلامة في عمليات الوصول الفردية، مثل fs-verity. تسمح عمليات التحقّق للواجهة الأمامية، مثل برنامج قراءة الملفات الذي يتم تشغيله في جهاز افتراضي شخصي (pVM)، برصد ما إذا كانت الواجهة الخلفية غير الموثوق بها، عادةً Android، قد تلاعبت بمحتوى الملف.

لتبادل الملفات، يتم بدء البرنامج الخلفي (fd\_server) باستخدام إعدادات لكل ملف تحدد ما إذا كان مخصّصًا للإدخال (للقراءة فقط) أو الإخراج (للقراءة والكتابة). بالنسبة إلى الإدخال، تفرض الواجهة الأمامية تطابق المحتوى مع علامة هاش معروفة، بالإضافة إلى شجرة Merkle لإثبات الهوية عند الوصول. بالنسبة إلى الإخراج، يحافظ AuthFS داخليًا على شجرة تجزئة للمحتوى كما لوحظ من عمليات الكتابة ، ويمكنه فرض السلامة عند إعادة قراءة البيانات.

يستند النقل الأساسي حاليًا إلى Binder RPC، ولكن قد يتغيّر ذلك في المستقبل لتحسين الأداء.

إدارة المفاتيح

يتم تزويد آلات افتراضية للبرامج بمفتاح إغلاق ثابت ومناسب لحماية البيانات الثابتة، ومفتاح إثبات الهوية مناسب لإنشاء التوقيعات التي يمكن التحقّق من إنشائها بواسطة آلة افتراضية للبرامج.

Binder RPC

يتم التعبير عن معظم واجهات Android في AIDL، والذي يتم إنشاؤه على أساس برنامج تشغيل Binder لنظام التشغيل Linux. لدعم الواجهات بين الأجهزة الافتراضية للبرامج، تمت إعادة كتابة بروتوكول Binder للعمل على مآخذ التوصيل، vsock في حال الأجهزة الافتراضية للبرامج. يتيح التشغيل عبر مآخذ التوصيل استخدام واجهات AIDL الحالية في Android في هذه البيئة الجديدة.

لإعداد الاتصال، تنشئ نقطة نهاية واحدة، مثل حمولة pVM، عنصر RpcServer وتُسجِّل عنصر جذر وتبدأ في الاستماع إلى عمليات الربط الجديدة. يمكن للعملاء الاتصال بهذا الخادم باستخدام عنصر RpcSession، وإحضار عنصر Binder واستخدامه تمامًا مثل استخدام عنصر Binder مع برنامج تشغيل Binder للنواة.