Microdroid là một hệ điều hành Android thu nhỏ chạy trong pVM. Bạn không nhất thiết phải sử dụng Microdroid, bạn có thể khởi động máy ảo 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 của 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 tính bảo mật và tính toàn vẹn cao 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 đảm bảo tính bảo mật và tính toàn vẹn mạnh mẽ đòi hỏi phải thực hiện 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 Android tổng thể. 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 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, 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 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ữ cũng như hiển thị một tập hợp con của API Android, chẳng hạn như kho khoá cho các hoạt động mã hoá bằng khoá được hỗ trợ phần cứng. 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à một phiên bản Android rút gọn 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 các API NDK (cung cấp tất cả API để 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 tệp nhị phân cùng với các thư viện dùng chung được nhúng trong tệp APK
- Binder RPC qua vsock và trao đổi tệp bằng các bước 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
Đồ 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ó 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 tổng hợp:
bootloader
– Xác minh và khởi động hạt nhân.boot.img
– Chứa hạt nhân và ổ đĩa ram khởi động.vendor_boot.img
– Chứa các mô-đun hạt nhân dành riêng cho máy ảo, 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.
Hình ảnh phân vùng được vận chuyển trong APEX Ảo hoá và được đóng gói trong hình ảnh ổ đĩa tổng hợp của VirtualizationService
. Ngoài hình ảnh đĩa tổng hợp chính của hệ điều hành, VirtualizationService
còn chịu trách nhiệm tạo các phân vùng sau:
payload
– Một tập hợp các phân vùng được APEX và APK của Android hỗ trợinstance
– Một phân vùng được mã hoá để lưu trữ dữ liệu khởi động đã xác minh cho mỗi thực thể, chẳng hạn như muối cho mỗi thực thể, khoá công khai APEX đáng tin cậy và bộ đếm rollback
Trình tự khởi động
Trình tự khởi động Microdroid xảy 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à nội dung 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 hai nhiệm 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 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 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á hình ảnh đó. Vì vậy, lần tiếp theo pVM 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 đó là danh tính đã lưu trước đó. Nếu các giá trị nhận dạng 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ề 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 theo chuỗi, chẳng hạn như
boot
vàsuper
, và nếu thành công, sẽ lấy bí mật pVM ở giai đoạn tiếp theo. Sau đó, Microdroid sẽ chuyển quyền kiểm soát cho hạt nhân.Vì trình tải khởi động đã xác minh phân vùng siêu (bước 3), nên hạt nhân sẽ gắn phân vùng siêu một cách vô điều kiện. Giống như Android đầy đủ, phân vùng siê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 đến 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
khởi động trình quản lý Microdroid, truy cập vào hình ảnh bản sao. 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 khoá công khai cũng như bộ đếm rollback của APK ứng dụng và APEX mà pVM này tin cậy. Thông tin này đượczipfuse
vàapexd
sử dụng sau này khi chúng 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 tại 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
sẽ 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 pVM truyền dưới dạng thiết bị khối ảo bằng dm-verity, giống như APEX. Tệp 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. Danh sách này đượcapexd
sử dụng 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ụ quản lý sẽ giao tiếp với
VirtualizationService
của Android bằng cách sử dụng RPC của Binder để 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 đó.
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 truyền các tệp này dưới dạng chỉ số mô tả tệp (loại ParcelFileDescriptor
trong AIDL) với quyền truy cập do hạt nhân Android kiểm soát. AuthFS hỗ trợ 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 từng thao tác truy cập, tương tự như fs-verity
. Các bước kiểm tra này 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 bằng cấu hình cho mỗi tệp, chỉ định xem tệp đó dành cho đầu vào (chỉ có thể đọc) hay đầu ra (đọc-ghi). Đối với dữ liệu đầu vào, giao diện người dùng thực thi để nội dung khớp với hàm băm đã biết, trên cây Merkle để xác minh khi truy cập. Đối với đầu ra, AuthFS duy trì một cây băm nội bộ 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 thức truyền tải cơ bản hiện dựa trên Binder RPC, tuy nhiên, phương thức 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 ổn định và một khoá chứng thực phù hợp để tạo chữ ký do pVM tạo ra và có thể xác minh.
RPC liên kết
Phần lớn giao diện của Android được thể hiện trong AIDL, được xây dựng dựa trên trình điều khiển hạt nhân Linux của Binder. Để hỗ trợ giao diện giữa các pVM, giao thức Binder đã được viết lại để hoạt động qua các ổ cắm, vsock trong trường hợp pVM. Việc hoạt động qua ổ 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. Ứ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 như đối tượng Binder
được sử dụng với trình điều khiển Binder hạt nhân.