blob: 0a158764f7164c2c2eaeb14a8e79eb2bb117b764 [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;
Alan Stokes3189af02021-09-30 17:51:19 +010022use binder_common::new_binder_exception;
Victor Hsieh9ed27182021-08-25 15:52:42 -070023use log::warn;
24use std::default::Default;
Victor Hsieh18775b12021-10-12 17:42:48 -070025use std::env;
Victor Hsieh51789de2021-08-06 16:50:49 -070026use std::path::PathBuf;
Victor Hsieh8fd03f02021-08-24 17:23:01 -070027use std::sync::{Arc, RwLock};
Victor Hsieh272aa242021-02-01 14:19:20 -080028
Victor Hsiehf9968692021-11-18 11:34:39 -080029use crate::compilation::{compile_cmd, odrefresh, CompilerOutput};
Victor Hsieh23f73592021-08-06 18:08:24 -070030use crate::compos_key_service::CompOsKeyService;
Victor Hsieh9ed27182021-08-25 15:52:42 -070031use crate::fsverity;
Victor Hsieh51789de2021-08-06 16:50:49 -070032use authfs_aidl_interface::aidl::com::android::virt::fs::IAuthFsService::IAuthFsService;
Victor Hsieh23f73592021-08-06 18:08:24 -070033use compos_aidl_interface::aidl::com::android::compos::{
34 CompOsKeyData::CompOsKeyData,
Victor Hsieh9ed27182021-08-25 15:52:42 -070035 CompilationResult::CompilationResult,
Victor Hsieh13333e82021-09-03 15:17:32 -070036 FdAnnotation::FdAnnotation,
Victor Hsieh23f73592021-08-06 18:08:24 -070037 ICompOsService::{BnCompOsService, ICompOsService},
Victor Hsieh272aa242021-02-01 14:19:20 -080038};
Victor Hsieh272aa242021-02-01 14:19:20 -080039use compos_aidl_interface::binder::{
Alan Stokes3189af02021-09-30 17:51:19 +010040 BinderFeatures, ExceptionCode, Interface, Result as BinderResult, Strong,
Victor Hsieh272aa242021-02-01 14:19:20 -080041};
42
Victor Hsiehebb1d902021-08-06 13:00:18 -070043const AUTHFS_SERVICE_NAME: &str = "authfs_service";
Victor Hsieh51789de2021-08-06 16:50:49 -070044const DEX2OAT_PATH: &str = "/apex/com.android.art/bin/dex2oat64";
Victor Hsiehf9968692021-11-18 11:34:39 -080045const ODREFRESH_PATH: &str = "/apex/com.android.art/bin/odrefresh";
Alan Stokes9e2c5d52021-07-21 11:29:10 +010046
Victor Hsieha64194b2021-08-06 17:43:36 -070047/// Constructs a binder object that implements ICompOsService.
Victor Hsieh9ebf7ee2021-09-03 16:14:14 -070048pub fn new_binder() -> Result<Strong<dyn ICompOsService>> {
Victor Hsieh23f73592021-08-06 18:08:24 -070049 let service = CompOsService {
50 dex2oat_path: PathBuf::from(DEX2OAT_PATH),
Victor Hsiehf9968692021-11-18 11:34:39 -080051 odrefresh_path: PathBuf::from(ODREFRESH_PATH),
Victor Hsieh9ebf7ee2021-09-03 16:14:14 -070052 key_service: CompOsKeyService::new()?,
Victor Hsieh8fd03f02021-08-24 17:23:01 -070053 key_blob: Arc::new(RwLock::new(Vec::new())),
Victor Hsieh23f73592021-08-06 18:08:24 -070054 };
Victor Hsieha64194b2021-08-06 17:43:36 -070055 Ok(BnCompOsService::new_binder(service, BinderFeatures::default()))
Alan Stokes9e2c5d52021-07-21 11:29:10 +010056}
57
Victor Hsieha64194b2021-08-06 17:43:36 -070058struct CompOsService {
Victor Hsieh51789de2021-08-06 16:50:49 -070059 dex2oat_path: PathBuf,
Victor Hsiehf9968692021-11-18 11:34:39 -080060 odrefresh_path: PathBuf,
Victor Hsieha64194b2021-08-06 17:43:36 -070061 key_service: CompOsKeyService,
Victor Hsieh8fd03f02021-08-24 17:23:01 -070062 key_blob: Arc<RwLock<Vec<u8>>>,
Victor Hsieh272aa242021-02-01 14:19:20 -080063}
64
Victor Hsieh9ed27182021-08-25 15:52:42 -070065impl CompOsService {
66 fn generate_raw_fsverity_signature(
67 &self,
68 key_blob: &[u8],
69 fsverity_digest: &fsverity::Sha256Digest,
70 ) -> Vec<u8> {
71 let formatted_digest = fsverity::to_formatted_digest(fsverity_digest);
72 self.key_service.do_sign(key_blob, &formatted_digest[..]).unwrap_or_else(|e| {
73 warn!("Failed to sign the fsverity digest, returning empty signature. Error: {}", e);
74 Vec::new()
75 })
76 }
77}
78
Victor Hsieha64194b2021-08-06 17:43:36 -070079impl Interface for CompOsService {}
Victor Hsieh272aa242021-02-01 14:19:20 -080080
Victor Hsieha64194b2021-08-06 17:43:36 -070081impl ICompOsService for CompOsService {
Victor Hsieh8fd03f02021-08-24 17:23:01 -070082 fn initializeSigningKey(&self, key_blob: &[u8]) -> BinderResult<()> {
83 let mut w = self.key_blob.write().unwrap();
84 if w.is_empty() {
85 *w = Vec::from(key_blob);
86 Ok(())
87 } else {
88 Err(new_binder_exception(ExceptionCode::ILLEGAL_STATE, "Cannot re-initialize the key"))
89 }
90 }
91
Victor Hsieh18775b12021-10-12 17:42:48 -070092 fn initializeClasspaths(
93 &self,
94 boot_classpath: &str,
95 dex2oat_boot_classpath: &str,
Victor Hsieh64290a52021-11-17 13:34:46 -080096 system_server_classpath: &str,
Victor Hsieh18775b12021-10-12 17:42:48 -070097 ) -> BinderResult<()> {
98 // TODO(198211396): Implement correctly.
99 env::set_var("BOOTCLASSPATH", boot_classpath);
100 env::set_var("DEX2OATBOOTCLASSPATH", dex2oat_boot_classpath);
Victor Hsieh64290a52021-11-17 13:34:46 -0800101 env::set_var("SYSTEMSERVERCLASSPATH", system_server_classpath);
Victor Hsieh18775b12021-10-12 17:42:48 -0700102 Ok(())
103 }
104
Victor Hsiehf9968692021-11-18 11:34:39 -0800105 fn odrefresh(
106 &self,
107 system_dir_fd: i32,
108 output_dir_fd: i32,
109 zygote_arch: &str,
110 ) -> BinderResult<CompilationResult> {
111 if system_dir_fd < 0 || output_dir_fd < 0 {
112 return Err(new_binder_exception(
113 ExceptionCode::ILLEGAL_ARGUMENT,
114 "The remote FDs are expected to be non-negative",
115 ));
116 }
117 if zygote_arch != "zygote64" && zygote_arch != "zygote64_32" {
118 return Err(new_binder_exception(
119 ExceptionCode::ILLEGAL_ARGUMENT,
120 "Invalid zygote arch",
121 ));
122 }
123
124 let authfs_service = get_authfs_service()?;
125 let output = odrefresh(
126 &self.odrefresh_path,
127 system_dir_fd,
128 output_dir_fd,
129 zygote_arch,
130 authfs_service,
131 )
132 .map_err(|e| {
133 warn!("odrefresh failed: {}", e);
134 new_binder_exception(
135 ExceptionCode::SERVICE_SPECIFIC,
136 format!("odrefresh failed: {}", e),
137 )
138 })?;
139 match output {
140 CompilerOutput::ExitCode(exit_code) => {
141 Ok(CompilationResult { exitCode: exit_code, ..Default::default() })
142 }
143 _ => Err(new_binder_exception(ExceptionCode::SERVICE_SPECIFIC, "odrefresh failed")),
144 }
145 }
146
Victor Hsieh3c044c42021-10-01 17:17:10 -0700147 fn compile_cmd(
Victor Hsieh13333e82021-09-03 15:17:32 -0700148 &self,
149 args: &[String],
150 fd_annotation: &FdAnnotation,
151 ) -> BinderResult<CompilationResult> {
Victor Hsieh51789de2021-08-06 16:50:49 -0700152 let authfs_service = get_authfs_service()?;
Victor Hsieh13333e82021-09-03 15:17:32 -0700153 let output =
Victor Hsieh3c044c42021-10-01 17:17:10 -0700154 compile_cmd(&self.dex2oat_path, args, authfs_service, fd_annotation).map_err(|e| {
Victor Hsieh13333e82021-09-03 15:17:32 -0700155 new_binder_exception(
156 ExceptionCode::SERVICE_SPECIFIC,
157 format!("Compilation failed: {}", e),
158 )
159 })?;
Victor Hsieh6e340382021-08-13 12:18:02 -0700160 match output {
161 CompilerOutput::Digests { oat, vdex, image } => {
Victor Hsieh9ed27182021-08-25 15:52:42 -0700162 let key = &*self.key_blob.read().unwrap();
163 if key.is_empty() {
164 Err(new_binder_exception(
165 ExceptionCode::ILLEGAL_STATE,
166 "Key is not initialized",
167 ))
168 } else {
169 let oat_signature = self.generate_raw_fsverity_signature(key, &oat);
170 let vdex_signature = self.generate_raw_fsverity_signature(key, &vdex);
171 let image_signature = self.generate_raw_fsverity_signature(key, &image);
172 Ok(CompilationResult {
173 exitCode: 0,
174 oatSignature: oat_signature,
175 vdexSignature: vdex_signature,
176 imageSignature: image_signature,
177 })
178 }
Victor Hsieh6e340382021-08-13 12:18:02 -0700179 }
Victor Hsieh9ed27182021-08-25 15:52:42 -0700180 CompilerOutput::ExitCode(exit_code) => {
181 Ok(CompilationResult { exitCode: exit_code, ..Default::default() })
182 }
Victor Hsieh6e340382021-08-13 12:18:02 -0700183 }
Victor Hsieh272aa242021-02-01 14:19:20 -0800184 }
Victor Hsieh23f73592021-08-06 18:08:24 -0700185
Victor Hsieh3c044c42021-10-01 17:17:10 -0700186 fn compile(&self, _marshaled: &[u8], _fd_annotation: &FdAnnotation) -> BinderResult<i8> {
187 Err(new_binder_exception(ExceptionCode::UNSUPPORTED_OPERATION, "Not yet implemented"))
188 }
189
Victor Hsieh23f73592021-08-06 18:08:24 -0700190 fn generateSigningKey(&self) -> BinderResult<CompOsKeyData> {
191 self.key_service
192 .do_generate()
193 .map_err(|e| new_binder_exception(ExceptionCode::ILLEGAL_STATE, e.to_string()))
194 }
195
196 fn verifySigningKey(&self, key_blob: &[u8], public_key: &[u8]) -> BinderResult<bool> {
197 Ok(if let Err(e) = self.key_service.do_verify(key_blob, public_key) {
198 warn!("Signing key verification failed: {}", e.to_string());
199 false
200 } else {
201 true
202 })
203 }
204
Victor Hsieh8fd03f02021-08-24 17:23:01 -0700205 fn sign(&self, data: &[u8]) -> BinderResult<Vec<u8>> {
206 let key = &*self.key_blob.read().unwrap();
207 if key.is_empty() {
208 Err(new_binder_exception(ExceptionCode::ILLEGAL_STATE, "Key is not initialized"))
209 } else {
210 self.key_service
211 .do_sign(key, data)
212 .map_err(|e| new_binder_exception(ExceptionCode::ILLEGAL_STATE, e.to_string()))
213 }
Victor Hsieh23f73592021-08-06 18:08:24 -0700214 }
Victor Hsieh272aa242021-02-01 14:19:20 -0800215}
Victor Hsiehebb1d902021-08-06 13:00:18 -0700216
217fn get_authfs_service() -> BinderResult<Strong<dyn IAuthFsService>> {
218 Ok(authfs_aidl_interface::binder::get_interface(AUTHFS_SERVICE_NAME)?)
219}