blob: 0f1629163d6100c0c12c6d8b28fb57fff80d36ab [file] [log] [blame]
David Brazdilafc9a9e2023-01-12 16:08:10 +00001// Copyright 2021, The Android Open Source Project
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15//! Implementation of the AIDL interface of the VirtualizationService.
16
David Brazdil33a31022023-01-12 16:55:16 +000017use crate::atom::{forward_vm_booted_atom, forward_vm_creation_atom, forward_vm_exited_atom};
David Drysdale79af2662024-02-19 14:50:31 +000018use crate::maintenance;
Alice Wange64dd182024-01-17 15:57:55 +000019use crate::remote_provisioning;
Alan Stokesac667072024-02-19 16:26:00 +000020use crate::rkpvm::{generate_ecdsa_p256_key_pair, request_attestation};
21use crate::{get_calling_pid, get_calling_uid, REMOTELY_PROVISIONED_COMPONENT_SERVICE_NAME};
David Brazdilafc9a9e2023-01-12 16:08:10 +000022use android_os_permissions_aidl::aidl::android::os::IPermissionController;
Alan Stokesac667072024-02-19 16:26:00 +000023use android_system_virtualizationcommon::aidl::android::system::virtualizationcommon;
David Drysdale79af2662024-02-19 14:50:31 +000024use android_system_virtualizationmaintenance::aidl::android::system::virtualizationmaintenance;
Alan Stokesac667072024-02-19 16:26:00 +000025use android_system_virtualizationservice::aidl::android::system::virtualizationservice;
26use android_system_virtualizationservice_internal as android_vs_internal;
27use android_system_virtualmachineservice::aidl::android::system::virtualmachineservice;
Seungjae Yoob6e4f1d2024-06-17 15:13:12 +090028use android_system_vmtethering::aidl::android::system::vmtethering;
Alan Stokesac667072024-02-19 16:26:00 +000029use android_vs_internal::aidl::android::system::virtualizationservice_internal;
Alice Wangd1b11a02023-04-18 12:30:20 +000030use anyhow::{anyhow, ensure, Context, Result};
Jiyong Parkd7bd2f22023-08-10 20:41:19 +090031use avflog::LogResult;
Alan Stokesac667072024-02-19 16:26:00 +000032use binder::{
33 self, wait_for_interface, BinderFeatures, ExceptionCode, Interface, IntoBinderResult,
34 LazyServiceGuard, ParcelFileDescriptor, Status, Strong,
35};
Alan Stokes8508bac2024-06-17 15:33:21 +010036use libc::{VMADDR_CID_HOST, VMADDR_CID_HYPERVISOR, VMADDR_CID_LOCAL};
David Brazdilafc9a9e2023-01-12 16:08:10 +000037use log::{error, info, warn};
Alan Stokesac667072024-02-19 16:26:00 +000038use nix::unistd::{chown, Uid};
39use openssl::x509::X509;
Shikha Panwar61a74b52024-02-16 13:17:01 +000040use rand::Fill;
Alice Wangbff017f2023-11-09 14:43:28 +000041use rkpd_client::get_rkpd_attestation_key;
David Drysdalee64de8e2024-02-29 11:54:29 +000042use rustutils::{
43 system_properties,
44 users::{multiuser_get_app_id, multiuser_get_user_id},
45};
Inseob Kimc4a774d2023-08-30 12:48:43 +090046use serde::Deserialize;
Alan Stokesac667072024-02-19 16:26:00 +000047use service_vm_comm::Response;
Inseob Kimc4a774d2023-08-30 12:48:43 +090048use std::collections::{HashMap, HashSet};
David Brazdil2dfefd12023-11-17 14:07:36 +000049use std::fs::{self, create_dir, remove_dir_all, remove_file, set_permissions, File, Permissions};
David Brazdilafc9a9e2023-01-12 16:08:10 +000050use std::io::{Read, Write};
51use std::os::unix::fs::PermissionsExt;
52use std::os::unix::raw::{pid_t, uid_t};
Inseob Kim55438b22023-08-09 20:16:01 +090053use std::path::{Path, PathBuf};
Andrew Walbran9c03a3a2024-09-03 12:12:59 +010054use std::sync::{Arc, Condvar, LazyLock, Mutex, Weak};
David Brazdilafc9a9e2023-01-12 16:08:10 +000055use tombstoned_client::{DebuggerdDumpType, TombstonedConnection};
Alan Stokesac667072024-02-19 16:26:00 +000056use virtualizationcommon::Certificate::Certificate;
Alan Stokes30ccacb2024-02-20 14:59:02 +000057use virtualizationmaintenance::{
58 IVirtualizationMaintenance::IVirtualizationMaintenance,
59 IVirtualizationReconciliationCallback::IVirtualizationReconciliationCallback,
60};
Alan Stokesac667072024-02-19 16:26:00 +000061use virtualizationservice::{
62 AssignableDevice::AssignableDevice, VirtualMachineDebugInfo::VirtualMachineDebugInfo,
63};
64use virtualizationservice_internal::{
65 AtomVmBooted::AtomVmBooted,
66 AtomVmCreationRequested::AtomVmCreationRequested,
67 AtomVmExited::AtomVmExited,
68 IBoundDevice::IBoundDevice,
69 IGlobalVmContext::{BnGlobalVmContext, IGlobalVmContext},
70 IVfioHandler::VfioDev::VfioDev,
71 IVfioHandler::{BpVfioHandler, IVfioHandler},
David Drysdale79af2662024-02-19 14:50:31 +000072 IVirtualizationServiceInternal::IVirtualizationServiceInternal,
Seungjae Yoo13af0b62024-05-20 14:15:13 +090073 IVmnic::{BpVmnic, IVmnic},
Alan Stokesac667072024-02-19 16:26:00 +000074};
75use virtualmachineservice::IVirtualMachineService::VM_TOMBSTONES_SERVICE_PORT;
Seungjae Yoob6e4f1d2024-06-17 15:13:12 +090076use vmtethering::IVmTethering::{BpVmTethering, IVmTethering};
David Brazdilafc9a9e2023-01-12 16:08:10 +000077use vsock::{VsockListener, VsockStream};
David Brazdilafc9a9e2023-01-12 16:08:10 +000078
79/// The unique ID of a VM used (together with a port number) for vsock communication.
80pub type Cid = u32;
81
David Brazdilafc9a9e2023-01-12 16:08:10 +000082/// Directory in which to write disk image files used while running VMs.
83pub const TEMPORARY_DIRECTORY: &str = "/data/misc/virtualizationservice";
84
85/// The first CID to assign to a guest VM managed by the VirtualizationService. CIDs lower than this
86/// are reserved for the host or other usage.
87const GUEST_CID_MIN: Cid = 2048;
88const GUEST_CID_MAX: Cid = 65535;
89
90const SYSPROP_LAST_CID: &str = "virtualizationservice.state.last_cid";
91
92const CHUNK_RECV_MAX_LEN: usize = 1024;
93
Alice Wange64dd182024-01-17 15:57:55 +000094/// The fake certificate is used for testing only when a client VM requests attestation in test
95/// mode, it is a single certificate extracted on an unregistered device for testing.
96/// Here is the snapshot of the certificate:
97///
98/// ```
99/// Certificate:
100/// Data:
101/// Version: 3 (0x2)
102/// Serial Number:
103/// 59:ae:50:98:95:e1:34:25:f1:21:93:c0:4c:e5:24:66
104/// Signature Algorithm: ecdsa-with-SHA256
105/// Issuer: CN = Droid Unregistered Device CA, O = Google Test LLC
106/// Validity
107/// Not Before: Feb 5 14:39:39 2024 GMT
108/// Not After : Feb 14 14:39:39 2024 GMT
109/// Subject: CN = 59ae509895e13425f12193c04ce52466, O = TEE
110/// Subject Public Key Info:
111/// Public Key Algorithm: id-ecPublicKey
112/// Public-Key: (256 bit)
113/// pub:
114/// 04:30:32:cd:95:12:b0:71:8b:b7:14:44:26:58:d5:
115/// 82:8c:25:55:2c:6d:ef:98:e3:4f:88:d0:74:82:09:
116/// 3e:8d:6c:f0:f2:18:d5:83:0e:0d:f2:ce:c5:15:38:
117/// e5:6a:e6:4d:4d:95:15:b7:24:e7:cb:4b:63:42:21:
118/// bc:36:c6:0a:d8
119/// ASN1 OID: prime256v1
120/// NIST CURVE: P-256
121/// X509v3 extensions:
122/// ...
123/// ```
124const FAKE_CERTIFICATE_FOR_TESTING: &[u8] = &[
125 0x30, 0x82, 0x01, 0xee, 0x30, 0x82, 0x01, 0x94, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x10, 0x59,
126 0xae, 0x50, 0x98, 0x95, 0xe1, 0x34, 0x25, 0xf1, 0x21, 0x93, 0xc0, 0x4c, 0xe5, 0x24, 0x66, 0x30,
127 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x30, 0x41, 0x31, 0x25, 0x30,
128 0x23, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x1c, 0x44, 0x72, 0x6f, 0x69, 0x64, 0x20, 0x55, 0x6e,
129 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x65, 0x64, 0x20, 0x44, 0x65, 0x76, 0x69, 0x63,
130 0x65, 0x20, 0x43, 0x41, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0f, 0x47,
131 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x20, 0x54, 0x65, 0x73, 0x74, 0x20, 0x4c, 0x4c, 0x43, 0x30, 0x1e,
132 0x17, 0x0d, 0x32, 0x34, 0x30, 0x32, 0x30, 0x35, 0x31, 0x34, 0x33, 0x39, 0x33, 0x39, 0x5a, 0x17,
133 0x0d, 0x32, 0x34, 0x30, 0x32, 0x31, 0x34, 0x31, 0x34, 0x33, 0x39, 0x33, 0x39, 0x5a, 0x30, 0x39,
134 0x31, 0x29, 0x30, 0x27, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x20, 0x35, 0x39, 0x61, 0x65, 0x35,
135 0x30, 0x39, 0x38, 0x39, 0x35, 0x65, 0x31, 0x33, 0x34, 0x32, 0x35, 0x66, 0x31, 0x32, 0x31, 0x39,
136 0x33, 0x63, 0x30, 0x34, 0x63, 0x65, 0x35, 0x32, 0x34, 0x36, 0x36, 0x31, 0x0c, 0x30, 0x0a, 0x06,
137 0x03, 0x55, 0x04, 0x0a, 0x13, 0x03, 0x54, 0x45, 0x45, 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a,
138 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07,
139 0x03, 0x42, 0x00, 0x04, 0x30, 0x32, 0xcd, 0x95, 0x12, 0xb0, 0x71, 0x8b, 0xb7, 0x14, 0x44, 0x26,
140 0x58, 0xd5, 0x82, 0x8c, 0x25, 0x55, 0x2c, 0x6d, 0xef, 0x98, 0xe3, 0x4f, 0x88, 0xd0, 0x74, 0x82,
141 0x09, 0x3e, 0x8d, 0x6c, 0xf0, 0xf2, 0x18, 0xd5, 0x83, 0x0e, 0x0d, 0xf2, 0xce, 0xc5, 0x15, 0x38,
142 0xe5, 0x6a, 0xe6, 0x4d, 0x4d, 0x95, 0x15, 0xb7, 0x24, 0xe7, 0xcb, 0x4b, 0x63, 0x42, 0x21, 0xbc,
143 0x36, 0xc6, 0x0a, 0xd8, 0xa3, 0x76, 0x30, 0x74, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04,
144 0x16, 0x04, 0x14, 0x39, 0x81, 0x41, 0x0a, 0xb9, 0xf3, 0xf4, 0x5b, 0x75, 0x97, 0x4a, 0x46, 0xd6,
145 0x30, 0x9e, 0x1d, 0x7a, 0x3b, 0xec, 0xa8, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18,
146 0x30, 0x16, 0x80, 0x14, 0x82, 0xbd, 0x00, 0xde, 0xcb, 0xc5, 0xe7, 0x72, 0x87, 0x3d, 0x1c, 0x0a,
147 0x1e, 0x78, 0x4f, 0xf5, 0xd3, 0xc1, 0x3e, 0xb8, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01,
148 0x01, 0xff, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f,
149 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x02, 0x04, 0x30, 0x11, 0x06, 0x0a, 0x2b, 0x06, 0x01,
150 0x04, 0x01, 0xd6, 0x79, 0x02, 0x01, 0x1e, 0x04, 0x03, 0xa1, 0x01, 0x08, 0x30, 0x0a, 0x06, 0x08,
151 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x03, 0x48, 0x00, 0x30, 0x45, 0x02, 0x21, 0x00,
152 0xae, 0xd8, 0x40, 0x9e, 0x37, 0x3e, 0x5c, 0x9c, 0xe2, 0x93, 0x3d, 0x8c, 0xf7, 0x05, 0x10, 0xe7,
153 0xd1, 0x2b, 0x87, 0x8a, 0xee, 0xd6, 0x1e, 0x6c, 0x3b, 0xd2, 0x91, 0x3e, 0xa5, 0xdf, 0x91, 0x20,
154 0x02, 0x20, 0x7f, 0x0f, 0x29, 0x54, 0x60, 0x80, 0x07, 0x50, 0x5f, 0x56, 0x6b, 0x9f, 0xe0, 0x94,
155 0xb4, 0x3f, 0x3b, 0x0f, 0x61, 0xa0, 0x33, 0x40, 0xe6, 0x1a, 0x42, 0xda, 0x4b, 0xa4, 0xfd, 0x92,
156 0xb9, 0x0f,
157];
158
Andrew Walbran9c03a3a2024-09-03 12:12:59 +0100159static FAKE_PROVISIONED_KEY_BLOB_FOR_TESTING: Mutex<Option<Vec<u8>>> = Mutex::new(None);
160static VFIO_SERVICE: LazyLock<Strong<dyn IVfioHandler>> = LazyLock::new(|| {
161 wait_for_interface(<BpVfioHandler as IVfioHandler>::get_descriptor())
162 .expect("Could not connect to VfioHandler")
163});
164static NETWORK_SERVICE: LazyLock<Strong<dyn IVmnic>> = LazyLock::new(|| {
165 wait_for_interface(<BpVmnic as IVmnic>::get_descriptor()).expect("Could not connect to Vmnic")
166});
167static TETHERING_SERVICE: LazyLock<Strong<dyn IVmTethering>> = LazyLock::new(|| {
168 wait_for_interface(<BpVmTethering as IVmTethering>::get_descriptor())
169 .expect("Could not connect to VmTethering")
170});
Jakob Vukalovicd42aa2c2023-11-09 16:04:00 +0000171
David Brazdilafc9a9e2023-01-12 16:08:10 +0000172fn is_valid_guest_cid(cid: Cid) -> bool {
173 (GUEST_CID_MIN..=GUEST_CID_MAX).contains(&cid)
174}
175
176/// Singleton service for allocating globally-unique VM resources, such as the CID, and running
177/// singleton servers, like tombstone receiver.
David Drysdale79af2662024-02-19 14:50:31 +0000178#[derive(Clone)]
David Brazdilafc9a9e2023-01-12 16:08:10 +0000179pub struct VirtualizationServiceInternal {
180 state: Arc<Mutex<GlobalState>>,
Jeongik Cha7add2a42024-04-02 14:52:39 +0900181 display_service_set: Arc<Condvar>,
David Brazdilafc9a9e2023-01-12 16:08:10 +0000182}
183
184impl VirtualizationServiceInternal {
David Drysdale79af2662024-02-19 14:50:31 +0000185 pub fn init() -> VirtualizationServiceInternal {
Jeongik Cha7add2a42024-04-02 14:52:39 +0900186 let service = VirtualizationServiceInternal {
187 state: Arc::new(Mutex::new(GlobalState::new())),
188 display_service_set: Arc::new(Condvar::new()),
189 };
David Brazdilafc9a9e2023-01-12 16:08:10 +0000190
191 std::thread::spawn(|| {
192 if let Err(e) = handle_stream_connection_tombstoned() {
193 warn!("Error receiving tombstone from guest or writing them. Error: {:?}", e);
194 }
195 });
196
David Drysdale79af2662024-02-19 14:50:31 +0000197 service
David Brazdilafc9a9e2023-01-12 16:08:10 +0000198 }
199}
200
201impl Interface for VirtualizationServiceInternal {}
202
203impl IVirtualizationServiceInternal for VirtualizationServiceInternal {
Jeongik Cha7add2a42024-04-02 14:52:39 +0900204 fn setDisplayService(
205 &self,
206 ibinder: &binder::SpIBinder,
207 ) -> std::result::Result<(), binder::Status> {
208 check_manage_access()?;
209 check_use_custom_virtual_machine()?;
210 let state = &mut *self.state.lock().unwrap();
211 state.display_service = Some(ibinder.clone());
212 self.display_service_set.notify_all();
213 Ok(())
214 }
215
Jeongik Chaeee137d2024-04-03 22:13:14 +0900216 fn clearDisplayService(&self) -> std::result::Result<(), binder::Status> {
217 check_manage_access()?;
218 check_use_custom_virtual_machine()?;
219 let state = &mut *self.state.lock().unwrap();
220 state.display_service = None;
221 self.display_service_set.notify_all();
222 Ok(())
223 }
224
Jeongik Cha7add2a42024-04-02 14:52:39 +0900225 fn waitDisplayService(&self) -> std::result::Result<binder::SpIBinder, binder::Status> {
226 check_manage_access()?;
227 check_use_custom_virtual_machine()?;
228 let state = self
229 .display_service_set
230 .wait_while(self.state.lock().unwrap(), |state| state.display_service.is_none())
231 .unwrap();
232 Ok((state.display_service)
233 .as_ref()
234 .cloned()
235 .expect("Display service cannot be None in this context"))
236 }
David Brazdilafc9a9e2023-01-12 16:08:10 +0000237 fn removeMemlockRlimit(&self) -> binder::Result<()> {
238 let pid = get_calling_pid();
239 let lim = libc::rlimit { rlim_cur: libc::RLIM_INFINITY, rlim_max: libc::RLIM_INFINITY };
240
Andrew Walbranb58d1b42023-07-07 13:54:49 +0100241 // SAFETY: borrowing the new limit struct only
David Brazdilafc9a9e2023-01-12 16:08:10 +0000242 let ret = unsafe { libc::prlimit(pid, libc::RLIMIT_MEMLOCK, &lim, std::ptr::null_mut()) };
243
244 match ret {
245 0 => Ok(()),
Jiyong Park2227eaa2023-08-04 11:59:18 +0900246 -1 => Err(std::io::Error::last_os_error().into()),
247 n => Err(anyhow!("Unexpected return value from prlimit(): {n}")),
David Brazdilafc9a9e2023-01-12 16:08:10 +0000248 }
Jiyong Park2227eaa2023-08-04 11:59:18 +0900249 .or_binder_exception(ExceptionCode::ILLEGAL_STATE)
David Brazdilafc9a9e2023-01-12 16:08:10 +0000250 }
251
252 fn allocateGlobalVmContext(
253 &self,
254 requester_debug_pid: i32,
255 ) -> binder::Result<Strong<dyn IGlobalVmContext>> {
256 check_manage_access()?;
257
258 let requester_uid = get_calling_uid();
259 let requester_debug_pid = requester_debug_pid as pid_t;
260 let state = &mut *self.state.lock().unwrap();
Jiyong Park2227eaa2023-08-04 11:59:18 +0900261 state
262 .allocate_vm_context(requester_uid, requester_debug_pid)
263 .or_binder_exception(ExceptionCode::ILLEGAL_STATE)
David Brazdilafc9a9e2023-01-12 16:08:10 +0000264 }
265
266 fn atomVmBooted(&self, atom: &AtomVmBooted) -> Result<(), Status> {
267 forward_vm_booted_atom(atom);
268 Ok(())
269 }
270
271 fn atomVmCreationRequested(&self, atom: &AtomVmCreationRequested) -> Result<(), Status> {
272 forward_vm_creation_atom(atom);
273 Ok(())
274 }
275
276 fn atomVmExited(&self, atom: &AtomVmExited) -> Result<(), Status> {
277 forward_vm_exited_atom(atom);
278 Ok(())
279 }
280
281 fn debugListVms(&self) -> binder::Result<Vec<VirtualMachineDebugInfo>> {
282 check_debug_access()?;
283
284 let state = &mut *self.state.lock().unwrap();
285 let cids = state
286 .held_contexts
287 .iter()
288 .filter_map(|(_, inst)| Weak::upgrade(inst))
Yi-Yo Chiang2fbf0da2024-06-14 22:56:56 +0800289 .map(|vm| {
290 let vm = vm.lock().unwrap();
291 VirtualMachineDebugInfo {
292 cid: vm.cid as i32,
293 temporaryDirectory: vm.get_temp_dir().to_string_lossy().to_string(),
294 requesterUid: vm.requester_uid as i32,
295 requesterPid: vm.requester_debug_pid,
296 hostConsoleName: vm.host_console_name.clone(),
297 }
David Brazdilafc9a9e2023-01-12 16:08:10 +0000298 })
299 .collect();
300 Ok(cids)
301 }
Alice Wangc2fec932023-02-23 16:24:02 +0000302
Alice Wange64dd182024-01-17 15:57:55 +0000303 fn enableTestAttestation(&self) -> binder::Result<()> {
304 check_manage_access()?;
305 check_use_custom_virtual_machine()?;
306 if !cfg!(remote_attestation) {
307 return Err(Status::new_exception_str(
308 ExceptionCode::UNSUPPORTED_OPERATION,
309 Some(
310 "enableTestAttestation is not supported with the remote_attestation \
311 feature disabled",
312 ),
313 ))
314 .with_log();
315 }
316 let res = generate_ecdsa_p256_key_pair()
317 .context("Failed to generate ECDSA P-256 key pair for testing")
318 .with_log()
319 .or_service_specific_exception(-1)?;
Alice Wang5daec072024-03-15 15:31:17 +0000320 // Wait until the service VM shuts down, so that the Service VM will be restarted when
321 // the key generated in the current session will be used for attestation.
322 // This ensures that different Service VM sessions have the same KEK for the key blob.
323 service_vm_manager::wait_until_service_vm_shuts_down()
324 .context("Failed to wait until the service VM shuts down")
325 .with_log()
326 .or_service_specific_exception(-1)?;
Alice Wange64dd182024-01-17 15:57:55 +0000327 match res {
328 Response::GenerateEcdsaP256KeyPair(key_pair) => {
329 FAKE_PROVISIONED_KEY_BLOB_FOR_TESTING
330 .lock()
331 .unwrap()
332 .replace(key_pair.key_blob.to_vec());
333 Ok(())
334 }
335 _ => Err(remote_provisioning::to_service_specific_error(res)),
336 }
337 .with_log()
338 }
339
Alice Wangbff017f2023-11-09 14:43:28 +0000340 fn requestAttestation(
341 &self,
342 csr: &[u8],
343 requester_uid: i32,
Alice Wange64dd182024-01-17 15:57:55 +0000344 test_mode: bool,
Alice Wangbff017f2023-11-09 14:43:28 +0000345 ) -> binder::Result<Vec<Certificate>> {
Alice Wangc2fec932023-02-23 16:24:02 +0000346 check_manage_access()?;
Alice Wang4c6c5582023-11-23 15:07:18 +0000347 if !cfg!(remote_attestation) {
348 return Err(Status::new_exception_str(
Alice Wange9ac2db2023-09-08 15:13:13 +0000349 ExceptionCode::UNSUPPORTED_OPERATION,
350 Some(
Alice Wanga410b642023-10-18 09:05:15 +0000351 "requestAttestation is not supported with the remote_attestation feature \
352 disabled",
Alice Wange9ac2db2023-09-08 15:13:13 +0000353 ),
354 ))
Alice Wang4c6c5582023-11-23 15:07:18 +0000355 .with_log();
Alice Wange9ac2db2023-09-08 15:13:13 +0000356 }
Alice Wang6c6535d2024-05-31 06:45:31 +0000357 if !is_remote_provisioning_hal_declared()? {
Alice Wang0dcab552024-03-20 14:42:30 +0000358 return Err(Status::new_exception_str(
359 ExceptionCode::UNSUPPORTED_OPERATION,
360 Some("AVF remotely provisioned component service is not declared"),
361 ))
362 .with_log();
363 }
Alice Wangeec580d2024-06-07 08:48:06 +0000364 remote_provisioning::check_remote_attestation_is_supported()?;
Alice Wang4c6c5582023-11-23 15:07:18 +0000365 info!("Received csr. Requestting attestation...");
Alice Wange64dd182024-01-17 15:57:55 +0000366 let (key_blob, certificate_chain) = if test_mode {
367 check_use_custom_virtual_machine()?;
368 info!("Using the fake key blob for testing...");
369 (
370 FAKE_PROVISIONED_KEY_BLOB_FOR_TESTING
371 .lock()
372 .unwrap()
373 .clone()
374 .ok_or_else(|| anyhow!("No key blob for testing"))
375 .with_log()
376 .or_service_specific_exception(-1)?,
377 FAKE_CERTIFICATE_FOR_TESTING.to_vec(),
378 )
379 } else {
380 info!("Retrieving the remotely provisioned keys from RKPD...");
381 let attestation_key = get_rkpd_attestation_key(
382 REMOTELY_PROVISIONED_COMPONENT_SERVICE_NAME,
383 requester_uid as u32,
384 )
385 .context("Failed to retrieve the remotely provisioned keys")
386 .with_log()
387 .or_service_specific_exception(-1)?;
388 (attestation_key.keyBlob, attestation_key.encodedCertChain)
389 };
390 let mut certificate_chain = split_x509_certificate_chain(&certificate_chain)
Alice Wang4c6c5582023-11-23 15:07:18 +0000391 .context("Failed to split the remotely provisioned certificate chain")
392 .with_log()
393 .or_service_specific_exception(-1)?;
394 if certificate_chain.is_empty() {
395 return Err(Status::new_service_specific_error_str(
396 -1,
397 Some("The certificate chain should contain at least 1 certificate"),
398 ))
399 .with_log();
400 }
Alice Wang20b8ebc2023-11-17 09:54:47 +0000401 let certificate = request_attestation(
402 csr.to_vec(),
Alice Wange64dd182024-01-17 15:57:55 +0000403 key_blob,
Alice Wang20b8ebc2023-11-17 09:54:47 +0000404 certificate_chain[0].encodedCertificate.clone(),
405 )
406 .context("Failed to request attestation")
407 .with_log()
408 .or_service_specific_exception(-1)?;
Alice Wang4c6c5582023-11-23 15:07:18 +0000409 certificate_chain.insert(0, Certificate { encodedCertificate: certificate });
410
411 Ok(certificate_chain)
Alice Wangc2fec932023-02-23 16:24:02 +0000412 }
Inseob Kim53d0b212023-07-20 16:58:37 +0900413
Alice Wang0362f7f2024-03-21 08:16:26 +0000414 fn isRemoteAttestationSupported(&self) -> binder::Result<bool> {
Alice Wangeec580d2024-06-07 08:48:06 +0000415 Ok(is_remote_provisioning_hal_declared()?
416 && remote_provisioning::is_remote_attestation_supported())
Alice Wang0362f7f2024-03-21 08:16:26 +0000417 }
418
Inseob Kim53d0b212023-07-20 16:58:37 +0900419 fn getAssignableDevices(&self) -> binder::Result<Vec<AssignableDevice>> {
420 check_use_custom_virtual_machine()?;
421
Inseob Kim7307a892023-09-14 13:37:58 +0900422 Ok(get_assignable_devices()?
423 .device
424 .into_iter()
Jaewan Kim0c99c612024-03-23 00:44:14 +0900425 .map(|x| AssignableDevice { node: x.sysfs_path, dtbo_label: x.dtbo_label })
Inseob Kim7307a892023-09-14 13:37:58 +0900426 .collect::<Vec<_>>())
Inseob Kim53d0b212023-07-20 16:58:37 +0900427 }
Inseob Kim1ca0f652023-07-20 17:18:12 +0900428
Jakob Vukalovicd42aa2c2023-11-09 16:04:00 +0000429 fn bindDevicesToVfioDriver(
430 &self,
431 devices: &[String],
432 ) -> binder::Result<Vec<Strong<dyn IBoundDevice>>> {
Inseob Kim1ca0f652023-07-20 17:18:12 +0900433 check_use_custom_virtual_machine()?;
434
Jakob Vukalovicd42aa2c2023-11-09 16:04:00 +0000435 let devices = get_assignable_devices()?
Inseob Kim7307a892023-09-14 13:37:58 +0900436 .device
437 .into_iter()
438 .filter_map(|x| {
439 if devices.contains(&x.sysfs_path) {
Jakob Vukalovicd42aa2c2023-11-09 16:04:00 +0000440 Some(VfioDev { sysfsPath: x.sysfs_path, dtboLabel: x.dtbo_label })
Inseob Kim7307a892023-09-14 13:37:58 +0900441 } else {
Jakob Vukalovicd42aa2c2023-11-09 16:04:00 +0000442 warn!("device {} is not assignable", x.sysfs_path);
Inseob Kim7307a892023-09-14 13:37:58 +0900443 None
444 }
445 })
Jakob Vukalovicd42aa2c2023-11-09 16:04:00 +0000446 .collect::<Vec<VfioDev>>();
447
448 VFIO_SERVICE.bindDevicesToVfioDriver(devices.as_slice())
Inseob Kim1ca0f652023-07-20 17:18:12 +0900449 }
David Brazdil2dfefd12023-11-17 14:07:36 +0000450
451 fn getDtboFile(&self) -> binder::Result<ParcelFileDescriptor> {
452 check_use_custom_virtual_machine()?;
453
454 let state = &mut *self.state.lock().unwrap();
455 let file = state.get_dtbo_file().or_service_specific_exception(-1)?;
456 Ok(ParcelFileDescriptor::new(file))
457 }
Shikha Panwar61a74b52024-02-16 13:17:01 +0000458
Shikha Panwar61a74b52024-02-16 13:17:01 +0000459 fn allocateInstanceId(&self) -> binder::Result<[u8; 64]> {
460 let mut id = [0u8; 64];
461 id.try_fill(&mut rand::thread_rng())
462 .context("Failed to allocate instance_id")
463 .or_service_specific_exception(-1)?;
464 let uid = get_calling_uid();
Shikha Panwar75e920b2024-06-14 06:12:37 +0000465 info!("Allocated a VM's instance_id: {:?}..., for uid: {:?}", &hex::encode(id)[..8], uid);
David Drysdalee64de8e2024-02-29 11:54:29 +0000466 let state = &mut *self.state.lock().unwrap();
467 if let Some(sk_state) = &mut state.sk_state {
468 let user_id = multiuser_get_user_id(uid);
469 let app_id = multiuser_get_app_id(uid);
David Drysdale1138fa02024-03-19 13:06:23 +0000470 info!("Recording possible existence of state for (user_id={user_id}, app_id={app_id})");
David Drysdalee64de8e2024-02-29 11:54:29 +0000471 if let Err(e) = sk_state.add_id(&id, user_id, app_id) {
472 error!("Failed to record the instance_id: {e:?}");
473 }
474 }
475
Shikha Panwar61a74b52024-02-16 13:17:01 +0000476 Ok(id)
477 }
David Drysdale79af2662024-02-19 14:50:31 +0000478
479 fn removeVmInstance(&self, instance_id: &[u8; 64]) -> binder::Result<()> {
480 let state = &mut *self.state.lock().unwrap();
481 if let Some(sk_state) = &mut state.sk_state {
Alan Stokesde40e642024-06-04 13:36:05 +0100482 let uid = get_calling_uid();
483 info!(
484 "Removing a VM's instance_id: {:?}, for uid: {:?}",
485 hex::encode(instance_id),
486 uid
487 );
488
489 let user_id = multiuser_get_user_id(uid);
490 let app_id = multiuser_get_app_id(uid);
491 sk_state.delete_id(instance_id, user_id, app_id);
David Drysdale79af2662024-02-19 14:50:31 +0000492 } else {
493 info!("ignoring removeVmInstance() as no ISecretkeeper");
494 }
495 Ok(())
496 }
David Drysdale3aa62b32024-03-25 12:31:48 +0000497
498 fn claimVmInstance(&self, instance_id: &[u8; 64]) -> binder::Result<()> {
499 let state = &mut *self.state.lock().unwrap();
500 if let Some(sk_state) = &mut state.sk_state {
501 let uid = get_calling_uid();
502 info!(
503 "Claiming a VM's instance_id: {:?}, for uid: {:?}",
504 hex::encode(instance_id),
505 uid
506 );
507
508 let user_id = multiuser_get_user_id(uid);
509 let app_id = multiuser_get_app_id(uid);
510 info!("Recording possible new owner of state for (user_id={user_id}, app_id={app_id})");
511 if let Err(e) = sk_state.add_id(instance_id, user_id, app_id) {
512 error!("Failed to update the instance_id owner: {e:?}");
513 }
514 } else {
515 info!("ignoring claimVmInstance() as no ISecretkeeper");
516 }
517 Ok(())
518 }
Seungjae Yoo13af0b62024-05-20 14:15:13 +0900519
Seungjae Yoo548346e2024-06-19 16:18:06 +0900520 fn createTapInterface(&self, _iface_name_suffix: &str) -> binder::Result<ParcelFileDescriptor> {
Seungjae Yooa6589bd2024-06-11 10:14:07 +0900521 check_internet_permission()?;
Seungjae Yoo13af0b62024-05-20 14:15:13 +0900522 check_use_custom_virtual_machine()?;
523 if !cfg!(network) {
524 return Err(Status::new_exception_str(
525 ExceptionCode::UNSUPPORTED_OPERATION,
526 Some("createTapInterface is not supported with the network feature disabled"),
527 ))
528 .with_log();
529 }
Seungjae Yoo548346e2024-06-19 16:18:06 +0900530 // TODO(340377643): Use iface_name_suffix after introducing bridge interface, not fixed
531 // value.
532 let tap_fd = NETWORK_SERVICE.createTapInterface("fixed")?;
Seungjae Yoob6e4f1d2024-06-17 15:13:12 +0900533
534 // TODO(340377643): Due to lack of implementation of creating bridge interface, tethering is
535 // enabled for TAP interface instead of bridge interface. After introducing creation of
536 // bridge interface in AVF, we should modify it.
Seungjae Yoo548346e2024-06-19 16:18:06 +0900537 TETHERING_SERVICE.enableVmTethering()?;
Seungjae Yoob6e4f1d2024-06-17 15:13:12 +0900538
539 Ok(tap_fd)
Seungjae Yoo13af0b62024-05-20 14:15:13 +0900540 }
Seungjae Yoo3271f172024-06-11 10:14:07 +0900541
542 fn deleteTapInterface(&self, tap_fd: &ParcelFileDescriptor) -> binder::Result<()> {
543 check_internet_permission()?;
544 check_use_custom_virtual_machine()?;
545 if !cfg!(network) {
546 return Err(Status::new_exception_str(
547 ExceptionCode::UNSUPPORTED_OPERATION,
548 Some("deleteTapInterface is not supported with the network feature disabled"),
549 ))
550 .with_log();
551 }
Seungjae Yooa442e672024-06-19 16:18:07 +0900552
553 // TODO(340377643): Disabling tethering should be for bridge interface, not TAP interface.
554 TETHERING_SERVICE.disableVmTethering()?;
555
Seungjae Yoo3271f172024-06-11 10:14:07 +0900556 NETWORK_SERVICE.deleteTapInterface(tap_fd)
557 }
David Drysdale79af2662024-02-19 14:50:31 +0000558}
559
560impl IVirtualizationMaintenance for VirtualizationServiceInternal {
561 fn appRemoved(&self, user_id: i32, app_id: i32) -> binder::Result<()> {
562 let state = &mut *self.state.lock().unwrap();
563 if let Some(sk_state) = &mut state.sk_state {
564 info!("packageRemoved(user_id={user_id}, app_id={app_id})");
565 sk_state.delete_ids_for_app(user_id, app_id).or_service_specific_exception(-1)?;
566 } else {
567 info!("ignoring packageRemoved(user_id={user_id}, app_id={app_id})");
568 }
569 Ok(())
570 }
571
572 fn userRemoved(&self, user_id: i32) -> binder::Result<()> {
573 let state = &mut *self.state.lock().unwrap();
574 if let Some(sk_state) = &mut state.sk_state {
575 info!("userRemoved({user_id})");
576 sk_state.delete_ids_for_user(user_id).or_service_specific_exception(-1)?;
577 } else {
578 info!("ignoring userRemoved(user_id={user_id})");
579 }
580 Ok(())
581 }
Alan Stokes30ccacb2024-02-20 14:59:02 +0000582
583 fn performReconciliation(
584 &self,
David Drysdale1138fa02024-03-19 13:06:23 +0000585 callback: &Strong<dyn IVirtualizationReconciliationCallback>,
Alan Stokes30ccacb2024-02-20 14:59:02 +0000586 ) -> binder::Result<()> {
David Drysdale1138fa02024-03-19 13:06:23 +0000587 let state = &mut *self.state.lock().unwrap();
588 if let Some(sk_state) = &mut state.sk_state {
589 info!("performReconciliation()");
590 sk_state.reconcile(callback).or_service_specific_exception(-1)?;
591 } else {
592 info!("ignoring performReconciliation()");
593 }
594 Ok(())
Alan Stokes30ccacb2024-02-20 14:59:02 +0000595 }
Inseob Kim1ca0f652023-07-20 17:18:12 +0900596}
597
Inseob Kimc4a774d2023-08-30 12:48:43 +0900598#[derive(Debug, Deserialize)]
599struct Device {
Jaewan Kim35e818d2023-10-18 05:36:38 +0000600 dtbo_label: String,
Inseob Kimc4a774d2023-08-30 12:48:43 +0900601 sysfs_path: String,
602}
603
Inseob Kim7307a892023-09-14 13:37:58 +0900604#[derive(Debug, Default, Deserialize)]
Inseob Kimc4a774d2023-08-30 12:48:43 +0900605struct Devices {
606 device: Vec<Device>,
607}
608
Inseob Kim7307a892023-09-14 13:37:58 +0900609fn get_assignable_devices() -> binder::Result<Devices> {
610 let xml_path = Path::new("/vendor/etc/avf/assignable_devices.xml");
611 if !xml_path.exists() {
612 return Ok(Devices { ..Default::default() });
613 }
614
615 let xml = fs::read(xml_path)
616 .context("Failed to read assignable_devices.xml")
617 .with_log()
618 .or_service_specific_exception(-1)?;
619
620 let xml = String::from_utf8(xml)
621 .context("assignable_devices.xml is not a valid UTF-8 file")
622 .with_log()
623 .or_service_specific_exception(-1)?;
624
625 let mut devices: Devices = serde_xml_rs::from_str(&xml)
626 .context("can't parse assignable_devices.xml")
627 .with_log()
628 .or_service_specific_exception(-1)?;
629
630 let mut device_set = HashSet::new();
631 devices.device.retain(move |device| {
632 if device_set.contains(&device.sysfs_path) {
633 warn!("duplicated assignable device {device:?}; ignoring...");
634 return false;
635 }
636
637 if !Path::new(&device.sysfs_path).exists() {
638 warn!("assignable device {device:?} doesn't exist; ignoring...");
639 return false;
640 }
641
642 device_set.insert(device.sysfs_path.clone());
643 true
644 });
645 Ok(devices)
646}
647
Alice Wang4c6c5582023-11-23 15:07:18 +0000648fn split_x509_certificate_chain(mut cert_chain: &[u8]) -> Result<Vec<Certificate>> {
649 let mut out = Vec::new();
650 while !cert_chain.is_empty() {
Alice Wangfc5a44a2023-12-21 12:22:40 +0000651 let cert = X509::from_der(cert_chain)?;
652 let end = cert.to_der()?.len();
Alice Wang4c6c5582023-11-23 15:07:18 +0000653 out.push(Certificate { encodedCertificate: cert_chain[..end].to_vec() });
Alice Wangfc5a44a2023-12-21 12:22:40 +0000654 cert_chain = &cert_chain[end..];
Alice Wang4c6c5582023-11-23 15:07:18 +0000655 }
656 Ok(out)
657}
658
David Brazdilafc9a9e2023-01-12 16:08:10 +0000659#[derive(Debug, Default)]
660struct GlobalVmInstance {
661 /// The unique CID assigned to the VM for vsock communication.
662 cid: Cid,
663 /// UID of the client who requested this VM instance.
664 requester_uid: uid_t,
665 /// PID of the client who requested this VM instance.
666 requester_debug_pid: pid_t,
Yi-Yo Chiang2fbf0da2024-06-14 22:56:56 +0800667 /// Name of the host console.
668 host_console_name: Option<String>,
David Brazdilafc9a9e2023-01-12 16:08:10 +0000669}
670
671impl GlobalVmInstance {
672 fn get_temp_dir(&self) -> PathBuf {
673 let cid = self.cid;
674 format!("{TEMPORARY_DIRECTORY}/{cid}").into()
675 }
676}
677
678/// The mutable state of the VirtualizationServiceInternal. There should only be one instance
679/// of this struct.
David Brazdilafc9a9e2023-01-12 16:08:10 +0000680struct GlobalState {
681 /// VM contexts currently allocated to running VMs. A CID is never recycled as long
682 /// as there is a strong reference held by a GlobalVmContext.
Yi-Yo Chiang2fbf0da2024-06-14 22:56:56 +0800683 held_contexts: HashMap<Cid, Weak<Mutex<GlobalVmInstance>>>,
David Brazdil2dfefd12023-11-17 14:07:36 +0000684
685 /// Cached read-only FD of VM DTBO file. Also serves as a lock for creating the file.
686 dtbo_file: Mutex<Option<File>>,
David Drysdale79af2662024-02-19 14:50:31 +0000687
688 /// State relating to secrets held by (optional) Secretkeeper instance on behalf of VMs.
689 sk_state: Option<maintenance::State>,
Jeongik Cha7add2a42024-04-02 14:52:39 +0900690
691 display_service: Option<binder::SpIBinder>,
David Brazdilafc9a9e2023-01-12 16:08:10 +0000692}
693
694impl GlobalState {
David Drysdale79af2662024-02-19 14:50:31 +0000695 fn new() -> Self {
696 Self {
697 held_contexts: HashMap::new(),
698 dtbo_file: Mutex::new(None),
699 sk_state: maintenance::State::new(),
Jeongik Cha7add2a42024-04-02 14:52:39 +0900700 display_service: None,
David Drysdale79af2662024-02-19 14:50:31 +0000701 }
702 }
703
David Brazdilafc9a9e2023-01-12 16:08:10 +0000704 /// Get the next available CID, or an error if we have run out. The last CID used is stored in
705 /// a system property so that restart of virtualizationservice doesn't reuse CID while the host
706 /// Android is up.
707 fn get_next_available_cid(&mut self) -> Result<Cid> {
708 // Start trying to find a CID from the last used CID + 1. This ensures
709 // that we do not eagerly recycle CIDs. It makes debugging easier but
710 // also means that retrying to allocate a CID, eg. because it is
711 // erroneously occupied by a process, will not recycle the same CID.
712 let last_cid_prop =
713 system_properties::read(SYSPROP_LAST_CID)?.and_then(|val| match val.parse::<Cid>() {
714 Ok(num) => {
715 if is_valid_guest_cid(num) {
716 Some(num)
717 } else {
718 error!("Invalid value '{}' of property '{}'", num, SYSPROP_LAST_CID);
719 None
720 }
721 }
722 Err(_) => {
723 error!("Invalid value '{}' of property '{}'", val, SYSPROP_LAST_CID);
724 None
725 }
726 });
727
728 let first_cid = if let Some(last_cid) = last_cid_prop {
729 if last_cid == GUEST_CID_MAX {
730 GUEST_CID_MIN
731 } else {
732 last_cid + 1
733 }
734 } else {
735 GUEST_CID_MIN
736 };
737
738 let cid = self
739 .find_available_cid(first_cid..=GUEST_CID_MAX)
740 .or_else(|| self.find_available_cid(GUEST_CID_MIN..first_cid))
741 .ok_or_else(|| anyhow!("Could not find an available CID."))?;
742
743 system_properties::write(SYSPROP_LAST_CID, &format!("{}", cid))?;
744 Ok(cid)
745 }
746
747 fn find_available_cid<I>(&self, mut range: I) -> Option<Cid>
748 where
749 I: Iterator<Item = Cid>,
750 {
751 range.find(|cid| !self.held_contexts.contains_key(cid))
752 }
753
754 fn allocate_vm_context(
755 &mut self,
756 requester_uid: uid_t,
757 requester_debug_pid: pid_t,
758 ) -> Result<Strong<dyn IGlobalVmContext>> {
759 // Garbage collect unused VM contexts.
760 self.held_contexts.retain(|_, instance| instance.strong_count() > 0);
761
762 let cid = self.get_next_available_cid()?;
Yi-Yo Chiang2fbf0da2024-06-14 22:56:56 +0800763 let instance = Arc::new(Mutex::new(GlobalVmInstance {
764 cid,
765 requester_uid,
766 requester_debug_pid,
767 ..Default::default()
768 }));
769 create_temporary_directory(&instance.lock().unwrap().get_temp_dir(), Some(requester_uid))?;
David Brazdilafc9a9e2023-01-12 16:08:10 +0000770
771 self.held_contexts.insert(cid, Arc::downgrade(&instance));
772 let binder = GlobalVmContext { instance, ..Default::default() };
773 Ok(BnGlobalVmContext::new_binder(binder, BinderFeatures::default()))
774 }
David Brazdil2dfefd12023-11-17 14:07:36 +0000775
776 fn get_dtbo_file(&mut self) -> Result<File> {
777 let mut file = self.dtbo_file.lock().unwrap();
778
779 let fd = if let Some(ref_fd) = &*file {
780 ref_fd.try_clone()?
781 } else {
782 let path = get_or_create_common_dir()?.join("vm.dtbo");
783 if path.exists() {
784 // All temporary files are deleted when the service is started.
785 // If the file exists but the FD is not cached, the file is
786 // likely corrupted.
787 remove_file(&path).context("Failed to clone cached VM DTBO file descriptor")?;
788 }
789
790 // Open a write-only file descriptor for vfio_handler.
791 let write_fd = File::create(&path).context("Failed to create VM DTBO file")?;
Jakob Vukalovicd42aa2c2023-11-09 16:04:00 +0000792 VFIO_SERVICE.writeVmDtbo(&ParcelFileDescriptor::new(write_fd))?;
David Brazdil2dfefd12023-11-17 14:07:36 +0000793
794 // Open read-only. This FD will be cached and returned to clients.
795 let read_fd = File::open(&path).context("Failed to open VM DTBO file")?;
796 let read_fd_clone =
797 read_fd.try_clone().context("Failed to clone VM DTBO file descriptor")?;
798 *file = Some(read_fd);
799 read_fd_clone
800 };
801
802 Ok(fd)
803 }
David Brazdilafc9a9e2023-01-12 16:08:10 +0000804}
805
David Brazdil2dfefd12023-11-17 14:07:36 +0000806fn create_temporary_directory(path: &PathBuf, requester_uid: Option<uid_t>) -> Result<()> {
807 // Directory may exist if previous attempt to create it had failed.
808 // Delete it before trying again.
David Brazdilafc9a9e2023-01-12 16:08:10 +0000809 if path.as_path().exists() {
810 remove_temporary_dir(path).unwrap_or_else(|e| {
811 warn!("Could not delete temporary directory {:?}: {}", path, e);
812 });
813 }
David Brazdil2dfefd12023-11-17 14:07:36 +0000814 // Create directory.
815 create_dir(path).with_context(|| format!("Could not create temporary directory {:?}", path))?;
816 // If provided, change ownership to client's UID but system's GID, and permissions 0700.
David Brazdilafc9a9e2023-01-12 16:08:10 +0000817 // If the chown() fails, this will leave behind an empty directory that will get removed
818 // at the next attempt, or if virtualizationservice is restarted.
David Brazdil2dfefd12023-11-17 14:07:36 +0000819 if let Some(uid) = requester_uid {
820 chown(path, Some(Uid::from_raw(uid)), None).with_context(|| {
821 format!("Could not set ownership of temporary directory {:?}", path)
822 })?;
823 }
David Brazdilafc9a9e2023-01-12 16:08:10 +0000824 Ok(())
825}
826
827/// Removes a directory owned by a different user by first changing its owner back
828/// to VirtualizationService.
829pub fn remove_temporary_dir(path: &PathBuf) -> Result<()> {
Alice Wangd1b11a02023-04-18 12:30:20 +0000830 ensure!(path.as_path().is_dir(), "Path {:?} is not a directory", path);
David Brazdilafc9a9e2023-01-12 16:08:10 +0000831 chown(path, Some(Uid::current()), None)?;
832 set_permissions(path, Permissions::from_mode(0o700))?;
Alice Wangd1b11a02023-04-18 12:30:20 +0000833 remove_dir_all(path)?;
David Brazdilafc9a9e2023-01-12 16:08:10 +0000834 Ok(())
835}
836
David Brazdil2dfefd12023-11-17 14:07:36 +0000837fn get_or_create_common_dir() -> Result<PathBuf> {
838 let path = Path::new(TEMPORARY_DIRECTORY).join("common");
839 if !path.exists() {
840 create_temporary_directory(&path, None)?;
841 }
842 Ok(path)
843}
844
David Brazdilafc9a9e2023-01-12 16:08:10 +0000845/// Implementation of the AIDL `IGlobalVmContext` interface.
846#[derive(Debug, Default)]
847struct GlobalVmContext {
848 /// Strong reference to the context's instance data structure.
Yi-Yo Chiang2fbf0da2024-06-14 22:56:56 +0800849 instance: Arc<Mutex<GlobalVmInstance>>,
David Brazdilafc9a9e2023-01-12 16:08:10 +0000850 /// Keeps our service process running as long as this VM context exists.
851 #[allow(dead_code)]
852 lazy_service_guard: LazyServiceGuard,
853}
854
855impl Interface for GlobalVmContext {}
856
857impl IGlobalVmContext for GlobalVmContext {
858 fn getCid(&self) -> binder::Result<i32> {
Yi-Yo Chiang2fbf0da2024-06-14 22:56:56 +0800859 Ok(self.instance.lock().unwrap().cid as i32)
David Brazdilafc9a9e2023-01-12 16:08:10 +0000860 }
861
862 fn getTemporaryDirectory(&self) -> binder::Result<String> {
Yi-Yo Chiang2fbf0da2024-06-14 22:56:56 +0800863 Ok(self.instance.lock().unwrap().get_temp_dir().to_string_lossy().to_string())
864 }
865
866 fn setHostConsoleName(&self, pathname: &str) -> binder::Result<()> {
867 self.instance.lock().unwrap().host_console_name = Some(pathname.to_string());
868 Ok(())
David Brazdilafc9a9e2023-01-12 16:08:10 +0000869 }
870}
871
872fn handle_stream_connection_tombstoned() -> Result<()> {
873 // Should not listen for tombstones on a guest VM's port.
874 assert!(!is_valid_guest_cid(VM_TOMBSTONES_SERVICE_PORT as Cid));
875 let listener =
876 VsockListener::bind_with_cid_port(VMADDR_CID_HOST, VM_TOMBSTONES_SERVICE_PORT as Cid)?;
877 for incoming_stream in listener.incoming() {
878 let mut incoming_stream = match incoming_stream {
879 Err(e) => {
Alan Stokes8508bac2024-06-17 15:33:21 +0100880 warn!("invalid incoming connection: {e:?}");
David Brazdilafc9a9e2023-01-12 16:08:10 +0000881 continue;
882 }
883 Ok(s) => s,
884 };
Alan Stokes8508bac2024-06-17 15:33:21 +0100885 if let Ok(addr) = incoming_stream.peer_addr() {
886 let cid = addr.cid();
887 match cid {
888 VMADDR_CID_LOCAL | VMADDR_CID_HOST | VMADDR_CID_HYPERVISOR => {
889 warn!("Rejecting non-guest tombstone vsock connection from cid={cid}");
890 continue;
891 }
892 _ => info!("Vsock Stream connected to cid={cid} for tombstones"),
893 }
894 }
David Brazdilafc9a9e2023-01-12 16:08:10 +0000895 std::thread::spawn(move || {
896 if let Err(e) = handle_tombstone(&mut incoming_stream) {
897 error!("Failed to write tombstone- {:?}", e);
898 }
899 });
900 }
901 Ok(())
902}
903
904fn handle_tombstone(stream: &mut VsockStream) -> Result<()> {
David Brazdilafc9a9e2023-01-12 16:08:10 +0000905 let tb_connection =
906 TombstonedConnection::connect(std::process::id() as i32, DebuggerdDumpType::Tombstone)
907 .context("Failed to connect to tombstoned")?;
908 let mut text_output = tb_connection
909 .text_output
910 .as_ref()
911 .ok_or_else(|| anyhow!("Could not get file to write the tombstones on"))?;
912 let mut num_bytes_read = 0;
913 loop {
914 let mut chunk_recv = [0; CHUNK_RECV_MAX_LEN];
915 let n = stream
916 .read(&mut chunk_recv)
917 .context("Failed to read tombstone data from Vsock stream")?;
918 if n == 0 {
919 break;
920 }
921 num_bytes_read += n;
922 text_output.write_all(&chunk_recv[0..n]).context("Failed to write guests tombstones")?;
923 }
924 info!("Received {} bytes from guest & wrote to tombstone file", num_bytes_read);
925 tb_connection.notify_completion()?;
926 Ok(())
927}
928
Alice Wang6c6535d2024-05-31 06:45:31 +0000929/// Returns true if the AVF remotely provisioned component service is declared in the
930/// VINTF manifest.
931pub(crate) fn is_remote_provisioning_hal_declared() -> binder::Result<bool> {
Alice Wang0dcab552024-03-20 14:42:30 +0000932 Ok(binder::is_declared(REMOTELY_PROVISIONED_COMPONENT_SERVICE_NAME)?)
933}
934
David Brazdilafc9a9e2023-01-12 16:08:10 +0000935/// Checks whether the caller has a specific permission
936fn check_permission(perm: &str) -> binder::Result<()> {
937 let calling_pid = get_calling_pid();
938 let calling_uid = get_calling_uid();
939 // Root can do anything
940 if calling_uid == 0 {
941 return Ok(());
942 }
943 let perm_svc: Strong<dyn IPermissionController::IPermissionController> =
Frederick Mayleb2a02872024-05-08 13:35:12 -0700944 binder::wait_for_interface("permission")?;
David Brazdilafc9a9e2023-01-12 16:08:10 +0000945 if perm_svc.checkPermission(perm, calling_pid, calling_uid as i32)? {
946 Ok(())
947 } else {
Jiyong Park2227eaa2023-08-04 11:59:18 +0900948 Err(anyhow!("does not have the {} permission", perm))
949 .or_binder_exception(ExceptionCode::SECURITY)
David Brazdilafc9a9e2023-01-12 16:08:10 +0000950 }
951}
952
953/// Check whether the caller of the current Binder method is allowed to call debug methods.
954fn check_debug_access() -> binder::Result<()> {
955 check_permission("android.permission.DEBUG_VIRTUAL_MACHINE")
956}
957
958/// Check whether the caller of the current Binder method is allowed to manage VMs
959fn check_manage_access() -> binder::Result<()> {
960 check_permission("android.permission.MANAGE_VIRTUAL_MACHINE")
961}
Inseob Kim53d0b212023-07-20 16:58:37 +0900962
963/// Check whether the caller of the current Binder method is allowed to use custom VMs
964fn check_use_custom_virtual_machine() -> binder::Result<()> {
965 check_permission("android.permission.USE_CUSTOM_VIRTUAL_MACHINE")
966}
Alice Wang4c6c5582023-11-23 15:07:18 +0000967
Seungjae Yooa6589bd2024-06-11 10:14:07 +0900968/// Check whether the caller of the current Binder method is allowed to create socket and
969/// establish connection between the VM and the Internet.
970fn check_internet_permission() -> binder::Result<()> {
971 check_permission("android.permission.INTERNET")
972}
973
Alice Wang4c6c5582023-11-23 15:07:18 +0000974#[cfg(test)]
975mod tests {
976 use super::*;
Alice Wang4c6c5582023-11-23 15:07:18 +0000977
978 const TEST_RKP_CERT_CHAIN_PATH: &str = "testdata/rkp_cert_chain.der";
979
980 #[test]
981 fn splitting_x509_certificate_chain_succeeds() -> Result<()> {
982 let bytes = fs::read(TEST_RKP_CERT_CHAIN_PATH)?;
983 let cert_chain = split_x509_certificate_chain(&bytes)?;
984
985 assert_eq!(4, cert_chain.len());
986 for cert in cert_chain {
Alice Wangfc5a44a2023-12-21 12:22:40 +0000987 let x509_cert = X509::from_der(&cert.encodedCertificate)?;
988 assert_eq!(x509_cert.to_der()?.len(), cert.encodedCertificate.len());
Alice Wang4c6c5582023-11-23 15:07:18 +0000989 }
990 Ok(())
991 }
992}