Microdroid là một hệ điều hành Android thu nhỏ chạy trong pVM. Bạn không 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 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 đả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 dùng Bionic, việc giao tiếp đòi hỏi phải có một giao thức tuỳ chỉnh qua so với cùng với 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 xây dựng 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 máy chủ và hiển thị một tập hợp con API Android, chẳng hạn như kho khoá cho các thao tác mã hoá bằng khoá dựa trên phần cứng. Nhìn chung, nhà phát triển nên tìm thấy Microdroid một môi trường quen thuộc với những công cụ mà họ đã quen thuộc 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
- Đ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ó 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 raminit.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 về quy trình khởi động đã xác minh.
Hình ảnh phân vùng xuất hiện trong APEX ảo hoá và được VirtualizationService
đóng gói trong hình ảnh ổ đĩa tổng hợp. 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ể, ban đầu, pVM đượ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, 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 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ề 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
, đồng thời 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 đượ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
sẽ khởi động trình quản lý Microdroid, trình quản lý này 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 truyền từ giai đoạn trước và đọc khoá công khai và bộ đếm khôi phục của APK ứng dụng và APEX mà pVM này tin cậy. Thông tin này sẽ đượ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
sẽ 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 Binder RPC để có thể báo cáo các sự kiện quan trọng như sự cố hoặc sự cố ngừng hoạt động, đồng thời 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)
Thông thường, các thành phần Android sẽ sử dụng tệp cho dữ liệu đầu vào, đầu ra và trạng thái, đồng thời truyền những 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 nhân hệ điều hành Android kiểm soát. AuthFS hỗ trợ chức năng tương tự trong việc trao đổi tệp giữa các điểm cuối không tin cậy 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ư 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 việc 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, điều đó 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 bền vững và một khoá chứng thực phù hợp để tạo các chữ ký do pVM xác minh được.
Binder RPC
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ợ các 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.