blob: df36ed9b9233b7cda13c2f2f0ee023e8372da8a1 [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 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 Hsiehec38ae22022-02-10 00:06:26 +000026use std::fs::read_dir;
27use std::path::{Path, PathBuf};
Alan Stokes183d7d32021-12-08 16:10:45 +000028use 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 Stokes611cc942022-02-01 10:16:21 +000033use crate::dice::Dice;
Victor Hsiehec38ae22022-02-10 00:06:26 +000034use crate::signing_key::DiceSigningKey;
Victor Hsieh51789de2021-08-06 16:50:49 -070035use authfs_aidl_interface::aidl::com::android::virt::fs::IAuthFsService::IAuthFsService;
Victor Hsieh23f73592021-08-06 18:08:24 -070036use compos_aidl_interface::aidl::com::android::compos::{
37 CompOsKeyData::CompOsKeyData,
Alan Stokes2d2e4db2022-01-28 16:41:52 +000038 ICompOsService::{BnCompOsService, CompilationMode::CompilationMode, 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";
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 {
Victor Hsiehf9968692021-11-18 11:34:39 -080050 odrefresh_path: PathBuf::from(ODREFRESH_PATH),
Alan Stokes611cc942022-02-01 10:16:21 +000051 signing_key: DiceSigningKey::new(Dice::new()?),
Alan Stokes183d7d32021-12-08 16:10:45 +000052 key_blob: RwLock::new(Vec::new()),
Victor Hsieh23f73592021-08-06 18:08:24 -070053 };
Victor Hsieha64194b2021-08-06 17:43:36 -070054 Ok(BnCompOsService::new_binder(service, BinderFeatures::default()))
Alan Stokes9e2c5d52021-07-21 11:29:10 +010055}
56
Victor Hsieha64194b2021-08-06 17:43:36 -070057struct CompOsService {
Victor Hsiehf9968692021-11-18 11:34:39 -080058 odrefresh_path: PathBuf,
Alan Stokes611cc942022-02-01 10:16:21 +000059 signing_key: DiceSigningKey,
Alan Stokes183d7d32021-12-08 16:10:45 +000060 key_blob: RwLock<Vec<u8>>,
Victor Hsieh272aa242021-02-01 14:19:20 -080061}
62
Victor Hsieha64194b2021-08-06 17:43:36 -070063impl Interface for CompOsService {}
Victor Hsieh272aa242021-02-01 14:19:20 -080064
Victor Hsieha64194b2021-08-06 17:43:36 -070065impl ICompOsService for CompOsService {
Victor Hsieh8fd03f02021-08-24 17:23:01 -070066 fn initializeSigningKey(&self, key_blob: &[u8]) -> BinderResult<()> {
67 let mut w = self.key_blob.write().unwrap();
68 if w.is_empty() {
69 *w = Vec::from(key_blob);
70 Ok(())
71 } else {
72 Err(new_binder_exception(ExceptionCode::ILLEGAL_STATE, "Cannot re-initialize the key"))
73 }
74 }
75
Victor Hsiehf9968692021-11-18 11:34:39 -080076 fn odrefresh(
77 &self,
Alan Stokes2d2e4db2022-01-28 16:41:52 +000078 compilation_mode: CompilationMode,
Victor Hsiehf9968692021-11-18 11:34:39 -080079 system_dir_fd: i32,
80 output_dir_fd: i32,
Alan Stokes9646db92021-12-14 13:22:33 +000081 staging_dir_fd: i32,
82 target_dir_name: &str,
Victor Hsiehf9968692021-11-18 11:34:39 -080083 zygote_arch: &str,
Victor Hsieh9bfbc5f2021-12-16 11:45:10 -080084 system_server_compiler_filter: &str,
Alan Stokes9646db92021-12-14 13:22:33 +000085 ) -> BinderResult<i8> {
Victor Hsiehec38ae22022-02-10 00:06:26 +000086 let key = &*self.key_blob.read().unwrap();
87 if key.is_empty() {
88 return Err(new_binder_exception(
89 ExceptionCode::ILLEGAL_STATE,
90 "Key is not initialized",
91 ));
92 }
93
Alan Stokes126fd512021-12-16 15:00:01 +000094 let context = to_binder_result(OdrefreshContext::new(
Alan Stokes2d2e4db2022-01-28 16:41:52 +000095 compilation_mode,
Victor Hsiehf9968692021-11-18 11:34:39 -080096 system_dir_fd,
97 output_dir_fd,
Alan Stokes9646db92021-12-14 13:22:33 +000098 staging_dir_fd,
Alan Stokes46a1dff2021-12-14 10:56:05 +000099 target_dir_name,
Victor Hsiehf9968692021-11-18 11:34:39 -0800100 zygote_arch,
Victor Hsieh9bfbc5f2021-12-16 11:45:10 -0800101 system_server_compiler_filter,
Alan Stokes126fd512021-12-16 15:00:01 +0000102 ))?;
Alan Stokes46a1dff2021-12-14 10:56:05 +0000103
104 let authfs_service = get_authfs_service()?;
Alan Stokes126fd512021-12-16 15:00:01 +0000105 let exit_code = to_binder_result(
Victor Hsiehec38ae22022-02-10 00:06:26 +0000106 odrefresh(&self.odrefresh_path, context, authfs_service, |output_dir| {
107 // authfs only shows us the files we created, so it's ok to just sign everything
108 // under the output directory.
109 let mut artifact_signer = ArtifactSigner::new(&output_dir);
110 add_artifacts(&output_dir, &mut artifact_signer)?;
111
Alan Stokes16fb8552022-02-10 15:07:27 +0000112 artifact_signer.write_info_and_signature(&output_dir.join("compos.info"))
Victor Hsiehec38ae22022-02-10 00:06:26 +0000113 })
114 .context("odrefresh failed"),
Alan Stokes126fd512021-12-16 15:00:01 +0000115 )?;
Alan Stokes46a1dff2021-12-14 10:56:05 +0000116 Ok(exit_code as i8)
Victor Hsiehf9968692021-11-18 11:34:39 -0800117 }
118
Victor Hsieh23f73592021-08-06 18:08:24 -0700119 fn generateSigningKey(&self) -> BinderResult<CompOsKeyData> {
Alan Stokes223a7462022-01-20 14:12:24 +0000120 to_binder_result(self.signing_key.generate())
Victor Hsieh23f73592021-08-06 18:08:24 -0700121 }
122
123 fn verifySigningKey(&self, key_blob: &[u8], public_key: &[u8]) -> BinderResult<bool> {
Alan Stokes223a7462022-01-20 14:12:24 +0000124 Ok(if let Err(e) = self.signing_key.verify(key_blob, public_key) {
Alan Stokes126fd512021-12-16 15:00:01 +0000125 warn!("Signing key verification failed: {:?}", e);
Victor Hsieh23f73592021-08-06 18:08:24 -0700126 false
127 } else {
128 true
129 })
130 }
Alan Stokes16fb8552022-02-10 15:07:27 +0000131
132 fn getPublicKey(&self) -> BinderResult<Vec<u8>> {
133 to_binder_result(compos_key::get_public_key())
134 }
Victor Hsieh272aa242021-02-01 14:19:20 -0800135}
Victor Hsiehebb1d902021-08-06 13:00:18 -0700136
137fn get_authfs_service() -> BinderResult<Strong<dyn IAuthFsService>> {
138 Ok(authfs_aidl_interface::binder::get_interface(AUTHFS_SERVICE_NAME)?)
139}
Victor Hsiehec38ae22022-02-10 00:06:26 +0000140
141fn add_artifacts(target_dir: &Path, artifact_signer: &mut ArtifactSigner) -> Result<()> {
142 for entry in
143 read_dir(&target_dir).with_context(|| format!("Traversing {}", target_dir.display()))?
144 {
145 let entry = entry?;
146 let file_type = entry.file_type()?;
147 if file_type.is_dir() {
148 add_artifacts(&entry.path(), artifact_signer)?;
149 } else if file_type.is_file() {
150 artifact_signer.add_artifact(&entry.path())?;
151 } else {
152 // authfs shouldn't create anything else, but just in case
153 bail!("Unexpected file type in artifacts: {:?}", entry);
154 }
155 }
156 Ok(())
157}