blob: 5d5822121cdfa79d5413dc454addcf8cbd2c9449 [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};
Victor Hsiehcb6d66b2022-05-10 16:12:06 -070022use binder_common::new_binder_exception;
Alan Stokes0fc6ce52022-08-02 17:01:48 +010023use log::{error, info};
Victor Hsiehcb6d66b2022-05-10 16:12:06 -070024use rustutils::system_properties;
Victor Hsieh9ed27182021-08-25 15:52:42 -070025use std::default::Default;
Victor Hsiehec38ae22022-02-10 00:06:26 +000026use std::fs::read_dir;
Victor Hsiehcb6d66b2022-05-10 16:12:06 -070027use std::iter::zip;
Victor Hsiehec38ae22022-02-10 00:06:26 +000028use std::path::{Path, PathBuf};
Victor Hsiehcb6d66b2022-05-10 16:12:06 -070029use std::sync::RwLock;
Victor Hsieh272aa242021-02-01 14:19:20 -080030
Victor Hsiehec38ae22022-02-10 00:06:26 +000031use crate::artifact_signer::ArtifactSigner;
Victor Hsieh616f8222022-01-14 13:06:32 -080032use crate::compilation::{odrefresh, OdrefreshContext};
Alan Stokes16fb8552022-02-10 15:07:27 +000033use crate::compos_key;
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};
Victor Hsiehcb6d66b2022-05-10 16:12:06 -070037use compos_aidl_interface::binder::{
38 BinderFeatures, ExceptionCode, Interface, Result as BinderResult, Strong,
39};
Alan Stokes6542fdd2022-02-17 15:21:46 +000040use compos_common::binder::to_binder_result;
Victor Hsiehcb6d66b2022-05-10 16:12:06 -070041use compos_common::odrefresh::{is_system_property_interesting, ODREFRESH_PATH};
Victor Hsieh272aa242021-02-01 14:19:20 -080042
Victor Hsiehebb1d902021-08-06 13:00:18 -070043const AUTHFS_SERVICE_NAME: &str = "authfs_service";
Alan Stokes9e2c5d52021-07-21 11:29:10 +010044
Victor Hsieha64194b2021-08-06 17:43:36 -070045/// Constructs a binder object that implements ICompOsService.
Victor Hsieh9ebf7ee2021-09-03 16:14:14 -070046pub fn new_binder() -> Result<Strong<dyn ICompOsService>> {
Victor Hsiehcb6d66b2022-05-10 16:12:06 -070047 let service = CompOsService {
48 odrefresh_path: PathBuf::from(ODREFRESH_PATH),
49 initialized: RwLock::new(None),
50 };
Victor Hsieha64194b2021-08-06 17:43:36 -070051 Ok(BnCompOsService::new_binder(service, BinderFeatures::default()))
Alan Stokes9e2c5d52021-07-21 11:29:10 +010052}
53
Victor Hsieha64194b2021-08-06 17:43:36 -070054struct CompOsService {
Victor Hsiehf9968692021-11-18 11:34:39 -080055 odrefresh_path: PathBuf,
Victor Hsiehcb6d66b2022-05-10 16:12:06 -070056
57 /// A locked protected tri-state.
58 /// * None: uninitialized
59 /// * Some(true): initialized successfully
60 /// * Some(false): failed to initialize
61 initialized: RwLock<Option<bool>>,
Victor Hsieh272aa242021-02-01 14:19:20 -080062}
63
Victor Hsieha64194b2021-08-06 17:43:36 -070064impl Interface for CompOsService {}
Victor Hsieh272aa242021-02-01 14:19:20 -080065
Victor Hsieha64194b2021-08-06 17:43:36 -070066impl ICompOsService for CompOsService {
Victor Hsiehcb6d66b2022-05-10 16:12:06 -070067 fn initializeSystemProperties(&self, names: &[String], values: &[String]) -> BinderResult<()> {
68 let mut initialized = self.initialized.write().unwrap();
69 if initialized.is_some() {
70 return Err(new_binder_exception(
71 ExceptionCode::ILLEGAL_STATE,
72 format!("Already initialized: {:?}", initialized),
73 ));
74 }
75 *initialized = Some(false);
76
77 if names.len() != values.len() {
78 return Err(new_binder_exception(
79 ExceptionCode::ILLEGAL_ARGUMENT,
80 format!(
81 "Received inconsistent number of keys ({}) and values ({})",
82 names.len(),
83 values.len()
84 ),
85 ));
86 }
87 for (name, value) in zip(names, values) {
88 if !is_system_property_interesting(name) {
89 return Err(new_binder_exception(
90 ExceptionCode::ILLEGAL_ARGUMENT,
91 format!("Received invalid system property {}", &name),
92 ));
93 }
94 let result = system_properties::write(name, value);
95 if result.is_err() {
96 error!("Failed to setprop {}", &name);
97 return to_binder_result(result);
98 }
99 }
100 *initialized = Some(true);
101 Ok(())
102 }
103
Victor Hsiehf9968692021-11-18 11:34:39 -0800104 fn odrefresh(
105 &self,
Alan Stokes2d2e4db2022-01-28 16:41:52 +0000106 compilation_mode: CompilationMode,
Victor Hsiehf9968692021-11-18 11:34:39 -0800107 system_dir_fd: i32,
108 output_dir_fd: i32,
Alan Stokes9646db92021-12-14 13:22:33 +0000109 staging_dir_fd: i32,
110 target_dir_name: &str,
Victor Hsiehf9968692021-11-18 11:34:39 -0800111 zygote_arch: &str,
Victor Hsieh9bfbc5f2021-12-16 11:45:10 -0800112 system_server_compiler_filter: &str,
Alan Stokes9646db92021-12-14 13:22:33 +0000113 ) -> BinderResult<i8> {
Victor Hsiehcb6d66b2022-05-10 16:12:06 -0700114 let initialized = *self.initialized.read().unwrap();
115 if !initialized.unwrap_or(false) {
116 return Err(new_binder_exception(
117 ExceptionCode::ILLEGAL_STATE,
118 "Service has not been initialized",
119 ));
120 }
121
Alan Stokes126fd512021-12-16 15:00:01 +0000122 let context = to_binder_result(OdrefreshContext::new(
Alan Stokes2d2e4db2022-01-28 16:41:52 +0000123 compilation_mode,
Victor Hsiehf9968692021-11-18 11:34:39 -0800124 system_dir_fd,
125 output_dir_fd,
Alan Stokes9646db92021-12-14 13:22:33 +0000126 staging_dir_fd,
Alan Stokes46a1dff2021-12-14 10:56:05 +0000127 target_dir_name,
Victor Hsiehf9968692021-11-18 11:34:39 -0800128 zygote_arch,
Victor Hsieh9bfbc5f2021-12-16 11:45:10 -0800129 system_server_compiler_filter,
Alan Stokes126fd512021-12-16 15:00:01 +0000130 ))?;
Alan Stokes46a1dff2021-12-14 10:56:05 +0000131
Alan Stokes6542fdd2022-02-17 15:21:46 +0000132 let authfs_service = authfs_aidl_interface::binder::get_interface(AUTHFS_SERVICE_NAME)?;
Alan Stokes126fd512021-12-16 15:00:01 +0000133 let exit_code = to_binder_result(
Victor Hsiehec38ae22022-02-10 00:06:26 +0000134 odrefresh(&self.odrefresh_path, context, authfs_service, |output_dir| {
135 // authfs only shows us the files we created, so it's ok to just sign everything
136 // under the output directory.
137 let mut artifact_signer = ArtifactSigner::new(&output_dir);
138 add_artifacts(&output_dir, &mut artifact_signer)?;
139
Alan Stokes16fb8552022-02-10 15:07:27 +0000140 artifact_signer.write_info_and_signature(&output_dir.join("compos.info"))
Victor Hsiehec38ae22022-02-10 00:06:26 +0000141 })
142 .context("odrefresh failed"),
Alan Stokes126fd512021-12-16 15:00:01 +0000143 )?;
Alan Stokes46a1dff2021-12-14 10:56:05 +0000144 Ok(exit_code as i8)
Victor Hsiehf9968692021-11-18 11:34:39 -0800145 }
146
Alan Stokes16fb8552022-02-10 15:07:27 +0000147 fn getPublicKey(&self) -> BinderResult<Vec<u8>> {
148 to_binder_result(compos_key::get_public_key())
149 }
Alan Stokes5430eca2022-03-21 14:02:09 +0000150
151 fn getAttestationChain(&self) -> BinderResult<Vec<u8>> {
152 to_binder_result(compos_key::get_attestation_chain())
153 }
Alan Stokes71403772022-06-21 14:56:28 +0100154
155 fn quit(&self) -> BinderResult<()> {
Alan Stokes71403772022-06-21 14:56:28 +0100156 // When our process exits, Microdroid will shut down the VM.
Alan Stokes0fc6ce52022-08-02 17:01:48 +0100157 info!("Received quit request, exiting");
Alan Stokes71403772022-06-21 14:56:28 +0100158 std::process::exit(0);
159 }
Victor Hsieh272aa242021-02-01 14:19:20 -0800160}
Victor Hsiehebb1d902021-08-06 13:00:18 -0700161
Victor Hsiehec38ae22022-02-10 00:06:26 +0000162fn add_artifacts(target_dir: &Path, artifact_signer: &mut ArtifactSigner) -> Result<()> {
163 for entry in
164 read_dir(&target_dir).with_context(|| format!("Traversing {}", target_dir.display()))?
165 {
166 let entry = entry?;
167 let file_type = entry.file_type()?;
168 if file_type.is_dir() {
169 add_artifacts(&entry.path(), artifact_signer)?;
170 } else if file_type.is_file() {
171 artifact_signer.add_artifact(&entry.path())?;
172 } else {
173 // authfs shouldn't create anything else, but just in case
174 bail!("Unexpected file type in artifacts: {:?}", entry);
175 }
176 }
177 Ok(())
178}