Microdroid là một hệ điều hành Android mini chạy trong pVM. Bạn không cần phải sử dụng Microdroid, bạn có thể khởi động một VM bằng bất kỳ hệ điều hành nào. Tuy nhiên, các trường hợp sử dụng chính cho pVM không phải là chạy một hệ điều hành độc lập mà là cung cấp một môi trường thực thi riêng biệt để chạy một phần của ứng dụng với các biện pháp đảm bảo tính bảo mật và tính toàn vẹn mạnh mẽ hơn so với những gì Android có thể cung cấp.
Với các hệ điều hành truyền thống, việc cung cấp tính bảo mật và tính toàn vẹn mạnh mẽ đòi hỏi một lượng công việc khá lớn (thường bị trùng lặp) vì các hệ điều hành truyền thống không phù hợp với cấu trúc tổng thể của Android. Ví dụ: với cấu trúc Android tiêu chuẩn, nhà phát triển cần triển khai một phương tiện tải và thực thi một cách an toàn một phần của ứng dụng trong pVM, đồng thời tải trọng được xây dựng dựa trên glibc. Ứng dụng Android sử dụng Bionic, giao tiếp yêu cầu một giao thức tuỳ chỉnh qua vsock và việc gỡ lỗi bằng adb là một thách thức.
Microdroid lấp đầy những khoảng trống này bằng cách cung cấp một hình ảnh hệ điều hành có sẵn được thiết kế để yêu cầu nhà phát triển nỗ lực ít nhất có thể để giảm tải một phần của ứng dụng vào pVM. Mã gốc được xây dựng dựa trên Bionic, giao tiếp diễn ra qua Binder và cho phép nhập APEX từ Android máy chủ, đồng thời hiển thị một tập hợp con của API Android, chẳng hạn như keystore cho các thao tác mã hoá bằng các khoá được phần cứng hỗ trợ. Nhìn chung, nhà phát triển sẽ thấy Microdroid là một môi trường quen thuộc với các công cụ mà họ đã quen dùng trong hệ điều hành Android đầy đủ.
Tính năng
Microdroid là phiên bản rút gọn của Android với một vài thành phần bổ sung dành riêng cho pVM. Microdroid hỗ trợ:
- Một tập hợp con của API NDK (tất cả API cho việc triển khai libc và Bionic của Android đều được cung cấp)
- Các tính năng gỡ lỗi, chẳng hạn như adb, logcat, tombstone và gdb
- Xác minh quy trình khởi động và SELinux
- Tải và thực thi một tệp nhị phân, cùng với các thư viện dùng chung, được nhúng trong một APK
- Binder RPC qua vsock và trao đổi tệp với các quy trình kiểm tra tính toàn vẹn ngầm ẩn
- Tải APEX
Microdroid không hỗ trợ:
API Java Android trong các gói
android.\*SystemServer và Zygote
Đồ hoạ/giao diện người dùng
HAL
Cấu trúc Microdroid
Microdroid tương tự như Cuttlefish ở chỗ cả hai đều có cấu trúc tương tự như Android tiêu chuẩn. Microdroid bao gồm các hình ảnh phân vùng sau đây được nhóm lại trong một hình ảnh đĩa tổng hợp:
bootloader– Xác minh và khởi động kernel.boot.img– Chứa kernel và init ramdisk.vendor_boot.img– Chứa các mô-đun kernel dành riêng cho VM, chẳng hạn như virtio.super.img– Bao gồm các phân vùng logic của hệ thống và nhà cung cấp.vbmeta.img– Chứa siêu dữ liệu xác minh quy trình khởi động.
Các hình ảnh phân vùng được vận chuyển trong APEX ảo hoá và được đóng gói trong một hình ảnh đĩa tổng hợp bằng VirtualizationService. Ngoài hình ảnh đĩa tổng hợp chính của hệ điều hành, VirtualizationService chịu trách nhiệm tạo các phân vùng khác sau đây:
payload– Một tập hợp các phân vùng được hỗ trợ bởi APEX và APK của Androidinstance– Một phân vùng được mã hoá để duy trì dữ liệu Xác minh quy trình khởi động cho mỗi thực thể, chẳng hạn như dữ liệu ngẫu nhiên cho mỗi thực thể, khoá công khai APEX đáng tin cậy và bộ đếm khôi phục
Trình tự khởi động
Trình tự khởi động Microdroid xảy ra sau khi Khởi động thiết bị. Quy trình khởi động thiết bị được thảo luận trong phần Phần sụn pVM của tài liệu Cấu trúc. Hình 1 cho thấy các bước diễn ra trong trình tự khởi động Microdroid:
Sau đây là phần giải thích về các bước:
Trình tải khởi động được crosvm tải vào bộ nhớ và pvmfw bắt đầu thực thi. Trước khi chuyển sang trình tải khởi động, pvmfw thực hiện 2 tác vụ:
- Xác minh trình tải khởi động để kiểm tra xem trình tải khởi động đó có phải từ một nguồn đáng tin cậy (Google hoặc OEM) hay không.
- Đảm bảo rằng cùng một trình tải khởi động được sử dụng nhất quán trên nhiều lần khởi động của cùng một pVM thông qua việc sử dụng hình ảnh thực thể. Cụ thể, pVM ban đầu được khởi động bằng một hình ảnh thực thể trống. pvmfw lưu trữ danh tính của trình tải khởi động trong hình ảnh thực thể và mã hoá danh tính đó. Vì vậy, vào lần tiếp theo khi pVM được khởi động bằng cùng một hình ảnh thực thể, pvmfw sẽ giải mã danh tính đã lưu từ hình ảnh thực thể và xác minh rằng danh tính đó giống với danh tính đã lưu trước đó. Nếu danh tính khác nhau, pvmfw sẽ từ chối khởi động.
Sau đó, trình tải khởi động sẽ khởi động Microdroid.
Trình tải khởi động truy cập vào đĩa thực thể. Tương tự như pvmfw, trình tải khởi động có một ổ đĩa thực thể chứa thông tin về các hình ảnh phân vùng được sử dụng trong thực thể này trong các lần khởi động trước, bao gồm cả khoá công khai.
Trình tải khởi động xác minh vbmeta và các phân vùng được liên kết, chẳng hạn như
bootvàsuper, đồng thời, nếu thành công, sẽ lấy các bí mật pVM ở giai đoạn tiếp theo. Sau đó, Microdroid sẽ chuyển quyền kiểm soát cho kernel.Vì phân vùng super đã được trình tải khởi động xác minh (bước 3), nên kernel sẽ gắn phân vùng super một cách vô điều kiện. Giống như Android đầy đủ, phân vùng super bao gồm nhiều phân vùng logic được gắn trên dm-verity. Sau đó, quyền kiểm soát sẽ được chuyển cho quy trình
init, quy trình này sẽ khởi động nhiều dịch vụ gốc. Tập lệnhinit.rctương tự như tập lệnh của Android đầy đủ nhưng được điều chỉnh cho phù hợp với nhu cầu của Microdroid.Quy trình
initkhởi động trình quản lý Microdroid, trình quản lý này sẽ truy cập vào hình ảnh thực thể. Dịch vụ trình quản lý Microdroid giải mã hình ảnh bằng khoá được chuyển từ giai đoạn trước và đọc các khoá công khai và bộ đếm quay lui của APK và APEX ứng dụng mà pVM này tin cậy.zipfusevàapexdsẽ sử dụng thông tin này sau đó khi chúng gắn APK ứng dụng và các APEX được yêu cầu.Dịch vụ trình quản lý Microdroid khởi động
apexd.apexdgắn các APEX vào các thư mục/apex/<name>. Điểm khác biệt duy nhất giữa cách Android và Microdroid gắn các APEX là trong Microdroid, các tệp APEX đến từ các thiết bị khối ảo (/dev/vdc1, …), chứ không phải từ các tệp thông thường (/system/apex/*.apex).zipfuselà hệ thống tệp FUSE của Microdroid.zipfusegắn APK ứng dụng, về cơ bản là một tệp Zip dưới dạng hệ thống tệp. Bên dưới, tệp APK được chuyển dưới dạng thiết bị khối ảo bởi pVM có dm-verity, giống như APEX. APK chứa một tệp cấu hình có danh sách các APEX mà nhà phát triển ứng dụng đã yêu cầu cho thực thể pVM này.apexdsử dụng danh sách này khi kích hoạt các APEX.Luồng khởi động quay lại dịch vụ trình quản lý Microdroid. Sau đó, dịch vụ trình quản lý giao tiếp với
VirtualizationServicecủa Android bằng Binder RPC để có thể báo cáo các sự kiện quan trọng như sự cố hoặc tắt máy và chấp nhận các yêu cầu như chấm dứt pVM. Dịch vụ trình quản lý đọc vị trí của tệp nhị phân chính từ tệp cấu hình của APK và thực thi tệp nhị phân đó.
Trao đổi tệp (AuthFS)
Các thành phần Android thường sử dụng tệp cho dữ liệu đầu vào, đầu ra và trạng thái, đồng thời chuyển các tệp này dưới dạng bộ mô tả tệp (loại ParcelFileDescriptor trong AIDL) với quyền truy cập được kiểm soát bởi kernel Android. AuthFS tạo điều kiện cho chức năng tương tự để trao đổi tệp giữa các điểm cuối không tin tưởng lẫn nhau trên các ranh giới pVM.
Về cơ bản, AuthFS là một hệ thống tệp từ xa có các quy trình kiểm tra tính toàn vẹn minh bạch trên các thao tác truy cập riêng lẻ, tương tự như fs-verity. Các quy trình kiểm tra cho phép giao diện người dùng, chẳng hạn như một chương trình đọc tệp chạy trong pVM, phát hiện xem phần phụ trợ không đáng tin cậy (thường là Android) có can thiệp vào nội dung tệp hay không.
Để trao đổi tệp, phần phụ trợ (fd\_server) được khởi động với cấu hình cho mỗi tệp, chỉ định xem tệp đó dành cho dữ liệu đầu vào (chỉ đọc) hay đầu ra (đọc-ghi). Đối với dữ liệu đầu vào, giao diện người dùng sẽ thực thi để nội dung khớp với một hàm băm đã biết, trên cây Merkle để xác minh khi truy cập. Đối với dữ liệu đầu ra, AuthFS sẽ duy trì nội bộ một cây hàm băm của nội dung được quan sát từ các thao tác ghi và có thể thực thi tính toàn vẹn khi dữ liệu được đọc lại.
Phương tiện truyền tải cơ bản hiện dựa trên Binder RPC, tuy nhiên, phương tiện này có thể thay đổi trong tương lai để tối ưu hoá hiệu suất.
Quản lý khoá
pVM được cung cấp một khoá niêm phong ổn định phù hợp để bảo vệ dữ liệu liên tục và một khoá chứng thực phù hợp để tạo chữ ký có thể xác minh được do pVM tạo.
Binder RPC
Phần lớn các giao diện của Android được biểu thị trong AIDL, được xây dựng dựa trên trình điều khiển kernel Binder Linux. Để hỗ trợ các giao diện giữa các pVM, giao thức Binder đã được viết lại để hoạt động trên các socket, vsock trong trường hợp pVM. Việc hoạt động trên các socket cho phép sử dụng các giao diện AIDL hiện có của Android trong môi trường mới này.
Để thiết lập kết nối, một điểm cuối, chẳng hạn như tải trọng pVM, sẽ tạo một đối tượng RpcServer, đăng ký một đối tượng gốc và bắt đầu lắng nghe các kết nối mới. Ứng dụng có thể kết nối với máy chủ này bằng đối tượng RpcSession, lấy đối tượng Binder và sử dụng đối tượng đó giống hệt như cách đối tượng Binder được sử dụng với trình điều khiển Binder kernel.