blob: 70da37b156e2895955fffd3b155c5eda4eb06a90 [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;
28use android_vs_internal::aidl::android::system::virtualizationservice_internal;
Alice Wangd1b11a02023-04-18 12:30:20 +000029use anyhow::{anyhow, ensure, Context, Result};
Jiyong Parkd7bd2f22023-08-10 20:41:19 +090030use avflog::LogResult;
Alan Stokesac667072024-02-19 16:26:00 +000031use binder::{
32 self, wait_for_interface, BinderFeatures, ExceptionCode, Interface, IntoBinderResult,
33 LazyServiceGuard, ParcelFileDescriptor, Status, Strong,
34};
Jakob Vukalovicd42aa2c2023-11-09 16:04:00 +000035use lazy_static::lazy_static;
David Brazdilafc9a9e2023-01-12 16:08:10 +000036use libc::VMADDR_CID_HOST;
37use 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};
Jeongik Cha7add2a42024-04-02 14:52:39 +090054use std::sync::{Arc, Condvar, 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;
David Brazdilafc9a9e2023-01-12 16:08:10 +000076use vsock::{VsockListener, VsockStream};
David Brazdilafc9a9e2023-01-12 16:08:10 +000077
78/// The unique ID of a VM used (together with a port number) for vsock communication.
79pub type Cid = u32;
80
David Brazdilafc9a9e2023-01-12 16:08:10 +000081/// Directory in which to write disk image files used while running VMs.
82pub const TEMPORARY_DIRECTORY: &str = "/data/misc/virtualizationservice";
83
84/// The first CID to assign to a guest VM managed by the VirtualizationService. CIDs lower than this
85/// are reserved for the host or other usage.
86const GUEST_CID_MIN: Cid = 2048;
87const GUEST_CID_MAX: Cid = 65535;
88
89const SYSPROP_LAST_CID: &str = "virtualizationservice.state.last_cid";
90
91const CHUNK_RECV_MAX_LEN: usize = 1024;
92
Alice Wange64dd182024-01-17 15:57:55 +000093/// The fake certificate is used for testing only when a client VM requests attestation in test
94/// mode, it is a single certificate extracted on an unregistered device for testing.
95/// Here is the snapshot of the certificate:
96///
97/// ```
98/// Certificate:
99/// Data:
100/// Version: 3 (0x2)
101/// Serial Number:
102/// 59:ae:50:98:95:e1:34:25:f1:21:93:c0:4c:e5:24:66
103/// Signature Algorithm: ecdsa-with-SHA256
104/// Issuer: CN = Droid Unregistered Device CA, O = Google Test LLC
105/// Validity
106/// Not Before: Feb 5 14:39:39 2024 GMT
107/// Not After : Feb 14 14:39:39 2024 GMT
108/// Subject: CN = 59ae509895e13425f12193c04ce52466, O = TEE
109/// Subject Public Key Info:
110/// Public Key Algorithm: id-ecPublicKey
111/// Public-Key: (256 bit)
112/// pub:
113/// 04:30:32:cd:95:12:b0:71:8b:b7:14:44:26:58:d5:
114/// 82:8c:25:55:2c:6d:ef:98:e3:4f:88:d0:74:82:09:
115/// 3e:8d:6c:f0:f2:18:d5:83:0e:0d:f2:ce:c5:15:38:
116/// e5:6a:e6:4d:4d:95:15:b7:24:e7:cb:4b:63:42:21:
117/// bc:36:c6:0a:d8
118/// ASN1 OID: prime256v1
119/// NIST CURVE: P-256
120/// X509v3 extensions:
121/// ...
122/// ```
123const FAKE_CERTIFICATE_FOR_TESTING: &[u8] = &[
124 0x30, 0x82, 0x01, 0xee, 0x30, 0x82, 0x01, 0x94, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x10, 0x59,
125 0xae, 0x50, 0x98, 0x95, 0xe1, 0x34, 0x25, 0xf1, 0x21, 0x93, 0xc0, 0x4c, 0xe5, 0x24, 0x66, 0x30,
126 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x30, 0x41, 0x31, 0x25, 0x30,
127 0x23, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x1c, 0x44, 0x72, 0x6f, 0x69, 0x64, 0x20, 0x55, 0x6e,
128 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x65, 0x64, 0x20, 0x44, 0x65, 0x76, 0x69, 0x63,
129 0x65, 0x20, 0x43, 0x41, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0f, 0x47,
130 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x20, 0x54, 0x65, 0x73, 0x74, 0x20, 0x4c, 0x4c, 0x43, 0x30, 0x1e,
131 0x17, 0x0d, 0x32, 0x34, 0x30, 0x32, 0x30, 0x35, 0x31, 0x34, 0x33, 0x39, 0x33, 0x39, 0x5a, 0x17,
132 0x0d, 0x32, 0x34, 0x30, 0x32, 0x31, 0x34, 0x31, 0x34, 0x33, 0x39, 0x33, 0x39, 0x5a, 0x30, 0x39,
133 0x31, 0x29, 0x30, 0x27, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x20, 0x35, 0x39, 0x61, 0x65, 0x35,
134 0x30, 0x39, 0x38, 0x39, 0x35, 0x65, 0x31, 0x33, 0x34, 0x32, 0x35, 0x66, 0x31, 0x32, 0x31, 0x39,
135 0x33, 0x63, 0x30, 0x34, 0x63, 0x65, 0x35, 0x32, 0x34, 0x36, 0x36, 0x31, 0x0c, 0x30, 0x0a, 0x06,
136 0x03, 0x55, 0x04, 0x0a, 0x13, 0x03, 0x54, 0x45, 0x45, 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a,
137 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07,
138 0x03, 0x42, 0x00, 0x04, 0x30, 0x32, 0xcd, 0x95, 0x12, 0xb0, 0x71, 0x8b, 0xb7, 0x14, 0x44, 0x26,
139 0x58, 0xd5, 0x82, 0x8c, 0x25, 0x55, 0x2c, 0x6d, 0xef, 0x98, 0xe3, 0x4f, 0x88, 0xd0, 0x74, 0x82,
140 0x09, 0x3e, 0x8d, 0x6c, 0xf0, 0xf2, 0x18, 0xd5, 0x83, 0x0e, 0x0d, 0xf2, 0xce, 0xc5, 0x15, 0x38,
141 0xe5, 0x6a, 0xe6, 0x4d, 0x4d, 0x95, 0x15, 0xb7, 0x24, 0xe7, 0xcb, 0x4b, 0x63, 0x42, 0x21, 0xbc,
142 0x36, 0xc6, 0x0a, 0xd8, 0xa3, 0x76, 0x30, 0x74, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04,
143 0x16, 0x04, 0x14, 0x39, 0x81, 0x41, 0x0a, 0xb9, 0xf3, 0xf4, 0x5b, 0x75, 0x97, 0x4a, 0x46, 0xd6,
144 0x30, 0x9e, 0x1d, 0x7a, 0x3b, 0xec, 0xa8, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18,
145 0x30, 0x16, 0x80, 0x14, 0x82, 0xbd, 0x00, 0xde, 0xcb, 0xc5, 0xe7, 0x72, 0x87, 0x3d, 0x1c, 0x0a,
146 0x1e, 0x78, 0x4f, 0xf5, 0xd3, 0xc1, 0x3e, 0xb8, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01,
147 0x01, 0xff, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f,
148 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x02, 0x04, 0x30, 0x11, 0x06, 0x0a, 0x2b, 0x06, 0x01,
149 0x04, 0x01, 0xd6, 0x79, 0x02, 0x01, 0x1e, 0x04, 0x03, 0xa1, 0x01, 0x08, 0x30, 0x0a, 0x06, 0x08,
150 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x03, 0x48, 0x00, 0x30, 0x45, 0x02, 0x21, 0x00,
151 0xae, 0xd8, 0x40, 0x9e, 0x37, 0x3e, 0x5c, 0x9c, 0xe2, 0x93, 0x3d, 0x8c, 0xf7, 0x05, 0x10, 0xe7,
152 0xd1, 0x2b, 0x87, 0x8a, 0xee, 0xd6, 0x1e, 0x6c, 0x3b, 0xd2, 0x91, 0x3e, 0xa5, 0xdf, 0x91, 0x20,
153 0x02, 0x20, 0x7f, 0x0f, 0x29, 0x54, 0x60, 0x80, 0x07, 0x50, 0x5f, 0x56, 0x6b, 0x9f, 0xe0, 0x94,
154 0xb4, 0x3f, 0x3b, 0x0f, 0x61, 0xa0, 0x33, 0x40, 0xe6, 0x1a, 0x42, 0xda, 0x4b, 0xa4, 0xfd, 0x92,
155 0xb9, 0x0f,
156];
157
Jakob Vukalovicd42aa2c2023-11-09 16:04:00 +0000158lazy_static! {
Alice Wange64dd182024-01-17 15:57:55 +0000159 static ref FAKE_PROVISIONED_KEY_BLOB_FOR_TESTING: Mutex<Option<Vec<u8>>> = Mutex::new(None);
Jakob Vukalovicd42aa2c2023-11-09 16:04:00 +0000160 static ref VFIO_SERVICE: Strong<dyn IVfioHandler> =
161 wait_for_interface(<BpVfioHandler as IVfioHandler>::get_descriptor())
162 .expect("Could not connect to VfioHandler");
Seungjae Yoo13af0b62024-05-20 14:15:13 +0900163 static ref NETWORK_SERVICE: Strong<dyn IVmnic> =
164 wait_for_interface(<BpVmnic as IVmnic>::get_descriptor())
165 .expect("Could not connect to Vmnic");
Jakob Vukalovicd42aa2c2023-11-09 16:04:00 +0000166}
167
David Brazdilafc9a9e2023-01-12 16:08:10 +0000168fn is_valid_guest_cid(cid: Cid) -> bool {
169 (GUEST_CID_MIN..=GUEST_CID_MAX).contains(&cid)
170}
171
172/// Singleton service for allocating globally-unique VM resources, such as the CID, and running
173/// singleton servers, like tombstone receiver.
David Drysdale79af2662024-02-19 14:50:31 +0000174#[derive(Clone)]
David Brazdilafc9a9e2023-01-12 16:08:10 +0000175pub struct VirtualizationServiceInternal {
176 state: Arc<Mutex<GlobalState>>,
Jeongik Cha7add2a42024-04-02 14:52:39 +0900177 display_service_set: Arc<Condvar>,
David Brazdilafc9a9e2023-01-12 16:08:10 +0000178}
179
180impl VirtualizationServiceInternal {
David Drysdale79af2662024-02-19 14:50:31 +0000181 pub fn init() -> VirtualizationServiceInternal {
Jeongik Cha7add2a42024-04-02 14:52:39 +0900182 let service = VirtualizationServiceInternal {
183 state: Arc::new(Mutex::new(GlobalState::new())),
184 display_service_set: Arc::new(Condvar::new()),
185 };
David Brazdilafc9a9e2023-01-12 16:08:10 +0000186
187 std::thread::spawn(|| {
188 if let Err(e) = handle_stream_connection_tombstoned() {
189 warn!("Error receiving tombstone from guest or writing them. Error: {:?}", e);
190 }
191 });
192
David Drysdale79af2662024-02-19 14:50:31 +0000193 service
David Brazdilafc9a9e2023-01-12 16:08:10 +0000194 }
195}
196
197impl Interface for VirtualizationServiceInternal {}
198
199impl IVirtualizationServiceInternal for VirtualizationServiceInternal {
Jeongik Cha7add2a42024-04-02 14:52:39 +0900200 fn setDisplayService(
201 &self,
202 ibinder: &binder::SpIBinder,
203 ) -> std::result::Result<(), binder::Status> {
204 check_manage_access()?;
205 check_use_custom_virtual_machine()?;
206 let state = &mut *self.state.lock().unwrap();
207 state.display_service = Some(ibinder.clone());
208 self.display_service_set.notify_all();
209 Ok(())
210 }
211
Jeongik Chaeee137d2024-04-03 22:13:14 +0900212 fn clearDisplayService(&self) -> std::result::Result<(), binder::Status> {
213 check_manage_access()?;
214 check_use_custom_virtual_machine()?;
215 let state = &mut *self.state.lock().unwrap();
216 state.display_service = None;
217 self.display_service_set.notify_all();
218 Ok(())
219 }
220
Jeongik Cha7add2a42024-04-02 14:52:39 +0900221 fn waitDisplayService(&self) -> std::result::Result<binder::SpIBinder, binder::Status> {
222 check_manage_access()?;
223 check_use_custom_virtual_machine()?;
224 let state = self
225 .display_service_set
226 .wait_while(self.state.lock().unwrap(), |state| state.display_service.is_none())
227 .unwrap();
228 Ok((state.display_service)
229 .as_ref()
230 .cloned()
231 .expect("Display service cannot be None in this context"))
232 }
David Brazdilafc9a9e2023-01-12 16:08:10 +0000233 fn removeMemlockRlimit(&self) -> binder::Result<()> {
234 let pid = get_calling_pid();
235 let lim = libc::rlimit { rlim_cur: libc::RLIM_INFINITY, rlim_max: libc::RLIM_INFINITY };
236
Andrew Walbranb58d1b42023-07-07 13:54:49 +0100237 // SAFETY: borrowing the new limit struct only
David Brazdilafc9a9e2023-01-12 16:08:10 +0000238 let ret = unsafe { libc::prlimit(pid, libc::RLIMIT_MEMLOCK, &lim, std::ptr::null_mut()) };
239
240 match ret {
241 0 => Ok(()),
Jiyong Park2227eaa2023-08-04 11:59:18 +0900242 -1 => Err(std::io::Error::last_os_error().into()),
243 n => Err(anyhow!("Unexpected return value from prlimit(): {n}")),
David Brazdilafc9a9e2023-01-12 16:08:10 +0000244 }
Jiyong Park2227eaa2023-08-04 11:59:18 +0900245 .or_binder_exception(ExceptionCode::ILLEGAL_STATE)
David Brazdilafc9a9e2023-01-12 16:08:10 +0000246 }
247
248 fn allocateGlobalVmContext(
249 &self,
250 requester_debug_pid: i32,
251 ) -> binder::Result<Strong<dyn IGlobalVmContext>> {
252 check_manage_access()?;
253
254 let requester_uid = get_calling_uid();
255 let requester_debug_pid = requester_debug_pid as pid_t;
256 let state = &mut *self.state.lock().unwrap();
Jiyong Park2227eaa2023-08-04 11:59:18 +0900257 state
258 .allocate_vm_context(requester_uid, requester_debug_pid)
259 .or_binder_exception(ExceptionCode::ILLEGAL_STATE)
David Brazdilafc9a9e2023-01-12 16:08:10 +0000260 }
261
262 fn atomVmBooted(&self, atom: &AtomVmBooted) -> Result<(), Status> {
263 forward_vm_booted_atom(atom);
264 Ok(())
265 }
266
267 fn atomVmCreationRequested(&self, atom: &AtomVmCreationRequested) -> Result<(), Status> {
268 forward_vm_creation_atom(atom);
269 Ok(())
270 }
271
272 fn atomVmExited(&self, atom: &AtomVmExited) -> Result<(), Status> {
273 forward_vm_exited_atom(atom);
274 Ok(())
275 }
276
277 fn debugListVms(&self) -> binder::Result<Vec<VirtualMachineDebugInfo>> {
278 check_debug_access()?;
279
280 let state = &mut *self.state.lock().unwrap();
281 let cids = state
282 .held_contexts
283 .iter()
284 .filter_map(|(_, inst)| Weak::upgrade(inst))
Yi-Yo Chiang2fbf0da2024-06-14 22:56:56 +0800285 .map(|vm| {
286 let vm = vm.lock().unwrap();
287 VirtualMachineDebugInfo {
288 cid: vm.cid as i32,
289 temporaryDirectory: vm.get_temp_dir().to_string_lossy().to_string(),
290 requesterUid: vm.requester_uid as i32,
291 requesterPid: vm.requester_debug_pid,
292 hostConsoleName: vm.host_console_name.clone(),
293 }
David Brazdilafc9a9e2023-01-12 16:08:10 +0000294 })
295 .collect();
296 Ok(cids)
297 }
Alice Wangc2fec932023-02-23 16:24:02 +0000298
Alice Wange64dd182024-01-17 15:57:55 +0000299 fn enableTestAttestation(&self) -> binder::Result<()> {
300 check_manage_access()?;
301 check_use_custom_virtual_machine()?;
302 if !cfg!(remote_attestation) {
303 return Err(Status::new_exception_str(
304 ExceptionCode::UNSUPPORTED_OPERATION,
305 Some(
306 "enableTestAttestation is not supported with the remote_attestation \
307 feature disabled",
308 ),
309 ))
310 .with_log();
311 }
312 let res = generate_ecdsa_p256_key_pair()
313 .context("Failed to generate ECDSA P-256 key pair for testing")
314 .with_log()
315 .or_service_specific_exception(-1)?;
Alice Wang5daec072024-03-15 15:31:17 +0000316 // Wait until the service VM shuts down, so that the Service VM will be restarted when
317 // the key generated in the current session will be used for attestation.
318 // This ensures that different Service VM sessions have the same KEK for the key blob.
319 service_vm_manager::wait_until_service_vm_shuts_down()
320 .context("Failed to wait until the service VM shuts down")
321 .with_log()
322 .or_service_specific_exception(-1)?;
Alice Wange64dd182024-01-17 15:57:55 +0000323 match res {
324 Response::GenerateEcdsaP256KeyPair(key_pair) => {
325 FAKE_PROVISIONED_KEY_BLOB_FOR_TESTING
326 .lock()
327 .unwrap()
328 .replace(key_pair.key_blob.to_vec());
329 Ok(())
330 }
331 _ => Err(remote_provisioning::to_service_specific_error(res)),
332 }
333 .with_log()
334 }
335
Alice Wangbff017f2023-11-09 14:43:28 +0000336 fn requestAttestation(
337 &self,
338 csr: &[u8],
339 requester_uid: i32,
Alice Wange64dd182024-01-17 15:57:55 +0000340 test_mode: bool,
Alice Wangbff017f2023-11-09 14:43:28 +0000341 ) -> binder::Result<Vec<Certificate>> {
Alice Wangc2fec932023-02-23 16:24:02 +0000342 check_manage_access()?;
Alice Wang4c6c5582023-11-23 15:07:18 +0000343 if !cfg!(remote_attestation) {
344 return Err(Status::new_exception_str(
Alice Wange9ac2db2023-09-08 15:13:13 +0000345 ExceptionCode::UNSUPPORTED_OPERATION,
346 Some(
Alice Wanga410b642023-10-18 09:05:15 +0000347 "requestAttestation is not supported with the remote_attestation feature \
348 disabled",
Alice Wange9ac2db2023-09-08 15:13:13 +0000349 ),
350 ))
Alice Wang4c6c5582023-11-23 15:07:18 +0000351 .with_log();
Alice Wange9ac2db2023-09-08 15:13:13 +0000352 }
Alice Wang6c6535d2024-05-31 06:45:31 +0000353 if !is_remote_provisioning_hal_declared()? {
Alice Wang0dcab552024-03-20 14:42:30 +0000354 return Err(Status::new_exception_str(
355 ExceptionCode::UNSUPPORTED_OPERATION,
356 Some("AVF remotely provisioned component service is not declared"),
357 ))
358 .with_log();
359 }
Alice Wangeec580d2024-06-07 08:48:06 +0000360 remote_provisioning::check_remote_attestation_is_supported()?;
Alice Wang4c6c5582023-11-23 15:07:18 +0000361 info!("Received csr. Requestting attestation...");
Alice Wange64dd182024-01-17 15:57:55 +0000362 let (key_blob, certificate_chain) = if test_mode {
363 check_use_custom_virtual_machine()?;
364 info!("Using the fake key blob for testing...");
365 (
366 FAKE_PROVISIONED_KEY_BLOB_FOR_TESTING
367 .lock()
368 .unwrap()
369 .clone()
370 .ok_or_else(|| anyhow!("No key blob for testing"))
371 .with_log()
372 .or_service_specific_exception(-1)?,
373 FAKE_CERTIFICATE_FOR_TESTING.to_vec(),
374 )
375 } else {
376 info!("Retrieving the remotely provisioned keys from RKPD...");
377 let attestation_key = get_rkpd_attestation_key(
378 REMOTELY_PROVISIONED_COMPONENT_SERVICE_NAME,
379 requester_uid as u32,
380 )
381 .context("Failed to retrieve the remotely provisioned keys")
382 .with_log()
383 .or_service_specific_exception(-1)?;
384 (attestation_key.keyBlob, attestation_key.encodedCertChain)
385 };
386 let mut certificate_chain = split_x509_certificate_chain(&certificate_chain)
Alice Wang4c6c5582023-11-23 15:07:18 +0000387 .context("Failed to split the remotely provisioned certificate chain")
388 .with_log()
389 .or_service_specific_exception(-1)?;
390 if certificate_chain.is_empty() {
391 return Err(Status::new_service_specific_error_str(
392 -1,
393 Some("The certificate chain should contain at least 1 certificate"),
394 ))
395 .with_log();
396 }
Alice Wang20b8ebc2023-11-17 09:54:47 +0000397 let certificate = request_attestation(
398 csr.to_vec(),
Alice Wange64dd182024-01-17 15:57:55 +0000399 key_blob,
Alice Wang20b8ebc2023-11-17 09:54:47 +0000400 certificate_chain[0].encodedCertificate.clone(),
401 )
402 .context("Failed to request attestation")
403 .with_log()
404 .or_service_specific_exception(-1)?;
Alice Wang4c6c5582023-11-23 15:07:18 +0000405 certificate_chain.insert(0, Certificate { encodedCertificate: certificate });
406
407 Ok(certificate_chain)
Alice Wangc2fec932023-02-23 16:24:02 +0000408 }
Inseob Kim53d0b212023-07-20 16:58:37 +0900409
Alice Wang0362f7f2024-03-21 08:16:26 +0000410 fn isRemoteAttestationSupported(&self) -> binder::Result<bool> {
Alice Wangeec580d2024-06-07 08:48:06 +0000411 Ok(is_remote_provisioning_hal_declared()?
412 && remote_provisioning::is_remote_attestation_supported())
Alice Wang0362f7f2024-03-21 08:16:26 +0000413 }
414
Inseob Kim53d0b212023-07-20 16:58:37 +0900415 fn getAssignableDevices(&self) -> binder::Result<Vec<AssignableDevice>> {
416 check_use_custom_virtual_machine()?;
417
Inseob Kim7307a892023-09-14 13:37:58 +0900418 Ok(get_assignable_devices()?
419 .device
420 .into_iter()
Jaewan Kim0c99c612024-03-23 00:44:14 +0900421 .map(|x| AssignableDevice { node: x.sysfs_path, dtbo_label: x.dtbo_label })
Inseob Kim7307a892023-09-14 13:37:58 +0900422 .collect::<Vec<_>>())
Inseob Kim53d0b212023-07-20 16:58:37 +0900423 }
Inseob Kim1ca0f652023-07-20 17:18:12 +0900424
Jakob Vukalovicd42aa2c2023-11-09 16:04:00 +0000425 fn bindDevicesToVfioDriver(
426 &self,
427 devices: &[String],
428 ) -> binder::Result<Vec<Strong<dyn IBoundDevice>>> {
Inseob Kim1ca0f652023-07-20 17:18:12 +0900429 check_use_custom_virtual_machine()?;
430
Jakob Vukalovicd42aa2c2023-11-09 16:04:00 +0000431 let devices = get_assignable_devices()?
Inseob Kim7307a892023-09-14 13:37:58 +0900432 .device
433 .into_iter()
434 .filter_map(|x| {
435 if devices.contains(&x.sysfs_path) {
Jakob Vukalovicd42aa2c2023-11-09 16:04:00 +0000436 Some(VfioDev { sysfsPath: x.sysfs_path, dtboLabel: x.dtbo_label })
Inseob Kim7307a892023-09-14 13:37:58 +0900437 } else {
Jakob Vukalovicd42aa2c2023-11-09 16:04:00 +0000438 warn!("device {} is not assignable", x.sysfs_path);
Inseob Kim7307a892023-09-14 13:37:58 +0900439 None
440 }
441 })
Jakob Vukalovicd42aa2c2023-11-09 16:04:00 +0000442 .collect::<Vec<VfioDev>>();
443
444 VFIO_SERVICE.bindDevicesToVfioDriver(devices.as_slice())
Inseob Kim1ca0f652023-07-20 17:18:12 +0900445 }
David Brazdil2dfefd12023-11-17 14:07:36 +0000446
447 fn getDtboFile(&self) -> binder::Result<ParcelFileDescriptor> {
448 check_use_custom_virtual_machine()?;
449
450 let state = &mut *self.state.lock().unwrap();
451 let file = state.get_dtbo_file().or_service_specific_exception(-1)?;
452 Ok(ParcelFileDescriptor::new(file))
453 }
Shikha Panwar61a74b52024-02-16 13:17:01 +0000454
Shikha Panwar61a74b52024-02-16 13:17:01 +0000455 fn allocateInstanceId(&self) -> binder::Result<[u8; 64]> {
456 let mut id = [0u8; 64];
457 id.try_fill(&mut rand::thread_rng())
458 .context("Failed to allocate instance_id")
459 .or_service_specific_exception(-1)?;
460 let uid = get_calling_uid();
Shikha Panwar75e920b2024-06-14 06:12:37 +0000461 info!("Allocated a VM's instance_id: {:?}..., for uid: {:?}", &hex::encode(id)[..8], uid);
David Drysdalee64de8e2024-02-29 11:54:29 +0000462 let state = &mut *self.state.lock().unwrap();
463 if let Some(sk_state) = &mut state.sk_state {
464 let user_id = multiuser_get_user_id(uid);
465 let app_id = multiuser_get_app_id(uid);
David Drysdale1138fa02024-03-19 13:06:23 +0000466 info!("Recording possible existence of state for (user_id={user_id}, app_id={app_id})");
David Drysdalee64de8e2024-02-29 11:54:29 +0000467 if let Err(e) = sk_state.add_id(&id, user_id, app_id) {
468 error!("Failed to record the instance_id: {e:?}");
469 }
470 }
471
Shikha Panwar61a74b52024-02-16 13:17:01 +0000472 Ok(id)
473 }
David Drysdale79af2662024-02-19 14:50:31 +0000474
475 fn removeVmInstance(&self, instance_id: &[u8; 64]) -> binder::Result<()> {
476 let state = &mut *self.state.lock().unwrap();
477 if let Some(sk_state) = &mut state.sk_state {
Alan Stokesde40e642024-06-04 13:36:05 +0100478 let uid = get_calling_uid();
479 info!(
480 "Removing a VM's instance_id: {:?}, for uid: {:?}",
481 hex::encode(instance_id),
482 uid
483 );
484
485 let user_id = multiuser_get_user_id(uid);
486 let app_id = multiuser_get_app_id(uid);
487 sk_state.delete_id(instance_id, user_id, app_id);
David Drysdale79af2662024-02-19 14:50:31 +0000488 } else {
489 info!("ignoring removeVmInstance() as no ISecretkeeper");
490 }
491 Ok(())
492 }
David Drysdale3aa62b32024-03-25 12:31:48 +0000493
494 fn claimVmInstance(&self, instance_id: &[u8; 64]) -> binder::Result<()> {
495 let state = &mut *self.state.lock().unwrap();
496 if let Some(sk_state) = &mut state.sk_state {
497 let uid = get_calling_uid();
498 info!(
499 "Claiming a VM's instance_id: {:?}, for uid: {:?}",
500 hex::encode(instance_id),
501 uid
502 );
503
504 let user_id = multiuser_get_user_id(uid);
505 let app_id = multiuser_get_app_id(uid);
506 info!("Recording possible new owner of state for (user_id={user_id}, app_id={app_id})");
507 if let Err(e) = sk_state.add_id(instance_id, user_id, app_id) {
508 error!("Failed to update the instance_id owner: {e:?}");
509 }
510 } else {
511 info!("ignoring claimVmInstance() as no ISecretkeeper");
512 }
513 Ok(())
514 }
Seungjae Yoo13af0b62024-05-20 14:15:13 +0900515
516 fn createTapInterface(&self, iface_name_suffix: &str) -> binder::Result<ParcelFileDescriptor> {
Seungjae Yooa6589bd2024-06-11 10:14:07 +0900517 check_internet_permission()?;
Seungjae Yoo13af0b62024-05-20 14:15:13 +0900518 check_use_custom_virtual_machine()?;
519 if !cfg!(network) {
520 return Err(Status::new_exception_str(
521 ExceptionCode::UNSUPPORTED_OPERATION,
522 Some("createTapInterface is not supported with the network feature disabled"),
523 ))
524 .with_log();
525 }
ELIYAZ MOMINf9676872024-06-14 11:43:55 +0000526 NETWORK_SERVICE.createTapInterface(iface_name_suffix)
Seungjae Yoo13af0b62024-05-20 14:15:13 +0900527 }
Seungjae Yoo3271f172024-06-11 10:14:07 +0900528
529 fn deleteTapInterface(&self, tap_fd: &ParcelFileDescriptor) -> binder::Result<()> {
530 check_internet_permission()?;
531 check_use_custom_virtual_machine()?;
532 if !cfg!(network) {
533 return Err(Status::new_exception_str(
534 ExceptionCode::UNSUPPORTED_OPERATION,
535 Some("deleteTapInterface is not supported with the network feature disabled"),
536 ))
537 .with_log();
538 }
539 NETWORK_SERVICE.deleteTapInterface(tap_fd)
540 }
David Drysdale79af2662024-02-19 14:50:31 +0000541}
542
543impl IVirtualizationMaintenance for VirtualizationServiceInternal {
544 fn appRemoved(&self, user_id: i32, app_id: i32) -> binder::Result<()> {
545 let state = &mut *self.state.lock().unwrap();
546 if let Some(sk_state) = &mut state.sk_state {
547 info!("packageRemoved(user_id={user_id}, app_id={app_id})");
548 sk_state.delete_ids_for_app(user_id, app_id).or_service_specific_exception(-1)?;
549 } else {
550 info!("ignoring packageRemoved(user_id={user_id}, app_id={app_id})");
551 }
552 Ok(())
553 }
554
555 fn userRemoved(&self, user_id: i32) -> binder::Result<()> {
556 let state = &mut *self.state.lock().unwrap();
557 if let Some(sk_state) = &mut state.sk_state {
558 info!("userRemoved({user_id})");
559 sk_state.delete_ids_for_user(user_id).or_service_specific_exception(-1)?;
560 } else {
561 info!("ignoring userRemoved(user_id={user_id})");
562 }
563 Ok(())
564 }
Alan Stokes30ccacb2024-02-20 14:59:02 +0000565
566 fn performReconciliation(
567 &self,
David Drysdale1138fa02024-03-19 13:06:23 +0000568 callback: &Strong<dyn IVirtualizationReconciliationCallback>,
Alan Stokes30ccacb2024-02-20 14:59:02 +0000569 ) -> binder::Result<()> {
David Drysdale1138fa02024-03-19 13:06:23 +0000570 let state = &mut *self.state.lock().unwrap();
571 if let Some(sk_state) = &mut state.sk_state {
572 info!("performReconciliation()");
573 sk_state.reconcile(callback).or_service_specific_exception(-1)?;
574 } else {
575 info!("ignoring performReconciliation()");
576 }
577 Ok(())
Alan Stokes30ccacb2024-02-20 14:59:02 +0000578 }
Inseob Kim1ca0f652023-07-20 17:18:12 +0900579}
580
Inseob Kimc4a774d2023-08-30 12:48:43 +0900581#[derive(Debug, Deserialize)]
582struct Device {
Jaewan Kim35e818d2023-10-18 05:36:38 +0000583 dtbo_label: String,
Inseob Kimc4a774d2023-08-30 12:48:43 +0900584 sysfs_path: String,
585}
586
Inseob Kim7307a892023-09-14 13:37:58 +0900587#[derive(Debug, Default, Deserialize)]
Inseob Kimc4a774d2023-08-30 12:48:43 +0900588struct Devices {
589 device: Vec<Device>,
590}
591
Inseob Kim7307a892023-09-14 13:37:58 +0900592fn get_assignable_devices() -> binder::Result<Devices> {
593 let xml_path = Path::new("/vendor/etc/avf/assignable_devices.xml");
594 if !xml_path.exists() {
595 return Ok(Devices { ..Default::default() });
596 }
597
598 let xml = fs::read(xml_path)
599 .context("Failed to read assignable_devices.xml")
600 .with_log()
601 .or_service_specific_exception(-1)?;
602
603 let xml = String::from_utf8(xml)
604 .context("assignable_devices.xml is not a valid UTF-8 file")
605 .with_log()
606 .or_service_specific_exception(-1)?;
607
608 let mut devices: Devices = serde_xml_rs::from_str(&xml)
609 .context("can't parse assignable_devices.xml")
610 .with_log()
611 .or_service_specific_exception(-1)?;
612
613 let mut device_set = HashSet::new();
614 devices.device.retain(move |device| {
615 if device_set.contains(&device.sysfs_path) {
616 warn!("duplicated assignable device {device:?}; ignoring...");
617 return false;
618 }
619
620 if !Path::new(&device.sysfs_path).exists() {
621 warn!("assignable device {device:?} doesn't exist; ignoring...");
622 return false;
623 }
624
625 device_set.insert(device.sysfs_path.clone());
626 true
627 });
628 Ok(devices)
629}
630
Alice Wang4c6c5582023-11-23 15:07:18 +0000631fn split_x509_certificate_chain(mut cert_chain: &[u8]) -> Result<Vec<Certificate>> {
632 let mut out = Vec::new();
633 while !cert_chain.is_empty() {
Alice Wangfc5a44a2023-12-21 12:22:40 +0000634 let cert = X509::from_der(cert_chain)?;
635 let end = cert.to_der()?.len();
Alice Wang4c6c5582023-11-23 15:07:18 +0000636 out.push(Certificate { encodedCertificate: cert_chain[..end].to_vec() });
Alice Wangfc5a44a2023-12-21 12:22:40 +0000637 cert_chain = &cert_chain[end..];
Alice Wang4c6c5582023-11-23 15:07:18 +0000638 }
639 Ok(out)
640}
641
David Brazdilafc9a9e2023-01-12 16:08:10 +0000642#[derive(Debug, Default)]
643struct GlobalVmInstance {
644 /// The unique CID assigned to the VM for vsock communication.
645 cid: Cid,
646 /// UID of the client who requested this VM instance.
647 requester_uid: uid_t,
648 /// PID of the client who requested this VM instance.
649 requester_debug_pid: pid_t,
Yi-Yo Chiang2fbf0da2024-06-14 22:56:56 +0800650 /// Name of the host console.
651 host_console_name: Option<String>,
David Brazdilafc9a9e2023-01-12 16:08:10 +0000652}
653
654impl GlobalVmInstance {
655 fn get_temp_dir(&self) -> PathBuf {
656 let cid = self.cid;
657 format!("{TEMPORARY_DIRECTORY}/{cid}").into()
658 }
659}
660
661/// The mutable state of the VirtualizationServiceInternal. There should only be one instance
662/// of this struct.
David Brazdilafc9a9e2023-01-12 16:08:10 +0000663struct GlobalState {
664 /// VM contexts currently allocated to running VMs. A CID is never recycled as long
665 /// as there is a strong reference held by a GlobalVmContext.
Yi-Yo Chiang2fbf0da2024-06-14 22:56:56 +0800666 held_contexts: HashMap<Cid, Weak<Mutex<GlobalVmInstance>>>,
David Brazdil2dfefd12023-11-17 14:07:36 +0000667
668 /// Cached read-only FD of VM DTBO file. Also serves as a lock for creating the file.
669 dtbo_file: Mutex<Option<File>>,
David Drysdale79af2662024-02-19 14:50:31 +0000670
671 /// State relating to secrets held by (optional) Secretkeeper instance on behalf of VMs.
672 sk_state: Option<maintenance::State>,
Jeongik Cha7add2a42024-04-02 14:52:39 +0900673
674 display_service: Option<binder::SpIBinder>,
David Brazdilafc9a9e2023-01-12 16:08:10 +0000675}
676
677impl GlobalState {
David Drysdale79af2662024-02-19 14:50:31 +0000678 fn new() -> Self {
679 Self {
680 held_contexts: HashMap::new(),
681 dtbo_file: Mutex::new(None),
682 sk_state: maintenance::State::new(),
Jeongik Cha7add2a42024-04-02 14:52:39 +0900683 display_service: None,
David Drysdale79af2662024-02-19 14:50:31 +0000684 }
685 }
686
David Brazdilafc9a9e2023-01-12 16:08:10 +0000687 /// Get the next available CID, or an error if we have run out. The last CID used is stored in
688 /// a system property so that restart of virtualizationservice doesn't reuse CID while the host
689 /// Android is up.
690 fn get_next_available_cid(&mut self) -> Result<Cid> {
691 // Start trying to find a CID from the last used CID + 1. This ensures
692 // that we do not eagerly recycle CIDs. It makes debugging easier but
693 // also means that retrying to allocate a CID, eg. because it is
694 // erroneously occupied by a process, will not recycle the same CID.
695 let last_cid_prop =
696 system_properties::read(SYSPROP_LAST_CID)?.and_then(|val| match val.parse::<Cid>() {
697 Ok(num) => {
698 if is_valid_guest_cid(num) {
699 Some(num)
700 } else {
701 error!("Invalid value '{}' of property '{}'", num, SYSPROP_LAST_CID);
702 None
703 }
704 }
705 Err(_) => {
706 error!("Invalid value '{}' of property '{}'", val, SYSPROP_LAST_CID);
707 None
708 }
709 });
710
711 let first_cid = if let Some(last_cid) = last_cid_prop {
712 if last_cid == GUEST_CID_MAX {
713 GUEST_CID_MIN
714 } else {
715 last_cid + 1
716 }
717 } else {
718 GUEST_CID_MIN
719 };
720
721 let cid = self
722 .find_available_cid(first_cid..=GUEST_CID_MAX)
723 .or_else(|| self.find_available_cid(GUEST_CID_MIN..first_cid))
724 .ok_or_else(|| anyhow!("Could not find an available CID."))?;
725
726 system_properties::write(SYSPROP_LAST_CID, &format!("{}", cid))?;
727 Ok(cid)
728 }
729
730 fn find_available_cid<I>(&self, mut range: I) -> Option<Cid>
731 where
732 I: Iterator<Item = Cid>,
733 {
734 range.find(|cid| !self.held_contexts.contains_key(cid))
735 }
736
737 fn allocate_vm_context(
738 &mut self,
739 requester_uid: uid_t,
740 requester_debug_pid: pid_t,
741 ) -> Result<Strong<dyn IGlobalVmContext>> {
742 // Garbage collect unused VM contexts.
743 self.held_contexts.retain(|_, instance| instance.strong_count() > 0);
744
745 let cid = self.get_next_available_cid()?;
Yi-Yo Chiang2fbf0da2024-06-14 22:56:56 +0800746 let instance = Arc::new(Mutex::new(GlobalVmInstance {
747 cid,
748 requester_uid,
749 requester_debug_pid,
750 ..Default::default()
751 }));
752 create_temporary_directory(&instance.lock().unwrap().get_temp_dir(), Some(requester_uid))?;
David Brazdilafc9a9e2023-01-12 16:08:10 +0000753
754 self.held_contexts.insert(cid, Arc::downgrade(&instance));
755 let binder = GlobalVmContext { instance, ..Default::default() };
756 Ok(BnGlobalVmContext::new_binder(binder, BinderFeatures::default()))
757 }
David Brazdil2dfefd12023-11-17 14:07:36 +0000758
759 fn get_dtbo_file(&mut self) -> Result<File> {
760 let mut file = self.dtbo_file.lock().unwrap();
761
762 let fd = if let Some(ref_fd) = &*file {
763 ref_fd.try_clone()?
764 } else {
765 let path = get_or_create_common_dir()?.join("vm.dtbo");
766 if path.exists() {
767 // All temporary files are deleted when the service is started.
768 // If the file exists but the FD is not cached, the file is
769 // likely corrupted.
770 remove_file(&path).context("Failed to clone cached VM DTBO file descriptor")?;
771 }
772
773 // Open a write-only file descriptor for vfio_handler.
774 let write_fd = File::create(&path).context("Failed to create VM DTBO file")?;
Jakob Vukalovicd42aa2c2023-11-09 16:04:00 +0000775 VFIO_SERVICE.writeVmDtbo(&ParcelFileDescriptor::new(write_fd))?;
David Brazdil2dfefd12023-11-17 14:07:36 +0000776
777 // Open read-only. This FD will be cached and returned to clients.
778 let read_fd = File::open(&path).context("Failed to open VM DTBO file")?;
779 let read_fd_clone =
780 read_fd.try_clone().context("Failed to clone VM DTBO file descriptor")?;
781 *file = Some(read_fd);
782 read_fd_clone
783 };
784
785 Ok(fd)
786 }
David Brazdilafc9a9e2023-01-12 16:08:10 +0000787}
788
David Brazdil2dfefd12023-11-17 14:07:36 +0000789fn create_temporary_directory(path: &PathBuf, requester_uid: Option<uid_t>) -> Result<()> {
790 // Directory may exist if previous attempt to create it had failed.
791 // Delete it before trying again.
David Brazdilafc9a9e2023-01-12 16:08:10 +0000792 if path.as_path().exists() {
793 remove_temporary_dir(path).unwrap_or_else(|e| {
794 warn!("Could not delete temporary directory {:?}: {}", path, e);
795 });
796 }
David Brazdil2dfefd12023-11-17 14:07:36 +0000797 // Create directory.
798 create_dir(path).with_context(|| format!("Could not create temporary directory {:?}", path))?;
799 // If provided, change ownership to client's UID but system's GID, and permissions 0700.
David Brazdilafc9a9e2023-01-12 16:08:10 +0000800 // If the chown() fails, this will leave behind an empty directory that will get removed
801 // at the next attempt, or if virtualizationservice is restarted.
David Brazdil2dfefd12023-11-17 14:07:36 +0000802 if let Some(uid) = requester_uid {
803 chown(path, Some(Uid::from_raw(uid)), None).with_context(|| {
804 format!("Could not set ownership of temporary directory {:?}", path)
805 })?;
806 }
David Brazdilafc9a9e2023-01-12 16:08:10 +0000807 Ok(())
808}
809
810/// Removes a directory owned by a different user by first changing its owner back
811/// to VirtualizationService.
812pub fn remove_temporary_dir(path: &PathBuf) -> Result<()> {
Alice Wangd1b11a02023-04-18 12:30:20 +0000813 ensure!(path.as_path().is_dir(), "Path {:?} is not a directory", path);
David Brazdilafc9a9e2023-01-12 16:08:10 +0000814 chown(path, Some(Uid::current()), None)?;
815 set_permissions(path, Permissions::from_mode(0o700))?;
Alice Wangd1b11a02023-04-18 12:30:20 +0000816 remove_dir_all(path)?;
David Brazdilafc9a9e2023-01-12 16:08:10 +0000817 Ok(())
818}
819
David Brazdil2dfefd12023-11-17 14:07:36 +0000820fn get_or_create_common_dir() -> Result<PathBuf> {
821 let path = Path::new(TEMPORARY_DIRECTORY).join("common");
822 if !path.exists() {
823 create_temporary_directory(&path, None)?;
824 }
825 Ok(path)
826}
827
David Brazdilafc9a9e2023-01-12 16:08:10 +0000828/// Implementation of the AIDL `IGlobalVmContext` interface.
829#[derive(Debug, Default)]
830struct GlobalVmContext {
831 /// Strong reference to the context's instance data structure.
Yi-Yo Chiang2fbf0da2024-06-14 22:56:56 +0800832 instance: Arc<Mutex<GlobalVmInstance>>,
David Brazdilafc9a9e2023-01-12 16:08:10 +0000833 /// Keeps our service process running as long as this VM context exists.
834 #[allow(dead_code)]
835 lazy_service_guard: LazyServiceGuard,
836}
837
838impl Interface for GlobalVmContext {}
839
840impl IGlobalVmContext for GlobalVmContext {
841 fn getCid(&self) -> binder::Result<i32> {
Yi-Yo Chiang2fbf0da2024-06-14 22:56:56 +0800842 Ok(self.instance.lock().unwrap().cid as i32)
David Brazdilafc9a9e2023-01-12 16:08:10 +0000843 }
844
845 fn getTemporaryDirectory(&self) -> binder::Result<String> {
Yi-Yo Chiang2fbf0da2024-06-14 22:56:56 +0800846 Ok(self.instance.lock().unwrap().get_temp_dir().to_string_lossy().to_string())
847 }
848
849 fn setHostConsoleName(&self, pathname: &str) -> binder::Result<()> {
850 self.instance.lock().unwrap().host_console_name = Some(pathname.to_string());
851 Ok(())
David Brazdilafc9a9e2023-01-12 16:08:10 +0000852 }
853}
854
855fn handle_stream_connection_tombstoned() -> Result<()> {
856 // Should not listen for tombstones on a guest VM's port.
857 assert!(!is_valid_guest_cid(VM_TOMBSTONES_SERVICE_PORT as Cid));
858 let listener =
859 VsockListener::bind_with_cid_port(VMADDR_CID_HOST, VM_TOMBSTONES_SERVICE_PORT as Cid)?;
860 for incoming_stream in listener.incoming() {
861 let mut incoming_stream = match incoming_stream {
862 Err(e) => {
863 warn!("invalid incoming connection: {:?}", e);
864 continue;
865 }
866 Ok(s) => s,
867 };
868 std::thread::spawn(move || {
869 if let Err(e) = handle_tombstone(&mut incoming_stream) {
870 error!("Failed to write tombstone- {:?}", e);
871 }
872 });
873 }
874 Ok(())
875}
876
877fn handle_tombstone(stream: &mut VsockStream) -> Result<()> {
878 if let Ok(addr) = stream.peer_addr() {
879 info!("Vsock Stream connected to cid={} for tombstones", addr.cid());
880 }
881 let tb_connection =
882 TombstonedConnection::connect(std::process::id() as i32, DebuggerdDumpType::Tombstone)
883 .context("Failed to connect to tombstoned")?;
884 let mut text_output = tb_connection
885 .text_output
886 .as_ref()
887 .ok_or_else(|| anyhow!("Could not get file to write the tombstones on"))?;
888 let mut num_bytes_read = 0;
889 loop {
890 let mut chunk_recv = [0; CHUNK_RECV_MAX_LEN];
891 let n = stream
892 .read(&mut chunk_recv)
893 .context("Failed to read tombstone data from Vsock stream")?;
894 if n == 0 {
895 break;
896 }
897 num_bytes_read += n;
898 text_output.write_all(&chunk_recv[0..n]).context("Failed to write guests tombstones")?;
899 }
900 info!("Received {} bytes from guest & wrote to tombstone file", num_bytes_read);
901 tb_connection.notify_completion()?;
902 Ok(())
903}
904
Alice Wang6c6535d2024-05-31 06:45:31 +0000905/// Returns true if the AVF remotely provisioned component service is declared in the
906/// VINTF manifest.
907pub(crate) fn is_remote_provisioning_hal_declared() -> binder::Result<bool> {
Alice Wang0dcab552024-03-20 14:42:30 +0000908 Ok(binder::is_declared(REMOTELY_PROVISIONED_COMPONENT_SERVICE_NAME)?)
909}
910
David Brazdilafc9a9e2023-01-12 16:08:10 +0000911/// Checks whether the caller has a specific permission
912fn check_permission(perm: &str) -> binder::Result<()> {
913 let calling_pid = get_calling_pid();
914 let calling_uid = get_calling_uid();
915 // Root can do anything
916 if calling_uid == 0 {
917 return Ok(());
918 }
919 let perm_svc: Strong<dyn IPermissionController::IPermissionController> =
Frederick Mayleb2a02872024-05-08 13:35:12 -0700920 binder::wait_for_interface("permission")?;
David Brazdilafc9a9e2023-01-12 16:08:10 +0000921 if perm_svc.checkPermission(perm, calling_pid, calling_uid as i32)? {
922 Ok(())
923 } else {
Jiyong Park2227eaa2023-08-04 11:59:18 +0900924 Err(anyhow!("does not have the {} permission", perm))
925 .or_binder_exception(ExceptionCode::SECURITY)
David Brazdilafc9a9e2023-01-12 16:08:10 +0000926 }
927}
928
929/// Check whether the caller of the current Binder method is allowed to call debug methods.
930fn check_debug_access() -> binder::Result<()> {
931 check_permission("android.permission.DEBUG_VIRTUAL_MACHINE")
932}
933
934/// Check whether the caller of the current Binder method is allowed to manage VMs
935fn check_manage_access() -> binder::Result<()> {
936 check_permission("android.permission.MANAGE_VIRTUAL_MACHINE")
937}
Inseob Kim53d0b212023-07-20 16:58:37 +0900938
939/// Check whether the caller of the current Binder method is allowed to use custom VMs
940fn check_use_custom_virtual_machine() -> binder::Result<()> {
941 check_permission("android.permission.USE_CUSTOM_VIRTUAL_MACHINE")
942}
Alice Wang4c6c5582023-11-23 15:07:18 +0000943
Seungjae Yooa6589bd2024-06-11 10:14:07 +0900944/// Check whether the caller of the current Binder method is allowed to create socket and
945/// establish connection between the VM and the Internet.
946fn check_internet_permission() -> binder::Result<()> {
947 check_permission("android.permission.INTERNET")
948}
949
Alice Wang4c6c5582023-11-23 15:07:18 +0000950#[cfg(test)]
951mod tests {
952 use super::*;
Alice Wang4c6c5582023-11-23 15:07:18 +0000953
954 const TEST_RKP_CERT_CHAIN_PATH: &str = "testdata/rkp_cert_chain.der";
955
956 #[test]
957 fn splitting_x509_certificate_chain_succeeds() -> Result<()> {
958 let bytes = fs::read(TEST_RKP_CERT_CHAIN_PATH)?;
959 let cert_chain = split_x509_certificate_chain(&bytes)?;
960
961 assert_eq!(4, cert_chain.len());
962 for cert in cert_chain {
Alice Wangfc5a44a2023-12-21 12:22:40 +0000963 let x509_cert = X509::from_der(&cert.encodedCertificate)?;
964 assert_eq!(x509_cert.to_der()?.len(), cert.encodedCertificate.len());
Alice Wang4c6c5582023-11-23 15:07:18 +0000965 }
966 Ok(())
967 }
968}