Microdroid là một hệ điều hành Android thu nhỏ 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 biệt lập để chạy một phần của ứng dụng với các đảm bảo mạnh mẽ hơn về tính bảo mật và tính toàn vẹ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 khả năng bảo mật và tính toàn vẹn cao đòi hỏi khá nhiều công sức (thường là công sức 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 thức tải và thực thi một phần ứng dụng của họ một cách an toàn trong pVM, đồng thời tải trọng được tạo dựa trên glibc. Ứng dụng Android sử dụng Bionic, hoạt động 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 tốn ít công sức nhất để chuyển một phần ứng dụng của họ vào pVM. Mã gốc được tạo dựa trên Bionic, hoạt động giao tiếp diễn ra qua Binder và cho phép nhập APEX từ Android lưu trữ, đồng thời hiển thị một nhóm nhỏ API Android, chẳng hạn như kho khoá cho các hoạt động mã hoá bằng khoá dựa trên phần cứng. Nhìn chung, các nhà phát triển sẽ thấy Microdroid là một môi trường quen thuộc với những công cụ mà họ đã quen dùng trong hệ điều hành Android đầy đủ.
Tính năng
Microdroid là một phiên bản rút gọn của Android với một số thành phần bổ sung dành riêng cho pVM. Microdroid hỗ trợ:
- Một tập hợp con gồm các API NDK (cung cấp tất cả API cho việc triển khai libc và Bionic của Android)
- 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 bước kiểm tra tính toàn vẹn ngầm
- Đang tải APEX
Microdroid không hỗ trợ:
API Java Android trong các gói
android.\*
SystemServer và Zygote
Đồ họa/giao diện người dùng
HAL
Cấu trúc Microdroid
Microdroid tương tự như Cuttlefish ở chỗ cả hai đều có một 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 với nhau trong một hình ảnh đĩa kết hợp:
bootloader
– Xác minh và khởi động nhân.boot.img
– Chứa nhân và ổ đĩa ngẫu nhiên khởi động.vendor_boot.img
– Chứa các mô-đun hạt nhân 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 của tính năng Xác minh quy trình khởi động.
Các hình ảnh phân vùng được chuyển trong APEX ảo hoá và được đóng gói trong một hình ảnh đĩa kết hợp của VirtualizationService
. Ngoài hình ảnh đĩa tổng hợp của hệ điều hành chính, VirtualizationService
còn 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 khởi động đã xác minh cho mỗi phiên bản, chẳng hạn như giá trị nhận dạng duy nhất cho mỗi phiên bản, khoá công khai APEX đáng tin cậy và bộ đếm quay lui
Trình tự khởi động
Trình tự khởi động Microdroid diễn ra sau khi Khởi động thiết bị. Quá trình khởi động thiết bị được thảo luận trong phần Chương trình cơ sở pVM của tài liệu Kiến 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 sẽ 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 là của một nguồn đáng tin cậy (Google hoặc một 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 phiên bản. 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 khởi động bằng cùng một hình ảnh phiên bản, pvmfw sẽ giải mã danh tính đã lưu từ hình ảnh phiên bản và xác minh rằng danh tính đó giống với danh tính đã được lưu trước đó. Nếu các 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 phiên bản. Tương tự như pvmfw, trình tải khởi động có một ổ đĩa phiên bản chứa thông tin về các hình ảnh phân vùng được dùng trong phiên bản 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ư
boot
vàsuper
, đồng thời, nếu thành công, sẽ lấy được các bí mật pVM ở giai đoạn tiếp theo. Sau đó, Microdroid sẽ chuyển quyền kiểm soát cho nhân.Vì phân vùng siêu dữ liệu đã được trình tải khởi động xác minh (bước 3), nên kernel sẽ gắn phân vùng siêu dữ liệu vô điều kiện. Giống như Android đầy đủ, phân vùng siêu dữ liệu 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.rc
tươ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
init
sẽ khởi động trình quản lý Microdroid, truy cập vào hình ảnh của phiên bản. Dịch vụ trình quản lý Microdroid giải mã hình ảnh bằng khoá được truyền từ giai đoạn trước và đọc các khoá công khai cũng như bộ đếm quay lui của APK và APEX của ứng dụng mà pVM này tin tưởng. Sau này,zipfuse
vàapexd
sẽ dùng thông tin này khi lần lượt gắn APK ứng dụng và các APEX được yêu cầu.Dịch vụ trình quản lý Microdroid bắt đầu
apexd
.apexd
gắ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 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
).zipfuse
là hệ thống tệp FUSE của Microdroid.zipfuse
gắ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 truyền dưới dạng một thiết bị khối ảo bằng 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 phiên bản pVM này.apexd
dùng danh sách này khi kích hoạt APEX.Luồng khởi động sẽ quay lại dịch vụ trình quản lý Microdroid. Sau đó, dịch vụ trình quản lý sẽ giao tiếp với
VirtualizationService
của Android bằng cách sử dụ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 trong tệp cấu hình của APK và thực thi tệp đó.
Trao đổi tệp (AuthFS)
Các thành phần Android thường dùng tệp cho dữ liệu đầu vào, đầu ra và trạng thái, đồng thời truyề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 do nhân Android kiểm soát. 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 đối với từng thao tác truy cập, 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 đang chạy trong pVM) phát hiện xem phần phụ trợ không đáng tin cậy (thường là Android) có giả mạo nội dung tệp hay không.
Để trao đổi tệp, phần phụ trợ (fd\_server
) sẽ bắt đầu bằng cấu hình cho mỗi tệp, chỉ định xem tệp đó dùng cho đầ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 việc nội dung khớp với một hàm băm đã biết, ngoài cây Merkle để xác minh khi truy cập. Đối với đầu ra, AuthFS duy trì nội bộ một cây băm nội dung như quan sát được 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.
Lớp truyền tải cơ bản hiện dựa trên Binder RPC, tuy nhiên, lớp 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 khoá niêm phong ổn định phù hợp để bảo vệ dữ liệu liên tục và khoá chứng thực phù hợp để tạo chữ ký mà pVM có thể xác minh là đã tạo.
Binder RPC
Phần lớn các giao diện của Android được thể hiện bằng AIDL, được xây dựng dựa trên trình điều khiển nhân 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 ổ cắm, vsock trong trường hợp pVM. Việc hoạt động trên các ổ cắm 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 nghe các kết nối mới. Các ứng dụng có thể kết nối với máy chủ này bằng đối tượng RpcSession
, nhận đối tượng Binder
và sử dụng đối tượng này giống hệt như cách sử dụng đối tượng Binder
với trình điều khiển Binder của nhân.