Android پیادهسازی مرجعی از همه عناصر لازم برای پیادهسازی «چارچوب مجازیسازی Android» ارائه میدهد. درحالحاضر این پیادهسازی به ARM64 محدود است. این صفحه معماری چارچوب را توضیح میدهد.
پسزمینه
معماری Arm حداکثر چهار سطح استثنا را مجاز میداند، بهطوریکه سطح استثنا ۰ (EL0) کمترین امتیاز را دارد و سطح استثنا ۳ (EL3) بیشترین امتیاز را دارد. بزرگترین بخش پایگاه کد Android (همه مؤلفههای فضای کاربر) در EL0 اجرا میشود. بقیه آنچه معمولاً «Android» نامیده میشود هسته Linux است که در EL1 اجرا میشود.
لایه EL2 امکان معرفی یک ابرناظر را فراهم میکند که امکان جداسازی حافظه و دستگاهها در pVMهای مجزا در EL1/EL0 را با تضمینهای قوی محرمانگی و یکپارچگی فراهم میکند.
Hypervisor
ماشین مجازی مبتنی بر هسته محافظتشده (pKVM) براساس فراسرپرست KVM لینوکس ساخته شده است، که با توانایی محدود کردن دسترسی به محمولههای درحال اجرا در ماشینهای مجازی مهمان که در زمان ایجاد بهعنوان «محافظتشده» علامتگذاری شدهاند، گسترش یافته است.
KVM/arm64 بسته به دردسترس بودن ویژگیهای خاص CPU، یعنی «افزونههای میزبان مجازیسازی» (VHE) (ARMv8.1 و نسخههای جدیدتر)، از حالتهای اجرای مختلفی پشتیبانی میکند. در یکی از این حالتها که معمولاً بهعنوان حالت غیرVHE شناخته میشود، کد
سرپرست درطول راهاندازی از تصویر هسته جدا میشود و در
EL2 نصب میشود، درحالیکه خود هسته در EL1 اجرا میشود. اگرچه بخشی از پایگاه کد Linux است، اما عنصر EL2 در KVM عنصر کوچکی است که مسئول
تعویض بین چندین EL1 است. مؤلفه ناظر ماشین مجازی با Linux کامپایل میشود، اما در بخش حافظه اختصاصی و جداگانهای از ایمیج vmlinux قرار دارد. pKVM با گسترش کد ناظر ماشین مجازی با ویژگیهای جدید، از این طراحی بهره میبرد و به آن اجازه میدهد محدودیتهایی را بر هسته میزبان Android و فضای کاربر اعمال کند و دسترسی میزبان به حافظه مهمان و ناظر ماشین مجازی را محدود کند.
واحدهای فروشنده pKVM
واحد فروشنده pKVM واحد سختافزاری خاصی است که حاوی عملکرد مختص دستگاه است، مثل درایورهای واحد مدیریت حافظه ورودی-خروجی (IOMMU). این واحدها به شما امکان میدهند ویژگیهای امنیتی را که نیاز به دسترسی سطح استثنا ۲ (EL2) به pKVM دارند انتقال دهید.
برای آشنایی با نحوه پیادهسازی و بار کردن واحد ارائهدهنده pKVM، به پیادهسازی واحد ارائهدهنده pKVM مراجعه کنید.
روش راهاندازی
شکل زیر فرایند راهاندازی pKVM را نشان میدهد:
- مقداردهی اولیه: راهانداز سیستم در EL2 وارد هسته عمومی میشود. کد هسته قابلاعتماد در هر دو EL2 و EL1 سپس pKVM و واحدهای آن را مقداردهی اولیه میکند. درطول این مرحله، EL1 مورد اعتماد EL2 است، بنابراین هیچ کد غیرقابلاعتمادی اجرا نمیشود.
- «هسته سلب امتیاز»: هسته عمومی تشخیص میدهد که در EL2 اجرا میشود و امتیاز خود را به EL1 کاهش میدهد. pKVM و واحدهای آن همچنان در EL2 اجرا میشوند.
- زمان اجرا: هسته عمومی به بوت شدن عادی ادامه میدهد و همه درایورهای دستگاه لازم را تا رسیدن به فضای کاربر بار میکند. در این نقطه، pKVM در جای خود قرار دارد و جدولهای صفحه مرحله ۲ را مدیریت میکند.
فرایند راهاندازی به bootloader اعتماد میکند تا تمامیت تصویر هسته را برای مرحله مقداردهی اولیه درستیسنجی و حفظ کند. پساز اینکه هسته از امتیازات محروم شد، دیگر ازنظر سرپرست مورد اعتماد نیست، و سرپرست مسئولیت محافظت از خود را برعهده میگیرد، حتی اگر هسته درمعرض خطر قرار گرفته باشد.
داشتن هسته Android و سرپرست در یک تصویر باینری امکان ایجاد میانای ارتباطی بسیار جفتشده بین آنها را فراهم میکند. این جفتسازی محکم بهروزرسانیهای اتمی دو مؤلفه را تضمین میکند، که نیاز به پایدار نگه داشتن میانای بین آنها را ازبین میبرد و بدون اینکه قابلیت نگهداری بلندمدت را بهخطر بیندازد، انعطافپذیری زیادی ارائه میدهد. جفتسازی محکم همچنین امکان بهینهسازی عملکرد را فراهم میکند، زیرا هر دو مؤلفه میتوانند بدون تأثیرگذاری بر تضمینهای امنیتی ارائهشده توسط Hypervisor با یکدیگر همکاری کنند.
علاوهبراین، پذیرش GKI در بومسازگان Android بهطور خودکار به هایپروایزر pKVM اجازه میدهد در همان باینری هسته در دستگاههای Android مستقر شود.
محافظت از دسترسی به حافظه واحد پردازش مرکزی
معماری Arm واحد مدیریت حافظه (MMU) را به دو مرحله مستقل تقسیم میکند که هر دو میتوانند برای پیادهسازی ترجمه نشانی و کنترل دسترسی به بخشهای مختلف حافظه استفاده شوند. MMU مرحله ۱ توسط EL1 کنترل میشود و سطح اول ترجمه نشانی را امکانپذیر میکند. MMU مرحله ۱ توسط Linux برای مدیریت فضای نشانی مجازی ارائهشده به هر فرایند فضای کاربر و فضای نشانی مجازی خودش استفاده میشود.
«واحد مدیریت حافظه» مرحله ۲ تحت کنترل EL2 است و امکان اعمال ترجمه نشانی دوم را روی نشانی برونداد «واحد مدیریت حافظه» مرحله ۱ فراهم میکند که منجر به نشانی فیزیکی (PA) میشود. ناظران میتوانند از ترجمه مرحله ۲ برای کنترل و ترجمه دسترسیهای حافظه از همه ماشینهای مجازی مهمان استفاده کنند. همانطور که در شکل ۲ نشان داده شده است، وقتی هر دو مرحله ترجمه فعال باشند، نشانی برونداد مرحله ۱ نشانی فیزیکی میانجی (IPA) نامیده میشود توجه: نشانی مجازی (VA) به IPA و سپس به PA ترجمه میشود.
ازنظر تاریخی، KVM با ترجمه مرحله ۲ فعال درحین اجرای مهمانان و با مرحله ۲ غیرفعال درحین اجرای هسته میزبان Linux اجرا میشود. این معماری به دسترسیهای حافظه از MMU مرحله ۱ میزبان اجازه میدهد از MMU مرحله ۲ عبور کنند، بنابراین دسترسی نامحدود از میزبان به صفحههای حافظه مهمان را ممکن میسازد. ازطرف دیگر، pKVM محافظت مرحله ۲ را حتی در زمینه میزبان فعال میکند و بهجای میزبان، ابرناظر را مسئول محافظت از صفحههای حافظه مهمان میکند.
KVM از ترجمه نشانی در مرحله ۲ برای پیادهسازی نگاشتهای پیچیده IPA/PA برای مهمانان استفاده کامل میکند، که توهم حافظه پیوسته را برای مهمانان ایجاد میکند، با وجود تکهتکه بودن فیزیکی. بااینحال، استفاده از MMU مرحله ۲ برای میزبان فقط به کنترل دسترسی محدود میشود. مرحله ۲ میزبان نگاشت هویتی دارد، که تضمین میکند حافظه مجاور در فضای IPA میزبان در فضای PA مجاور است. این معماری امکان استفاده از نگاشتهای بزرگ در جدول صفحه را فراهم میکند و درنتیجه فشار بر بافر جانبی ترجمه (TLB) را کاهش میدهد. ازآنجاییکه PA میتواند تخصیص هویت را نمایهگذاری کند، از مرحله میزبان ۲ نیز برای ردیابی مستقیم مالکیت صفحه در جدول صفحه استفاده میشود.
محافظت از دسترسی مستقیم به حافظه (DMA)
همانطور که قبلاً توضیح داده شد، لغو نگاشت صفحههای مهمان از میزبان Linux در جدولهای صفحه CPU گامی ضروری اما ناکافی برای محافظت از حافظه مهمان است. pKVM همچنین باید دربرابر دسترسیهای حافظه انجامشده توسط دستگاههای دارای قابلیت DMA تحت کنترل هسته میزبان و احتمال حمله DMA آغازشده توسط میزبان مخرب محافظت کند. برای جلوگیری از دسترسی چنین دستگاهی به حافظه مهمان، pKVM به سختافزار واحد مدیریت حافظه ورودی-خروجی (IOMMU) برای هر دستگاه دارای قابلیت DMA در سیستم نیاز دارد، همانطور که در شکل ۳ نشان داده شده است.
حداقل، سختافزار IOMMU امکان اعطای و لغو دسترسی خواندن/نوشتن برای دستگاه به حافظه فیزیکی در سطح صفحه را فراهم میکند. بااینحال، این سختافزار IOMMU استفاده از دستگاهها در pVM را محدود میکند زیرا آنها مرحله ۲ با هویت نگاشتشده را فرض میکنند.
برای اطمینان از جداسازی بین ماشینهای مجازی، تراکنشهای حافظه تولیدشده ازطرف نهادهای مختلف باید توسط IOMMU قابل تشخیص باشند تا بتوان از مجموعه مناسب جدولهای صفحه برای ترجمه استفاده کرد.
علاوهبراین، کاهش مقدار کد مختص SoC در EL2 یک استراتژی کلیدی برای کاهش کل پایگاه محاسباتی مطمئن (TCB) در pKVM است و با گنجاندن درایورهای IOMMU در فراناظر مغایرت دارد. برای کاهش این مشکل، میزبان در EL1 مسئولیت کارهای مدیریت IOMMU کمکی، مانند مدیریت توان، مقداردهی اولیه، و درصورت لزوم، مدیریت وقفه را برعهده دارد.
بااینحال، قرار دادن میزبان در کنترل وضعیت دستگاه، الزامات بیشتری را بر رابط برنامهنویسی سختافزار IOMMU تحمیل میکند تا اطمینان حاصل شود که بررسیهای مجوز نمیتواند ازطریق روشهای دیگر، برای مثال، پساز بازنشانی دستگاه، دور زده شود.
یک IOMMU استاندارد و با پشتیبانی خوب برای دستگاههای Arm که هم جداسازی و هم تخصیص مستقیم را ممکن میسازد، معماری Arm System Memory Management Unit (SMMU) است. این معماری راهحل مرجع توصیهشده است.
مالکیت حافظه
در زمان راهاندازی، فرض میشود که همه حافظههای غیرفراسرپرست متعلق به میزبان است و فراسرپرست آنها را بهعنوان حافظه میزبان ردیابی میکند. وقتی pVM ایجاد میشود، میزبان صفحههای حافظه را اهدا میکند تا به آن اجازه دهد راهاندازی شود و فراسرپرست مالکیت آن صفحهها را از میزبان به pVM منتقل میکند. بنابراین، سرپرست ماشین مجازی محدودیتهای کنترل دسترسی را در جدول صفحه مرحله ۲ میزبان قرار میدهد تا از دسترسی مجدد آن به صفحات جلوگیری کند و محرمانگی را برای مهمان فراهم کند.
برقراری ارتباط بین میزبان و مهمانان ازطریق همرسانی کنترلشده حافظه بین آنها امکانپذیر میشود. مهمانان مجازند برخیاز صفحههایشان را بااستفاده از فرادرخواست با میزبان همرسانی کنند، که به فراناظر دستور میدهد آن صفحهها را در جدول صفحه مرحله ۲ میزبان بازنگاشت کند. بهطور مشابه، ارتباط میزبان با TrustZone ازطریق عملیات همرسانی و/یا قرض دادن حافظه امکانپذیر میشود که همه آنها توسط pKVM بااستفاده از مشخصات چارچوب میانافزار برای Arm (FF-A) بهدقت نظارت و کنترل میشوند.
ازآنجاییکه الزامات حافظه pVM میتواند درطول زمان تغییر کند، یک فرادرخواست ارائه میشود که اجازه میدهد مالکیت صفحههای مشخصشده متعلق به تماسگیرنده به میزبان واگذار شود. در عمل، این فرادرخواست با پروتکل virtio balloon استفاده میشود تا به VMM اجازه دهد حافظه را از pVM درخواست کند و pVM بتواند صفحات واگذارشده را بهصورت کنترلشده به VMM اطلاع دهد.
هایپروایزر مسئول ردیابی مالکیت همه صفحات حافظه در سیستم و اینکه آیا این صفحات با سایر نهادها بهاشتراک گذاشته میشوند یا به آنها قرض داده میشوند، است. بیشتر این ردیابی وضعیت بااستفاده از فرادادههای پیوستشده به جدولهای صفحه مرحله ۲ میزبان و مهمانها انجام میشود، بااستفاده از بیتهای رزروشده در ورودیهای جدول صفحه (PTE) که همانطور که از نامشان پیداست، برای استفاده نرمافزار رزرو شدهاند.
میزبان باید مطمئن شود که تلاش نمیکند به صفحههایی که ابرناظر آنها را غیرقابلدسترس کرده است دسترسی پیدا کند. دسترسی غیرقانونی میزبان باعث میشود که یک استثنای همگام توسط ناظر ماشین مجازی به میزبان تزریق شود، که میتواند منجر به دریافت سیگنال SEGV توسط وظیفه فضای کاربر مسئول یا ازکارافتادن هسته میزبان شود. برای جلوگیری از دسترسیهای تصادفی، صفحههای اهداشده به مهمانان توسط هسته میزبان برای تعویض یا ادغام غیرواجدشرایط میشوند.
مدیریت وقفه و زمانسنجها
وقفهها بخش ضروری از نحوه تعامل مهمان با دستگاهها و برای ارتباط بین CPUها هستند، که وقفههای بینپردازندهای (IPI) سازوکار اصلی ارتباط هستند. مدل KVM به این صورت است که همه مدیریت وقفه مجازی را به میزبان در EL1 واگذار میکند، که برای این منظور بهعنوان بخشی غیرقابلاعتماد از ابرسرپرست عمل میکند.
pKVM شبیهسازی کامل Generic Interrupt Controller نسخه ۳ (GICv3) را براساس کد KVM موجود ارائه میدهد. زمانسنج و IPI بهعنوان بخشی از این کد شبیهسازی غیرقابلاعتماد مدیریت میشوند.
پشتیبانی GICv3
میانای بین EL1 و EL2 باید تضمین کند که وضعیت کامل وقفه برای میزبان EL1 قابلمشاهده است، ازجمله نسخههایی از ثباتهای سرپرست مربوط به وقفهها. این رؤیتپذیری معمولاً بااستفاده از مناطق حافظه مشترک، یک منطقه برای هر واحد پردازش مرکزی مجازی (vCPU)، انجام میشود.
کد پشتیبانی زمان اجرای ثبت سیستم را میتوان ساده کرد تا فقط از ثبت «وقفه تولیدشده توسط نرمافزار» (SGIR) و ثبت «وقفه غیرفعالسازی» ثبت (DIR) پشتیبانی کند. معماری حکم میکند که این ثبتها همیشه به EL2 تلهگذاری شوند، درحالیکه تلههای دیگر تاکنون فقط برای کاهش خطاها مفید بودهاند. همه چیزهای دیگر در سختافزار مدیریت میشود.
در سمت MMIO، همه چیز در EL1 شبیهسازی میشود و از همه زیرساختهای فعلی در KVM استفاده مجدد میشود. درنهایت، Wait for Interrupt (WFI) همیشه به EL1 منتقل میشود، زیرا این یکی از ابتداییترین عناصر زمانبندی است که KVM استفاده میکند.
پشتیبانی زمانسنج
مقدار مقایسهگر برای زمانسنج مجازی باید در هر وقفه WFI به EL1 ارائه شود تا EL1 بتواند درحالیکه vCPU مسدود است، وقفههای زمانسنج را تزریق کند. زمانسنج فیزیکی کاملاً شبیهسازی شده است و همه تلهها به EL1 منتقل میشوند.
اداره کردن MMIO
برای ارتباط با پایشگر ماشین مجازی (VMM) و انجام شبیهسازی GIC، وقفه MMIO باید برای بررسی بیشتر به میزبان در EL1 برگردانده شود. pKVM به موارد زیر نیاز دارد:
- IPA و اندازه دسترسی
- دادهها درصورت نوشتن
- ترتیب بایتهای CPU در نقطه تلهگذاری
علاوهبراین، تلههایی که از ثبتکننده با هدف کلی (GPR) بهعنوان منبع/مقصد استفاده میکنند، بااستفاده از ثبتکننده شبهانتقال انتزاعی منتقل میشوند.
میاناهای مهمان
مهمان میتواند بااستفاده از ترکیبی از فراخوانیهای ابر و دسترسی به حافظه مناطق بهدامافتاده با مهمان محافظتشده ارتباط برقرار کند. ابرتماسها طبق استاندارد SMCCC آشکار میشوند و محدودهای برای تخصیص فروشنده توسط KVM رزرو میشود. فرادرخواستهای زیر برای مهمانان pKVM اهمیت ویژهای دارند.
فراخوانیهای ابرعمومی
- PSCI سازوکار استانداردی برای مهمان فراهم میکند تا چرخه حیات vCPUهای خود را کنترل کند، ازجمله آنلاین کردن، آفلاین کردن، و خاموش کردن سیستم.
- TRNG سازوکاری استاندارد برای مهمان فراهم میکند تا آنتروپی را از pKVM درخواست کند که تماس را به EL3 رله میکند. این سازوکار بهویژه در مواردی مفید است که نمیتوان به میزبان برای مجازیسازی مولد اعداد تصادفی سختافزاری (RNG) اعتماد کرد.
فرادرخواستهای pKVM
- همرسانی حافظه با میزبان. در ابتدا، میزبان به حافظه مهمان دسترسی ندارد، اما دسترسی میزبان برای ارتباط حافظه مشترک و برای دستگاههای مجازیسازیشده که به بافرهای مشترک متکی هستند ضروری است. فراخوانیهای سریع برای همرسانی و لغو همرسانی صفحهها با میزبان به مهمان اجازه میدهد دقیقاً تصمیم بگیرد کدام بخشهای حافظه بدون نیاز به دست دادن دراختیار بقیه Android قرار گیرد.
- واگذاری حافظه به میزبان. معمولاً همه حافظه مهمان تا زمانی که ازبین نرود به مهمان تعلق دارد. این وضعیت برای ماشینهای مجازی با عمر طولانی که الزامات حافظه آنها درطول زمان تغییر میکند ناکافی است.
relinquishفراخوانی به مهمان اجازه میدهد تا بهطور صریح مالکیت صفحهها را بدون نیاز به خاتمه دادن به مهمان به میزبان برگرداند. - بهدام انداختن دسترسی به حافظه میزبان. بهطور سنتی، اگر مهمان KVM به نشانیای دسترسی پیدا کند که با ناحیه حافظه معتبری مطابقت ندارد، رشته vCPU به میزبان خارج میشود و دسترسی معمولاً برای MMIO استفاده میشود و توسط VMM در فضای کاربر شبیهسازی میشود. برای تسهیل این مدیریت، pKVM باید جزئیات مربوط به دستورالعمل معیوب را، مثل نشانی آن، پارامترهای ثبت، و احتمالاً محتوای آنها، به میزبان برگرداند، که درصورت پیشبینی نشدن تله، میتواند بهطور ناخواسته دادههای حساس مهمان محافظتشده را افشا کند. pKVM این مشکل را با مهلک درنظر گرفتن این خطاها حل میکند، مگر اینکه مهمان قبلاً ابرتماسی برای شناسایی محدوده IPA معیوب بهعنوان محدودهای که دسترسی به آن برای تلهگذاری به میزبان مجاز است صادر کرده باشد. این راهحل بهعنوان محافظ MMIO شناخته میشود.
دستگاه ورودی/خروجی مجازی (virtio)
Virtio یک استاندارد محبوب، قابلحمل، و بالغ برای پیادهسازی و تعامل با دستگاههای نیمهمجازیسازیشده است. اکثر دستگاههای درمعرض مهمانان محافظتشده بااستفاده از virtio پیادهسازی میشوند. Virtio همچنین از پیادهسازی vsock که برای ارتباط بین مهمان محافظتشده و بقیه Android استفاده میشود پشتیبانی میکند.
دستگاههای Virtio معمولاً در فضای کاربر میزبان توسط VMM پیادهسازی میشوند، که دسترسیهای حافظه بهدامافتاده از مهمان به رابط MMIO دستگاه virtio را رهگیری میکند و رفتار موردانتظار را شبیهسازی میکند. دسترسی MMIO نسبتاً پرهزینه است زیرا هر دسترسی به دستگاه مستلزم رفتوبرگشت به VMM است، بنابراین بیشتر انتقال واقعی داده بین دستگاه و مهمان بااستفاده از مجموعهای از virtqueue در حافظه انجام میشود. یکی از مفروضات اصلی virtio این است که میزبان میتواند بهطور دلخواه به حافظه مهمان دسترسی داشته باشد. این فرض در طراحی virtqueue مشهود است که ممکن است حاوی اشارهگرهایی به میانگیرها در مهمان باشد که شبیهسازی دستگاه برای دسترسی مستقیم به آنها درنظر گرفته شده است.
اگرچه از فرادرخواستهای همرسانی حافظه که قبلاً شرح داده شد میتوان برای همرسانی میانگیرهای داده virtio از مهمان به میزبان استفاده کرد، این همرسانی لزوماً در دانهبندی صفحه انجام میشود و اگر اندازه میانگیر کمتر از اندازه صفحه باشد، ممکن است درنهایت دادههای بیشتری از آنچه لازم است افشا شود. درعوض، مهمان بهگونهای پیکربندی میشود که هم صفهای مجازی و هم بافرهای داده مربوط به آنها را از پنجرهای ثابت از حافظه مشترک تخصیص دهد و دادهها درصورت نیاز به پنجره و از پنجره کپی (جهش) شوند.
تعامل با TrustZone
اگرچه مهمانان نمیتوانند مستقیماً با TrustZone تعامل داشته باشند، میزبان باید همچنان بتواند تماسهای SMC را در دنیای امن صادر کند. این فراخوانیها میتوانند میانگیرهای حافظه با نشانی فیزیکی را که میزبان به آنها دسترسی ندارد مشخص کنند. ازآنجاییکه نرمافزار امن معمولاً از دسترسپذیری بافر آگاه نیست، میزبان مخرب میتواند از این بافر برای انجام حمله معاون گیج شده (مشابه حمله DMA) استفاده کند. برای جلوگیری از چنین حملاتی، pKVM همه فراخوانیهای میزبان SMC را به EL2 بهدام میاندازد و بهعنوان پراکسی بین میزبان و پایشگر امن در EL3 عمل میکند.
تماسهای PSCI از میزبان با حداقل تغییرات به میانافزار EL3 بازارسال میشوند. بهطور خاص، نقطه ورودی برای CPU که آنلاین میشود یا از حالت تعلیق ازسر گرفته میشود بازنویسی میشود تا جدول صفحه مرحله ۲ قبلاز بازگشت به میزبان در EL1، در EL2 نصب شود. درطول راهاندازی، این محافظت توسط pKVM اعمال میشود.
این معماری به SoC متکی است که از PSCI پشتیبانی کند، ترجیحاً ازطریق استفاده از نسخه بهروز TF-A بهعنوان میانافزار EL3 خود.
استاندارد «چارچوب میانافزار برای Arm» (FF-A) تعاملات بین دنیای عادی و امن را استانداردسازی میکند، بهویژه در حضور یک سرپرست امن. بخش عمدهای از مشخصات، سازوکاری را برای همرسانی حافظه با دنیای امن تعریف میکند که از هر دو قالب پیام مشترک و مدل اجازههای خوشتعریف برای صفحههای زیرین استفاده میکند. کارگزاران pKVM پیامهای FF-A را برای اطمینان از اینکه میزبان تلاش نمیکند حافظه را با طرف امنی که اجازههای کافی برای آن ندارد همرسانی کند، پراکسی میکنند.
این معماری به نرمافزار دنیای امن متکی است که مدل دسترسی به حافظه را اجرا میکند تا اطمینان حاصل شود که برنامههای مورداعتماد و هر نرمافزار دیگری که در دنیای امن اجرا میشود، تنها درصورتی میتوانند به حافظه دسترسی داشته باشند که یا بهطور انحصاری متعلق به دنیای امن باشد یا بهطور صریح بااستفاده از FF-A با آن همرسانی شده باشد. در سیستمی با S-EL2، اعمال مدل دسترسی به حافظه باید توسط «هسته مدیر پارتیشن امن» (SPMC) انجام شود، برای مثال Hafnium، که جدولهای صفحه مرحله ۲ را برای دنیای امن حفظ میکند. در سیستمهای فاقد S-EL2، TEE میتواند بهجای آن مدل دسترسی به حافظه را ازطریق جدولهای صفحه مرحله ۱ خود اعمال کند.
اگر تماس SMC با EL2 تماس PSCI یا پیام تعریفشده FF-A نباشد، SMCهای مدیریتنشده به EL3 بازارسال میشوند. فرض بر این است که سفتافزار ایمن (که لزوماً قابلاعتماد است) میتواند SMCهای مدیریتنشده را بهطور ایمن مدیریت کند زیرا سفتافزار اقدامات احتیاطی لازم برای حفظ جداسازی pVM را درک میکند.
پایشگر ماشین مجازی
crosvm یک پایشگر ماشین مجازی (VMM) است که ماشینهای مجازی را ازطریق میانای KVM در Linux اجرا میکند. آنچه crosvm را منحصربهفرد میکند تمرکز آن بر ایمنی بااستفاده از زبان برنامهنویسی Rust و محیط امن اطراف دستگاههای مجازی برای محافظت از هسته میزبان است. برای اطلاعات بیشتر درباره crosvm، به مستندات رسمی آن در اینجا مراجعه کنید.
توصیفگرهای فایل و ioctl
KVM دستگاه نویسه /dev/kvm را با ioctlهایی که
میانای برنامهسازی کاربردی KVM را تشکیل میدهند در فضای کاربر آشکار میکند. ioctls به دستههای زیر تعلق دارد:
- سیستم ioctls ویژگیهای سراسری را که بر کل زیرسیستم KVM تأثیر میگذارد پُرسمان و تنظیم میکند و pVM ایجاد میکند.
- VM ioctls مشخصههایی را که واحدهای پردازش مرکزی مجازی (vCPUs) و دستگاهها را ایجاد میکنند پُرسمان و تنظیم میکند و بر کل pVM تأثیر میگذارد، مثلاً شامل چیدمان حافظه و تعداد واحدهای پردازش مرکزی مجازی (vCPUs) و دستگاهها میشود.
- پرسش و تنظیم ویژگیهای ioctl vCPU که عملکرد یک واحد پردازش مرکزی مجازی را کنترل میکند.
- ioctls دستگاه مشخصههایی را که عملکرد یک دستگاه مجازی را کنترل میکنند، جستجو و تنظیم میکند.
هر فرایند crosvm دقیقاً یک نمونه از ماشین مجازی را اجرا میکند. این فرایند
از ioctl سیستم KVM_CREATE_VM برای ایجاد توصیفگر فایل VM استفاده میکند که میتواند
برای صدور ioctlهای pVM استفاده شود. KVM_CREATE_VCPU یا KVM_CREATE_DEVICE ioctl
در VM FD یک vCPU/دستگاه ایجاد میکند و توصیفگر فایلی را برمیگرداند که به
منبع جدید اشاره میکند. از ioctl در vCPU یا دستگاه FD میتوان برای کنترل دستگاهی که
بااستفاده از ioctl در VM FD ایجاد شده است استفاده کرد. برای vCPU، این شامل تکلیف مهم اجرای کد مهمان میشود.
در داخل، crosvm توصیفگرهای فایل ماشین مجازی را بااستفاده از میانای epoll لبهراهانداز در هسته ثبت میکند. سپس هسته هرگاه رویداد جدیدی در هریک از توصیفگرهای فایل درانتظار باشد به crosvm اطلاع میدهد.
pKVM قابلیت جدیدی به نام KVM_CAP_ARM_PROTECTED_VM اضافه میکند که میتوان از آن برای
دریافت اطلاعات درباره محیط pVM و راهاندازی حالت محافظتشده برای ماشین مجازی استفاده کرد.
اگر پرچم --protected-vm ارسال شود، crosvm از این قابلیت درطول ایجاد pVM استفاده میکند
تا مقدار مناسب حافظه را برای
سختافزار pVM پُرسمان و رزرو کند و سپس حالت محافظتشده را فعال کند.
تخصیص حافظه
یکی از مسئولیتهای اصلی VMM تخصیص حافظه ماشین مجازی و مدیریت چیدمان حافظه آن است. crosvm چیدمان حافظه ثابتی را که بهطور کلی در جدول زیر توضیح داده شده است تولید میکند.
| FDT در حالت عادی | PHYS_MEMORY_END - 0x200000
|
| فضای آزاد | ...
|
| Ramdisk | ALIGN_UP(KERNEL_END, 0x1000000)
|
| مرکزی | 0x80080000
|
| راهانداز سیستم | 0x80200000
|
| FDT در حالت سامانه ورودی/خروجی پایه | 0x80000000
|
| پایه حافظه فیزیکی | 0x80000000
|
| سفتافزار pVM | 0x7FE00000
|
| فضای ذخیرهسازی دستگاه | 0x10000 - 0x40000000
|
حافظه فیزیکی با mmap اختصاص داده میشود و حافظه به ماشین مجازی اهدا میشود تا
مناطق حافظه آن، که مکانهای حافظه نامیده میشود، با
KVM_SET_USER_MEMORY_REGION ioctl پر شود. بنابراین، همه حافظه pVM مهمان به نمونه crosvm که آن را مدیریت میکند نسبت داده میشود و اگر میزبان با کمبود حافظه آزاد مواجه شود، ممکن است منجر به کشته شدن فرایند (پایان دادن به VM) شود. وقتی ماشین مجازی متوقف میشود، حافظه بهطور خودکار توسط
سرپرست پاک میشود و به هسته میزبان برمیگردد.
در KVM معمولی، VMM دسترسی به همه حافظه مهمان را حفظ میکند. با pKVM، وقتی حافظه مهمان به مهمان اهدا میشود، حافظه مهمان از فضای نشانی فیزیکی میزبان لغو تخصیص میشود. تنها استثنا حافظهای است که صریحاً توسط مهمان همرسانی شده است، مانند دستگاههای virtio.
مناطق MMIO در فضای نشانی مهمان بدون نگاشت باقی میمانند. دسترسی مهمان به این مناطق بهدام میافتد و منجر به رویداد ورودی/خروجی در توصیفگر فایل ماشین مجازی میشود. از این سازوکار برای پیادهسازی دستگاههای مجازی استفاده میشود. در حالت محافظتشده، مهمان باید بااستفاده از یک ابرتماس تأیید کند که ناحیهای از فضای نشانی آن برای MMIO استفاده میشود تا خطر نشت تصادفی اطلاعات کاهش یابد.
برنامهریزی کردن
هر CPU مجازی با یک رشته POSIX نشان داده میشود و توسط زمانبند Linux میزبان زمانبندی میشود. رشته KVM_RUN ioctl را در vCPU FD فرا میخواند که منجر به
رفتن hypervisor به زمینه vCPU مهمان میشود. زمانبند میزبان
زمان صرفشده در زمینه مهمان را بهعنوان زمان استفادهشده توسط رشته vCPU مربوطه
درنظر میگیرد. KVM_RUN زمانی برمیگردد که رویدادی وجود داشته باشد که باید توسط
VMM مدیریت شود، مانند I/O، پایان وقفه، یا توقف vCPU. «ماشین مجازی» رویداد را مدیریت میکند و دوباره KVM_RUN را فرا میخواند.
درطول KVM_RUN، رشته توسط زمانبند میزبان قابل پیشگیری باقی میماند، بهجز
برای اجرای کد سرپرست EL2 که قابل پیشگیری نیست. خود pVM مهمان هیچ سازوکاری برای کنترل این رفتار ندارد.
ازآنجاییکه همه رشتههای vCPU مانند سایر وظایف فضای کاربر زمانبندی میشوند، مشمول همه سازوکارهای استاندارد QoS هستند. بهطور خاص، هر رشته vCPU میتواند به CPU فیزیکی اختصاص داده شود، در مجموعههای CPU قرار گیرد، بااستفاده از محدود کردن استفاده تقویت یا محدود شود، اولویت/خطمشی زمانبندی آن تغییر کند، و غیره.
دستگاههای مجازی
crosvm از تعدادی دستگاه، ازجمله موارد زیر، پشتیبانی میکند:
- virtio-blk برای تصاویر دیسک ترکیبی، فقط خواندنی یا خواندنی-نوشتنی
- vhost-vsock برای ارتباط با میزبان
- virtio-pci بهعنوان انتقال virtio
- ساعت همزمان (RTC) pl030
- 16550a UART برای ارتباط سریال
سفتافزار pVM
سفتافزار pVM (pvmfw) اولین کدی است که توسط pVM اجرا میشود، مشابه ROM راهاندازی دستگاه فیزیکی. هدف اصلی pvmfw راهاندازی راهاندازی امن و استخراج رمز یکتای pVM است. pvmfw محدود به استفاده با سیستمعامل خاصی، مانند Microdroid، نیست، بهشرطی که سیستمعامل توسط crosvm پشتیبانی شود و بهدرستی امضا شده باشد.
دودویی pvmfw در بخش فلش با همین نام ذخیره میشود و بااستفاده از OTA بهروز میشود.
راهاندازی دستگاه
توالی مراحل زیر به فرایند راهاندازی دستگاه دارای pKVM اضافه میشود:
- «بارکننده Android» (ABL) pvmfw را از پارتیشن آن در حافظه بار میکند و تصویر را درستیسنجی میکند.
- ABL رمزهای «موتور ترکیب شناسه دستگاه» (DICE) خود را (شناسههای دستگاه مرکب (CDI) و زنجیره گواهی DICE) از «ریشه اعتماد» دریافت میکند.
- ABL شناسه دستگاه مرکب لازم را برای pvmfw استخراج میکند و آنها را به باینری pvmfw اضافه میکند.
- ABL گره منطقه حافظه رزروشده
linux,pkvm-guest-firmware-memoryرا به DT اضافه میکند و مکان و اندازه باینری pvmfw و رمزهایی را که در مرحله قبلی استخراج کرده است توصیف میکند. - ABL کنترل را به Linux واگذار میکند و Linux pKVM را مقداردهی اولیه میکند.
- pKVM ناحیه حافظه pvmfw را از جدولهای صفحه مرحله ۲ میزبان لغو میکند و درطول زمان کار دستگاه آن را دربرابر میزبان (و مهمانان) محافظت میکند.
پساز راهاندازی دستگاه، Microdroid طبق مراحل بخش ترتیب راهاندازی سند Microdroid راهاندازی میشود.
راهاندازی pVM
هنگام ایجاد pVM، crosvm (یا VMM دیگر) باید memslot بهاندازه کافی بزرگ ایجاد کند تا hypervisor بتواند تصویر pvmfw را در آن قرار دهد. VMM همچنین در فهرست ثباتهایی که میتواند مقدار اولیه آنها را تنظیم کند محدود شده است (x0-x14 برای vCPU اولیه، هیچکدام برای vCPU ثانویه). ثبتهای باقیمانده رزرو شدهاند و بخشی از hypervisor-pvmfw ABI هستند.
وقتی pVM اجرا میشود، ابتدا سرپرست کنترل vCPU اصلی را به pvmfw واگذار میکند. میانافزار انتظار دارد crosvm هسته امضاشده AVB را بار کرده باشد،
که میتواند یک بارکننده یا هر تصویر دیگری باشد، و FDT بدون امضا را در
آدرسهای جابهجایی شناختهشده در حافظه بار کرده باشد. pvmfw امضای AVB را اعتبارسنجی میکند و درصورت موفقیت،
درخت دستگاه مطمئنی از FDT دریافتی تولید میکند، اسرار آن را از
حافظه پاک میکند، و به نقطه ورودی بار اصلی انشعاب میدهد. اگر یکی از
مراحل درستیسنجی ناموفق باشد، سفتافزار یک فرادرخواست PSCI SYSTEM_RESET صادر میکند.
بین بوتها، اطلاعات مربوط به نمونه pVM در پارتیشن (دستگاه virtio-blk) ذخیره میشود و با رمز pvmfw رمزگذاری میشود تا اطمینان حاصل شود که پساز بازراهاندازی، رمز در نمونه صحیح آماده میشود.