blob: 3dbb4daadb096f1b2a30dcd03f544e432c2d2d63 [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 Hsiehec38ae22022-02-10 00:06:26 +000021use anyhow::{bail, Context, Result};
Alan Stokes0fc6ce52022-08-02 17:01:48 +010022use log::{error, info};
Victor Hsiehcb6d66b2022-05-10 16:12:06 -070023use rustutils::system_properties;
Victor Hsieh9ed27182021-08-25 15:52:42 -070024use std::default::Default;
Victor Hsiehec38ae22022-02-10 00:06:26 +000025use std::fs::read_dir;
Victor Hsiehcb6d66b2022-05-10 16:12:06 -070026use std::iter::zip;
Victor Hsiehec38ae22022-02-10 00:06:26 +000027use std::path::{Path, PathBuf};
Victor Hsiehcb6d66b2022-05-10 16:12:06 -070028use std::sync::RwLock;
Victor Hsieh272aa242021-02-01 14:19:20 -080029
Victor Hsiehec38ae22022-02-10 00:06:26 +000030use crate::artifact_signer::ArtifactSigner;
Victor Hsieh616f8222022-01-14 13:06:32 -080031use crate::compilation::{odrefresh, OdrefreshContext};
Alan Stokes16fb8552022-02-10 15:07:27 +000032use crate::compos_key;
Alan Stokes0e82b502022-08-08 14:44:48 +010033use binder::{BinderFeatures, ExceptionCode, Interface, Result as BinderResult, Status, Strong};
Alan Stokes6542fdd2022-02-17 15:21:46 +000034use compos_aidl_interface::aidl::com::android::compos::ICompOsService::{
35 BnCompOsService, CompilationMode::CompilationMode, ICompOsService,
Victor Hsieh272aa242021-02-01 14:19:20 -080036};
Alan Stokes6542fdd2022-02-17 15:21:46 +000037use compos_common::binder::to_binder_result;
Victor Hsiehcb6d66b2022-05-10 16:12:06 -070038use compos_common::odrefresh::{is_system_property_interesting, ODREFRESH_PATH};
Victor Hsieh272aa242021-02-01 14:19:20 -080039
Victor Hsiehebb1d902021-08-06 13:00:18 -070040const AUTHFS_SERVICE_NAME: &str = "authfs_service";
Alan Stokes9e2c5d52021-07-21 11:29:10 +010041
Victor Hsieha64194b2021-08-06 17:43:36 -070042/// Constructs a binder object that implements ICompOsService.
Victor Hsieh9ebf7ee2021-09-03 16:14:14 -070043pub fn new_binder() -> Result<Strong<dyn ICompOsService>> {
Victor Hsiehcb6d66b2022-05-10 16:12:06 -070044 let service = CompOsService {
45 odrefresh_path: PathBuf::from(ODREFRESH_PATH),
46 initialized: RwLock::new(None),
47 };
Victor Hsieha64194b2021-08-06 17:43:36 -070048 Ok(BnCompOsService::new_binder(service, BinderFeatures::default()))
Alan Stokes9e2c5d52021-07-21 11:29:10 +010049}
50
Victor Hsieha64194b2021-08-06 17:43:36 -070051struct CompOsService {
Victor Hsiehf9968692021-11-18 11:34:39 -080052 odrefresh_path: PathBuf,
Victor Hsiehcb6d66b2022-05-10 16:12:06 -070053
54 /// A locked protected tri-state.
55 /// * None: uninitialized
56 /// * Some(true): initialized successfully
57 /// * Some(false): failed to initialize
58 initialized: RwLock<Option<bool>>,
Victor Hsieh272aa242021-02-01 14:19:20 -080059}
60
Victor Hsieha64194b2021-08-06 17:43:36 -070061impl Interface for CompOsService {}
Victor Hsieh272aa242021-02-01 14:19:20 -080062
Victor Hsieha64194b2021-08-06 17:43:36 -070063impl ICompOsService for CompOsService {
Victor Hsiehcb6d66b2022-05-10 16:12:06 -070064 fn initializeSystemProperties(&self, names: &[String], values: &[String]) -> BinderResult<()> {
65 let mut initialized = self.initialized.write().unwrap();
66 if initialized.is_some() {
Andrew Walbrandcf9d582022-08-03 11:25:24 +000067 return Err(Status::new_exception_str(
Victor Hsiehcb6d66b2022-05-10 16:12:06 -070068 ExceptionCode::ILLEGAL_STATE,
Andrew Walbrandcf9d582022-08-03 11:25:24 +000069 Some(format!("Already initialized: {:?}", initialized)),
Victor Hsiehcb6d66b2022-05-10 16:12:06 -070070 ));
71 }
72 *initialized = Some(false);
73
74 if names.len() != values.len() {
Andrew Walbrandcf9d582022-08-03 11:25:24 +000075 return Err(Status::new_exception_str(
Victor Hsiehcb6d66b2022-05-10 16:12:06 -070076 ExceptionCode::ILLEGAL_ARGUMENT,
Andrew Walbrandcf9d582022-08-03 11:25:24 +000077 Some(format!(
Victor Hsiehcb6d66b2022-05-10 16:12:06 -070078 "Received inconsistent number of keys ({}) and values ({})",
79 names.len(),
80 values.len()
Andrew Walbrandcf9d582022-08-03 11:25:24 +000081 )),
Victor Hsiehcb6d66b2022-05-10 16:12:06 -070082 ));
83 }
84 for (name, value) in zip(names, values) {
85 if !is_system_property_interesting(name) {
Andrew Walbrandcf9d582022-08-03 11:25:24 +000086 return Err(Status::new_exception_str(
Victor Hsiehcb6d66b2022-05-10 16:12:06 -070087 ExceptionCode::ILLEGAL_ARGUMENT,
Andrew Walbrandcf9d582022-08-03 11:25:24 +000088 Some(format!("Received invalid system property {}", &name)),
Victor Hsiehcb6d66b2022-05-10 16:12:06 -070089 ));
90 }
91 let result = system_properties::write(name, value);
92 if result.is_err() {
93 error!("Failed to setprop {}", &name);
94 return to_binder_result(result);
95 }
96 }
97 *initialized = Some(true);
98 Ok(())
99 }
100
Victor Hsiehf9968692021-11-18 11:34:39 -0800101 fn odrefresh(
102 &self,
Alan Stokes2d2e4db2022-01-28 16:41:52 +0000103 compilation_mode: CompilationMode,
Victor Hsiehf9968692021-11-18 11:34:39 -0800104 system_dir_fd: i32,
Victor Hsieh64d88622022-09-21 17:32:00 -0700105 system_ext_dir_fd: i32,
Victor Hsiehf9968692021-11-18 11:34:39 -0800106 output_dir_fd: i32,
Alan Stokes9646db92021-12-14 13:22:33 +0000107 staging_dir_fd: i32,
108 target_dir_name: &str,
Victor Hsiehf9968692021-11-18 11:34:39 -0800109 zygote_arch: &str,
Victor Hsieh9bfbc5f2021-12-16 11:45:10 -0800110 system_server_compiler_filter: &str,
Alan Stokes9646db92021-12-14 13:22:33 +0000111 ) -> BinderResult<i8> {
Victor Hsiehcb6d66b2022-05-10 16:12:06 -0700112 let initialized = *self.initialized.read().unwrap();
113 if !initialized.unwrap_or(false) {
Andrew Walbrandcf9d582022-08-03 11:25:24 +0000114 return Err(Status::new_exception_str(
Victor Hsiehcb6d66b2022-05-10 16:12:06 -0700115 ExceptionCode::ILLEGAL_STATE,
Andrew Walbrandcf9d582022-08-03 11:25:24 +0000116 Some("Service has not been initialized"),
Victor Hsiehcb6d66b2022-05-10 16:12:06 -0700117 ));
118 }
119
Alan Stokes01b3ef02022-09-22 17:43:24 +0100120 let context = OdrefreshContext::new(
Alan Stokes2d2e4db2022-01-28 16:41:52 +0000121 compilation_mode,
Victor Hsiehf9968692021-11-18 11:34:39 -0800122 system_dir_fd,
Victor Hsieh64d88622022-09-21 17:32:00 -0700123 if system_ext_dir_fd >= 0 { Some(system_ext_dir_fd) } else { None },
Victor Hsiehf9968692021-11-18 11:34:39 -0800124 output_dir_fd,
Alan Stokes9646db92021-12-14 13:22:33 +0000125 staging_dir_fd,
Alan Stokes46a1dff2021-12-14 10:56:05 +0000126 target_dir_name,
Victor Hsiehf9968692021-11-18 11:34:39 -0800127 zygote_arch,
Victor Hsieh9bfbc5f2021-12-16 11:45:10 -0800128 system_server_compiler_filter,
Alan Stokes01b3ef02022-09-22 17:43:24 +0100129 );
Alan Stokes46a1dff2021-12-14 10:56:05 +0000130
Alan Stokes01b3ef02022-09-22 17:43:24 +0100131 to_binder_result(context.and_then(|c| self.do_odrefresh(c)))
Victor Hsiehf9968692021-11-18 11:34:39 -0800132 }
133
Alan Stokes16fb8552022-02-10 15:07:27 +0000134 fn getPublicKey(&self) -> BinderResult<Vec<u8>> {
135 to_binder_result(compos_key::get_public_key())
136 }
Alan Stokes5430eca2022-03-21 14:02:09 +0000137
138 fn getAttestationChain(&self) -> BinderResult<Vec<u8>> {
139 to_binder_result(compos_key::get_attestation_chain())
140 }
Alan Stokes71403772022-06-21 14:56:28 +0100141
142 fn quit(&self) -> BinderResult<()> {
Alan Stokes71403772022-06-21 14:56:28 +0100143 // When our process exits, Microdroid will shut down the VM.
Alan Stokes0fc6ce52022-08-02 17:01:48 +0100144 info!("Received quit request, exiting");
Alan Stokes71403772022-06-21 14:56:28 +0100145 std::process::exit(0);
146 }
Victor Hsieh272aa242021-02-01 14:19:20 -0800147}
Victor Hsiehebb1d902021-08-06 13:00:18 -0700148
Alan Stokes01b3ef02022-09-22 17:43:24 +0100149impl CompOsService {
150 fn do_odrefresh(&self, context: OdrefreshContext) -> Result<i8> {
151 let authfs_service = binder::get_interface(AUTHFS_SERVICE_NAME)
152 .context("Unable to connect to AuthFS service")?;
153 let exit_code = odrefresh(&self.odrefresh_path, context, authfs_service, |output_dir| {
154 // authfs only shows us the files we created, so it's ok to just sign everything
155 // under the output directory.
156 let mut artifact_signer = ArtifactSigner::new(&output_dir);
157 add_artifacts(&output_dir, &mut artifact_signer)?;
158
159 artifact_signer.write_info_and_signature(&output_dir.join("compos.info"))
160 })
161 .context("odrefresh failed")?;
162 Ok(exit_code as i8)
163 }
164}
165
Victor Hsiehec38ae22022-02-10 00:06:26 +0000166fn add_artifacts(target_dir: &Path, artifact_signer: &mut ArtifactSigner) -> Result<()> {
167 for entry in
168 read_dir(&target_dir).with_context(|| format!("Traversing {}", target_dir.display()))?
169 {
170 let entry = entry?;
171 let file_type = entry.file_type()?;
172 if file_type.is_dir() {
173 add_artifacts(&entry.path(), artifact_signer)?;
174 } else if file_type.is_file() {
175 artifact_signer.add_artifact(&entry.path())?;
176 } else {
177 // authfs shouldn't create anything else, but just in case
178 bail!("Unexpected file type in artifacts: {:?}", entry);
179 }
180 }
181 Ok(())
182}