میکرودروئید

Microdroid یک سیستم عامل مینی اندروید است که در یک pVM اجرا می شود. شما نیازی به استفاده از Microdroid ندارید، می توانید VM را با هر سیستم عاملی راه اندازی کنید. با این حال، موارد استفاده اولیه برای pVM ها یک سیستم عامل مستقل را اجرا نمی کنند، بلکه یک محیط اجرای ایزوله برای اجرای بخشی از یک برنامه با ضمانت های محرمانه و یکپارچگی قوی تر از آنچه اندروید می تواند ارائه دهد، ارائه می دهند.

با سیستم عامل های سنتی، ارائه محرمانه بودن و یکپارچگی قوی نیاز به مقدار زیادی کار (اغلب تکراری) دارد، زیرا سیستم عامل های سنتی با معماری کلی اندروید سازگاری ندارند. به عنوان مثال، با معماری استاندارد اندروید، توسعه‌دهندگان باید ابزاری را برای بارگذاری و اجرای ایمن بخشی از برنامه خود در pVM پیاده‌سازی کنند، و payload بر اساس glibc ساخته شده است. برنامه اندروید از Bionic استفاده می کند، ارتباط نیاز به یک پروتکل سفارشی روی vsock دارد و اشکال زدایی با استفاده از adb چالش برانگیز است.

Microdroid این شکاف‌ها را با ارائه یک تصویر سیستم‌عامل خارج از قفسه پر می‌کند که به کمترین تلاش توسعه‌دهندگان نیاز دارد تا بخشی از برنامه خود را در یک pVM بارگذاری کنند. کد بومی بر خلاف Bionic ساخته شده است، ارتباطات از طریق Binder انجام می شود، و اجازه می دهد تا APEX ها را از Android وارد کنید و زیرمجموعه ای از API Android، مانند keystore برای عملیات رمزنگاری با کلیدهای سخت افزاری را در معرض دید قرار دهید. به طور کلی، توسعه دهندگان باید Microdroid را با ابزارهایی که در سیستم عامل اندروید کامل عادت کرده اند، محیطی آشنا بدانند.

امکانات

Microdroid یک نسخه حذف شده از اندروید با چند مؤلفه اضافی خاص برای pVM است. Microdroid پشتیبانی می کند:

  • زیرمجموعه ای از APIهای NDK (همه APIها برای اجرای libc و Bionic در اندروید ارائه شده است)
  • ویژگی های اشکال زدایی مانند adb، logcat، tombstone و gdb
  • بوت تایید شده و SELinux فعال هستند
  • بارگیری و اجرای یک باینری، همراه با کتابخانه های مشترک، جاسازی شده در یک APK
  • Binder RPC روی vsock و تبادل فایل ها با بررسی صحت ضمنی
  • بارگیری APEX ها

Microdroid پشتیبانی نمی کند:

  • API های Android Java در بسته های android.\*

  • SystemServer و Zygote

  • گرافیک/UI

  • HAL ها

معماری میکرودروئید

Microdroid شبیه Cuttlefish است که هر دو دارای معماری مشابه اندروید استاندارد هستند. Microdroid از تصاویر پارتیشن زیر تشکیل شده است که در یک تصویر دیسک کامپوزیت گروه بندی شده اند:

  • bootloader - کرنل را تأیید و راه اندازی می کند.
  • boot.img - حاوی کرنل و ramdisk init است.
  • vendor_boot.img - شامل ماژول های هسته ویژه VM مانند virtio است.
  • super.img - از پارتیشن های منطقی سیستم و فروشنده تشکیل شده است.
  • vbmeta.img - حاوی فراداده بوت تایید شده است.

تصاویر پارتیشن در Virtualization APEX ارسال می شوند و توسط VirtualizationService در یک تصویر دیسک ترکیبی بسته بندی می شوند. علاوه بر تصویر دیسک ترکیبی اصلی سیستم عامل، VirtualizationService مسئول ایجاد این پارتیشن‌های دیگر است:

  • payload - مجموعه ای از پارتیشن ها که توسط APEX ها و APK های اندروید پشتیبانی می شوند
  • instance - یک پارتیشن رمزگذاری شده برای ماندگاری داده های بوت تایید شده هر نمونه، مانند salt هر نمونه، کلیدهای عمومی APEX قابل اعتماد، و شمارنده های برگشتی

دنباله بوت

دنباله راه‌اندازی Microdroid پس از راه‌اندازی دستگاه رخ می‌دهد. راه اندازی دستگاه در سند معماری مورد بحث قرار گرفته است. شکل 1 مراحلی را نشان می دهد که در طول دنباله بوت Microdroid انجام می شود:

بوت فلو ایمن نمونه میکرودروئید

شکل 1. جریان راه انداز ایمن نمونه میکرودروئید

در اینجا توضیحی در مورد مراحل ارائه شده است:

  1. بوت لودر توسط crosvm در حافظه بارگذاری می شود و pvmfw شروع به اجرا می کند. قبل از پرش به بوت لودر، pvmfw دو کار را انجام می دهد:

    • بوت لودر را تأیید می کند تا بررسی کند که آیا از یک منبع قابل اعتماد (Google یا OEM) است یا خیر.
    • اطمینان حاصل می کند که بوت لودر یکسان به طور مداوم در چندین بوت یک pVM از طریق استفاده از تصویر نمونه استفاده می شود. به طور خاص، pVM در ابتدا با یک تصویر نمونه خالی بوت می شود. pvmfw هویت بوت لودر را در تصویر نمونه ذخیره می کند و آن را رمزگذاری می کند. بنابراین، دفعه بعد که pVM با همان تصویر نمونه بوت می‌شود، pvmfw هویت ذخیره‌شده را از تصویر نمونه رمزگشایی می‌کند و تأیید می‌کند که همان چیزی است که قبلاً ذخیره شده است. اگر هویت ها متفاوت باشد، pvmfw از بوت کردن خودداری می کند.

    سپس بوت لودر Microdroid را بوت می کند.

  2. بوت لودر به دیسک نمونه دسترسی پیدا می کند. مشابه pvmfw، بوت لودر دارای یک درایو دیسک نمونه با اطلاعات مربوط به تصاویر پارتیشن مورد استفاده در این نمونه در طول بوت های قبلی، از جمله کلید عمومی است.

  3. بوت لودر vbmeta و پارتیشن‌های زنجیره‌ای مانند boot و super را تأیید می‌کند و در صورت موفقیت، اسرار pVM مرحله بعدی را استخراج می‌کند. سپس، Microdroid کنترل را به هسته می‌دهد.

  4. از آنجایی که پارتیشن فوق قبلاً توسط بوت لودر تأیید شده است (مرحله 3)، هسته بدون قید و شرط پارتیشن فوق العاده را سوار می کند. همانند اندروید کامل، پارتیشن فوق‌العاده شامل چندین پارتیشن منطقی است که روی dm-verity نصب شده‌اند. سپس کنترل به فرآیند init منتقل می شود، که خدمات بومی مختلف را شروع می کند. اسکریپت init.rc شبیه اسکریپت اندروید کامل است اما متناسب با نیازهای Microdroid است.

  5. فرآیند init مدیر Microdroid را شروع می کند که به تصویر نمونه دسترسی پیدا می کند. سرویس مدیر Microdroid تصویر را با استفاده از کلید ارسال شده از مرحله قبل رمزگشایی می‌کند و کلیدهای عمومی و شمارنده‌های برگشتی APK و APEXهای مشتری را که این pVM به آنها اعتماد دارد، می‌خواند. این اطلاعات بعداً توسط zipfuse و apexd هنگامی که به ترتیب APK کلاینت و درخواست APEX را نصب می کنند، استفاده می شود.

  6. سرویس مدیر Microdroid apexd شروع می شود.

  7. apexd APEX ها را در دایرکتوری های /apex/<name> سوار می کند. تنها تفاوت بین Android و Microdroid mounta 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 باز می گردد. سپس سرویس مدیر با استفاده از Binder RPC با VirtualizationService اندروید ارتباط برقرار می کند تا بتواند رویدادهای مهمی مانند خرابی یا خاموش شدن را گزارش کند و درخواست هایی مانند خاتمه دادن به pVM را بپذیرد. سرویس مدیر مکان باینری اصلی را از فایل پیکربندی APK می خواند و آن را اجرا می کند.

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

معمولاً اجزای Android از فایل‌ها برای ورودی، خروجی و حالت استفاده می‌کنند و آن‌ها را به‌عنوان توصیف‌گر فایل (نوع ParcelFileDescriptor در AIDL) با دسترسی کنترل‌شده توسط هسته آندروید ارسال می‌کنند. AuthFS عملکرد مشابهی را برای تبادل فایل‌ها بین نقاط پایانی بی‌اعتماد متقابل در مرزهای pVM تسهیل می‌کند.

اساساً، AuthFS یک سیستم فایل از راه دور با بررسی یکپارچگی شفاف در عملیات دسترسی فردی است، شبیه به fs-verity . بررسی‌ها به فرانت‌اند، مانند یک برنامه خواندن فایل که در یک pVM اجرا می‌شود، اجازه می‌دهد تا تشخیص دهد که آیا باطن نامعتبر، معمولاً Android، محتوای فایل را دستکاری کرده است یا خیر.

برای تبادل فایل‌ها، backend ( fd\_server ) با پیکربندی هر فایل شروع می‌شود و مشخص می‌کند که آیا برای ورودی (فقط خواندنی) یا خروجی (خواندن-نوشتن) است. برای ورودی، فرانت‌اند الزام می‌کند که محتویات با یک هش شناخته‌شده مطابقت داشته باشد، در بالای درخت Merkle برای تأیید دسترسی. برای خروجی، AuthFS به صورت داخلی یک درخت هش از محتویات مشاهده شده از عملیات نوشتن را حفظ می کند و می تواند یکپارچگی را هنگام بازخوانی داده ها اعمال کند.

حمل و نقل اساسی در حال حاضر بر اساس Binder RPC است، با این حال ممکن است در آینده برای بهینه سازی عملکرد تغییر کند.

مدیریت کلیدی

pVM ها دارای یک کلید مهر و موم پایدار است که برای داده های پایدار محافظت شده مناسب است، و یک کلید تصدیق که برای تولید امضاهایی که به طور قابل تایید توسط pVM تولید می شوند، مناسب است.

بایندر RPC

اکثر رابط های اندروید در AIDL بیان می شوند که در بالای درایور هسته لینوکس Binder ساخته شده است. برای پشتیبانی از رابط های بین pVM ها، پروتکل Binder بازنویسی شده است تا روی سوکت ها کار کند، در مورد pVM ها vsock . کار بر روی سوکت ها اجازه می دهد تا از رابط های AIDL موجود اندروید در این محیط جدید استفاده شود.

برای راه اندازی اتصال، یک نقطه پایانی، مانند بارگذاری pVM، یک شی RpcServer ایجاد می کند، یک شی ریشه را ثبت می کند و شروع به گوش دادن برای اتصالات جدید می کند. کلاینت ها می توانند با استفاده از یک شی RpcSession به این سرور متصل شوند، شی Binder را دریافت کنند و دقیقاً مانند شی Binder که با درایور هسته Binder استفاده می شود، از آن استفاده کنند.