blob: 0d32841fe2927d61368cfcc7363f7db1a48c3606 [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
Alan Stokes126fd512021-12-16 15:00:01 +000021use anyhow::{Context, Result};
Alan Stokes3189af02021-09-30 17:51:19 +010022use binder_common::new_binder_exception;
Alan Stokes126fd512021-12-16 15:00:01 +000023use compos_common::binder::to_binder_result;
Victor Hsieh9ed27182021-08-25 15:52:42 -070024use log::warn;
25use std::default::Default;
Victor Hsieh18775b12021-10-12 17:42:48 -070026use std::env;
Victor Hsieh51789de2021-08-06 16:50:49 -070027use std::path::PathBuf;
Alan Stokes183d7d32021-12-08 16:10:45 +000028use std::sync::RwLock;
Victor Hsieh272aa242021-02-01 14:19:20 -080029
Alan Stokes46a1dff2021-12-14 10:56:05 +000030use crate::compilation::{compile_cmd, odrefresh, CompilerOutput, OdrefreshContext};
31use crate::compos_key_service::{CompOsKeyService, Signer};
Victor Hsieh9ed27182021-08-25 15:52:42 -070032use crate::fsverity;
Victor Hsieh51789de2021-08-06 16:50:49 -070033use authfs_aidl_interface::aidl::com::android::virt::fs::IAuthFsService::IAuthFsService;
Victor Hsieh23f73592021-08-06 18:08:24 -070034use compos_aidl_interface::aidl::com::android::compos::{
35 CompOsKeyData::CompOsKeyData,
Victor Hsieh9ed27182021-08-25 15:52:42 -070036 CompilationResult::CompilationResult,
Victor Hsieh13333e82021-09-03 15:17:32 -070037 FdAnnotation::FdAnnotation,
Victor Hsieh23f73592021-08-06 18:08:24 -070038 ICompOsService::{BnCompOsService, ICompOsService},
Victor Hsieh272aa242021-02-01 14:19:20 -080039};
Victor Hsieh272aa242021-02-01 14:19:20 -080040use compos_aidl_interface::binder::{
Alan Stokes3189af02021-09-30 17:51:19 +010041 BinderFeatures, ExceptionCode, Interface, Result as BinderResult, Strong,
Victor Hsieh272aa242021-02-01 14:19:20 -080042};
Alan Stokes46a1dff2021-12-14 10:56:05 +000043use compos_common::odrefresh::ODREFRESH_PATH;
Victor Hsieh272aa242021-02-01 14:19:20 -080044
Victor Hsiehebb1d902021-08-06 13:00:18 -070045const AUTHFS_SERVICE_NAME: &str = "authfs_service";
Victor Hsieh51789de2021-08-06 16:50:49 -070046const DEX2OAT_PATH: &str = "/apex/com.android.art/bin/dex2oat64";
Alan Stokes9e2c5d52021-07-21 11:29:10 +010047
Victor Hsieha64194b2021-08-06 17:43:36 -070048/// Constructs a binder object that implements ICompOsService.
Victor Hsieh9ebf7ee2021-09-03 16:14:14 -070049pub fn new_binder() -> Result<Strong<dyn ICompOsService>> {
Victor Hsieh23f73592021-08-06 18:08:24 -070050 let service = CompOsService {
51 dex2oat_path: PathBuf::from(DEX2OAT_PATH),
Victor Hsiehf9968692021-11-18 11:34:39 -080052 odrefresh_path: PathBuf::from(ODREFRESH_PATH),
Victor Hsieh9ebf7ee2021-09-03 16:14:14 -070053 key_service: CompOsKeyService::new()?,
Alan Stokes183d7d32021-12-08 16:10:45 +000054 key_blob: RwLock::new(Vec::new()),
Victor Hsieh23f73592021-08-06 18:08:24 -070055 };
Victor Hsieha64194b2021-08-06 17:43:36 -070056 Ok(BnCompOsService::new_binder(service, BinderFeatures::default()))
Alan Stokes9e2c5d52021-07-21 11:29:10 +010057}
58
Victor Hsieha64194b2021-08-06 17:43:36 -070059struct CompOsService {
Victor Hsieh51789de2021-08-06 16:50:49 -070060 dex2oat_path: PathBuf,
Victor Hsiehf9968692021-11-18 11:34:39 -080061 odrefresh_path: PathBuf,
Victor Hsieha64194b2021-08-06 17:43:36 -070062 key_service: CompOsKeyService,
Alan Stokes183d7d32021-12-08 16:10:45 +000063 key_blob: RwLock<Vec<u8>>,
Victor Hsieh272aa242021-02-01 14:19:20 -080064}
65
Victor Hsieh9ed27182021-08-25 15:52:42 -070066impl CompOsService {
67 fn generate_raw_fsverity_signature(
68 &self,
Victor Hsieh9ed27182021-08-25 15:52:42 -070069 fsverity_digest: &fsverity::Sha256Digest,
Alan Stokes46a1dff2021-12-14 10:56:05 +000070 ) -> BinderResult<Vec<u8>> {
Victor Hsieh9ed27182021-08-25 15:52:42 -070071 let formatted_digest = fsverity::to_formatted_digest(fsverity_digest);
Alan Stokes126fd512021-12-16 15:00:01 +000072 to_binder_result(self.new_signer()?.sign(&formatted_digest[..]))
Alan Stokes46a1dff2021-12-14 10:56:05 +000073 }
74
75 fn new_signer(&self) -> BinderResult<Signer> {
76 let key = &*self.key_blob.read().unwrap();
77 if key.is_empty() {
78 Err(new_binder_exception(ExceptionCode::ILLEGAL_STATE, "Key is not initialized"))
79 } else {
80 Ok(self.key_service.new_signer(key))
81 }
Victor Hsieh9ed27182021-08-25 15:52:42 -070082 }
83}
84
Victor Hsieha64194b2021-08-06 17:43:36 -070085impl Interface for CompOsService {}
Victor Hsieh272aa242021-02-01 14:19:20 -080086
Victor Hsieha64194b2021-08-06 17:43:36 -070087impl ICompOsService for CompOsService {
Victor Hsieh8fd03f02021-08-24 17:23:01 -070088 fn initializeSigningKey(&self, key_blob: &[u8]) -> BinderResult<()> {
89 let mut w = self.key_blob.write().unwrap();
90 if w.is_empty() {
91 *w = Vec::from(key_blob);
92 Ok(())
93 } else {
94 Err(new_binder_exception(ExceptionCode::ILLEGAL_STATE, "Cannot re-initialize the key"))
95 }
96 }
97
Victor Hsieh18775b12021-10-12 17:42:48 -070098 fn initializeClasspaths(
99 &self,
100 boot_classpath: &str,
101 dex2oat_boot_classpath: &str,
Victor Hsieh64290a52021-11-17 13:34:46 -0800102 system_server_classpath: &str,
Victor Hsieh18775b12021-10-12 17:42:48 -0700103 ) -> BinderResult<()> {
104 // TODO(198211396): Implement correctly.
105 env::set_var("BOOTCLASSPATH", boot_classpath);
106 env::set_var("DEX2OATBOOTCLASSPATH", dex2oat_boot_classpath);
Victor Hsieh64290a52021-11-17 13:34:46 -0800107 env::set_var("SYSTEMSERVERCLASSPATH", system_server_classpath);
Victor Hsieh18775b12021-10-12 17:42:48 -0700108 Ok(())
109 }
110
Victor Hsiehf9968692021-11-18 11:34:39 -0800111 fn odrefresh(
112 &self,
113 system_dir_fd: i32,
114 output_dir_fd: i32,
Alan Stokes9646db92021-12-14 13:22:33 +0000115 staging_dir_fd: i32,
116 target_dir_name: &str,
Victor Hsiehf9968692021-11-18 11:34:39 -0800117 zygote_arch: &str,
Alan Stokes9646db92021-12-14 13:22:33 +0000118 ) -> BinderResult<i8> {
Alan Stokes126fd512021-12-16 15:00:01 +0000119 let context = to_binder_result(OdrefreshContext::new(
Victor Hsiehf9968692021-11-18 11:34:39 -0800120 system_dir_fd,
121 output_dir_fd,
Alan Stokes9646db92021-12-14 13:22:33 +0000122 staging_dir_fd,
Alan Stokes46a1dff2021-12-14 10:56:05 +0000123 target_dir_name,
Victor Hsiehf9968692021-11-18 11:34:39 -0800124 zygote_arch,
Alan Stokes126fd512021-12-16 15:00:01 +0000125 ))?;
Alan Stokes46a1dff2021-12-14 10:56:05 +0000126
127 let authfs_service = get_authfs_service()?;
Alan Stokes126fd512021-12-16 15:00:01 +0000128 let exit_code = to_binder_result(
129 odrefresh(&self.odrefresh_path, context, authfs_service, self.new_signer()?)
130 .context("odrefresh failed"),
131 )?;
Alan Stokes46a1dff2021-12-14 10:56:05 +0000132 Ok(exit_code as i8)
Victor Hsiehf9968692021-11-18 11:34:39 -0800133 }
134
Victor Hsieh3c044c42021-10-01 17:17:10 -0700135 fn compile_cmd(
Victor Hsieh13333e82021-09-03 15:17:32 -0700136 &self,
137 args: &[String],
138 fd_annotation: &FdAnnotation,
139 ) -> BinderResult<CompilationResult> {
Victor Hsieh51789de2021-08-06 16:50:49 -0700140 let authfs_service = get_authfs_service()?;
Alan Stokes126fd512021-12-16 15:00:01 +0000141 let output = to_binder_result(
142 compile_cmd(&self.dex2oat_path, args, authfs_service, fd_annotation)
143 .context("Compilation failed"),
144 )?;
Victor Hsieh6e340382021-08-13 12:18:02 -0700145 match output {
146 CompilerOutput::Digests { oat, vdex, image } => {
Alan Stokes46a1dff2021-12-14 10:56:05 +0000147 let oat_signature = self.generate_raw_fsverity_signature(&oat)?;
148 let vdex_signature = self.generate_raw_fsverity_signature(&vdex)?;
149 let image_signature = self.generate_raw_fsverity_signature(&image)?;
150 Ok(CompilationResult {
151 exitCode: 0,
152 oatSignature: oat_signature,
153 vdexSignature: vdex_signature,
154 imageSignature: image_signature,
155 })
Victor Hsieh6e340382021-08-13 12:18:02 -0700156 }
Victor Hsieh9ed27182021-08-25 15:52:42 -0700157 CompilerOutput::ExitCode(exit_code) => {
158 Ok(CompilationResult { exitCode: exit_code, ..Default::default() })
159 }
Victor Hsieh6e340382021-08-13 12:18:02 -0700160 }
Victor Hsieh272aa242021-02-01 14:19:20 -0800161 }
Victor Hsieh23f73592021-08-06 18:08:24 -0700162
Victor Hsieh3c044c42021-10-01 17:17:10 -0700163 fn compile(&self, _marshaled: &[u8], _fd_annotation: &FdAnnotation) -> BinderResult<i8> {
164 Err(new_binder_exception(ExceptionCode::UNSUPPORTED_OPERATION, "Not yet implemented"))
165 }
166
Victor Hsieh23f73592021-08-06 18:08:24 -0700167 fn generateSigningKey(&self) -> BinderResult<CompOsKeyData> {
Alan Stokes126fd512021-12-16 15:00:01 +0000168 to_binder_result(self.key_service.generate())
Victor Hsieh23f73592021-08-06 18:08:24 -0700169 }
170
171 fn verifySigningKey(&self, key_blob: &[u8], public_key: &[u8]) -> BinderResult<bool> {
Alan Stokes183d7d32021-12-08 16:10:45 +0000172 Ok(if let Err(e) = self.key_service.verify(key_blob, public_key) {
Alan Stokes126fd512021-12-16 15:00:01 +0000173 warn!("Signing key verification failed: {:?}", e);
Victor Hsieh23f73592021-08-06 18:08:24 -0700174 false
175 } else {
176 true
177 })
178 }
179
Victor Hsieh8fd03f02021-08-24 17:23:01 -0700180 fn sign(&self, data: &[u8]) -> BinderResult<Vec<u8>> {
Alan Stokes126fd512021-12-16 15:00:01 +0000181 to_binder_result(self.new_signer()?.sign(data))
Victor Hsieh23f73592021-08-06 18:08:24 -0700182 }
Victor Hsieh272aa242021-02-01 14:19:20 -0800183}
Victor Hsiehebb1d902021-08-06 13:00:18 -0700184
185fn get_authfs_service() -> BinderResult<Strong<dyn IAuthFsService>> {
186 Ok(authfs_aidl_interface::binder::get_interface(AUTHFS_SERVICE_NAME)?)
187}