blob: aae97fd092e7b7689e62910fc91f83b2a7f492c0 [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};
Jakob Vukalovicd42aa2c2023-11-09 16:04:00 +000036use lazy_static::lazy_static;
David Brazdilafc9a9e2023-01-12 16:08:10 +000037use libc::VMADDR_CID_HOST;
38use log::{error, info, warn};
Alan Stokesac667072024-02-19 16:26:00 +000039use nix::unistd::{chown, Uid};
40use openssl::x509::X509;
Shikha Panwar61a74b52024-02-16 13:17:01 +000041use rand::Fill;
Alice Wangbff017f2023-11-09 14:43:28 +000042use rkpd_client::get_rkpd_attestation_key;
David Drysdalee64de8e2024-02-29 11:54:29 +000043use rustutils::{
44 system_properties,
45 users::{multiuser_get_app_id, multiuser_get_user_id},
46};
Inseob Kimc4a774d2023-08-30 12:48:43 +090047use serde::Deserialize;
Alan Stokesac667072024-02-19 16:26:00 +000048use service_vm_comm::Response;
Inseob Kimc4a774d2023-08-30 12:48:43 +090049use std::collections::{HashMap, HashSet};
David Brazdil2dfefd12023-11-17 14:07:36 +000050use std::fs::{self, create_dir, remove_dir_all, remove_file, set_permissions, File, Permissions};
David Brazdilafc9a9e2023-01-12 16:08:10 +000051use std::io::{Read, Write};
52use std::os::unix::fs::PermissionsExt;
53use std::os::unix::raw::{pid_t, uid_t};
Inseob Kim55438b22023-08-09 20:16:01 +090054use std::path::{Path, PathBuf};
Jeongik Cha7add2a42024-04-02 14:52:39 +090055use std::sync::{Arc, Condvar, Mutex, Weak};
David Brazdilafc9a9e2023-01-12 16:08:10 +000056use tombstoned_client::{DebuggerdDumpType, TombstonedConnection};
Alan Stokesac667072024-02-19 16:26:00 +000057use virtualizationcommon::Certificate::Certificate;
Alan Stokes30ccacb2024-02-20 14:59:02 +000058use virtualizationmaintenance::{
59 IVirtualizationMaintenance::IVirtualizationMaintenance,
60 IVirtualizationReconciliationCallback::IVirtualizationReconciliationCallback,
61};
Alan Stokesac667072024-02-19 16:26:00 +000062use virtualizationservice::{
63 AssignableDevice::AssignableDevice, VirtualMachineDebugInfo::VirtualMachineDebugInfo,
64};
65use virtualizationservice_internal::{
66 AtomVmBooted::AtomVmBooted,
67 AtomVmCreationRequested::AtomVmCreationRequested,
68 AtomVmExited::AtomVmExited,
69 IBoundDevice::IBoundDevice,
70 IGlobalVmContext::{BnGlobalVmContext, IGlobalVmContext},
71 IVfioHandler::VfioDev::VfioDev,
72 IVfioHandler::{BpVfioHandler, IVfioHandler},
David Drysdale79af2662024-02-19 14:50:31 +000073 IVirtualizationServiceInternal::IVirtualizationServiceInternal,
Seungjae Yoo13af0b62024-05-20 14:15:13 +090074 IVmnic::{BpVmnic, IVmnic},
Alan Stokesac667072024-02-19 16:26:00 +000075};
76use virtualmachineservice::IVirtualMachineService::VM_TOMBSTONES_SERVICE_PORT;
Seungjae Yoob6e4f1d2024-06-17 15:13:12 +090077use vmtethering::IVmTethering::{BpVmTethering, IVmTethering};
David Brazdilafc9a9e2023-01-12 16:08:10 +000078use vsock::{VsockListener, VsockStream};
David Brazdilafc9a9e2023-01-12 16:08:10 +000079
80/// The unique ID of a VM used (together with a port number) for vsock communication.
81pub type Cid = u32;
82
David Brazdilafc9a9e2023-01-12 16:08:10 +000083/// Directory in which to write disk image files used while running VMs.
84pub const TEMPORARY_DIRECTORY: &str = "/data/misc/virtualizationservice";
85
86/// The first CID to assign to a guest VM managed by the VirtualizationService. CIDs lower than this
87/// are reserved for the host or other usage.
88const GUEST_CID_MIN: Cid = 2048;
89const GUEST_CID_MAX: Cid = 65535;
90
91const SYSPROP_LAST_CID: &str = "virtualizationservice.state.last_cid";
92
93const CHUNK_RECV_MAX_LEN: usize = 1024;
94
Alice Wange64dd182024-01-17 15:57:55 +000095/// The fake certificate is used for testing only when a client VM requests attestation in test
96/// mode, it is a single certificate extracted on an unregistered device for testing.
97/// Here is the snapshot of the certificate:
98///
99/// ```
100/// Certificate:
101/// Data:
102/// Version: 3 (0x2)
103/// Serial Number:
104/// 59:ae:50:98:95:e1:34:25:f1:21:93:c0:4c:e5:24:66
105/// Signature Algorithm: ecdsa-with-SHA256
106/// Issuer: CN = Droid Unregistered Device CA, O = Google Test LLC
107/// Validity
108/// Not Before: Feb 5 14:39:39 2024 GMT
109/// Not After : Feb 14 14:39:39 2024 GMT
110/// Subject: CN = 59ae509895e13425f12193c04ce52466, O = TEE
111/// Subject Public Key Info:
112/// Public Key Algorithm: id-ecPublicKey
113/// Public-Key: (256 bit)
114/// pub:
115/// 04:30:32:cd:95:12:b0:71:8b:b7:14:44:26:58:d5:
116/// 82:8c:25:55:2c:6d:ef:98:e3:4f:88:d0:74:82:09:
117/// 3e:8d:6c:f0:f2:18:d5:83:0e:0d:f2:ce:c5:15:38:
118/// e5:6a:e6:4d:4d:95:15:b7:24:e7:cb:4b:63:42:21:
119/// bc:36:c6:0a:d8
120/// ASN1 OID: prime256v1
121/// NIST CURVE: P-256
122/// X509v3 extensions:
123/// ...
124/// ```
125const FAKE_CERTIFICATE_FOR_TESTING: &[u8] = &[
126 0x30, 0x82, 0x01, 0xee, 0x30, 0x82, 0x01, 0x94, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x10, 0x59,
127 0xae, 0x50, 0x98, 0x95, 0xe1, 0x34, 0x25, 0xf1, 0x21, 0x93, 0xc0, 0x4c, 0xe5, 0x24, 0x66, 0x30,
128 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x30, 0x41, 0x31, 0x25, 0x30,
129 0x23, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x1c, 0x44, 0x72, 0x6f, 0x69, 0x64, 0x20, 0x55, 0x6e,
130 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x65, 0x64, 0x20, 0x44, 0x65, 0x76, 0x69, 0x63,
131 0x65, 0x20, 0x43, 0x41, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0f, 0x47,
132 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x20, 0x54, 0x65, 0x73, 0x74, 0x20, 0x4c, 0x4c, 0x43, 0x30, 0x1e,
133 0x17, 0x0d, 0x32, 0x34, 0x30, 0x32, 0x30, 0x35, 0x31, 0x34, 0x33, 0x39, 0x33, 0x39, 0x5a, 0x17,
134 0x0d, 0x32, 0x34, 0x30, 0x32, 0x31, 0x34, 0x31, 0x34, 0x33, 0x39, 0x33, 0x39, 0x5a, 0x30, 0x39,
135 0x31, 0x29, 0x30, 0x27, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x20, 0x35, 0x39, 0x61, 0x65, 0x35,
136 0x30, 0x39, 0x38, 0x39, 0x35, 0x65, 0x31, 0x33, 0x34, 0x32, 0x35, 0x66, 0x31, 0x32, 0x31, 0x39,
137 0x33, 0x63, 0x30, 0x34, 0x63, 0x65, 0x35, 0x32, 0x34, 0x36, 0x36, 0x31, 0x0c, 0x30, 0x0a, 0x06,
138 0x03, 0x55, 0x04, 0x0a, 0x13, 0x03, 0x54, 0x45, 0x45, 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a,
139 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07,
140 0x03, 0x42, 0x00, 0x04, 0x30, 0x32, 0xcd, 0x95, 0x12, 0xb0, 0x71, 0x8b, 0xb7, 0x14, 0x44, 0x26,
141 0x58, 0xd5, 0x82, 0x8c, 0x25, 0x55, 0x2c, 0x6d, 0xef, 0x98, 0xe3, 0x4f, 0x88, 0xd0, 0x74, 0x82,
142 0x09, 0x3e, 0x8d, 0x6c, 0xf0, 0xf2, 0x18, 0xd5, 0x83, 0x0e, 0x0d, 0xf2, 0xce, 0xc5, 0x15, 0x38,
143 0xe5, 0x6a, 0xe6, 0x4d, 0x4d, 0x95, 0x15, 0xb7, 0x24, 0xe7, 0xcb, 0x4b, 0x63, 0x42, 0x21, 0xbc,
144 0x36, 0xc6, 0x0a, 0xd8, 0xa3, 0x76, 0x30, 0x74, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04,
145 0x16, 0x04, 0x14, 0x39, 0x81, 0x41, 0x0a, 0xb9, 0xf3, 0xf4, 0x5b, 0x75, 0x97, 0x4a, 0x46, 0xd6,
146 0x30, 0x9e, 0x1d, 0x7a, 0x3b, 0xec, 0xa8, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18,
147 0x30, 0x16, 0x80, 0x14, 0x82, 0xbd, 0x00, 0xde, 0xcb, 0xc5, 0xe7, 0x72, 0x87, 0x3d, 0x1c, 0x0a,
148 0x1e, 0x78, 0x4f, 0xf5, 0xd3, 0xc1, 0x3e, 0xb8, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01,
149 0x01, 0xff, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f,
150 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x02, 0x04, 0x30, 0x11, 0x06, 0x0a, 0x2b, 0x06, 0x01,
151 0x04, 0x01, 0xd6, 0x79, 0x02, 0x01, 0x1e, 0x04, 0x03, 0xa1, 0x01, 0x08, 0x30, 0x0a, 0x06, 0x08,
152 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x03, 0x48, 0x00, 0x30, 0x45, 0x02, 0x21, 0x00,
153 0xae, 0xd8, 0x40, 0x9e, 0x37, 0x3e, 0x5c, 0x9c, 0xe2, 0x93, 0x3d, 0x8c, 0xf7, 0x05, 0x10, 0xe7,
154 0xd1, 0x2b, 0x87, 0x8a, 0xee, 0xd6, 0x1e, 0x6c, 0x3b, 0xd2, 0x91, 0x3e, 0xa5, 0xdf, 0x91, 0x20,
155 0x02, 0x20, 0x7f, 0x0f, 0x29, 0x54, 0x60, 0x80, 0x07, 0x50, 0x5f, 0x56, 0x6b, 0x9f, 0xe0, 0x94,
156 0xb4, 0x3f, 0x3b, 0x0f, 0x61, 0xa0, 0x33, 0x40, 0xe6, 0x1a, 0x42, 0xda, 0x4b, 0xa4, 0xfd, 0x92,
157 0xb9, 0x0f,
158];
159
Jakob Vukalovicd42aa2c2023-11-09 16:04:00 +0000160lazy_static! {
Alice Wange64dd182024-01-17 15:57:55 +0000161 static ref FAKE_PROVISIONED_KEY_BLOB_FOR_TESTING: Mutex<Option<Vec<u8>>> = Mutex::new(None);
Jakob Vukalovicd42aa2c2023-11-09 16:04:00 +0000162 static ref VFIO_SERVICE: Strong<dyn IVfioHandler> =
163 wait_for_interface(<BpVfioHandler as IVfioHandler>::get_descriptor())
164 .expect("Could not connect to VfioHandler");
Seungjae Yoo13af0b62024-05-20 14:15:13 +0900165 static ref NETWORK_SERVICE: Strong<dyn IVmnic> =
166 wait_for_interface(<BpVmnic as IVmnic>::get_descriptor())
167 .expect("Could not connect to Vmnic");
Seungjae Yoob6e4f1d2024-06-17 15:13:12 +0900168 static ref TETHERING_SERVICE: Strong<dyn IVmTethering> =
169 wait_for_interface(<BpVmTethering as IVmTethering>::get_descriptor())
170 .expect("Could not connect to VmTethering");
Jakob Vukalovicd42aa2c2023-11-09 16:04:00 +0000171}
172
David Brazdilafc9a9e2023-01-12 16:08:10 +0000173fn is_valid_guest_cid(cid: Cid) -> bool {
174 (GUEST_CID_MIN..=GUEST_CID_MAX).contains(&cid)
175}
176
177/// Singleton service for allocating globally-unique VM resources, such as the CID, and running
178/// singleton servers, like tombstone receiver.
David Drysdale79af2662024-02-19 14:50:31 +0000179#[derive(Clone)]
David Brazdilafc9a9e2023-01-12 16:08:10 +0000180pub struct VirtualizationServiceInternal {
181 state: Arc<Mutex<GlobalState>>,
Jeongik Cha7add2a42024-04-02 14:52:39 +0900182 display_service_set: Arc<Condvar>,
David Brazdilafc9a9e2023-01-12 16:08:10 +0000183}
184
185impl VirtualizationServiceInternal {
David Drysdale79af2662024-02-19 14:50:31 +0000186 pub fn init() -> VirtualizationServiceInternal {
Jeongik Cha7add2a42024-04-02 14:52:39 +0900187 let service = VirtualizationServiceInternal {
188 state: Arc::new(Mutex::new(GlobalState::new())),
189 display_service_set: Arc::new(Condvar::new()),
190 };
David Brazdilafc9a9e2023-01-12 16:08:10 +0000191
192 std::thread::spawn(|| {
193 if let Err(e) = handle_stream_connection_tombstoned() {
194 warn!("Error receiving tombstone from guest or writing them. Error: {:?}", e);
195 }
196 });
197
David Drysdale79af2662024-02-19 14:50:31 +0000198 service
David Brazdilafc9a9e2023-01-12 16:08:10 +0000199 }
200}
201
202impl Interface for VirtualizationServiceInternal {}
203
204impl IVirtualizationServiceInternal for VirtualizationServiceInternal {
Jeongik Cha7add2a42024-04-02 14:52:39 +0900205 fn setDisplayService(
206 &self,
207 ibinder: &binder::SpIBinder,
208 ) -> std::result::Result<(), binder::Status> {
209 check_manage_access()?;
210 check_use_custom_virtual_machine()?;
211 let state = &mut *self.state.lock().unwrap();
212 state.display_service = Some(ibinder.clone());
213 self.display_service_set.notify_all();
214 Ok(())
215 }
216
Jeongik Chaeee137d2024-04-03 22:13:14 +0900217 fn clearDisplayService(&self) -> std::result::Result<(), binder::Status> {
218 check_manage_access()?;
219 check_use_custom_virtual_machine()?;
220 let state = &mut *self.state.lock().unwrap();
221 state.display_service = None;
222 self.display_service_set.notify_all();
223 Ok(())
224 }
225
Jeongik Cha7add2a42024-04-02 14:52:39 +0900226 fn waitDisplayService(&self) -> std::result::Result<binder::SpIBinder, binder::Status> {
227 check_manage_access()?;
228 check_use_custom_virtual_machine()?;
229 let state = self
230 .display_service_set
231 .wait_while(self.state.lock().unwrap(), |state| state.display_service.is_none())
232 .unwrap();
233 Ok((state.display_service)
234 .as_ref()
235 .cloned()
236 .expect("Display service cannot be None in this context"))
237 }
David Brazdilafc9a9e2023-01-12 16:08:10 +0000238 fn removeMemlockRlimit(&self) -> binder::Result<()> {
239 let pid = get_calling_pid();
240 let lim = libc::rlimit { rlim_cur: libc::RLIM_INFINITY, rlim_max: libc::RLIM_INFINITY };
241
Andrew Walbranb58d1b42023-07-07 13:54:49 +0100242 // SAFETY: borrowing the new limit struct only
David Brazdilafc9a9e2023-01-12 16:08:10 +0000243 let ret = unsafe { libc::prlimit(pid, libc::RLIMIT_MEMLOCK, &lim, std::ptr::null_mut()) };
244
245 match ret {
246 0 => Ok(()),
Jiyong Park2227eaa2023-08-04 11:59:18 +0900247 -1 => Err(std::io::Error::last_os_error().into()),
248 n => Err(anyhow!("Unexpected return value from prlimit(): {n}")),
David Brazdilafc9a9e2023-01-12 16:08:10 +0000249 }
Jiyong Park2227eaa2023-08-04 11:59:18 +0900250 .or_binder_exception(ExceptionCode::ILLEGAL_STATE)
David Brazdilafc9a9e2023-01-12 16:08:10 +0000251 }
252
253 fn allocateGlobalVmContext(
254 &self,
255 requester_debug_pid: i32,
256 ) -> binder::Result<Strong<dyn IGlobalVmContext>> {
257 check_manage_access()?;
258
259 let requester_uid = get_calling_uid();
260 let requester_debug_pid = requester_debug_pid as pid_t;
261 let state = &mut *self.state.lock().unwrap();
Jiyong Park2227eaa2023-08-04 11:59:18 +0900262 state
263 .allocate_vm_context(requester_uid, requester_debug_pid)
264 .or_binder_exception(ExceptionCode::ILLEGAL_STATE)
David Brazdilafc9a9e2023-01-12 16:08:10 +0000265 }
266
267 fn atomVmBooted(&self, atom: &AtomVmBooted) -> Result<(), Status> {
268 forward_vm_booted_atom(atom);
269 Ok(())
270 }
271
272 fn atomVmCreationRequested(&self, atom: &AtomVmCreationRequested) -> Result<(), Status> {
273 forward_vm_creation_atom(atom);
274 Ok(())
275 }
276
277 fn atomVmExited(&self, atom: &AtomVmExited) -> Result<(), Status> {
278 forward_vm_exited_atom(atom);
279 Ok(())
280 }
281
282 fn debugListVms(&self) -> binder::Result<Vec<VirtualMachineDebugInfo>> {
283 check_debug_access()?;
284
285 let state = &mut *self.state.lock().unwrap();
286 let cids = state
287 .held_contexts
288 .iter()
289 .filter_map(|(_, inst)| Weak::upgrade(inst))
Yi-Yo Chiang2fbf0da2024-06-14 22:56:56 +0800290 .map(|vm| {
291 let vm = vm.lock().unwrap();
292 VirtualMachineDebugInfo {
293 cid: vm.cid as i32,
294 temporaryDirectory: vm.get_temp_dir().to_string_lossy().to_string(),
295 requesterUid: vm.requester_uid as i32,
296 requesterPid: vm.requester_debug_pid,
297 hostConsoleName: vm.host_console_name.clone(),
298 }
David Brazdilafc9a9e2023-01-12 16:08:10 +0000299 })
300 .collect();
301 Ok(cids)
302 }
Alice Wangc2fec932023-02-23 16:24:02 +0000303
Alice Wange64dd182024-01-17 15:57:55 +0000304 fn enableTestAttestation(&self) -> binder::Result<()> {
305 check_manage_access()?;
306 check_use_custom_virtual_machine()?;
307 if !cfg!(remote_attestation) {
308 return Err(Status::new_exception_str(
309 ExceptionCode::UNSUPPORTED_OPERATION,
310 Some(
311 "enableTestAttestation is not supported with the remote_attestation \
312 feature disabled",
313 ),
314 ))
315 .with_log();
316 }
317 let res = generate_ecdsa_p256_key_pair()
318 .context("Failed to generate ECDSA P-256 key pair for testing")
319 .with_log()
320 .or_service_specific_exception(-1)?;
Alice Wang5daec072024-03-15 15:31:17 +0000321 // Wait until the service VM shuts down, so that the Service VM will be restarted when
322 // the key generated in the current session will be used for attestation.
323 // This ensures that different Service VM sessions have the same KEK for the key blob.
324 service_vm_manager::wait_until_service_vm_shuts_down()
325 .context("Failed to wait until the service VM shuts down")
326 .with_log()
327 .or_service_specific_exception(-1)?;
Alice Wange64dd182024-01-17 15:57:55 +0000328 match res {
329 Response::GenerateEcdsaP256KeyPair(key_pair) => {
330 FAKE_PROVISIONED_KEY_BLOB_FOR_TESTING
331 .lock()
332 .unwrap()
333 .replace(key_pair.key_blob.to_vec());
334 Ok(())
335 }
336 _ => Err(remote_provisioning::to_service_specific_error(res)),
337 }
338 .with_log()
339 }
340
Alice Wangbff017f2023-11-09 14:43:28 +0000341 fn requestAttestation(
342 &self,
343 csr: &[u8],
344 requester_uid: i32,
Alice Wange64dd182024-01-17 15:57:55 +0000345 test_mode: bool,
Alice Wangbff017f2023-11-09 14:43:28 +0000346 ) -> binder::Result<Vec<Certificate>> {
Alice Wangc2fec932023-02-23 16:24:02 +0000347 check_manage_access()?;
Alice Wang4c6c5582023-11-23 15:07:18 +0000348 if !cfg!(remote_attestation) {
349 return Err(Status::new_exception_str(
Alice Wange9ac2db2023-09-08 15:13:13 +0000350 ExceptionCode::UNSUPPORTED_OPERATION,
351 Some(
Alice Wanga410b642023-10-18 09:05:15 +0000352 "requestAttestation is not supported with the remote_attestation feature \
353 disabled",
Alice Wange9ac2db2023-09-08 15:13:13 +0000354 ),
355 ))
Alice Wang4c6c5582023-11-23 15:07:18 +0000356 .with_log();
Alice Wange9ac2db2023-09-08 15:13:13 +0000357 }
Alice Wang6c6535d2024-05-31 06:45:31 +0000358 if !is_remote_provisioning_hal_declared()? {
Alice Wang0dcab552024-03-20 14:42:30 +0000359 return Err(Status::new_exception_str(
360 ExceptionCode::UNSUPPORTED_OPERATION,
361 Some("AVF remotely provisioned component service is not declared"),
362 ))
363 .with_log();
364 }
Alice Wangeec580d2024-06-07 08:48:06 +0000365 remote_provisioning::check_remote_attestation_is_supported()?;
Alice Wang4c6c5582023-11-23 15:07:18 +0000366 info!("Received csr. Requestting attestation...");
Alice Wange64dd182024-01-17 15:57:55 +0000367 let (key_blob, certificate_chain) = if test_mode {
368 check_use_custom_virtual_machine()?;
369 info!("Using the fake key blob for testing...");
370 (
371 FAKE_PROVISIONED_KEY_BLOB_FOR_TESTING
372 .lock()
373 .unwrap()
374 .clone()
375 .ok_or_else(|| anyhow!("No key blob for testing"))
376 .with_log()
377 .or_service_specific_exception(-1)?,
378 FAKE_CERTIFICATE_FOR_TESTING.to_vec(),
379 )
380 } else {
381 info!("Retrieving the remotely provisioned keys from RKPD...");
382 let attestation_key = get_rkpd_attestation_key(
383 REMOTELY_PROVISIONED_COMPONENT_SERVICE_NAME,
384 requester_uid as u32,
385 )
386 .context("Failed to retrieve the remotely provisioned keys")
387 .with_log()
388 .or_service_specific_exception(-1)?;
389 (attestation_key.keyBlob, attestation_key.encodedCertChain)
390 };
391 let mut certificate_chain = split_x509_certificate_chain(&certificate_chain)
Alice Wang4c6c5582023-11-23 15:07:18 +0000392 .context("Failed to split the remotely provisioned certificate chain")
393 .with_log()
394 .or_service_specific_exception(-1)?;
395 if certificate_chain.is_empty() {
396 return Err(Status::new_service_specific_error_str(
397 -1,
398 Some("The certificate chain should contain at least 1 certificate"),
399 ))
400 .with_log();
401 }
Alice Wang20b8ebc2023-11-17 09:54:47 +0000402 let certificate = request_attestation(
403 csr.to_vec(),
Alice Wange64dd182024-01-17 15:57:55 +0000404 key_blob,
Alice Wang20b8ebc2023-11-17 09:54:47 +0000405 certificate_chain[0].encodedCertificate.clone(),
406 )
407 .context("Failed to request attestation")
408 .with_log()
409 .or_service_specific_exception(-1)?;
Alice Wang4c6c5582023-11-23 15:07:18 +0000410 certificate_chain.insert(0, Certificate { encodedCertificate: certificate });
411
412 Ok(certificate_chain)
Alice Wangc2fec932023-02-23 16:24:02 +0000413 }
Inseob Kim53d0b212023-07-20 16:58:37 +0900414
Alice Wang0362f7f2024-03-21 08:16:26 +0000415 fn isRemoteAttestationSupported(&self) -> binder::Result<bool> {
Alice Wangeec580d2024-06-07 08:48:06 +0000416 Ok(is_remote_provisioning_hal_declared()?
417 && remote_provisioning::is_remote_attestation_supported())
Alice Wang0362f7f2024-03-21 08:16:26 +0000418 }
419
Inseob Kim53d0b212023-07-20 16:58:37 +0900420 fn getAssignableDevices(&self) -> binder::Result<Vec<AssignableDevice>> {
421 check_use_custom_virtual_machine()?;
422
Inseob Kim7307a892023-09-14 13:37:58 +0900423 Ok(get_assignable_devices()?
424 .device
425 .into_iter()
Jaewan Kim0c99c612024-03-23 00:44:14 +0900426 .map(|x| AssignableDevice { node: x.sysfs_path, dtbo_label: x.dtbo_label })
Inseob Kim7307a892023-09-14 13:37:58 +0900427 .collect::<Vec<_>>())
Inseob Kim53d0b212023-07-20 16:58:37 +0900428 }
Inseob Kim1ca0f652023-07-20 17:18:12 +0900429
Jakob Vukalovicd42aa2c2023-11-09 16:04:00 +0000430 fn bindDevicesToVfioDriver(
431 &self,
432 devices: &[String],
433 ) -> binder::Result<Vec<Strong<dyn IBoundDevice>>> {
Inseob Kim1ca0f652023-07-20 17:18:12 +0900434 check_use_custom_virtual_machine()?;
435
Jakob Vukalovicd42aa2c2023-11-09 16:04:00 +0000436 let devices = get_assignable_devices()?
Inseob Kim7307a892023-09-14 13:37:58 +0900437 .device
438 .into_iter()
439 .filter_map(|x| {
440 if devices.contains(&x.sysfs_path) {
Jakob Vukalovicd42aa2c2023-11-09 16:04:00 +0000441 Some(VfioDev { sysfsPath: x.sysfs_path, dtboLabel: x.dtbo_label })
Inseob Kim7307a892023-09-14 13:37:58 +0900442 } else {
Jakob Vukalovicd42aa2c2023-11-09 16:04:00 +0000443 warn!("device {} is not assignable", x.sysfs_path);
Inseob Kim7307a892023-09-14 13:37:58 +0900444 None
445 }
446 })
Jakob Vukalovicd42aa2c2023-11-09 16:04:00 +0000447 .collect::<Vec<VfioDev>>();
448
449 VFIO_SERVICE.bindDevicesToVfioDriver(devices.as_slice())
Inseob Kim1ca0f652023-07-20 17:18:12 +0900450 }
David Brazdil2dfefd12023-11-17 14:07:36 +0000451
452 fn getDtboFile(&self) -> binder::Result<ParcelFileDescriptor> {
453 check_use_custom_virtual_machine()?;
454
455 let state = &mut *self.state.lock().unwrap();
456 let file = state.get_dtbo_file().or_service_specific_exception(-1)?;
457 Ok(ParcelFileDescriptor::new(file))
458 }
Shikha Panwar61a74b52024-02-16 13:17:01 +0000459
Shikha Panwar61a74b52024-02-16 13:17:01 +0000460 fn allocateInstanceId(&self) -> binder::Result<[u8; 64]> {
461 let mut id = [0u8; 64];
462 id.try_fill(&mut rand::thread_rng())
463 .context("Failed to allocate instance_id")
464 .or_service_specific_exception(-1)?;
465 let uid = get_calling_uid();
Shikha Panwar75e920b2024-06-14 06:12:37 +0000466 info!("Allocated a VM's instance_id: {:?}..., for uid: {:?}", &hex::encode(id)[..8], uid);
David Drysdalee64de8e2024-02-29 11:54:29 +0000467 let state = &mut *self.state.lock().unwrap();
468 if let Some(sk_state) = &mut state.sk_state {
469 let user_id = multiuser_get_user_id(uid);
470 let app_id = multiuser_get_app_id(uid);
David Drysdale1138fa02024-03-19 13:06:23 +0000471 info!("Recording possible existence of state for (user_id={user_id}, app_id={app_id})");
David Drysdalee64de8e2024-02-29 11:54:29 +0000472 if let Err(e) = sk_state.add_id(&id, user_id, app_id) {
473 error!("Failed to record the instance_id: {e:?}");
474 }
475 }
476
Shikha Panwar61a74b52024-02-16 13:17:01 +0000477 Ok(id)
478 }
David Drysdale79af2662024-02-19 14:50:31 +0000479
480 fn removeVmInstance(&self, instance_id: &[u8; 64]) -> binder::Result<()> {
481 let state = &mut *self.state.lock().unwrap();
482 if let Some(sk_state) = &mut state.sk_state {
Alan Stokesde40e642024-06-04 13:36:05 +0100483 let uid = get_calling_uid();
484 info!(
485 "Removing a VM's instance_id: {:?}, for uid: {:?}",
486 hex::encode(instance_id),
487 uid
488 );
489
490 let user_id = multiuser_get_user_id(uid);
491 let app_id = multiuser_get_app_id(uid);
492 sk_state.delete_id(instance_id, user_id, app_id);
David Drysdale79af2662024-02-19 14:50:31 +0000493 } else {
494 info!("ignoring removeVmInstance() as no ISecretkeeper");
495 }
496 Ok(())
497 }
David Drysdale3aa62b32024-03-25 12:31:48 +0000498
499 fn claimVmInstance(&self, instance_id: &[u8; 64]) -> binder::Result<()> {
500 let state = &mut *self.state.lock().unwrap();
501 if let Some(sk_state) = &mut state.sk_state {
502 let uid = get_calling_uid();
503 info!(
504 "Claiming a VM's instance_id: {:?}, for uid: {:?}",
505 hex::encode(instance_id),
506 uid
507 );
508
509 let user_id = multiuser_get_user_id(uid);
510 let app_id = multiuser_get_app_id(uid);
511 info!("Recording possible new owner of state for (user_id={user_id}, app_id={app_id})");
512 if let Err(e) = sk_state.add_id(instance_id, user_id, app_id) {
513 error!("Failed to update the instance_id owner: {e:?}");
514 }
515 } else {
516 info!("ignoring claimVmInstance() as no ISecretkeeper");
517 }
518 Ok(())
519 }
Seungjae Yoo13af0b62024-05-20 14:15:13 +0900520
Seungjae Yoo548346e2024-06-19 16:18:06 +0900521 fn createTapInterface(&self, _iface_name_suffix: &str) -> binder::Result<ParcelFileDescriptor> {
Seungjae Yooa6589bd2024-06-11 10:14:07 +0900522 check_internet_permission()?;
Seungjae Yoo13af0b62024-05-20 14:15:13 +0900523 check_use_custom_virtual_machine()?;
524 if !cfg!(network) {
525 return Err(Status::new_exception_str(
526 ExceptionCode::UNSUPPORTED_OPERATION,
527 Some("createTapInterface is not supported with the network feature disabled"),
528 ))
529 .with_log();
530 }
Seungjae Yoo548346e2024-06-19 16:18:06 +0900531 // TODO(340377643): Use iface_name_suffix after introducing bridge interface, not fixed
532 // value.
533 let tap_fd = NETWORK_SERVICE.createTapInterface("fixed")?;
Seungjae Yoob6e4f1d2024-06-17 15:13:12 +0900534
535 // TODO(340377643): Due to lack of implementation of creating bridge interface, tethering is
536 // enabled for TAP interface instead of bridge interface. After introducing creation of
537 // bridge interface in AVF, we should modify it.
Seungjae Yoo548346e2024-06-19 16:18:06 +0900538 TETHERING_SERVICE.enableVmTethering()?;
Seungjae Yoob6e4f1d2024-06-17 15:13:12 +0900539
540 Ok(tap_fd)
Seungjae Yoo13af0b62024-05-20 14:15:13 +0900541 }
Seungjae Yoo3271f172024-06-11 10:14:07 +0900542
543 fn deleteTapInterface(&self, tap_fd: &ParcelFileDescriptor) -> binder::Result<()> {
544 check_internet_permission()?;
545 check_use_custom_virtual_machine()?;
546 if !cfg!(network) {
547 return Err(Status::new_exception_str(
548 ExceptionCode::UNSUPPORTED_OPERATION,
549 Some("deleteTapInterface is not supported with the network feature disabled"),
550 ))
551 .with_log();
552 }
553 NETWORK_SERVICE.deleteTapInterface(tap_fd)
554 }
David Drysdale79af2662024-02-19 14:50:31 +0000555}
556
557impl IVirtualizationMaintenance for VirtualizationServiceInternal {
558 fn appRemoved(&self, user_id: i32, app_id: i32) -> binder::Result<()> {
559 let state = &mut *self.state.lock().unwrap();
560 if let Some(sk_state) = &mut state.sk_state {
561 info!("packageRemoved(user_id={user_id}, app_id={app_id})");
562 sk_state.delete_ids_for_app(user_id, app_id).or_service_specific_exception(-1)?;
563 } else {
564 info!("ignoring packageRemoved(user_id={user_id}, app_id={app_id})");
565 }
566 Ok(())
567 }
568
569 fn userRemoved(&self, user_id: i32) -> binder::Result<()> {
570 let state = &mut *self.state.lock().unwrap();
571 if let Some(sk_state) = &mut state.sk_state {
572 info!("userRemoved({user_id})");
573 sk_state.delete_ids_for_user(user_id).or_service_specific_exception(-1)?;
574 } else {
575 info!("ignoring userRemoved(user_id={user_id})");
576 }
577 Ok(())
578 }
Alan Stokes30ccacb2024-02-20 14:59:02 +0000579
580 fn performReconciliation(
581 &self,
David Drysdale1138fa02024-03-19 13:06:23 +0000582 callback: &Strong<dyn IVirtualizationReconciliationCallback>,
Alan Stokes30ccacb2024-02-20 14:59:02 +0000583 ) -> binder::Result<()> {
David Drysdale1138fa02024-03-19 13:06:23 +0000584 let state = &mut *self.state.lock().unwrap();
585 if let Some(sk_state) = &mut state.sk_state {
586 info!("performReconciliation()");
587 sk_state.reconcile(callback).or_service_specific_exception(-1)?;
588 } else {
589 info!("ignoring performReconciliation()");
590 }
591 Ok(())
Alan Stokes30ccacb2024-02-20 14:59:02 +0000592 }
Inseob Kim1ca0f652023-07-20 17:18:12 +0900593}
594
Inseob Kimc4a774d2023-08-30 12:48:43 +0900595#[derive(Debug, Deserialize)]
596struct Device {
Jaewan Kim35e818d2023-10-18 05:36:38 +0000597 dtbo_label: String,
Inseob Kimc4a774d2023-08-30 12:48:43 +0900598 sysfs_path: String,
599}
600
Inseob Kim7307a892023-09-14 13:37:58 +0900601#[derive(Debug, Default, Deserialize)]
Inseob Kimc4a774d2023-08-30 12:48:43 +0900602struct Devices {
603 device: Vec<Device>,
604}
605
Inseob Kim7307a892023-09-14 13:37:58 +0900606fn get_assignable_devices() -> binder::Result<Devices> {
607 let xml_path = Path::new("/vendor/etc/avf/assignable_devices.xml");
608 if !xml_path.exists() {
609 return Ok(Devices { ..Default::default() });
610 }
611
612 let xml = fs::read(xml_path)
613 .context("Failed to read assignable_devices.xml")
614 .with_log()
615 .or_service_specific_exception(-1)?;
616
617 let xml = String::from_utf8(xml)
618 .context("assignable_devices.xml is not a valid UTF-8 file")
619 .with_log()
620 .or_service_specific_exception(-1)?;
621
622 let mut devices: Devices = serde_xml_rs::from_str(&xml)
623 .context("can't parse assignable_devices.xml")
624 .with_log()
625 .or_service_specific_exception(-1)?;
626
627 let mut device_set = HashSet::new();
628 devices.device.retain(move |device| {
629 if device_set.contains(&device.sysfs_path) {
630 warn!("duplicated assignable device {device:?}; ignoring...");
631 return false;
632 }
633
634 if !Path::new(&device.sysfs_path).exists() {
635 warn!("assignable device {device:?} doesn't exist; ignoring...");
636 return false;
637 }
638
639 device_set.insert(device.sysfs_path.clone());
640 true
641 });
642 Ok(devices)
643}
644
Alice Wang4c6c5582023-11-23 15:07:18 +0000645fn split_x509_certificate_chain(mut cert_chain: &[u8]) -> Result<Vec<Certificate>> {
646 let mut out = Vec::new();
647 while !cert_chain.is_empty() {
Alice Wangfc5a44a2023-12-21 12:22:40 +0000648 let cert = X509::from_der(cert_chain)?;
649 let end = cert.to_der()?.len();
Alice Wang4c6c5582023-11-23 15:07:18 +0000650 out.push(Certificate { encodedCertificate: cert_chain[..end].to_vec() });
Alice Wangfc5a44a2023-12-21 12:22:40 +0000651 cert_chain = &cert_chain[end..];
Alice Wang4c6c5582023-11-23 15:07:18 +0000652 }
653 Ok(out)
654}
655
David Brazdilafc9a9e2023-01-12 16:08:10 +0000656#[derive(Debug, Default)]
657struct GlobalVmInstance {
658 /// The unique CID assigned to the VM for vsock communication.
659 cid: Cid,
660 /// UID of the client who requested this VM instance.
661 requester_uid: uid_t,
662 /// PID of the client who requested this VM instance.
663 requester_debug_pid: pid_t,
Yi-Yo Chiang2fbf0da2024-06-14 22:56:56 +0800664 /// Name of the host console.
665 host_console_name: Option<String>,
David Brazdilafc9a9e2023-01-12 16:08:10 +0000666}
667
668impl GlobalVmInstance {
669 fn get_temp_dir(&self) -> PathBuf {
670 let cid = self.cid;
671 format!("{TEMPORARY_DIRECTORY}/{cid}").into()
672 }
673}
674
675/// The mutable state of the VirtualizationServiceInternal. There should only be one instance
676/// of this struct.
David Brazdilafc9a9e2023-01-12 16:08:10 +0000677struct GlobalState {
678 /// VM contexts currently allocated to running VMs. A CID is never recycled as long
679 /// as there is a strong reference held by a GlobalVmContext.
Yi-Yo Chiang2fbf0da2024-06-14 22:56:56 +0800680 held_contexts: HashMap<Cid, Weak<Mutex<GlobalVmInstance>>>,
David Brazdil2dfefd12023-11-17 14:07:36 +0000681
682 /// Cached read-only FD of VM DTBO file. Also serves as a lock for creating the file.
683 dtbo_file: Mutex<Option<File>>,
David Drysdale79af2662024-02-19 14:50:31 +0000684
685 /// State relating to secrets held by (optional) Secretkeeper instance on behalf of VMs.
686 sk_state: Option<maintenance::State>,
Jeongik Cha7add2a42024-04-02 14:52:39 +0900687
688 display_service: Option<binder::SpIBinder>,
David Brazdilafc9a9e2023-01-12 16:08:10 +0000689}
690
691impl GlobalState {
David Drysdale79af2662024-02-19 14:50:31 +0000692 fn new() -> Self {
693 Self {
694 held_contexts: HashMap::new(),
695 dtbo_file: Mutex::new(None),
696 sk_state: maintenance::State::new(),
Jeongik Cha7add2a42024-04-02 14:52:39 +0900697 display_service: None,
David Drysdale79af2662024-02-19 14:50:31 +0000698 }
699 }
700
David Brazdilafc9a9e2023-01-12 16:08:10 +0000701 /// Get the next available CID, or an error if we have run out. The last CID used is stored in
702 /// a system property so that restart of virtualizationservice doesn't reuse CID while the host
703 /// Android is up.
704 fn get_next_available_cid(&mut self) -> Result<Cid> {
705 // Start trying to find a CID from the last used CID + 1. This ensures
706 // that we do not eagerly recycle CIDs. It makes debugging easier but
707 // also means that retrying to allocate a CID, eg. because it is
708 // erroneously occupied by a process, will not recycle the same CID.
709 let last_cid_prop =
710 system_properties::read(SYSPROP_LAST_CID)?.and_then(|val| match val.parse::<Cid>() {
711 Ok(num) => {
712 if is_valid_guest_cid(num) {
713 Some(num)
714 } else {
715 error!("Invalid value '{}' of property '{}'", num, SYSPROP_LAST_CID);
716 None
717 }
718 }
719 Err(_) => {
720 error!("Invalid value '{}' of property '{}'", val, SYSPROP_LAST_CID);
721 None
722 }
723 });
724
725 let first_cid = if let Some(last_cid) = last_cid_prop {
726 if last_cid == GUEST_CID_MAX {
727 GUEST_CID_MIN
728 } else {
729 last_cid + 1
730 }
731 } else {
732 GUEST_CID_MIN
733 };
734
735 let cid = self
736 .find_available_cid(first_cid..=GUEST_CID_MAX)
737 .or_else(|| self.find_available_cid(GUEST_CID_MIN..first_cid))
738 .ok_or_else(|| anyhow!("Could not find an available CID."))?;
739
740 system_properties::write(SYSPROP_LAST_CID, &format!("{}", cid))?;
741 Ok(cid)
742 }
743
744 fn find_available_cid<I>(&self, mut range: I) -> Option<Cid>
745 where
746 I: Iterator<Item = Cid>,
747 {
748 range.find(|cid| !self.held_contexts.contains_key(cid))
749 }
750
751 fn allocate_vm_context(
752 &mut self,
753 requester_uid: uid_t,
754 requester_debug_pid: pid_t,
755 ) -> Result<Strong<dyn IGlobalVmContext>> {
756 // Garbage collect unused VM contexts.
757 self.held_contexts.retain(|_, instance| instance.strong_count() > 0);
758
759 let cid = self.get_next_available_cid()?;
Yi-Yo Chiang2fbf0da2024-06-14 22:56:56 +0800760 let instance = Arc::new(Mutex::new(GlobalVmInstance {
761 cid,
762 requester_uid,
763 requester_debug_pid,
764 ..Default::default()
765 }));
766 create_temporary_directory(&instance.lock().unwrap().get_temp_dir(), Some(requester_uid))?;
David Brazdilafc9a9e2023-01-12 16:08:10 +0000767
768 self.held_contexts.insert(cid, Arc::downgrade(&instance));
769 let binder = GlobalVmContext { instance, ..Default::default() };
770 Ok(BnGlobalVmContext::new_binder(binder, BinderFeatures::default()))
771 }
David Brazdil2dfefd12023-11-17 14:07:36 +0000772
773 fn get_dtbo_file(&mut self) -> Result<File> {
774 let mut file = self.dtbo_file.lock().unwrap();
775
776 let fd = if let Some(ref_fd) = &*file {
777 ref_fd.try_clone()?
778 } else {
779 let path = get_or_create_common_dir()?.join("vm.dtbo");
780 if path.exists() {
781 // All temporary files are deleted when the service is started.
782 // If the file exists but the FD is not cached, the file is
783 // likely corrupted.
784 remove_file(&path).context("Failed to clone cached VM DTBO file descriptor")?;
785 }
786
787 // Open a write-only file descriptor for vfio_handler.
788 let write_fd = File::create(&path).context("Failed to create VM DTBO file")?;
Jakob Vukalovicd42aa2c2023-11-09 16:04:00 +0000789 VFIO_SERVICE.writeVmDtbo(&ParcelFileDescriptor::new(write_fd))?;
David Brazdil2dfefd12023-11-17 14:07:36 +0000790
791 // Open read-only. This FD will be cached and returned to clients.
792 let read_fd = File::open(&path).context("Failed to open VM DTBO file")?;
793 let read_fd_clone =
794 read_fd.try_clone().context("Failed to clone VM DTBO file descriptor")?;
795 *file = Some(read_fd);
796 read_fd_clone
797 };
798
799 Ok(fd)
800 }
David Brazdilafc9a9e2023-01-12 16:08:10 +0000801}
802
David Brazdil2dfefd12023-11-17 14:07:36 +0000803fn create_temporary_directory(path: &PathBuf, requester_uid: Option<uid_t>) -> Result<()> {
804 // Directory may exist if previous attempt to create it had failed.
805 // Delete it before trying again.
David Brazdilafc9a9e2023-01-12 16:08:10 +0000806 if path.as_path().exists() {
807 remove_temporary_dir(path).unwrap_or_else(|e| {
808 warn!("Could not delete temporary directory {:?}: {}", path, e);
809 });
810 }
David Brazdil2dfefd12023-11-17 14:07:36 +0000811 // Create directory.
812 create_dir(path).with_context(|| format!("Could not create temporary directory {:?}", path))?;
813 // If provided, change ownership to client's UID but system's GID, and permissions 0700.
David Brazdilafc9a9e2023-01-12 16:08:10 +0000814 // If the chown() fails, this will leave behind an empty directory that will get removed
815 // at the next attempt, or if virtualizationservice is restarted.
David Brazdil2dfefd12023-11-17 14:07:36 +0000816 if let Some(uid) = requester_uid {
817 chown(path, Some(Uid::from_raw(uid)), None).with_context(|| {
818 format!("Could not set ownership of temporary directory {:?}", path)
819 })?;
820 }
David Brazdilafc9a9e2023-01-12 16:08:10 +0000821 Ok(())
822}
823
824/// Removes a directory owned by a different user by first changing its owner back
825/// to VirtualizationService.
826pub fn remove_temporary_dir(path: &PathBuf) -> Result<()> {
Alice Wangd1b11a02023-04-18 12:30:20 +0000827 ensure!(path.as_path().is_dir(), "Path {:?} is not a directory", path);
David Brazdilafc9a9e2023-01-12 16:08:10 +0000828 chown(path, Some(Uid::current()), None)?;
829 set_permissions(path, Permissions::from_mode(0o700))?;
Alice Wangd1b11a02023-04-18 12:30:20 +0000830 remove_dir_all(path)?;
David Brazdilafc9a9e2023-01-12 16:08:10 +0000831 Ok(())
832}
833
David Brazdil2dfefd12023-11-17 14:07:36 +0000834fn get_or_create_common_dir() -> Result<PathBuf> {
835 let path = Path::new(TEMPORARY_DIRECTORY).join("common");
836 if !path.exists() {
837 create_temporary_directory(&path, None)?;
838 }
839 Ok(path)
840}
841
David Brazdilafc9a9e2023-01-12 16:08:10 +0000842/// Implementation of the AIDL `IGlobalVmContext` interface.
843#[derive(Debug, Default)]
844struct GlobalVmContext {
845 /// Strong reference to the context's instance data structure.
Yi-Yo Chiang2fbf0da2024-06-14 22:56:56 +0800846 instance: Arc<Mutex<GlobalVmInstance>>,
David Brazdilafc9a9e2023-01-12 16:08:10 +0000847 /// Keeps our service process running as long as this VM context exists.
848 #[allow(dead_code)]
849 lazy_service_guard: LazyServiceGuard,
850}
851
852impl Interface for GlobalVmContext {}
853
854impl IGlobalVmContext for GlobalVmContext {
855 fn getCid(&self) -> binder::Result<i32> {
Yi-Yo Chiang2fbf0da2024-06-14 22:56:56 +0800856 Ok(self.instance.lock().unwrap().cid as i32)
David Brazdilafc9a9e2023-01-12 16:08:10 +0000857 }
858
859 fn getTemporaryDirectory(&self) -> binder::Result<String> {
Yi-Yo Chiang2fbf0da2024-06-14 22:56:56 +0800860 Ok(self.instance.lock().unwrap().get_temp_dir().to_string_lossy().to_string())
861 }
862
863 fn setHostConsoleName(&self, pathname: &str) -> binder::Result<()> {
864 self.instance.lock().unwrap().host_console_name = Some(pathname.to_string());
865 Ok(())
David Brazdilafc9a9e2023-01-12 16:08:10 +0000866 }
867}
868
869fn handle_stream_connection_tombstoned() -> Result<()> {
870 // Should not listen for tombstones on a guest VM's port.
871 assert!(!is_valid_guest_cid(VM_TOMBSTONES_SERVICE_PORT as Cid));
872 let listener =
873 VsockListener::bind_with_cid_port(VMADDR_CID_HOST, VM_TOMBSTONES_SERVICE_PORT as Cid)?;
874 for incoming_stream in listener.incoming() {
875 let mut incoming_stream = match incoming_stream {
876 Err(e) => {
877 warn!("invalid incoming connection: {:?}", e);
878 continue;
879 }
880 Ok(s) => s,
881 };
882 std::thread::spawn(move || {
883 if let Err(e) = handle_tombstone(&mut incoming_stream) {
884 error!("Failed to write tombstone- {:?}", e);
885 }
886 });
887 }
888 Ok(())
889}
890
891fn handle_tombstone(stream: &mut VsockStream) -> Result<()> {
892 if let Ok(addr) = stream.peer_addr() {
893 info!("Vsock Stream connected to cid={} for tombstones", addr.cid());
894 }
895 let tb_connection =
896 TombstonedConnection::connect(std::process::id() as i32, DebuggerdDumpType::Tombstone)
897 .context("Failed to connect to tombstoned")?;
898 let mut text_output = tb_connection
899 .text_output
900 .as_ref()
901 .ok_or_else(|| anyhow!("Could not get file to write the tombstones on"))?;
902 let mut num_bytes_read = 0;
903 loop {
904 let mut chunk_recv = [0; CHUNK_RECV_MAX_LEN];
905 let n = stream
906 .read(&mut chunk_recv)
907 .context("Failed to read tombstone data from Vsock stream")?;
908 if n == 0 {
909 break;
910 }
911 num_bytes_read += n;
912 text_output.write_all(&chunk_recv[0..n]).context("Failed to write guests tombstones")?;
913 }
914 info!("Received {} bytes from guest & wrote to tombstone file", num_bytes_read);
915 tb_connection.notify_completion()?;
916 Ok(())
917}
918
Alice Wang6c6535d2024-05-31 06:45:31 +0000919/// Returns true if the AVF remotely provisioned component service is declared in the
920/// VINTF manifest.
921pub(crate) fn is_remote_provisioning_hal_declared() -> binder::Result<bool> {
Alice Wang0dcab552024-03-20 14:42:30 +0000922 Ok(binder::is_declared(REMOTELY_PROVISIONED_COMPONENT_SERVICE_NAME)?)
923}
924
David Brazdilafc9a9e2023-01-12 16:08:10 +0000925/// Checks whether the caller has a specific permission
926fn check_permission(perm: &str) -> binder::Result<()> {
927 let calling_pid = get_calling_pid();
928 let calling_uid = get_calling_uid();
929 // Root can do anything
930 if calling_uid == 0 {
931 return Ok(());
932 }
933 let perm_svc: Strong<dyn IPermissionController::IPermissionController> =
Frederick Mayleb2a02872024-05-08 13:35:12 -0700934 binder::wait_for_interface("permission")?;
David Brazdilafc9a9e2023-01-12 16:08:10 +0000935 if perm_svc.checkPermission(perm, calling_pid, calling_uid as i32)? {
936 Ok(())
937 } else {
Jiyong Park2227eaa2023-08-04 11:59:18 +0900938 Err(anyhow!("does not have the {} permission", perm))
939 .or_binder_exception(ExceptionCode::SECURITY)
David Brazdilafc9a9e2023-01-12 16:08:10 +0000940 }
941}
942
943/// Check whether the caller of the current Binder method is allowed to call debug methods.
944fn check_debug_access() -> binder::Result<()> {
945 check_permission("android.permission.DEBUG_VIRTUAL_MACHINE")
946}
947
948/// Check whether the caller of the current Binder method is allowed to manage VMs
949fn check_manage_access() -> binder::Result<()> {
950 check_permission("android.permission.MANAGE_VIRTUAL_MACHINE")
951}
Inseob Kim53d0b212023-07-20 16:58:37 +0900952
953/// Check whether the caller of the current Binder method is allowed to use custom VMs
954fn check_use_custom_virtual_machine() -> binder::Result<()> {
955 check_permission("android.permission.USE_CUSTOM_VIRTUAL_MACHINE")
956}
Alice Wang4c6c5582023-11-23 15:07:18 +0000957
Seungjae Yooa6589bd2024-06-11 10:14:07 +0900958/// Check whether the caller of the current Binder method is allowed to create socket and
959/// establish connection between the VM and the Internet.
960fn check_internet_permission() -> binder::Result<()> {
961 check_permission("android.permission.INTERNET")
962}
963
Alice Wang4c6c5582023-11-23 15:07:18 +0000964#[cfg(test)]
965mod tests {
966 use super::*;
Alice Wang4c6c5582023-11-23 15:07:18 +0000967
968 const TEST_RKP_CERT_CHAIN_PATH: &str = "testdata/rkp_cert_chain.der";
969
970 #[test]
971 fn splitting_x509_certificate_chain_succeeds() -> Result<()> {
972 let bytes = fs::read(TEST_RKP_CERT_CHAIN_PATH)?;
973 let cert_chain = split_x509_certificate_chain(&bytes)?;
974
975 assert_eq!(4, cert_chain.len());
976 for cert in cert_chain {
Alice Wangfc5a44a2023-12-21 12:22:40 +0000977 let x509_cert = X509::from_der(&cert.encodedCertificate)?;
978 assert_eq!(x509_cert.to_der()?.len(), cert.encodedCertificate.len());
Alice Wang4c6c5582023-11-23 15:07:18 +0000979 }
980 Ok(())
981 }
982}