Microdroid

‫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 - يحتوي على النواة وinit ramdisk.
  • 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 في التنفيذ. قبل الانتقال إلى برنامج bootloader، ينفّذ pvmfw مهمتَين:

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

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

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

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

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

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

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

  7. تثبِّت apexd حِزم APEX في أدلة /apex/<name>. الفرق الوحيد بين طريقة تحميل حِزم APEX في Android وMicrodroid هو أنّ ملفات APEX في Microdroid تأتي من أجهزة حظر افتراضية (/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. تسمح عمليات التحقّق للواجهة الأمامية، مثل برنامج قراءة الملفات الذي يتم تشغيله في آلة افتراضية محمية، برصد ما إذا كانت الواجهة الخلفية غير الموثوق بها، والتي تكون عادةً نظام التشغيل Android، قد تلاعبت بمحتوى الملف.

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

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

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

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

Binder RPC

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

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