يوفّر Android تنفيذًا مرجعيًا لجميع المكوّنات اللازمة لتنفيذ إطار عمل Android Virtualization Framework. تقتصر عملية التنفيذ هذه حاليًا على ARM64. توضّح هذه الصفحة بنية الإطار.
خلفية
تسمح بنية Arm بحد أقصى أربعة مستويات للاستثناءات، مع أنّ مستوى الاستثناء 0 (EL0) هو الأقل امتيازًا، ومستوى الاستثناء 3 (EL3) هو الأعلى امتيازًا. يتم تنفيذ الجزء الأكبر من قاعدة رموز Android البرمجية (جميع مكونات مساحة المستخدم) باستخدام EL0. أما بقية ما يُعرف عادةً باسم "Android"، فهو نواة Linux التي تعمل في EL1.
تسمح طبقة EL2 بإدخال جهاز افتراضي يوفّر إمكانية عزل الذاكرة والأجهزة في أجهزة افتراضية فردية في EL1/EL0، مع ضمانات قوية لسرية البيانات وسلامتها.
برنامج Hypervisor (مراقب الأجهزة الظاهرية)
تم إنشاء الجهاز الافتراضي المحمي المستند إلى النواة (pKVM) استنادًا إلى نظام إدارة المحتوى الافتراضي Linux KVM، الذي تم توسيعه ليشمل إمكانية تقييد الوصول إلى الحمولات التي تعمل في الأجهزة الافتراضية للضيوف التي تم وضع علامة "محمية" عليها عند الإنشاء.
يتوافق KVM/arm64 مع أوضاع تنفيذ مختلفة بناءً على مدى توفُّر بعض ميزات وحدة المعالجة المركزية (CPU)،
مثل إضافات مضيف المحاكاة الافتراضية (VHE) (ARMv8.1
والإصدارات الأحدث). في أحد هذه الأوضاع، المعروفة بشكل شائع باسم وضع عدم استخدام تقنية VHE، يتم تقسيم رمز الهايبر visor من صورة النواة أثناء عملية التمهيد وتثبيته في EL2، في حين يتم تشغيل النواة نفسها في EL1. على الرغم من أنّ مكوّن EL2 في KVM هو جزء من قاعدة بيانات برمجية لنظام التشغيل Linux، إلا أنّه مكوّن صغير مسؤول عن التبديل بين عدة مكوّنات EL1. يتم تجميع مكوّن المشرف الظاهري باستخدام
نظام التشغيل Linux، ولكنه يقيم في قسم ذاكرة منفصل ومخصّص من vmlinux
الصورة. يستفيد pKVM من هذا التصميم من خلال توسيع رمز المشرف الظاهري باستخدام
ميزات جديدة تسمح له بفرض قيود على نواة مضيف Android ومساحة
المستخدم، وتقييد وصول المضيف إلى ذاكرة الضيف والمشرف الظاهري.
وحدات مورّدي وحدات التحكّم عن بُعد في وحدات التحكّم في طاقة الفيديو (pKVM)
وحدة المورّد الخاصة ببرنامج pKVM هي وحدة خاصة بالأجهزة تحتوي على وظائف متعلقة بالجهاز، مثل برامج تشغيل وحدة إدارة الذاكرة الخاصة بعمليات الإدخال والإخراج (IOMMU). تتيح لك هذه الوحدات نقل ميزات الأمان التي تتطلّب مستوى استثنائيًا 2 (EL2) من الوصول إلى أجهزة pKVM.
للتعرّف على طريقة تطبيق وحدة مورّد pKVM وتحميلها، يمكنك الاطّلاع على مقالة تطبيق وحدة مورّد pKVM.
إجراءات التشغيل
ويوضّح الشكل التالي إجراء تمهيد pKVM:
- يدخل برنامج الإقلاع إلى النواة العامة في EL2.
- وترصد النواة العامة أنّ الجهاز يعمل في EL2 ويحرم تشغيله من EL1، في حين يستمر تشغيل pKVM ووحداته في EL2. بالإضافة إلى ذلك، يتم تحميل وحدات مورّدي pKVM في الوقت الحالي.
- تستمر النواة العامة في بدء التشغيل بشكل طبيعي، حيث تحمِّل جميع برامج تشغيل الأجهزة اللازمة إلى أن تصل إلى مساحة المستخدم. في هذه المرحلة، يكون pKVM في مكانه ويتعامل مع جداول صفحات المرحلة الثانية.
تثق عملية التمهيد في برنامج الإقلاع للحفاظ على سلامة ملف رمز التمهيد النواة فقط أثناء مرحلة التمهيد المبكّر. عندما يتم حرمان النواة kernel، لا يعتبرها برنامج Hypervisor (مراقب الأجهزة الظاهرية) موثوقًا به، وبالتالي يكون مسؤولاً عن حماية نفسه حتى إذا تعرضت النواة للخطر.
يتيح توفُّر نواة Android وبرنامج التشغيل الظاهري في الصورة الثنائية نفسها إنشاء واجهة تواصل مرتبطة ببعضها بشكلٍ وثيق. يضمن هذا الربط الوثيق تعديلات أساسية للعنصرَين، ما يتجنّب الحاجة إلى الحفاظ على ثبات الواجهة بينهما، ويوفّر قدرًا كبيرًا من المرونة بدون التأثير في إمكانية الصيانة على المدى الطويل. كما يتيح الإقران المحدود تحسينات الأداء عندما يمكن لكلا المكونين التعاون دون التأثير على ضمانات الأمان التي يوفرها برنامج Hypervisor (مراقب الأجهزة الظاهرية).
علاوة على ذلك، يتيح استخدام GKI في منظومة Android المتكاملة تلقائيًا نشر برنامج pKVM Hypervisor (مراقب الأجهزة الظاهرية) الخاص بـ pKVM على أجهزة Android بالبرنامج الثنائي نفسه مثل النواة.
حماية الوصول إلى ذاكرة وحدة المعالجة المركزية (CPU)
تحدد بنية Arm وحدة إدارة الذاكرة (MMU) مقسمة إلى مرحلتين مستقلتين، يمكن استخدام كلتيهما لتنفيذ ترجمة العنوان والتحكم في الوصول إلى أجزاء مختلفة من الذاكرة. يتم التحكم في المرحلة الأولى MMU بواسطة EL1 وتسمح بالمستوى الأول من ترجمة العناوين. يستخدم نظام التشغيل Linux وحدة إدارة الذاكرة (MMU) في المرحلة 1 بهدف إدارة مساحة العنوان الافتراضي المقدَّمة لكل عملية في مساحة المستخدمين ومساحة العنوان الافتراضي الخاصة بها.
تتحكّم وحدة التحكّم في الذاكرة (MMU) من المرحلة 2 في وحدة التحكّم في الطاقة من المستوى 2 (EL2) وتتيح تطبيق ترجمة عنوان ثانية على عنوان الإخراج لوحدة التحكّم في الذاكرة من المرحلة 1، ما يؤدي إلى الحصول على عنوان مادي (PA). يمكن لأنظمة التشغيل الافتراضية استخدام الترجمة في المرحلة 2 للتحكّم في عمليات الوصول إلى الذاكرة وترجمتها من جميع الأجهزة الافتراضية للضيف. كما هو موضّح في الشكل 2، عند تفعيل كلتا مرحلتَي الترجمة، يُطلق على عنوان الإخراج في المرحلة 1 اسم عنوان جغرافي وسيط (IPA). ملاحظة: تتم ترجمة العنوان الافتراضي (VA) إلى عنوان جغرافي وسيط ثم إلى عنوان جغرافي.
في السابق، كان يتم تشغيل KVM مع تفعيل الترجمة في المرحلة 2 أثناء تشغيل الأجهزة الضيف وإيقاف المرحلة 2 أثناء تشغيل نواة Linux المضيف. تسمح هذه البنية بالوصول إلى الذاكرة من وحدة إدارة الذاكرة (MMU) للمضيف في المرحلة 1 للمرور منعدمة وحدة إدارة الذاكرة (MMU) للمضيف في المرحلة 2، ما يسمح بالوصول غير المحدود من المضيف إلى صفحات ذاكرة العميل. ومن ناحية أخرى، يتيح pKVM حماية المرحلة الثانية حتى في سياق المضيف، ويضع برنامج Hypervisor (مراقب الأجهزة الظاهرية) مسؤولاً عن حماية صفحات ذاكرة الضيوف بدلاً من المضيف.
تستفيد KVM بشكل كامل من ترجمة العناوين في المرحلة الثانية لتنفيذ تعيينات IPA/PA المعقدة للضيوف، مما يخلق وهمًا بوجود ذاكرة متجاورة لدى الضيوف على الرغم من التجزئة المادية. ومع ذلك، يقتصر استخدام وحدة التحكّم في الذاكرة من المرحلة 2 في المضيف على التحكّم في الوصول فقط. يتم ربط مرحلة المضيف 2 بالمعرّف، ما يضمن أن تكون الذاكرة المتجاوبة في مساحة IPA للمضيف متجاوبة في مساحة PA. تسمح هذه البنية باستخدام عناوين ترجمة كبيرة في جدول الصفحات، وبالتالي تقليل الضغط على ذاكرة التخزين المؤقت لترجمة عنوان الذاكرة (TLB). وبما أنّه يمكن أن يفهرس "التحليل الوصفي للصفحات" عملية ربط الهوية، يتم استخدام مرحلة المضيف 2 أيضًا لتتبُّع ملكية الصفحة مباشرةً في جدول الصفحات.
حماية الوصول المباشر إلى الذاكرة (DMA)
كما هو موضّح سابقًا، فإنّ إلغاء ربط صفحات الضيف من مضيف Linux في جداول صفحات وحدة المعالجة المركزية (CPU) هو خطوة ضرورية ولكنها غير كافية لحماية ذاكرة الضيف. يجب أن تحمي أداة pKVM أيضًا من عمليات الوصول إلى الذاكرة التي تجريها الأجهزة المزوّدة بإمكانية بدء طلبات ازدحام الذاكرة (DMA) تحت سيطرة نواة المضيف، وإمكانية بدء هجوم ازدحام ذاكرة من مضيف ضار. لمنع هذا الجهاز من الوصول إلى ذاكرة الضيف، تتطلّب تقنية pKVM توفُّر وحدة إدارة ذاكرة الإدخال/الإخراج (IOMMU) لكل جهاز مزوّد بإمكانية الوصول المباشر إلى الذاكرة في النظام، كما هو موضّح في الشكل 3.
على الأقل، توفّر أجهزة وحدة إدارة الذاكرة I/O وسائل منح وإسقاط إذن الوصول للقراءة/الكتابة لجهاز إلى الذاكرة الفعلية بدقة الصفحة. ومع ذلك، يحدّ هذا الجهاز من استخدام الأجهزة في الأجهزة الافتراضية المخصّصة للبرامج (pVM) لأنّه يفترض أنّه مرحلة 2 تمّ ربطها بالتعرّف.
لضمان العزل بين الأجهزة الافتراضية، يجب أن يميز IOMMU بين معاملات الذاكرة التي يتم إنشاؤها نيابةً عن كيانات مختلفة حتى يمكن استخدام المجموعة المناسبة من جداول الصفحات للترجمة.
بالإضافة إلى ذلك، يُعدّ تقليل مقدار الرمز البرمجي الخاص بوحدة المعالجة المركزية (SoC) في EL2 استراتيجية رئيسية لتقليل قاعدة الحوسبة الموثوق بها (TCB) الإجمالية لبرنامج pKVM، ويخالف تضمين برامج تشغيل وحدة إدارة الذاكرة (IOMMU) في برنامج التشغيل الآلي. للتخفيف من هذه المشكلة، يتحمّل المضيف في EL1 مسؤولية مهام إدارة IOMMU المساعدة، مثل إدارة الطاقة وبدء التشغيل ومعالجة المقاطعات عند الاقتضاء.
ومع ذلك، فإنّ منح المضيف التحكّم في حالة الجهاز يفرض متطلبات إضافية على واجهة البرمجة لأجهزة IOMMU لضمان عدم إمكانية تجاوز عمليات التحقّق من الأذونات بوسائل أخرى، على سبيل المثال، بعد إعادة ضبط الجهاز.
إنّ بنية وحدة إدارة ذاكرة النظام (SMMU) في Arm هي وحدة إدارة I/O المعيارية والمتوافقة بشكل جيد مع أجهزة Arm التي تتيح كلاً من العزل والتخصيص المباشر. وتعدّ هذه البنية هي الحلّ المرجعي المقترَح.
ملكية الذاكرة
عند بدء التشغيل، يُفترض أنّ جميع الذاكرة غير المخصّصة لنظام التشغيل الافتراضي هي ملك للمضيف، ويرصدها نظام التشغيل الافتراضي على هذا النحو. عند إنشاء جهاز افتراضي شخصي، يقدّم المضيف صفحات ذاكرة للسماح ببدء تشغيله وينقل المشرف الظاهري ملكية هذه الصفحات من المضيف إلى الجهاز الافتراضي الشخصي. وبالتالي، يفرض نظام التشغيل الظاهري قيود التحكّم في الوصول في جدول صفحات المرحلة 2 للمضيف لمنع الوصول إلى الصفحات مرة أخرى، ما يضمن السرية للضيف.
يمكن التواصل بين المضيف والضيوف من خلال مشاركة ذاكرة تتم التحكّم فيها بينهم. يُسمح للضيوف بمشاركة بعض صفحاتهم مع المضيف باستخدام طلب hypercall الذي يوجّه نظام التشغيل الظاهري إلى إعادة ربط هذه الصفحات في جدول صفحات المرحلة 2 للمضيف. وبالمثل، يمكن التواصل بين المضيف وTrustZone من خلال عمليات مشاركة الذاكرة و/أو إقراضها، ويتم تتبُّع جميع هذه العمليات عن كثب والتحكّم فيها من خلال pKVM باستخدام مواصفات إطار عمل البرامج الثابتة لمعالجات Arm (FF-A).
وبما أنّ متطلبات ذاكرة الأجهزة الافتراضية قد تتغير بمرور الوقت، يتم توفير اتصال فائق يسمح باستعادة ملكية صفحات محددة تابعة للمتصل إلى المضيف. في الممارسة العملية، يتم استخدام هذا الطلب الفائق مع بروتوكول virtio balloon للسماح لـ VMM بطلب الذاكرة مجددًا من pVM، وللسماح لـ pVM بإعلام VMM بالصفحات التي تم التخلي عنها، بطريقة خاضعة للرقابة.
يتحمّل نظام التشغيل الظاهري مسؤولية تتبُّع ملكية جميع صفحات الذاكرة في النظام وما إذا كانت تتم مشاركتها أو إقراضها إلى كيانات أخرى. يتم معظم تتبُّع هذه الحالة باستخدام البيانات الوصفية المرفقة بجداول صفحات الطور 2 الخاصة بالمضيف والضيوف، وذلك باستخدام الوحدات المحجوزة في إدخالات جدول الصفحات (PTEs) والتي، كما يوحي اسمها، تكون محجوزة لاستخدام البرامج.
على المضيف التأكّد من عدم محاولة الوصول إلى الصفحات التي تم حظر الوصول إليها من خلال نظام التشغيل الافتراضي. يؤدي الوصول غير القانوني إلى المضيف إلى إدخال استثناء برمجي تزامني في المضيف من خلال برنامج إدارة الأجهزة الافتراضية، ما قد يؤدي بدوره إلى تلقّي مهمة مساحة المستخدم المسؤولة إشارة SEGV أو تعطُّل ملف تعريف التمهيد لنظام التشغيل (kernel) في المضيف. لمنع عمليات الوصول غير المقصودة، تجعل نواة المضيف الصفحات الممنوحة للضيوف غير مؤهَّلة للتبديل أو الدمج.
معالجة المقاطعات والموقّتات
إنّ عمليات المقاطعة هي جزء أساسي من طريقة تفاعل الضيف مع الأجهزة ولعملية التواصل بين وحدات المعالجة المركزية، حيث تكون عمليات المقاطعة بين المعالجات (IPIs) هي آلية التواصل الرئيسية. ويتمثل نموذج KVM في تفويض جميع عمليات إدارة المقاطعات الافتراضية إلى المضيف في EL1، والذي يعمل لهذا الغرض كجزء من برنامج Hypervisor (مراقب الأجهزة الظاهرية).
توفّر pKVM محاكاة كاملة للإصدار 3 من وحدة التحكّم في المقاطعات العامة (GICv3) استنادًا إلى رمز KVM الحالي. تتم معالجة الموقّت وأرقام تعريف الأجهزة المتسلسلة (IPI) كجزء من رمز المحاكاة غير الموثوق به هذا.
إتاحة GICv3
يجب أن تضمن الواجهة بين EL1 وEL2 أن تكون حالة المقاطعة الكاملة مرئية لمضيف EL1، بما في ذلك نُسخ من سجلات برنامج التشغيل الظاهري ذات الصلة بالمقاطعات. ويتم عادةً تحقيق هذه الرؤية باستخدام مناطق مشاركة الذاكرة، واحدة لكل وحدة معالجة مركزية افتراضية (vCPU).
يمكن تبسيط رمز دعم وقت تشغيل سجلّ النظام للتوافق فقط مع تسجيل المقاطعات التي يتم إنشاؤها للبرامج (SGIR) وإيقاف "إيقاف سجل المقاطعة" (DIR). تفرض البنية أن يتم دائمًا معالجة أخطاء المعالجة في هذه السجلات من خلال EL2، في حين أنّ الأخطاء الأخرى لم تكن مفيدة حتى الآن سوى لتخفيف الأخطاء المطبعية. ويتم التعامل مع جميع الإجراءات الأخرى في الأجهزة.
من جهة MMIO، يتم محاكاة كل شيء في EL1، مع إعادة استخدام كل البنية الأساسية الحالية في KVM. أخيرًا، يتم دائمًا إعادة توجيه الانتظار إلى أن يتمّ المقاطعة (WFI) إلى EL1، لأنّ هذا هو أحد الإجراءات الأساسية لتحديد المهام التي تستخدمها KVM.
إتاحة الموقّت
يجب عرض قيمة المقارن للموقّت الافتراضي على EL1 في كل عملية توقّف WFI حتى يتمكّن EL1 من إدخال عمليات مقاطعة الموقّت أثناء حظر وحدة المعالجة المركزية الافتراضية. يتم محاكاة الموقّت المادي بالكامل، ويتم إعادة توجيه جميع الفخاخ إلى EL1.
معالجة MMIO
للتواصل مع مراقب الجهاز الافتراضي (VMM) وتنفيذ محاكاة GIC، يجب إعادة توجيه فخاخ MMIO إلى المضيف في EL1 لإجراء المزيد من عمليات تحديد الأولويات. تتطلّب تقنية pKVM ما يلي:
- عنوان IP وحجم إذن الوصول
- البيانات في حال الكتابة
- ترتيب البتات في وحدة المعالجة المركزية عند نقطة الالتقاط
بالإضافة إلى ذلك، يتم إعادة توجيه الفخاخ التي تحتوي على سجلّ غرض عام (GPR) كأحد المصدر أو الوجهة باستخدام سجلّ زائف لنقل البيانات المجردة.
واجهات الضيوف
يمكن للضيف التواصل مع ضيف محمي باستخدام مجموعة من المكالمات الفائقة وإمكانية الوصول إلى الذاكرة في المناطق المحاصرة. يتم عرض المكالمات الفائقة وفقًا لمعيار SMCCC، مع نطاق محجوز لتحديد المورّد من خلال KVM. إنّ المكالمات الفائقة التالية مهمة بشكلٍ خاص للضيوف في تقنية pKVM.
المكالمات الفائقة العامة
- توفّر واجهة PSCI آلية قياسية للضيف للتحكّم في دورة حياة معالجاته الافتراضية، بما في ذلك تفعيلها وإيقافها وإيقاف النظام.
- توفّر ميزة TRNG آلية قياسية للضيف لطلب كمية من العشوائية من pKVM الذي يعيد توجيه الطلب إلى EL3. وهذه الآلية مفيدة بشكل خاص في الحالات التي لا يمكن فيها الوثوق بالمضيف لإنشاء ظاهري لمنشئ الأرقام العشوائية (RNG).
مكالمات pKVM الفائقة
- مشاركة الذكرى مع المضيف لا يمكن للجهاز المضيف في البداية الوصول إلى كل ذاكرة الضيف، ولكنّ الوصول إلى الضيف ضروري للتواصل عبر الذاكرة المشتركة وللأجهزة التي تستخدم تقنية المحاكاة الافتراضية الجزئية والتي تعتمد على ذاكرة التخزين المؤقت المشتركة. تتيح المكالمات الفائقة لمشاركة الصفحات وإلغاء مشاركتها مع المضيف للضيف تحديد أجزاء الذاكرة التي يمكن للأجهزة الأخرى الوصول إليها على Android بدون الحاجة إلى إجراء عملية مصافحة.
- التنازل عن الذاكرة للمضيف عادةً ما تكون جميع ذاكرة الضيف ملكًا
للضيف إلى أن يتم إتلافها. قد لا تكون هذه الحالة مناسبة لأجهزة الكمبيوتر الافتراضية التي تعمل لفترة طويلة والتي تتطلّب ذاكرة بكميات تختلف بمرور الوقت. تسمح المكالمة الفائقة
relinquish
للضيف بنقل ملكية الصفحات بشكل صريح إلى المضيف بدون الحاجة إلى إنهاء الضيف. - اعتراض الوصول إلى الذاكرة من المضيف بشكل تقليدي، إذا وصل ضيف KVM إلى عنوان لا يتوافق مع منطقة ذاكرة صالحة، فإن سلسلة وحدة المعالجة المركزية الافتراضية يتم الخروج من وحدة المعالجة المركزية الافتراضية إلى المضيف ويتم عادة استخدام الوصول لاستخدام تقنية MMIO و محاكاتها عن طريق VMM في مساحة المستخدم. لتسهيل عملية المعالجة هذه، يجب على pKVM الإعلان عن تفاصيل التعليمات المتعلقة بالخطأ، مثل العنوان وتسجيل المعلمات ومن المحتمل أن تعيد المحتوى إلى المضيف، ما قد يؤدي بدون قصد إلى الكشف عن بيانات حساسة من ضيف محمي إذا لم يكن جهاز pKVM متوقَّعًا. ويحلّ pKVM هذه المشكلة من خلال التعامل مع هذه الأخطاء باعتبارها أخطاء قاتلة، ما لم يصرِّح الضيف مسبقًا أنّ الجهاز المضيف يتخطى إمكانية الوصول إلى بروتوكول IPA. يُشار إلى هذا الحلّ باسم حاجز MMIO.
جهاز I/O افتراضي (virtio)
Virtio هو معيار مشهور ومحمول ونضج لتطبيق الأجهزة الشبه الافتراضية والتفاعل معها. يتم تنفيذ معظم الأجهزة التي تم ربطها بالضيوف المحميين باستخدام virtio. تستند Virtio أيضًا إلى تنفيذ vsock المستخدَم للتواصل بين نظام التشغيل الضيف المحمي وبقية نظام التشغيل Android.
يتم عادةً تنفيذ أجهزة Virtio في مساحة المستخدم على المضيف من خلال VMM، الذي يعترض عمليات الوصول العالقة إلى الذاكرة من الضيف إلى واجهة MMIO لجهاز virtio ويحاكي السلوك المتوقع. إنّ الوصول إلى MMIO مكلف نسبيًا لأنّ كل عملية وصول إلى الجهاز تتطلّب رحلة ذهابًا وإيابًا إلى وحدة التحكّم في الأجهزة الافتراضية والعكس، لذا يحدث معظم نقل البيانات الفعلي بين الجهاز والضيف باستخدام مجموعة من قوائم الانتظار الافتراضية في الذاكرة. الافتراض الرئيسي لـ virtio هو أن المضيف يمكنه الوصول إلى ذاكرة الضيف بشكل عشوائي. يتجلى هذا الافتراض في تصميم قائمة الانتظار، والتي قد تحتوي على مؤشرات إلى الموارد الاحتياطية لدى الضيف بأن محاكاة الجهاز تهدف إلى الوصول مباشرةً.
على الرغم من أنّه يمكن استخدام طلبات البيانات الفائقة لمشاركة الذاكرة الموضّحة سابقًا لمشاركة ملفّات تخزين مؤقتة لبيانات virtio من الجهاز الضيف إلى الجهاز المضيف، يتم تنفيذ هذه المشاركة بالضرورة بدقة الصفحة وقد تؤدي إلى عرض المزيد من البيانات مما هو مطلوب إذا كان حجم ملف التخزين المؤقت أقل من حجم الصفحة. بدلاً من ذلك، يتم ضبط الضيف لتحديد كل من قوائم الانتظار الافتراضية ومصادر ذاكرة التخزين المؤقت للبيانات المقابلة لها من نافذة ثابتة للذاكرة المشتركة، مع نسخ البيانات (الارتداد) من النافذة وإليها حسب الحاجة.
التفاعل مع TrustZone
على الرغم من أنّ الضيوف لا يمكنهم التفاعل مباشرةً مع TrustZone، يجب أن يظل بإمكان المضيف إصدار طلبات SMC في العالم الآمن. يمكن لهذه الاتصالات تحديد مخازن الذاكرة المؤقتة التي لا يمكن للمضيف الوصول إليها. ولأنّ البرامج الآمنة لا تكون على دراية بشكل عام بإمكانية الوصول إلى المخزن المؤقت، يمكن لأحد المضيفين الضارّين استخدام هذا المخزن المؤقت لتنفيذ هجوم وكيل مشوش (يشبه هجوم DMA). لمنع مثل هذه الهجمات، تصطاد وحدة pKVM جميع طلبات SMC المضيفة إلى EL2 وتعمل كوكيل بين المضيف والشاشة الآمنة في EL3.
تتم إعادة توجيه طلبات PSCI الواردة من المضيف إلى البرامج الثابتة EL3 مع إجراء أقل قدر من التعديلات. على وجه التحديد، تتم إعادة كتابة نقطة دخول وحدة المعالجة المركزية التي يتم توصيلها بالإنترنت أو تتم استعادتها من حالة التعليق لكي يتم تركيب جدول صفحات المرحلة 2 في EL2 قبل العودة إلى المضيف في EL1. أثناء عملية التشغيل، يتم فرض الحماية هذه بواسطة pKVM.
تعتمد هذه البنية على شريحة المعالجة المركزية (SoC) المتوافقة مع PSCI، ويُفضَّل استخدام TF-A مثبَّتًا كبرنامج ثابت لوحدة EL3.
يعمل إطار عمل البرامج الثابتة لمعالجات Arm (FF-A) على توحيد التفاعلات بين العالمَين العادي والآمن، لا سيما في حال توفُّر نظام تشغيل افتراضي آمن. يحدِّد جزء كبير من المواصفات آلية لمشاركة الذاكرة مع الجانب الآمن، باستخدام تنسيق رسالة شائع ونموذج أذونات محدَّد جيدًا للصفحات الأساسية. يعمل pKVM كوسيط لرسائل FF-A لضمان عدم محاولة المضيف مشاركة الذاكرة مع الجانب الآمن الذي ليس لديه سوى أذونات غير كافية.
تعتمد هذه البنية على تطبيق "الوضع الآمن" الذي يفرض نموذج الوصول إلى الذاكرة، لضمان أنّ التطبيقات الموثوق بها وأي برامج أخرى تعمل في "الوضع الآمن" لا يمكنها الوصول إلى الذاكرة إلا إذا كانت مملوكة حصريًا من قِبل "الوضع الآمن" أو تمت مشاركتها معه صراحةً باستخدام FF-A. في النظام الذي يتضمّن S-EL2، يجب أن يتم فرض نموذج الوصول إلى الذاكرة من خلال "وحدة إدارة الأقسام الآمنة" (SPMC)، مثل Hafnium، التي تحافظ على جداول صفحات المرحلة 2 للعالم الآمن. في النظام الذي لا يتضمّن S-EL2، يمكن لوحدة TEE فرض نموذج وصول إلى الذاكرة من خلال جداول صفحات مرحلة 1.
إذا لم تكن مكالمة SMC إلى EL2 هي مكالمة PSCI أو رسالة محدّدة في FF-A، تتم إعادة توجيه طلبات SMC التي لم تتم معالجتها إلى EL3. ويُفترض أنّ البرامج الثابتة الآمنة (الموثوقة بالضرورة) يمكنها التعامل مع وحدات SMC غير المُدارة بأمان لأنّ البرامج الثابتة تفهم الاحتياطات اللازمة للحفاظ على عزل pVM.
أداة مراقبة الآلة الافتراضية
crosvm هو برنامج مراقبة للأجهزة الافتراضية (VMM) يعمل على تشغيل الأجهزة الافتراضية من خلال واجهة KVM في Linux. ما يميّز crosvm هو تركيزه على الأمان باستخدام لغة البرمجة Rust ووضع حماية حول الأجهزة الافتراضية لحماية نواة المضيف. لمزيد من المعلومات عن crosvm، يمكنك الاطّلاع على المستندات الرسمية هنا.
أوصاف الملفات وioctls
تُعرِض KVM جهاز الخطوط /dev/kvm
لمساحة المستخدم باستخدام ioctls التي تشكّل
واجهة برمجة التطبيقات KVM. تنتمي طلبات ioctl إلى الفئات التالية:
- تطلب ioctls النظام وتعيِّن السمات العامة التي تؤثر في النظام الفرعي KVM بالكامل، وتنشئ أجهزة pVM.
- تُستخدَم طلبات ioctl الخاصة بالأجهزة الافتراضية لطلب السمات التي تنشئ وحدات المعالجة المركزية الافتراضية (vCPU) و الأجهزة، وتؤثر في جهاز افتراضي بالكامل، مثل تضمين تنسيق الذاكرة و عدد وحدات المعالجة المركزية الافتراضية (vCPU) والأجهزة.
- تُستخدَم طلبات ioctl الخاصة بوحدة المعالجة المركزية الافتراضية (vCPU) لطلب السمات التي تتحكّم في تشغيل وحدة معالجة مركزية افتراضية واحدة وضبطها.
- تُستخدَم طلبات ioctls للأجهزة من أجل طلب السمات التي تتحكّم في تشغيل جهاز افتراضي واحد وضبطها.
تعمل كل عملية crosvm على تشغيل مثيل واحد بالضبط من جهاز افتراضي. تستخدِم هذه العملية ioctl لنظام KVM_CREATE_VM
لإنشاء وصف ملف لوحدة تحكّم افتراضية يمكن
استخدامه لإصدار ioctls لوحدة تحكّم افتراضية. تؤدي ioctl KVM_CREATE_VCPU
أو KVM_CREATE_DEVICE
على FD لوحدة افتراضية إلى إنشاء وحدة معالجة مركزية افتراضية أو جهاز افتراضي وعرض وصف ملف يشير إلى
المورد الجديد. يمكن استخدام ioctls على وحدة معالجة مركزية افتراضية أو FD للجهاز للتحكّم في الجهاز
الذي تم إنشاؤه باستخدام ioctl على FD لوحدة افتراضية. بالنسبة إلى وحدات المعالجة المركزية الافتراضية، يشمل ذلك مهمة مهمة وهي تنفيذ رمز الضيف.
في الداخل، يسجِّل crosvm أوصاف ملفات الجهاز الافتراضي مع النواة باستخدام
واجهة epoll
التي يتم تنشيطها عند تغيُّر إشارة. بعد ذلك، تُرسِل النواة إشعارًا إلى crosvm في حال
توفّر حدث جديد في انتظار المعالجة في أيّ من أوصاف الملفات.
تضيف تقنية pKVM ميزة جديدة، وهي KVM_CAP_ARM_PROTECTED_VM
، والتي يمكن استخدامها للحصول على معلومات عن بيئة pVM وإعداد الوضع المحمي للجهاز الظاهري. ويستخدم crosvm هذه الميزة أثناء إنشاء pVM في حال تم تمرير العلامة --protected-vm
، وذلك للبحث عن المساحة المناسبة من الذاكرة لحجزها واستخدامها في البرامج الثابتة لـ pVM، ثم تفعيل الوضع المحمي.
تخصيص الذاكرة
تتمثل إحدى المسؤوليات الرئيسية لمحاكي إدارة الذاكرة في تخصيص ذاكرة الجهاز الظاهري و إدارة تنسيق الذاكرة. تنشئ أداة crosvm تنسيق ذاكرة ثابتًا موضّحًا بشكل فضفاض في الجدول أدناه.
FDT في الوضع العادي | PHYS_MEMORY_END - 0x200000
|
إخلاء مساحة | ...
|
رامديسك | ALIGN_UP(KERNEL_END, 0x1000000)
|
Kernel | 0x80080000
|
برنامج الإقلاع | 0x80200000
|
ملف FDT في وضع BIOS | 0x80000000
|
قاعدة الذاكرة الفعلية | 0x80000000
|
البرامج الثابتة لنظام التشغيل pVM | 0x7FE00000
|
ذاكرة الجهاز | 0x10000 - 0x40000000
|
يتم تخصيص الذاكرة الفعلية باستخدام mmap
ويتم منح الذاكرة للآلة الافتراضية ل заполнения مناطق الذاكرة، التي تُعرف باسم memslots، باستخدام KVM_SET_USER_MEMORY_REGION
ioctl. وبالتالي، يتم تحديد كل ذاكرة pVM للضيف
على أنها مثيل crosvm الذي يديرها، ويمكن أن يؤدي ذلك إلى
إيقاف العملية (إنهاء الجهاز الظاهري) إذا بدأ المضيف في استخدام
الذاكرة الفارغة. عند إيقاف جهاز افتراضي (VM)، يتم محو الذاكرة تلقائيًا من خلال برنامج Hypervisor (مراقب الأجهزة الظاهرية) وتتم إعادتها إلى نواة المضيف.
ضمن KVM العادي، يحتفظ VMM بإمكانية الوصول إلى ذاكرة جميع الضيوف. باستخدام pKVM، تتم إزالة ربط ذاكرة الضيف من مساحة العناوين الفيزيائية للمضيف عند منحها للضيف. الاستثناء الوحيد هو الذاكرة التي شاركها الضيف بصراحة، مثل أجهزة virtio.
لا يتمّ ربط مناطق MMIO في مساحة عناوين الضيف. يتم حظر وصول الضيف إلى هذه المناطق، ما يؤدي إلى حدوث حدث I/O في FD لوحدة VM. تُستخدَم هذه المحاولة لتطبيق الأجهزة الافتراضية. في الوضع المحمي، يجب أن يقرّ الضيف باستخدام منطقة من مساحة العناوين الخاصة به لواجهة MMIO باستخدام طلب فائقة، وذلك للحد من خطر تسرُّب المعلومات عن طريق الخطأ.
الجدولة
يتم تمثيل كل وحدة معالجة مركزية افتراضية بخيط POSIX ويحدِّد جدولة مهامها جدولة Linux المضيف. يُطلِق الخيط دالة KVM_RUN
ioctl على FD لوحدة المعالجة المركزية الافتراضية، ما يؤدي
إلى تبديل نظام التشغيل الظاهري إلى سياق وحدة المعالجة المركزية الافتراضية للضيف. تحتسب أداة جدولة المضيف الوقت المستغرَق في سياق الضيف باعتباره الوقت الذي تستخدمه سلسلة عمليات وحدة المعالجة المركزية الافتراضية المقابلة. يعرض KVM_RUN
عندما يكون هناك حدث يجب معالجته بواسطة VMM، مثل I/O أو نهاية المقاطعة أو إيقاف وحدة المعالجة المركزية الافتراضية. يعالج مدير الخدمات الافتراضية
الحدث ويتصل بـ KVM_RUN
مرة أخرى.
خلال فترة KVM_RUN
، تظل سلسلة المحادثات استباقية من خلال أداة جدولة المضيف، باستثناء تنفيذ رمز برنامج Hypervisor (مراقب EL2)، وهو إجراء غير استباقي. لا تتضمّن مثيل VM الضيف آلية للتحكّم في هذا السلوك.
وبما أنّه يتم جدولة جميع مؤشرات تسلسل وحدة المعالجة المركزية الافتراضية مثل أي مهام أخرى في مساحة المستخدم، فإنّها تخضع لجميع آليات جودة الخدمة العادية. على وجه التحديد، يمكن تحسين كلّ سلسلة مهام وحدة المعالجة المركزية الافتراضية لتناسب وحدات المعالجة المركزية الفعلية، ووضعها في مجموعات وحدات المعالجة المركزية، وتعزيزها أو وضع حدّ أقصى لها باستخدام تقييد الاستخدام، وتغيير أولويتها/سياستها المتعلقة بالجدولة، وغير ذلك.
الأجهزة الافتراضية
يتوافق crosvm مع عدد من الأجهزة، بما في ذلك ما يلي:
- virtio-blk لصور الأقراص المركبة، للقراءة فقط أو للقراءة والكتابة
- vhost-vsock للتواصل مع المضيف
- virtio-pci كنقل virtio
- ساعة الوقت الفعلي pl030
- واجهة 16550a UART للاتصال التسلسلي
البرامج الثابتة لنظام التشغيل pVM
تجدر الإشارة إلى أنّ برامج pvm الثابتة (pvmfw) هي أول رمز يتم تنفيذه بواسطة جهاز افتراضي (pVM)، وهو يشبه ذاكرة التخزين المؤقت للتشغيل على جهاز فعلي. ويتمثّل الهدف الأساسي من pvmfw في بدء التشغيل الآمن واستخلاص السر الفريد للجهاز في الوقت الفعلي (pvmfw).
يتم تخزين البرنامج الثنائي pvmfw في قسم فلاش يحمل الاسم نفسه ويتم تعديله باستخدام عبر الهواء.
تشغيل الجهاز
تتم إضافة تسلسل الخطوات التالي إلى عملية تشغيل جهاز مزوّد بتقنية pKVM:
- يحمّل برنامج تحميل Android (ABL) pvmfw من القسم إلى الذاكرة ويتحقق من الصورة.
- تحصل ABL على أسرار محرك تركيب معرّفات الأجهزة (DICE) (معرّفات الأجهزة المركبة (CDI) وسلسلة شهادات DICE) من قاعدة أساسية للثقة.
- تستخرج أداة ABL وحدات CDI اللازمة لـ pvmfw، وتُلحقها بالملف الثنائي pvmfw.
- تُضيف أداة ABL عقدة
linux,pkvm-guest-firmware-memory
منطقة ذاكرة محجوزة إلى DT، وتوضّح الموقع الجغرافي وحجم الملف الثنائي pvmfw والملف العميق الذي تم الحصول عليه في الخطوة السابقة. - ينقل ABL التحكّم إلى Linux، ويبدأ Linux عملية إعداد pKVM.
- تُلغي أداة pKVM ربط منطقة ذاكرة pvmfw من جداول الصفحات في المرحلة 2 للمضيف، ويحميها من المضيف (والأجهزة الضيف) طوال وقت تشغيل الجهاز.
بعد تشغيل الجهاز، يتم تشغيل Microdroid وفقًا للخطوات الواردة في قسم تسلسل التشغيل من مستند Microdroid.
تشغيل جهاز افتراضي (PVM)
عند إنشاء جهاز افتراضي شخصي، يجب أن ينشئ crosvm (أو برنامج إدارة آلات افتراضية آخر) مساحة ذاكرة كبيرة بما يكفي لتتم تعبئتها بتطبيق pvmfw من خلال برنامج إدارة الأجهزة الافتراضية. يتم أيضًا حصر وحدة إدارة الخدمات الافتراضية في قائمة السجلات التي يمكنها ضبط قيمتها الأولية (x0-x14 لوحدة المعالجة المركزية الافتراضية الأساسية، ولا يمكن ضبط أي قيمة لوحدات المعالجة المركزية الافتراضية الثانوية). يتم حجز السجلات المتبقية وهي جزء من Hypervisor-pvmfw ABI.
عند تشغيل آلة افتراضية خفيفة، ينقل المضيف الظاهري أولاً التحكّم في وحدة المعالجة المركزية الافتراضية الأساسية
إلى pvmfw. يتوقّع البرنامج الثابت أن يكون crosvm قد حمّل نواة موقَّعة بتقنية AVB،
ويمكن أن تكون برنامج إقلاع أو أي صورة أخرى، وملف FDT غير موقَّع في الذاكرة عند
إزاحات معروفة. يُجري pvmfw عملية التحقّق من توقيع AVB، وفي حال نجاحه،
يُنشئ شجرة جهاز موثوق بها من ملف FDT المستلَم، ويحذف أسراره من
الذاكرة، ويتفرع إلى نقطة دخول الحمولة. في حال عدم نجاح إحدى خطوات التحقّق، تُصدر البرامج الثابتة مكالمة PSCI SYSTEM_RESET
الفائقة.
بين عمليات التشغيل، يتم تخزين معلومات عن مثيل pVM في قسم (جهاز virtio-blk) ويتم تشفيرها باستخدام مفتاح pvmfw لضمان أن يتم توفير المفتاح في المثيل الصحيح بعد إعادة التشغيل.