blob: 3738e18cfdffae9209246b4d0f6e89238d615021 [file] [log] [blame]
Alan Stokes3ef78d92021-09-08 11:51:06 +01001/*
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
17//! Implementation of IIsolatedCompilationService, called from system server when compilation is
18//! desired.
19
Alan Stokes9ca14ca2021-10-20 14:25:57 +010020use crate::compilation_task::CompilationTask;
Victor Hsieh72c774c2021-11-18 15:52:28 -080021use crate::fd_server_helper::FdServerConfig;
Alan Stokesa2869d22021-09-22 09:06:41 +010022use crate::instance_manager::InstanceManager;
Victor Hsieh72c774c2021-11-18 15:52:28 -080023use crate::instance_starter::CompOsInstance;
Alan Stokes9ca14ca2021-10-20 14:25:57 +010024use crate::util::to_binder_result;
25use android_system_composd::aidl::android::system::composd::{
26 ICompilationTask::{BnCompilationTask, ICompilationTask},
27 ICompilationTaskCallback::ICompilationTaskCallback,
28 IIsolatedCompilationService::{BnIsolatedCompilationService, IIsolatedCompilationService},
Alan Stokes3ef78d92021-09-08 11:51:06 +010029};
Alan Stokescb732dc2021-11-16 15:18:13 +000030use android_system_composd::binder::{
31 self, BinderFeatures, ExceptionCode, Interface, Status, Strong, ThreadState,
32};
Alan Stokes9ca14ca2021-10-20 14:25:57 +010033use anyhow::{Context, Result};
Victor Hsieh72c774c2021-11-18 15:52:28 -080034use compos_common::COMPOS_DATA_ROOT;
35use rustutils::{system_properties, users::AID_ROOT, users::AID_SYSTEM};
36use std::fs::{create_dir, File, OpenOptions};
37use std::os::unix::fs::OpenOptionsExt;
38use std::os::unix::io::AsRawFd;
39use std::path::{Path, PathBuf};
Alan Stokese5e1d8d2021-11-19 16:31:14 +000040use std::sync::Arc;
Alan Stokes3ef78d92021-09-08 11:51:06 +010041
Alan Stokesa2869d22021-09-22 09:06:41 +010042pub struct IsolatedCompilationService {
Alan Stokese5e1d8d2021-11-19 16:31:14 +000043 instance_manager: Arc<InstanceManager>,
Alan Stokesa2869d22021-09-22 09:06:41 +010044}
Alan Stokes3ef78d92021-09-08 11:51:06 +010045
Alan Stokese5e1d8d2021-11-19 16:31:14 +000046pub fn new_binder(
47 instance_manager: Arc<InstanceManager>,
48) -> Strong<dyn IIsolatedCompilationService> {
Alan Stokes69c610f2021-09-27 14:03:31 +010049 let service = IsolatedCompilationService { instance_manager };
Alan Stokes3ef78d92021-09-08 11:51:06 +010050 BnIsolatedCompilationService::new_binder(service, BinderFeatures::default())
51}
52
Alan Stokes3ef78d92021-09-08 11:51:06 +010053impl Interface for IsolatedCompilationService {}
54
55impl IIsolatedCompilationService for IsolatedCompilationService {
Alan Stokes9ca14ca2021-10-20 14:25:57 +010056 fn startTestCompile(
57 &self,
58 callback: &Strong<dyn ICompilationTaskCallback>,
59 ) -> binder::Result<Strong<dyn ICompilationTask>> {
Victor Hsieh72c774c2021-11-18 15:52:28 -080060 check_test_permissions()?;
Alan Stokes9ca14ca2021-10-20 14:25:57 +010061 to_binder_result(self.do_start_test_compile(callback))
Alan Stokesb2cc79e2021-09-14 14:08:46 +010062 }
Victor Hsieh72c774c2021-11-18 15:52:28 -080063
64 fn startTestOdrefresh(&self) -> binder::Result<i8> {
65 check_test_permissions()?;
66 to_binder_result(self.do_odrefresh_for_test())
67 }
Alan Stokesb2cc79e2021-09-14 14:08:46 +010068}
69
Alan Stokesb2cc79e2021-09-14 14:08:46 +010070impl IsolatedCompilationService {
Alan Stokes9ca14ca2021-10-20 14:25:57 +010071 fn do_start_test_compile(
72 &self,
73 callback: &Strong<dyn ICompilationTaskCallback>,
74 ) -> Result<Strong<dyn ICompilationTask>> {
Alan Stokes388b88a2021-10-13 16:03:17 +010075 let comp_os = self.instance_manager.start_test_instance().context("Starting CompOS")?;
Alan Stokesb2cc79e2021-09-14 14:08:46 +010076
Alan Stokes9ca14ca2021-10-20 14:25:57 +010077 let task = CompilationTask::start_test_compile(comp_os, callback)?;
Alan Stokesb2cc79e2021-09-14 14:08:46 +010078
Alan Stokes9ca14ca2021-10-20 14:25:57 +010079 Ok(BnCompilationTask::new_binder(task, BinderFeatures::default()))
Alan Stokes3ef78d92021-09-08 11:51:06 +010080 }
Victor Hsieh72c774c2021-11-18 15:52:28 -080081
82 fn do_odrefresh_for_test(&self) -> Result<i8> {
83 let mut staging_dir_path = PathBuf::from(COMPOS_DATA_ROOT);
84 staging_dir_path.push("test-artifacts");
85 to_binder_result(create_dir(&staging_dir_path))?;
86
87 let compos = self
88 .instance_manager
89 .start_test_instance()
90 .context("Starting CompOS for odrefresh test")?;
91 self.do_odrefresh(compos, &staging_dir_path)
92 }
93
94 fn do_odrefresh(&self, compos: Arc<CompOsInstance>, staging_dir_path: &Path) -> Result<i8> {
95 let output_dir = open_dir_path(staging_dir_path)?;
96 let system_dir = open_dir_path(Path::new("/system"))?;
97
98 // Spawn a fd_server to serve the FDs.
99 let fd_server_config = FdServerConfig {
100 ro_dir_fds: vec![system_dir.as_raw_fd()],
101 rw_dir_fds: vec![output_dir.as_raw_fd()],
102 ..Default::default()
103 };
104 let fd_server_raii = fd_server_config.into_fd_server()?;
105
106 let zygote_arch = system_properties::read("ro.zygote")?;
107 let result = compos.get_service().odrefresh(
108 system_dir.as_raw_fd(),
109 output_dir.as_raw_fd(),
110 &zygote_arch,
111 );
112 drop(fd_server_raii);
113 Ok(result?.exitCode)
114 }
115}
116
117fn check_test_permissions() -> binder::Result<()> {
118 let calling_uid = ThreadState::get_calling_uid();
119 // This should only be called by system server, or root while testing
120 if calling_uid != AID_SYSTEM && calling_uid != AID_ROOT {
121 Err(Status::new_exception(ExceptionCode::SECURITY, None))
122 } else {
123 Ok(())
124 }
125}
126
127/// Returns an owned FD of the directory path. It currently returns a `File` as a FD owner, but
128/// it's better to use `std::os::unix::io::OwnedFd` once/if it becomes standard.
129fn open_dir_path(path: &Path) -> Result<File> {
130 OpenOptions::new()
131 .custom_flags(libc::O_PATH | libc::O_DIRECTORY)
132 // The custom flags above is not taken into consideration by the unix implementation of
133 // OpenOptions for flag validation. So even though the man page of open(2) says that
134 // most flags include access mode are ignored, we still need to set a "valid" mode to
135 // make the library happy. The value does not appear to matter elsewhere in the library.
136 .read(true)
137 .open(path)
138 .with_context(|| format!("Failed to open {} directory as path fd", path.display()))
Alan Stokes3ef78d92021-09-08 11:51:06 +0100139}