blob: 4a19030bc067333dd61b6468f096d3b0326ace3e [file] [log] [blame]
Victor Hsieh272aa242021-02-01 14:19:20 -08001/*
2 * Copyright (C) 2021 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Victor Hsieh51789de2021-08-06 16:50:49 -070017//! compsvc is a service to run compilation tasks in a PVM upon request. It is able to set up
Victor Hsiehebb1d902021-08-06 13:00:18 -070018//! file descriptors backed by authfs (via authfs_service) and pass the file descriptors to the
Victor Hsieh51789de2021-08-06 16:50:49 -070019//! actual compiler.
Victor Hsieh272aa242021-02-01 14:19:20 -080020
Victor Hsieha64194b2021-08-06 17:43:36 -070021use anyhow::Result;
Victor Hsieh9ed27182021-08-25 15:52:42 -070022use log::warn;
23use std::default::Default;
Victor Hsieha64194b2021-08-06 17:43:36 -070024use std::ffi::CString;
Victor Hsieh51789de2021-08-06 16:50:49 -070025use std::path::PathBuf;
Victor Hsieh8fd03f02021-08-24 17:23:01 -070026use std::sync::{Arc, RwLock};
Victor Hsieh272aa242021-02-01 14:19:20 -080027
Victor Hsieh6e340382021-08-13 12:18:02 -070028use crate::compilation::{compile, CompilerOutput};
Victor Hsieh23f73592021-08-06 18:08:24 -070029use crate::compos_key_service::CompOsKeyService;
Victor Hsieh9ed27182021-08-25 15:52:42 -070030use crate::fsverity;
Victor Hsieh51789de2021-08-06 16:50:49 -070031use authfs_aidl_interface::aidl::com::android::virt::fs::IAuthFsService::IAuthFsService;
Victor Hsieh23f73592021-08-06 18:08:24 -070032use compos_aidl_interface::aidl::com::android::compos::{
33 CompOsKeyData::CompOsKeyData,
Victor Hsieh9ed27182021-08-25 15:52:42 -070034 CompilationResult::CompilationResult,
Victor Hsieh23f73592021-08-06 18:08:24 -070035 ICompOsService::{BnCompOsService, ICompOsService},
36 Metadata::Metadata,
Victor Hsieh272aa242021-02-01 14:19:20 -080037};
Victor Hsieh272aa242021-02-01 14:19:20 -080038use compos_aidl_interface::binder::{
Victor Hsieh51789de2021-08-06 16:50:49 -070039 BinderFeatures, ExceptionCode, Interface, Result as BinderResult, Status, Strong,
Victor Hsieh272aa242021-02-01 14:19:20 -080040};
41
Victor Hsiehebb1d902021-08-06 13:00:18 -070042const AUTHFS_SERVICE_NAME: &str = "authfs_service";
Victor Hsieh51789de2021-08-06 16:50:49 -070043const DEX2OAT_PATH: &str = "/apex/com.android.art/bin/dex2oat64";
Alan Stokes9e2c5d52021-07-21 11:29:10 +010044
Victor Hsieha64194b2021-08-06 17:43:36 -070045/// Constructs a binder object that implements ICompOsService.
Victor Hsieh23f73592021-08-06 18:08:24 -070046pub fn new_binder(rpc_binder: bool) -> Result<Strong<dyn ICompOsService>> {
47 let service = CompOsService {
48 dex2oat_path: PathBuf::from(DEX2OAT_PATH),
49 key_service: CompOsKeyService::new(rpc_binder)?,
Victor Hsieh8fd03f02021-08-24 17:23:01 -070050 key_blob: Arc::new(RwLock::new(Vec::new())),
Victor Hsieh23f73592021-08-06 18:08:24 -070051 };
Victor Hsieha64194b2021-08-06 17:43:36 -070052 Ok(BnCompOsService::new_binder(service, BinderFeatures::default()))
Alan Stokes9e2c5d52021-07-21 11:29:10 +010053}
54
Victor Hsieha64194b2021-08-06 17:43:36 -070055struct CompOsService {
Victor Hsieh51789de2021-08-06 16:50:49 -070056 dex2oat_path: PathBuf,
Victor Hsieha64194b2021-08-06 17:43:36 -070057 key_service: CompOsKeyService,
Victor Hsieh8fd03f02021-08-24 17:23:01 -070058 key_blob: Arc<RwLock<Vec<u8>>>,
Victor Hsieh272aa242021-02-01 14:19:20 -080059}
60
Victor Hsieh9ed27182021-08-25 15:52:42 -070061impl CompOsService {
62 fn generate_raw_fsverity_signature(
63 &self,
64 key_blob: &[u8],
65 fsverity_digest: &fsverity::Sha256Digest,
66 ) -> Vec<u8> {
67 let formatted_digest = fsverity::to_formatted_digest(fsverity_digest);
68 self.key_service.do_sign(key_blob, &formatted_digest[..]).unwrap_or_else(|e| {
69 warn!("Failed to sign the fsverity digest, returning empty signature. Error: {}", e);
70 Vec::new()
71 })
72 }
73}
74
Victor Hsieha64194b2021-08-06 17:43:36 -070075impl Interface for CompOsService {}
Victor Hsieh272aa242021-02-01 14:19:20 -080076
Victor Hsieha64194b2021-08-06 17:43:36 -070077impl ICompOsService for CompOsService {
Victor Hsieh8fd03f02021-08-24 17:23:01 -070078 fn initializeSigningKey(&self, key_blob: &[u8]) -> BinderResult<()> {
79 let mut w = self.key_blob.write().unwrap();
80 if w.is_empty() {
81 *w = Vec::from(key_blob);
82 Ok(())
83 } else {
84 Err(new_binder_exception(ExceptionCode::ILLEGAL_STATE, "Cannot re-initialize the key"))
85 }
86 }
87
Victor Hsieh9ed27182021-08-25 15:52:42 -070088 fn compile(&self, args: &[String], metadata: &Metadata) -> BinderResult<CompilationResult> {
Victor Hsieh51789de2021-08-06 16:50:49 -070089 let authfs_service = get_authfs_service()?;
Victor Hsieh6e340382021-08-13 12:18:02 -070090 let output = compile(&self.dex2oat_path, args, authfs_service, metadata).map_err(|e| {
Victor Hsieh51789de2021-08-06 16:50:49 -070091 new_binder_exception(
92 ExceptionCode::SERVICE_SPECIFIC,
93 format!("Compilation failed: {}", e),
94 )
Victor Hsieh6e340382021-08-13 12:18:02 -070095 })?;
96 match output {
97 CompilerOutput::Digests { oat, vdex, image } => {
Victor Hsieh9ed27182021-08-25 15:52:42 -070098 let key = &*self.key_blob.read().unwrap();
99 if key.is_empty() {
100 Err(new_binder_exception(
101 ExceptionCode::ILLEGAL_STATE,
102 "Key is not initialized",
103 ))
104 } else {
105 let oat_signature = self.generate_raw_fsverity_signature(key, &oat);
106 let vdex_signature = self.generate_raw_fsverity_signature(key, &vdex);
107 let image_signature = self.generate_raw_fsverity_signature(key, &image);
108 Ok(CompilationResult {
109 exitCode: 0,
110 oatSignature: oat_signature,
111 vdexSignature: vdex_signature,
112 imageSignature: image_signature,
113 })
114 }
Victor Hsieh6e340382021-08-13 12:18:02 -0700115 }
Victor Hsieh9ed27182021-08-25 15:52:42 -0700116 CompilerOutput::ExitCode(exit_code) => {
117 Ok(CompilationResult { exitCode: exit_code, ..Default::default() })
118 }
Victor Hsieh6e340382021-08-13 12:18:02 -0700119 }
Victor Hsieh272aa242021-02-01 14:19:20 -0800120 }
Victor Hsieh23f73592021-08-06 18:08:24 -0700121
122 fn generateSigningKey(&self) -> BinderResult<CompOsKeyData> {
123 self.key_service
124 .do_generate()
125 .map_err(|e| new_binder_exception(ExceptionCode::ILLEGAL_STATE, e.to_string()))
126 }
127
128 fn verifySigningKey(&self, key_blob: &[u8], public_key: &[u8]) -> BinderResult<bool> {
129 Ok(if let Err(e) = self.key_service.do_verify(key_blob, public_key) {
130 warn!("Signing key verification failed: {}", e.to_string());
131 false
132 } else {
133 true
134 })
135 }
136
Victor Hsieh8fd03f02021-08-24 17:23:01 -0700137 fn sign(&self, data: &[u8]) -> BinderResult<Vec<u8>> {
138 let key = &*self.key_blob.read().unwrap();
139 if key.is_empty() {
140 Err(new_binder_exception(ExceptionCode::ILLEGAL_STATE, "Key is not initialized"))
141 } else {
142 self.key_service
143 .do_sign(key, data)
144 .map_err(|e| new_binder_exception(ExceptionCode::ILLEGAL_STATE, e.to_string()))
145 }
Victor Hsieh23f73592021-08-06 18:08:24 -0700146 }
Victor Hsieh272aa242021-02-01 14:19:20 -0800147}
Victor Hsiehebb1d902021-08-06 13:00:18 -0700148
149fn get_authfs_service() -> BinderResult<Strong<dyn IAuthFsService>> {
150 Ok(authfs_aidl_interface::binder::get_interface(AUTHFS_SERVICE_NAME)?)
151}
152
Victor Hsiehebb1d902021-08-06 13:00:18 -0700153fn new_binder_exception<T: AsRef<str>>(exception: ExceptionCode, message: T) -> Status {
154 Status::new_exception(exception, CString::new(message.as_ref()).as_deref().ok())
155}