يوفّر Android تنفيذًا مرجعيًا لجميع المكوّنات اللازمة لتنفيذ إطار عمل Android Virtualization Framework. تقتصر عملية التنفيذ هذه حاليًا على ARM64. توضّح هذه الصفحة بنية الإطار.
خلفية
تسمح بنية Arm بحد أقصى أربعة مستويات للاستثناءات، مع أنّ مستوى الاستثناء 0 (EL0) هو الأقل امتيازًا، ومستوى الاستثناء 3 (EL3) هو الأعلى امتيازًا. يتم تنفيذ الجزء الأكبر من قاعدة رموز Android البرمجية (جميع مكونات مساحة المستخدم) باستخدام EL0. أما بقية ما يُعرف عادةً باسم "Android"، فهو نواة Linux التي تعمل في EL1.
تسمح طبقة EL2 بإدخال جهاز افتراضي يوفّر إمكانية عزل الذاكرة والأجهزة في أجهزة افتراضية فردية في EL1/EL0، مع ضمانات قوية للحفاظ على السرية والتكامل.
برنامج Hypervisor (مراقب الأجهزة الظاهرية)
تم إنشاء الجهاز الافتراضي المحمي المستنِد إلى النواة (pKVM) استنادًا إلى برنامج تشغيل الأجهزة الافتراضية KVM في Linux، الذي تم توسيع نطاقه ليشمل إمكانية حظر الوصول إلى الحمولات التي تعمل في الأجهزة الافتراضية الضيف التي تم وضع علامة "محمي" عليها في وقت الإنشاء.
تتوافق تقنية KVM/arm64 مع أوضاع تنفيذ مختلفة استنادًا إلى مدى توفّر
ميزات معيّنة لوحدة المعالجة المركزية، مثل الإضافات الخاصة بمضيف المحاكاة الافتراضية (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 في الوقت الحالي.
- تستمرّ النواة العامة في التحميل بشكلٍ طبيعي، وتحميل جميع برامج IDE اللازمة للجهاز إلى أن تصل إلى مساحة المستخدم. في هذه المرحلة، يتم تثبيت برنامج pKVM ومعالجة جداول الصفحات في المرحلة 2.
تثق عملية التمهيد في برنامج الإقلاع للحفاظ على سلامة ملف رمز التمهيد النواة فقط أثناء مرحلة التمهيد المبكّر. عند إلغاء امتيازات kernel، لم يعُد يُعتبر موثوقًا به من قِبل برنامج التشغيل الظاهري، الذي يصبح مسؤولاً بعد ذلك عن حماية نفسه حتى في حال اختراق kernel.
يتيح توفُّر نواة Android وبرنامج التشغيل الظاهري في الصورة الثنائية نفسها إنشاء واجهة تواصل مرتبطة ببعضها بشكلٍ وثيق. يضمن هذا الربط الوثيق تعديلات أساسية للعنصرَين، ما يتجنّب الحاجة إلى الحفاظ على ثبات الواجهة بينهما، ويوفّر قدرًا كبيرًا من المرونة بدون التأثير في إمكانية الصيانة على المدى الطويل. ويسمح الربط الوثيق أيضًا بتحسينات الأداء عندما يمكن للعنصرَين التعاون بدون التأثير في ضمانات الأمان التي يوفّرها برنامج التشغيل الظاهري.
بالإضافة إلى ذلك، يتيح استخدام GKI في منظومة Android المتكاملة تلقائيًا نشر برنامج تشغيل الأجهزة الافتراضية pKVM على أجهزة Android في الملف الثنائي نفسه الذي يستخدمه النواة.
حماية الوصول إلى ذاكرة وحدة المعالجة المركزية
تحدّد بنية Arm وحدة إدارة الذاكرة (MMU) مقسّمة إلى مرحلتين مستقلتين، ويمكن استخدامهما لتنفيذ ترجمة العنوان وإدارة الوصول إلى أجزاء مختلفة من الذاكرة. يتم التحكّم في وحدة إدارة الذاكرة (MMU) من المرحلة 1 من خلال EL1، وتتيح المستوى الأول من ترجمة العناوين. يستخدم نظام التشغيل Linux وحدة إدارة الذاكرة (MMU) في المرحلة 1 بهدف إدارة مساحة العنوان الافتراضي المقدَّمة لكل عملية في مساحة المستخدمين ومساحة العنوان الافتراضي الخاصة بها.
تتحكّم وحدة التحكّم في الذاكرة (MMU) من المرحلة 2 في وحدة التحكّم في الطاقة من المستوى 2 (EL2) وتتيح تطبيق ترجمة عنوان ثانية على عنوان الإخراج لوحدة التحكّم في الذاكرة من المرحلة 1، ما يؤدي إلى الحصول على عنوان مادي (PA). يمكن لأنظمة التشغيل الافتراضية استخدام الترجمة في المرحلة 2 للتحكّم في عمليات الوصول إلى الذاكرة وترجمتها من جميع الأجهزة الافتراضية للضيف. كما هو موضّح في الشكل 2، عند تفعيل كلتا مرحلتَي الترجمة، يُطلق على عنوان الإخراج في المرحلة 1 اسم عنوان جغرافي وسيط (IPA). ملاحظة: تتم ترجمة العنوان الافتراضي (VA) إلى عنوان جغرافي وسيط ثم إلى عنوان جغرافي.
في السابق، كان يتم تشغيل KVM مع تفعيل الترجمة في المرحلة 2 أثناء تشغيل الأجهزة الضيف وإيقاف المرحلة 2 أثناء تشغيل نواة Linux المضيف. تسمح هذه البنية بالوصول إلى الذاكرة من وحدة تحكّم الذاكرة (MMU) للمضيف في المرحلة 1 بالمرور من وحدة تحكّم الذاكرة (MMU) للمضيف في المرحلة 2، ما يسمح بالوصول غير المحدود من المضيف إلى صفحات ذاكرة العميل. من ناحية أخرى، تفعِّل تقنية pKVM حماية المرحلة 2 حتى في سياق المضيف، وتُسنِد إلى نظام التشغيل الظاهري مهمة حماية صفحات ذاكرة الضيف بدلاً من المضيف.
تستفيد KVM بشكل كامل من ترجمة العناوين في المرحلة 2 لتنفيذ عمليات ربط معقدة IPA/PA للضيوف، ما يخلق الوهم بوجود ذاكرة متّصلة للضيوف على الرغم من التجزئة المادية. ومع ذلك، يقتصر استخدام وحدة التحكّم في الذاكرة من المرحلة 2 في المضيف على التحكّم في الوصول فقط. يتم ربط مرحلة المضيف 2 بالمعرّف، ما يضمن أن تكون الذاكرة المتجاوبة في مساحة IPA للمضيف متجاوبة في مساحة PA. تسمح هذه البنية باستخدام عناوين ترجمة كبيرة في جدول الصفحات، وبالتالي تقليل الضغط على ذاكرة التخزين المؤقت لترجمة عنوان الذاكرة (TLB). بما أنّه يمكن أن يفهرس "التحليل الوصفي للصفحات" عملية ربط الهوية، يتم أيضًا استخدام مرحلة الشدَّاد 2 للمتابعة من أجل تتبُّع ملكية الصفحة مباشرةً في جدول الصفحات.
حماية الوصول المباشر إلى الذاكرة (DMA)
كما هو موضّح سابقًا، فإنّ إلغاء ربط صفحات الضيف من مضيف Linux في جداول صفحات وحدة المعالجة المركزية هو خطوة ضرورية ولكنّها غير كافية لحماية ملف عناوين ذاكرة الضيف. يجب أن تحمي تقنية pKVM أيضًا من عمليات الوصول إلى الذاكرة التي تجريها الأجهزة المزوّدة بإمكانية معالجة الذاكرة المباشرة (DMA) تحت سيطرة نواة المضيف، وإمكانية هجوم معالجة الذاكرة المباشرة الذي يبدأه مضيف ضار. لمنع هذا الجهاز من الوصول إلى ذاكرة الضيف، تتطلّب تقنية pKVM توفُّر وحدة إدارة ذاكرة الإدخال/الإخراج (IOMMU) لكل جهاز مزوّد بإمكانية الوصول المباشر إلى الذاكرة في النظام، كما هو موضّح في الشكل 3.
على الأقل، توفّر أجهزة وحدة إدارة الذاكرة I/O وسائل منح وإسقاط إذن الوصول للقراءة/الكتابة لجهاز إلى الذاكرة الفعلية بدقة الصفحة. ومع ذلك، يحدّ هذا الجهاز من استخدام الأجهزة في الأجهزة الافتراضية المخصّصة للبرامج (pVM) لأنّه يفترض أنّه مرحلة 2 تمّ ربطها بالتعرّف.
لضمان العزل بين الأجهزة الافتراضية، يجب أن يميز IOMMU بين معاملات الذاكرة التي يتم إنشاؤها نيابةً عن كيانات مختلفة حتى يمكن استخدام المجموعة المناسبة من جداول الصفحات للترجمة.
بالإضافة إلى ذلك، يُعدّ تقليل مقدار الرمز البرمجي الخاص بوحدة المعالجة المركزية (SoC) في EL2 استراتيجية رئيسية لتقليل قاعدة الحوسبة الموثوق بها (TCB) الإجمالية لبرنامج pKVM، ويخالف تضمين برامج تشغيل وحدة إدارة الذاكرة (IOMMU) في برنامج التشغيل الآلي. للتخفيف من هذه المشكلة، يتحمّل المضيف في EL1 مسؤولية المهام الإضافية لإدارة وحدة إدارة الذاكرة I/O، مثل إدارة الطاقة وبدء التشغيل ومعالجة المقاطعات عند الاقتضاء.
ومع ذلك، فإنّ منح المضيف التحكّم في حالة الجهاز يفرض متطلبات إضافية على واجهة البرمجة لأجهزة وحدة إدارة الذاكرة I/O لضمان عدم إمكانية تجاوز عمليات التحقّق من الأذونات بوسائل أخرى، على سبيل المثال، بعد إعادة ضبط الجهاز.
إنّ بنية وحدة إدارة ذاكرة النظام (SMMU) في Arm هي وحدة إدارة I/O المعيارية والمتوافقة بشكل جيد مع أجهزة Arm التي تتيح كلاً من العزل والتخصيص المباشر. وتعدّ هذه البنية هي الحلّ المرجعي المقترَح.
ملكية الذاكرة
عند بدء التشغيل، يُفترض أنّ جميع الذاكرة غير المخصّصة لنظام التشغيل الافتراضي هي ملك للمضيف، ويرصدها نظام التشغيل الافتراضي على هذا النحو. عند إنشاء جهاز افتراضي شخصي، يقدّم المضيف صفحات ذاكرة للسماح ببدء تشغيله وينقل المشرف الظاهري ملكية هذه الصفحات من المضيف إلى الجهاز الافتراضي الشخصي. وبالتالي، يفرض نظام التشغيل الظاهري قيود التحكّم في الوصول في جدول صفحات المرحلة 2 للمضيف لمنع الوصول إلى الصفحات مرة أخرى، ما يضمن السرية للضيف.
يمكن التواصل بين المضيف والضيوف من خلال مشاركة ذاكرة تتم التحكّم فيها بينهم. يُسمح للضيوف بمشاركة بعض صفحاتهم مع المضيف باستخدام طلب hypercall الذي يوجّه نظام التشغيل الظاهري إلى إعادة ربط هذه الصفحات في جدول صفحات المرحلة 2 للمضيف. وبالمثل، يمكن التواصل بين المضيف وTrustZone من خلال عمليات مشاركة الذاكرة و/أو إقراضها، ويتم تتبُّع جميع هذه العمليات عن كثب والتحكّم فيها من خلال pKVM باستخدام مواصفات إطار عمل البرامج الثابتة لمعالجات Arm (FF-A).
بما أنّ متطلبات الذاكرة لوحدة pVM يمكن أن تتغيّر بمرور الوقت، يتم توفير مكالمة فائقة تسمح بإعادة ملكية صفحات محدّدة تابعة للمتصل إلى المضيف. في الممارسة العملية، يتم استخدام هذا الطلب الفائق مع بروتوكول virtio balloon للسماح لـ VMM بطلب الذاكرة مجددًا من pVM، وللسماح لـ pVM بإعلام VMM بالصفحات التي تم التخلي عنها، بطريقة خاضعة للرقابة.
يتحمّل نظام التشغيل الظاهري مسؤولية تتبُّع ملكية جميع صفحات الذاكرة في النظام وما إذا كانت تتم مشاركتها أو إقراضها إلى كيانات أخرى. يتم معظم تتبُّع هذه الحالة باستخدام البيانات الوصفية المرفقة بجداول صفحات الطور 2 الخاصة بالمضيف والضيوف، وذلك باستخدام الوحدات المحجوزة في إدخالات جدول الصفحات (PTEs) التي يتم حجزها لاستخدام البرامج، كما يشير اسمها.
يجب أن يضمن المضيف عدم محاولة الوصول إلى الصفحات التي تم حظر الوصول إليها من خلال برنامج إدارة الأجهزة الافتراضية. يؤدي الوصول غير القانوني إلى المضيف إلى إدخال استثناء برمجي سويسري في المضيف من خلال برنامج التشغيل الظاهري، ما قد يؤدي بدوره إلى تلقّي مهمة مساحة المستخدم المسؤولة إشارة SEGV أو تعطُّل ملف برمجي المضيف. لمنع عمليات الوصول غير المقصودة، تجعل نواة المضيف الصفحات الممنوحة للضيوف غير مؤهَّلة للتبديل أو الدمج.
معالجة المقاطعات والموقّتات
إنّ عمليات المقاطعة هي جزء أساسي من طريقة تفاعل الضيف مع الأجهزة ولعملية التواصل بين وحدات المعالجة المركزية، حيث تكون عمليات المقاطعة بين المعالجات (IPIs) هي آلية التواصل الرئيسية. يهدف نموذج KVM إلى تفويض جميع إدارة المقاطعات الافتراضية إلى المضيف في EL1، والذي يعمل لهذا الغرض كجزء غير موثوق به من برنامج التشغيل الافتراضي.
يوفّر 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 إلى عنوان لا يتطابق مع منطقة ذاكرة صالحة، يخرج مؤشر تسلسل vCPU إلى المضيف ويتم استخدام الوصول عادةً إلى MMIO ويُحاكيه مدير تشغيل الأجهزة الافتراضية في مساحة المستخدم. لتسهيل هذه العملية، على pKVM عرض تفاصيل عن التعليمة التي حدث فيها خطأ، مثل عنوانها ومَعلمات السجلّ وربما محتوياتها، وإرسالها إلى المضيف، ما قد يؤدي إلى عرض بيانات حسّاسة بدون قصد من ضيف محمي إذا لم يكن من المتوقّع حدوث خطأ. يحلّ pKVM هذه المشكلة من خلال التعامل مع هذه الأخطاء على أنّها خطيرة ما لم يُصدر الضيف في السابق طلبًا فائقيًا لتحديد نطاق عنوان IP الذي حدث فيه الخطأ على أنّه نطاق يُسمح فيه بعمليات الوصول إلى المضيف. يُشار إلى هذا الحلّ باسم حاجز MMIO.
جهاز I/O افتراضي (virtio)
Virtio هو معيار شائع ومتوافق وقديم لتنفيذ الأجهزة التي تم تحويلها إلى أجهزة افتراضية جزئية والتفاعل معها. يتم تنفيذ معظم الأجهزة المعروضة للضيوف المحميين باستخدام virtio. تستند Virtio أيضًا إلى تنفيذ vsock المستخدَم للتواصل بين نظام التشغيل الضيف المحمي وبقية نظام التشغيل Android.
يتم عادةً تنفيذ أجهزة Virtio في مساحة المستخدم الخاصة بالمضيف من خلال "مدير تشغيل الأجهزة الافتراضية"، الذي يعترض عمليات الوصول إلى الذاكرة المحاصرة من الضيف إلى واجهة MMIO لجهاز Virtio ويُحاكي السلوك المتوقّع. إنّ الوصول إلى MMIO مكلف نسبيًا لأنّ كل عملية وصول إلى الجهاز تتطلّب رحلة ذهابًا وإيابًا إلى وحدة التحكّم في الأجهزة الافتراضية والعكس، لذا يحدث معظم نقل البيانات الفعلي بين الجهاز والضيف باستخدام مجموعة من قوائم الانتظار الافتراضية في الذاكرة. من الافتراضات الرئيسية لبرنامج virtio أنّه يمكن للمضيف الوصول إلى ذاكرة الضيف بشكل عشوائي. يتضح هذا الافتراض في تصميم virtqueue، الذي قد يحتوي على مؤشرات إلى المخازن المؤقتة في الجهاز الضيف الذي يهدف إلى محاكاة الجهاز للوصول إليه مباشرةً.
على الرغم من أنّه يمكن استخدام طلبات البيانات الفائقة لمشاركة الذاكرة الموضّحة سابقًا لمشاركة ملفّات تخزين مؤقتة لبيانات 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 بأكمله وإعدادها، وإنشاء آلات افتراضية مخصّصة.
- تُستخدَم طلبات 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)
|
فرقعة | 0x80080000
|
برنامج الإقلاع | 0x80200000
|
ملف FDT في وضع BIOS | 0x80000000
|
قاعدة الذاكرة الفعلية | 0x80000000
|
البرامج الثابتة لنظام التشغيل pVM | 0x7FE00000
|
ذاكرة الجهاز | 0x10000 - 0x40000000
|
يتم تخصيص الذاكرة الفعلية باستخدام mmap
ويتم منح الذاكرة للآلة الافتراضية ل заполнения مناطق الذاكرة، التي تُعرف باسم memslots، باستخدام KVM_SET_USER_MEMORY_REGION
ioctl. وبالتالي، يتم تحديد كل ذاكرة pVM للضيف
على أنها مثيل crosvm الذي يديرها، ويمكن أن يؤدي ذلك إلى
إيقاف العملية (إنهاء الجهاز الظاهري) إذا بدأ المضيف في استخدام
الذاكرة الفارغة. عند إيقاف جهاز افتراضي، يُمحو محتوى الذاكرة تلقائيًا من قِبل الهايبر visor ويتم إرجاعه إلى نواة المضيف.
في إطار KVM العادي، يحتفظ برنامج إدارة الأجهزة الافتراضية (VMM) بإمكانية الوصول إلى جميع ذاكرة الضيف. باستخدام pKVM، تتم إزالة ربط ذاكرة الضيف من مساحة العناوين الفيزيائية للمضيف عند منحها للضيف. الاستثناء الوحيد هو الذاكرة التي يشاركها الضيف بشكل صريح، مثل أجهزة virtio.
لا يتمّ ربط مناطق MMIO في مساحة عناوين الضيف. يتم حظر وصول الضيف إلى هذه المناطق، ما يؤدي إلى حدوث حدث I/O في FD لوحدة VM. تُستخدَم هذه المحاولة لتطبيق الأجهزة الافتراضية. في الوضع المحمي، يجب أن يقرّ الضيف باستخدام منطقة من مساحة العناوين الخاصة به لواجهة MMIO باستخدام طلب فائقة، وذلك للحد من خطر تسرُّب المعلومات عن طريق الخطأ.
الجدولة
يتم تمثيل كل وحدة معالجة مركزية افتراضية بخيط POSIX ويحدِّد جدولة مهامها جدولة Linux المضيف. يُطلِق الخيط دالة KVM_RUN
ioctl على FD لوحدة المعالجة المركزية الافتراضية، ما يؤدي
إلى تبديل نظام التشغيل الظاهري إلى سياق وحدة المعالجة المركزية الافتراضية للضيف. يأخذ جدولة المضيف
الوقت الذي يقضيه في سياق الضيف على أنّه الوقت المستخدَم من قِبل سلسلتَي المهام المقابلة
لوحدة المعالجة الافتراضية. يتم عرض القيمة KVM_RUN
عندما يكون هناك حدث يجب أن يعالجه
برنامج إدارة الأجهزة الافتراضية، مثل I/O أو نهاية المقاطعة أو توقُّف وحدة المعالجة المركزية الافتراضية. يعالج مدير الخدمات الجوّالة للمؤسسات
الحدث ويتصل بـ KVM_RUN
مرة أخرى.
خلال مرحلة KVM_RUN
، يظلّ مؤشر التسلسل قابلاً للاستبدال من قِبل جدولة المضيف، باستثناء
تنفيذ رمز برنامج تشغيل الأجهزة الافتراضية EL2 الذي لا يمكن استبداله. لا تتضمّن مثيل VM الضيف آلية للتحكّم في هذا السلوك.
وبما أنّه يتم جدولة جميع مؤشرات تسلسل عمليات وحدة المعالجة المركزية الافتراضية مثل أي مهام أخرى في مساحة المستخدم، فإنّها تخضع لجميع آليات جودة الخدمة العادية. على وجه التحديد، يمكن تحسين كلّ سلسلة مهام وحدة المعالجة المركزية الافتراضية لتتلاءم مع وحدات المعالجة المركزية الفعلية، ووضعها في مجموعات وحدات المعالجة المركزية، وتعزيزها أو وضع حدّ أقصى لها باستخدام ميزة تثبيت معدّل الاستخدام، وتغيير أولويتها أو سياسة جدولة المهام، وغير ذلك.
الأجهزة الافتراضية
يتوافق crosvm مع عدد من الأجهزة، بما في ذلك ما يلي:
- virtio-blk لصور الأقراص المركبة، للقراءة فقط أو للقراءة والكتابة
- vhost-vsock للتواصل مع المضيف
- virtio-pci كوسيط نقل virtio
- ساعة الوقت الفعلي pl030
- واجهة 16550a UART للاتصال التسلسلي
البرامج الثابتة لنظام التشغيل pVM
رمز البرامج الثابتة لنظام التشغيل pVM (pvmfw) هو الرمز البرمجي الأول الذي ينفذه نظام التشغيل pVM، وهو مشابه لرمز بدء التشغيل (ROM) لجهاز فعلي. والهدف الأساسي من pvmfw هو بدء التشغيل بأمان وإنشاء المفتاح السري الفريد لنظام التشغيل pVM. لا يقتصر استخدام pvmfw على أي نظام تشغيل معيّن، مثل Microdroid، ما دام نظام التشغيل متوافقًا مع crosvm وتم توقيعه بشكل صحيح.
يتم تخزين الملف الثنائي pvmfw في قسم فلاش يحمل الاسم نفسه ويتم تحديثه باستخدام OTA.
تشغيل الجهاز
تتم إضافة تسلسل الخطوات التالي إلى عملية تشغيل جهاز مزوّد بتقنية pKVM:
- يحمِّل برنامج Android Bootloader (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.
تشغيل جهاز افتراضي
عند إنشاء جهاز افتراضي شخصي، يجب أن ينشئ crosvm (أو برنامج إدارة آلات افتراضية آخر) مساحة ذاكرة كبيرة بما يكفي لتعبئتها بتطبيق pvmfw من خلال برنامج إدارة الأجهزة الافتراضية. يتم أيضًا حصر وحدة إدارة الذاكرة في قائمة السجلات التي يمكنها ضبط قيمتها الأولية (x0-x14 لوحدة المعالجة المركزية الافتراضية الأساسية، ولا يمكن ضبط أي قيمة لوحدات المعالجة المركزية الافتراضية الثانوية). إنّ السجلات المتبقية محجوزة وجزء من واجهة ABI الخاصة ببرنامج hypervisor-pvmfw.
عند تشغيل آلة افتراضية خفيفة، ينقل المضيف الظاهري أولاً التحكّم في وحدة المعالجة المركزية الافتراضية الأساسية
إلى pvmfw. يتوقّع البرنامج الثابت أن يكون crosvm قد حمّل نواة موقَّعة بتقنية AVB،
ويمكن أن تكون برنامج إقلاع أو أي صورة أخرى، وملف FDT غير موقَّع في الذاكرة عند
إزاحات معروفة. يُجري pvmfw عملية التحقّق من توقيع AVB، وفي حال نجاحه،
يُنشئ شجرة جهاز موثوق بها من ملف FDT المستلَم، ويحذف أسراره من
الذاكرة، ويتفرع إلى نقطة دخول الحمولة. إذا تعذّر إكمال إحدى خطوات
التحقّق، يُصدر البرنامج الثابت طلبًا SYSTEM_RESET
لنظام التشغيل PSCI.
بين عمليات التشغيل، يتم تخزين معلومات عن مثيل pVM في قسم (جهاز virtio-blk) ويتم تشفيرها باستخدام مفتاح pvmfw لضمان أن يتم توفير المفتاح في المثيل الصحيح بعد إعادة التشغيل.