blob: e26cd4f73fbdb360b38219f61fa53aa31d996db7 [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 }
Shikha Panwareeae6402025-02-06 19:05:31 +0000199
200 // Attempt to update the sk_state maintenance database. Errors are ignored - calling app
201 // can not really do much to fix the errors & letting AVF VMs run irrespective of such internal
202 // error is acceptable.
203 fn try_updating_sk_state(&self, id: &[u8; 64]) {
204 let state = &mut *self.state.lock().unwrap();
205 if let Some(sk_state) = &mut state.sk_state {
206 let uid = get_calling_uid();
207 let user_id = multiuser_get_user_id(uid);
208 let app_id = multiuser_get_app_id(uid);
209 info!(
210 "Recording possible new owner of Secretkeeper entry={:?}:
211 (user_id={user_id}, app_id={app_id},)",
212 hex::encode(id)
213 );
214 if let Err(e) = sk_state.add_id(id, user_id, app_id) {
215 error!("Failed to update the Secretkeeper entry owner: {e:?}");
216 }
217 } else {
218 info!("ignoring update of Secretkeeper entry as no ISecretkeeper");
219 }
220 }
David Brazdilafc9a9e2023-01-12 16:08:10 +0000221}
222
223impl Interface for VirtualizationServiceInternal {}
224
225impl IVirtualizationServiceInternal for VirtualizationServiceInternal {
Jeongik Cha7add2a42024-04-02 14:52:39 +0900226 fn setDisplayService(
227 &self,
228 ibinder: &binder::SpIBinder,
229 ) -> std::result::Result<(), binder::Status> {
230 check_manage_access()?;
231 check_use_custom_virtual_machine()?;
232 let state = &mut *self.state.lock().unwrap();
233 state.display_service = Some(ibinder.clone());
234 self.display_service_set.notify_all();
235 Ok(())
236 }
237
Jeongik Chaeee137d2024-04-03 22:13:14 +0900238 fn clearDisplayService(&self) -> std::result::Result<(), binder::Status> {
239 check_manage_access()?;
240 check_use_custom_virtual_machine()?;
241 let state = &mut *self.state.lock().unwrap();
242 state.display_service = None;
243 self.display_service_set.notify_all();
244 Ok(())
245 }
246
Jeongik Cha7add2a42024-04-02 14:52:39 +0900247 fn waitDisplayService(&self) -> std::result::Result<binder::SpIBinder, binder::Status> {
248 check_manage_access()?;
249 check_use_custom_virtual_machine()?;
250 let state = self
251 .display_service_set
252 .wait_while(self.state.lock().unwrap(), |state| state.display_service.is_none())
253 .unwrap();
254 Ok((state.display_service)
255 .as_ref()
256 .cloned()
257 .expect("Display service cannot be None in this context"))
258 }
David Brazdilafc9a9e2023-01-12 16:08:10 +0000259 fn removeMemlockRlimit(&self) -> binder::Result<()> {
260 let pid = get_calling_pid();
261 let lim = libc::rlimit { rlim_cur: libc::RLIM_INFINITY, rlim_max: libc::RLIM_INFINITY };
262
Andrew Walbranb58d1b42023-07-07 13:54:49 +0100263 // SAFETY: borrowing the new limit struct only
David Brazdilafc9a9e2023-01-12 16:08:10 +0000264 let ret = unsafe { libc::prlimit(pid, libc::RLIMIT_MEMLOCK, &lim, std::ptr::null_mut()) };
265
266 match ret {
267 0 => Ok(()),
Jiyong Park2227eaa2023-08-04 11:59:18 +0900268 -1 => Err(std::io::Error::last_os_error().into()),
269 n => Err(anyhow!("Unexpected return value from prlimit(): {n}")),
David Brazdilafc9a9e2023-01-12 16:08:10 +0000270 }
Jiyong Park2227eaa2023-08-04 11:59:18 +0900271 .or_binder_exception(ExceptionCode::ILLEGAL_STATE)
David Brazdilafc9a9e2023-01-12 16:08:10 +0000272 }
273
274 fn allocateGlobalVmContext(
275 &self,
Jiyong Park18ceddc2025-03-18 13:30:02 +0900276 name: &str,
David Brazdilafc9a9e2023-01-12 16:08:10 +0000277 requester_debug_pid: i32,
278 ) -> binder::Result<Strong<dyn IGlobalVmContext>> {
279 check_manage_access()?;
280
281 let requester_uid = get_calling_uid();
282 let requester_debug_pid = requester_debug_pid as pid_t;
283 let state = &mut *self.state.lock().unwrap();
Jiyong Park2227eaa2023-08-04 11:59:18 +0900284 state
Jiyong Park18ceddc2025-03-18 13:30:02 +0900285 .allocate_vm_context(name, requester_uid, requester_debug_pid)
Jiyong Park2227eaa2023-08-04 11:59:18 +0900286 .or_binder_exception(ExceptionCode::ILLEGAL_STATE)
David Brazdilafc9a9e2023-01-12 16:08:10 +0000287 }
288
289 fn atomVmBooted(&self, atom: &AtomVmBooted) -> Result<(), Status> {
290 forward_vm_booted_atom(atom);
291 Ok(())
292 }
293
294 fn atomVmCreationRequested(&self, atom: &AtomVmCreationRequested) -> Result<(), Status> {
295 forward_vm_creation_atom(atom);
296 Ok(())
297 }
298
299 fn atomVmExited(&self, atom: &AtomVmExited) -> Result<(), Status> {
300 forward_vm_exited_atom(atom);
301 Ok(())
302 }
303
304 fn debugListVms(&self) -> binder::Result<Vec<VirtualMachineDebugInfo>> {
305 check_debug_access()?;
306
307 let state = &mut *self.state.lock().unwrap();
308 let cids = state
309 .held_contexts
310 .iter()
311 .filter_map(|(_, inst)| Weak::upgrade(inst))
Yi-Yo Chiang2fbf0da2024-06-14 22:56:56 +0800312 .map(|vm| {
313 let vm = vm.lock().unwrap();
314 VirtualMachineDebugInfo {
Jiyong Park18ceddc2025-03-18 13:30:02 +0900315 name: vm.name.clone(),
Yi-Yo Chiang2fbf0da2024-06-14 22:56:56 +0800316 cid: vm.cid as i32,
317 temporaryDirectory: vm.get_temp_dir().to_string_lossy().to_string(),
318 requesterUid: vm.requester_uid as i32,
319 requesterPid: vm.requester_debug_pid,
320 hostConsoleName: vm.host_console_name.clone(),
321 }
David Brazdilafc9a9e2023-01-12 16:08:10 +0000322 })
323 .collect();
324 Ok(cids)
325 }
Alice Wangc2fec932023-02-23 16:24:02 +0000326
Alice Wange64dd182024-01-17 15:57:55 +0000327 fn enableTestAttestation(&self) -> binder::Result<()> {
328 check_manage_access()?;
329 check_use_custom_virtual_machine()?;
330 if !cfg!(remote_attestation) {
331 return Err(Status::new_exception_str(
332 ExceptionCode::UNSUPPORTED_OPERATION,
333 Some(
334 "enableTestAttestation is not supported with the remote_attestation \
335 feature disabled",
336 ),
337 ))
338 .with_log();
339 }
340 let res = generate_ecdsa_p256_key_pair()
341 .context("Failed to generate ECDSA P-256 key pair for testing")
342 .with_log()
343 .or_service_specific_exception(-1)?;
Alice Wang5daec072024-03-15 15:31:17 +0000344 // Wait until the service VM shuts down, so that the Service VM will be restarted when
345 // the key generated in the current session will be used for attestation.
346 // This ensures that different Service VM sessions have the same KEK for the key blob.
347 service_vm_manager::wait_until_service_vm_shuts_down()
348 .context("Failed to wait until the service VM shuts down")
349 .with_log()
350 .or_service_specific_exception(-1)?;
Alice Wange64dd182024-01-17 15:57:55 +0000351 match res {
352 Response::GenerateEcdsaP256KeyPair(key_pair) => {
353 FAKE_PROVISIONED_KEY_BLOB_FOR_TESTING
354 .lock()
355 .unwrap()
356 .replace(key_pair.key_blob.to_vec());
357 Ok(())
358 }
359 _ => Err(remote_provisioning::to_service_specific_error(res)),
360 }
361 .with_log()
362 }
363
Alice Wangbff017f2023-11-09 14:43:28 +0000364 fn requestAttestation(
365 &self,
366 csr: &[u8],
367 requester_uid: i32,
Alice Wange64dd182024-01-17 15:57:55 +0000368 test_mode: bool,
Alice Wangbff017f2023-11-09 14:43:28 +0000369 ) -> binder::Result<Vec<Certificate>> {
Alice Wangc2fec932023-02-23 16:24:02 +0000370 check_manage_access()?;
Alice Wang4c6c5582023-11-23 15:07:18 +0000371 if !cfg!(remote_attestation) {
372 return Err(Status::new_exception_str(
Alice Wange9ac2db2023-09-08 15:13:13 +0000373 ExceptionCode::UNSUPPORTED_OPERATION,
374 Some(
Alice Wanga410b642023-10-18 09:05:15 +0000375 "requestAttestation is not supported with the remote_attestation feature \
376 disabled",
Alice Wange9ac2db2023-09-08 15:13:13 +0000377 ),
378 ))
Alice Wang4c6c5582023-11-23 15:07:18 +0000379 .with_log();
Alice Wange9ac2db2023-09-08 15:13:13 +0000380 }
Alice Wang6c6535d2024-05-31 06:45:31 +0000381 if !is_remote_provisioning_hal_declared()? {
Alice Wang0dcab552024-03-20 14:42:30 +0000382 return Err(Status::new_exception_str(
383 ExceptionCode::UNSUPPORTED_OPERATION,
384 Some("AVF remotely provisioned component service is not declared"),
385 ))
386 .with_log();
387 }
Alice Wangeec580d2024-06-07 08:48:06 +0000388 remote_provisioning::check_remote_attestation_is_supported()?;
Alice Wang4c6c5582023-11-23 15:07:18 +0000389 info!("Received csr. Requestting attestation...");
Alice Wange64dd182024-01-17 15:57:55 +0000390 let (key_blob, certificate_chain) = if test_mode {
391 check_use_custom_virtual_machine()?;
392 info!("Using the fake key blob for testing...");
393 (
394 FAKE_PROVISIONED_KEY_BLOB_FOR_TESTING
395 .lock()
396 .unwrap()
397 .clone()
398 .ok_or_else(|| anyhow!("No key blob for testing"))
399 .with_log()
400 .or_service_specific_exception(-1)?,
401 FAKE_CERTIFICATE_FOR_TESTING.to_vec(),
402 )
403 } else {
404 info!("Retrieving the remotely provisioned keys from RKPD...");
405 let attestation_key = get_rkpd_attestation_key(
406 REMOTELY_PROVISIONED_COMPONENT_SERVICE_NAME,
407 requester_uid as u32,
408 )
409 .context("Failed to retrieve the remotely provisioned keys")
410 .with_log()
411 .or_service_specific_exception(-1)?;
412 (attestation_key.keyBlob, attestation_key.encodedCertChain)
413 };
414 let mut certificate_chain = split_x509_certificate_chain(&certificate_chain)
Alice Wang4c6c5582023-11-23 15:07:18 +0000415 .context("Failed to split the remotely provisioned certificate chain")
416 .with_log()
417 .or_service_specific_exception(-1)?;
418 if certificate_chain.is_empty() {
419 return Err(Status::new_service_specific_error_str(
420 -1,
421 Some("The certificate chain should contain at least 1 certificate"),
422 ))
423 .with_log();
424 }
Alice Wang20b8ebc2023-11-17 09:54:47 +0000425 let certificate = request_attestation(
426 csr.to_vec(),
Alice Wange64dd182024-01-17 15:57:55 +0000427 key_blob,
Alice Wang20b8ebc2023-11-17 09:54:47 +0000428 certificate_chain[0].encodedCertificate.clone(),
429 )
430 .context("Failed to request attestation")
431 .with_log()
432 .or_service_specific_exception(-1)?;
Alice Wang4c6c5582023-11-23 15:07:18 +0000433 certificate_chain.insert(0, Certificate { encodedCertificate: certificate });
434
435 Ok(certificate_chain)
Alice Wangc2fec932023-02-23 16:24:02 +0000436 }
Inseob Kim53d0b212023-07-20 16:58:37 +0900437
Alice Wang0362f7f2024-03-21 08:16:26 +0000438 fn isRemoteAttestationSupported(&self) -> binder::Result<bool> {
Alice Wang801eb752025-02-19 00:48:31 +0000439 if is_remote_provisioning_hal_declared()? {
440 Ok(remote_provisioning::is_remote_attestation_supported())
441 } else {
442 warn!("AVF IRemotelyProvisionedComponent HAL is not declared");
443 Ok(false)
444 }
Alice Wang0362f7f2024-03-21 08:16:26 +0000445 }
446
Inseob Kim53d0b212023-07-20 16:58:37 +0900447 fn getAssignableDevices(&self) -> binder::Result<Vec<AssignableDevice>> {
448 check_use_custom_virtual_machine()?;
449
Inseob Kim7307a892023-09-14 13:37:58 +0900450 Ok(get_assignable_devices()?
451 .device
452 .into_iter()
Jaewan Kim0c99c612024-03-23 00:44:14 +0900453 .map(|x| AssignableDevice { node: x.sysfs_path, dtbo_label: x.dtbo_label })
Inseob Kim7307a892023-09-14 13:37:58 +0900454 .collect::<Vec<_>>())
Inseob Kim53d0b212023-07-20 16:58:37 +0900455 }
Inseob Kim1ca0f652023-07-20 17:18:12 +0900456
Jakob Vukalovicd42aa2c2023-11-09 16:04:00 +0000457 fn bindDevicesToVfioDriver(
458 &self,
459 devices: &[String],
460 ) -> binder::Result<Vec<Strong<dyn IBoundDevice>>> {
Inseob Kim1ca0f652023-07-20 17:18:12 +0900461 check_use_custom_virtual_machine()?;
462
Jakob Vukalovicd42aa2c2023-11-09 16:04:00 +0000463 let devices = get_assignable_devices()?
Inseob Kim7307a892023-09-14 13:37:58 +0900464 .device
465 .into_iter()
466 .filter_map(|x| {
467 if devices.contains(&x.sysfs_path) {
Jakob Vukalovicd42aa2c2023-11-09 16:04:00 +0000468 Some(VfioDev { sysfsPath: x.sysfs_path, dtboLabel: x.dtbo_label })
Inseob Kim7307a892023-09-14 13:37:58 +0900469 } else {
Jakob Vukalovicd42aa2c2023-11-09 16:04:00 +0000470 warn!("device {} is not assignable", x.sysfs_path);
Inseob Kim7307a892023-09-14 13:37:58 +0900471 None
472 }
473 })
Jakob Vukalovicd42aa2c2023-11-09 16:04:00 +0000474 .collect::<Vec<VfioDev>>();
475
476 VFIO_SERVICE.bindDevicesToVfioDriver(devices.as_slice())
Inseob Kim1ca0f652023-07-20 17:18:12 +0900477 }
David Brazdil2dfefd12023-11-17 14:07:36 +0000478
479 fn getDtboFile(&self) -> binder::Result<ParcelFileDescriptor> {
480 check_use_custom_virtual_machine()?;
481
482 let state = &mut *self.state.lock().unwrap();
483 let file = state.get_dtbo_file().or_service_specific_exception(-1)?;
484 Ok(ParcelFileDescriptor::new(file))
485 }
Shikha Panwar61a74b52024-02-16 13:17:01 +0000486
Shikha Panwar61a74b52024-02-16 13:17:01 +0000487 fn allocateInstanceId(&self) -> binder::Result<[u8; 64]> {
488 let mut id = [0u8; 64];
489 id.try_fill(&mut rand::thread_rng())
490 .context("Failed to allocate instance_id")
491 .or_service_specific_exception(-1)?;
Frederick Mayle01dff422025-02-13 16:52:06 -0800492 // Randomly allocated IDs always start with all 7s to avoid colliding with statically
493 // assigned IDs.
494 id[..4].fill(0x77);
Shikha Panwar61a74b52024-02-16 13:17:01 +0000495 let uid = get_calling_uid();
Shikha Panwar75e920b2024-06-14 06:12:37 +0000496 info!("Allocated a VM's instance_id: {:?}..., for uid: {:?}", &hex::encode(id)[..8], uid);
Shikha Panwareeae6402025-02-06 19:05:31 +0000497 self.try_updating_sk_state(&id);
Shikha Panwar61a74b52024-02-16 13:17:01 +0000498 Ok(id)
499 }
David Drysdale79af2662024-02-19 14:50:31 +0000500
501 fn removeVmInstance(&self, instance_id: &[u8; 64]) -> binder::Result<()> {
502 let state = &mut *self.state.lock().unwrap();
503 if let Some(sk_state) = &mut state.sk_state {
Alan Stokesde40e642024-06-04 13:36:05 +0100504 let uid = get_calling_uid();
505 info!(
506 "Removing a VM's instance_id: {:?}, for uid: {:?}",
507 hex::encode(instance_id),
508 uid
509 );
510
511 let user_id = multiuser_get_user_id(uid);
512 let app_id = multiuser_get_app_id(uid);
513 sk_state.delete_id(instance_id, user_id, app_id);
David Drysdale79af2662024-02-19 14:50:31 +0000514 } else {
515 info!("ignoring removeVmInstance() as no ISecretkeeper");
516 }
517 Ok(())
518 }
David Drysdale3aa62b32024-03-25 12:31:48 +0000519
520 fn claimVmInstance(&self, instance_id: &[u8; 64]) -> binder::Result<()> {
Shikha Panwareeae6402025-02-06 19:05:31 +0000521 info!("Claiming a VM's instance_id: {:?}", hex::encode(instance_id));
522 self.try_updating_sk_state(instance_id);
David Drysdale3aa62b32024-03-25 12:31:48 +0000523 Ok(())
524 }
Seungjae Yoo13af0b62024-05-20 14:15:13 +0900525
Seungjae Yoo548346e2024-06-19 16:18:06 +0900526 fn createTapInterface(&self, _iface_name_suffix: &str) -> binder::Result<ParcelFileDescriptor> {
Seungjae Yooa6589bd2024-06-11 10:14:07 +0900527 check_internet_permission()?;
Seungjae Yoo13af0b62024-05-20 14:15:13 +0900528 check_use_custom_virtual_machine()?;
529 if !cfg!(network) {
530 return Err(Status::new_exception_str(
531 ExceptionCode::UNSUPPORTED_OPERATION,
532 Some("createTapInterface is not supported with the network feature disabled"),
533 ))
534 .with_log();
535 }
Seungjae Yoo548346e2024-06-19 16:18:06 +0900536 // TODO(340377643): Use iface_name_suffix after introducing bridge interface, not fixed
537 // value.
538 let tap_fd = NETWORK_SERVICE.createTapInterface("fixed")?;
Seungjae Yoob6e4f1d2024-06-17 15:13:12 +0900539
540 // TODO(340377643): Due to lack of implementation of creating bridge interface, tethering is
541 // enabled for TAP interface instead of bridge interface. After introducing creation of
542 // bridge interface in AVF, we should modify it.
Seungjae Yoo548346e2024-06-19 16:18:06 +0900543 TETHERING_SERVICE.enableVmTethering()?;
Seungjae Yoob6e4f1d2024-06-17 15:13:12 +0900544
545 Ok(tap_fd)
Seungjae Yoo13af0b62024-05-20 14:15:13 +0900546 }
Seungjae Yoo3271f172024-06-11 10:14:07 +0900547
548 fn deleteTapInterface(&self, tap_fd: &ParcelFileDescriptor) -> binder::Result<()> {
549 check_internet_permission()?;
550 check_use_custom_virtual_machine()?;
551 if !cfg!(network) {
552 return Err(Status::new_exception_str(
553 ExceptionCode::UNSUPPORTED_OPERATION,
554 Some("deleteTapInterface is not supported with the network feature disabled"),
555 ))
556 .with_log();
557 }
Seungjae Yooa442e672024-06-19 16:18:07 +0900558
559 // TODO(340377643): Disabling tethering should be for bridge interface, not TAP interface.
560 TETHERING_SERVICE.disableVmTethering()?;
561
Seungjae Yoo3271f172024-06-11 10:14:07 +0900562 NETWORK_SERVICE.deleteTapInterface(tap_fd)
563 }
Shikha Panwareeae6402025-02-06 19:05:31 +0000564
565 fn claimSecretkeeperEntry(&self, id: &[u8; 64]) -> binder::Result<()> {
566 info!("Claiming Secretkeeper entry: {:?}", hex::encode(id));
567 self.try_updating_sk_state(id);
568 Ok(())
569 }
David Drysdale79af2662024-02-19 14:50:31 +0000570}
571
572impl IVirtualizationMaintenance for VirtualizationServiceInternal {
573 fn appRemoved(&self, user_id: i32, app_id: i32) -> binder::Result<()> {
574 let state = &mut *self.state.lock().unwrap();
575 if let Some(sk_state) = &mut state.sk_state {
576 info!("packageRemoved(user_id={user_id}, app_id={app_id})");
577 sk_state.delete_ids_for_app(user_id, app_id).or_service_specific_exception(-1)?;
578 } else {
579 info!("ignoring packageRemoved(user_id={user_id}, app_id={app_id})");
580 }
581 Ok(())
582 }
583
584 fn userRemoved(&self, user_id: i32) -> binder::Result<()> {
585 let state = &mut *self.state.lock().unwrap();
586 if let Some(sk_state) = &mut state.sk_state {
587 info!("userRemoved({user_id})");
588 sk_state.delete_ids_for_user(user_id).or_service_specific_exception(-1)?;
589 } else {
590 info!("ignoring userRemoved(user_id={user_id})");
591 }
592 Ok(())
593 }
Alan Stokes30ccacb2024-02-20 14:59:02 +0000594
595 fn performReconciliation(
596 &self,
David Drysdale1138fa02024-03-19 13:06:23 +0000597 callback: &Strong<dyn IVirtualizationReconciliationCallback>,
Alan Stokes30ccacb2024-02-20 14:59:02 +0000598 ) -> binder::Result<()> {
David Drysdale1138fa02024-03-19 13:06:23 +0000599 let state = &mut *self.state.lock().unwrap();
600 if let Some(sk_state) = &mut state.sk_state {
601 info!("performReconciliation()");
602 sk_state.reconcile(callback).or_service_specific_exception(-1)?;
603 } else {
604 info!("ignoring performReconciliation()");
605 }
606 Ok(())
Alan Stokes30ccacb2024-02-20 14:59:02 +0000607 }
Inseob Kim1ca0f652023-07-20 17:18:12 +0900608}
609
Inseob Kimc4a774d2023-08-30 12:48:43 +0900610#[derive(Debug, Deserialize)]
611struct Device {
Jaewan Kim35e818d2023-10-18 05:36:38 +0000612 dtbo_label: String,
Inseob Kimc4a774d2023-08-30 12:48:43 +0900613 sysfs_path: String,
614}
615
Inseob Kim7307a892023-09-14 13:37:58 +0900616#[derive(Debug, Default, Deserialize)]
Inseob Kimc4a774d2023-08-30 12:48:43 +0900617struct Devices {
618 device: Vec<Device>,
619}
620
Inseob Kim7307a892023-09-14 13:37:58 +0900621fn get_assignable_devices() -> binder::Result<Devices> {
622 let xml_path = Path::new("/vendor/etc/avf/assignable_devices.xml");
623 if !xml_path.exists() {
624 return Ok(Devices { ..Default::default() });
625 }
626
627 let xml = fs::read(xml_path)
628 .context("Failed to read assignable_devices.xml")
629 .with_log()
630 .or_service_specific_exception(-1)?;
631
632 let xml = String::from_utf8(xml)
633 .context("assignable_devices.xml is not a valid UTF-8 file")
634 .with_log()
635 .or_service_specific_exception(-1)?;
636
637 let mut devices: Devices = serde_xml_rs::from_str(&xml)
638 .context("can't parse assignable_devices.xml")
639 .with_log()
640 .or_service_specific_exception(-1)?;
641
642 let mut device_set = HashSet::new();
643 devices.device.retain(move |device| {
644 if device_set.contains(&device.sysfs_path) {
645 warn!("duplicated assignable device {device:?}; ignoring...");
646 return false;
647 }
648
649 if !Path::new(&device.sysfs_path).exists() {
650 warn!("assignable device {device:?} doesn't exist; ignoring...");
651 return false;
652 }
653
654 device_set.insert(device.sysfs_path.clone());
655 true
656 });
657 Ok(devices)
658}
659
Alice Wang4c6c5582023-11-23 15:07:18 +0000660fn split_x509_certificate_chain(mut cert_chain: &[u8]) -> Result<Vec<Certificate>> {
661 let mut out = Vec::new();
662 while !cert_chain.is_empty() {
Alice Wangfc5a44a2023-12-21 12:22:40 +0000663 let cert = X509::from_der(cert_chain)?;
664 let end = cert.to_der()?.len();
Alice Wang4c6c5582023-11-23 15:07:18 +0000665 out.push(Certificate { encodedCertificate: cert_chain[..end].to_vec() });
Alice Wangfc5a44a2023-12-21 12:22:40 +0000666 cert_chain = &cert_chain[end..];
Alice Wang4c6c5582023-11-23 15:07:18 +0000667 }
668 Ok(out)
669}
670
David Brazdilafc9a9e2023-01-12 16:08:10 +0000671#[derive(Debug, Default)]
672struct GlobalVmInstance {
Jiyong Park18ceddc2025-03-18 13:30:02 +0900673 /// Name of the VM
674 name: String,
David Brazdilafc9a9e2023-01-12 16:08:10 +0000675 /// The unique CID assigned to the VM for vsock communication.
676 cid: Cid,
677 /// UID of the client who requested this VM instance.
678 requester_uid: uid_t,
679 /// PID of the client who requested this VM instance.
680 requester_debug_pid: pid_t,
Yi-Yo Chiang2fbf0da2024-06-14 22:56:56 +0800681 /// Name of the host console.
682 host_console_name: Option<String>,
David Brazdilafc9a9e2023-01-12 16:08:10 +0000683}
684
685impl GlobalVmInstance {
686 fn get_temp_dir(&self) -> PathBuf {
687 let cid = self.cid;
688 format!("{TEMPORARY_DIRECTORY}/{cid}").into()
689 }
690}
691
692/// The mutable state of the VirtualizationServiceInternal. There should only be one instance
693/// of this struct.
David Brazdilafc9a9e2023-01-12 16:08:10 +0000694struct GlobalState {
695 /// VM contexts currently allocated to running VMs. A CID is never recycled as long
696 /// as there is a strong reference held by a GlobalVmContext.
Yi-Yo Chiang2fbf0da2024-06-14 22:56:56 +0800697 held_contexts: HashMap<Cid, Weak<Mutex<GlobalVmInstance>>>,
David Brazdil2dfefd12023-11-17 14:07:36 +0000698
699 /// Cached read-only FD of VM DTBO file. Also serves as a lock for creating the file.
700 dtbo_file: Mutex<Option<File>>,
David Drysdale79af2662024-02-19 14:50:31 +0000701
702 /// State relating to secrets held by (optional) Secretkeeper instance on behalf of VMs.
703 sk_state: Option<maintenance::State>,
Jeongik Cha7add2a42024-04-02 14:52:39 +0900704
705 display_service: Option<binder::SpIBinder>,
David Brazdilafc9a9e2023-01-12 16:08:10 +0000706}
707
708impl GlobalState {
David Drysdale79af2662024-02-19 14:50:31 +0000709 fn new() -> Self {
710 Self {
711 held_contexts: HashMap::new(),
712 dtbo_file: Mutex::new(None),
713 sk_state: maintenance::State::new(),
Jeongik Cha7add2a42024-04-02 14:52:39 +0900714 display_service: None,
David Drysdale79af2662024-02-19 14:50:31 +0000715 }
716 }
717
David Brazdilafc9a9e2023-01-12 16:08:10 +0000718 /// Get the next available CID, or an error if we have run out. The last CID used is stored in
719 /// a system property so that restart of virtualizationservice doesn't reuse CID while the host
720 /// Android is up.
721 fn get_next_available_cid(&mut self) -> Result<Cid> {
722 // Start trying to find a CID from the last used CID + 1. This ensures
723 // that we do not eagerly recycle CIDs. It makes debugging easier but
724 // also means that retrying to allocate a CID, eg. because it is
725 // erroneously occupied by a process, will not recycle the same CID.
726 let last_cid_prop =
727 system_properties::read(SYSPROP_LAST_CID)?.and_then(|val| match val.parse::<Cid>() {
728 Ok(num) => {
729 if is_valid_guest_cid(num) {
730 Some(num)
731 } else {
732 error!("Invalid value '{}' of property '{}'", num, SYSPROP_LAST_CID);
733 None
734 }
735 }
736 Err(_) => {
737 error!("Invalid value '{}' of property '{}'", val, SYSPROP_LAST_CID);
738 None
739 }
740 });
741
742 let first_cid = if let Some(last_cid) = last_cid_prop {
743 if last_cid == GUEST_CID_MAX {
744 GUEST_CID_MIN
745 } else {
746 last_cid + 1
747 }
748 } else {
749 GUEST_CID_MIN
750 };
751
752 let cid = self
753 .find_available_cid(first_cid..=GUEST_CID_MAX)
754 .or_else(|| self.find_available_cid(GUEST_CID_MIN..first_cid))
755 .ok_or_else(|| anyhow!("Could not find an available CID."))?;
756
757 system_properties::write(SYSPROP_LAST_CID, &format!("{}", cid))?;
758 Ok(cid)
759 }
760
761 fn find_available_cid<I>(&self, mut range: I) -> Option<Cid>
762 where
763 I: Iterator<Item = Cid>,
764 {
765 range.find(|cid| !self.held_contexts.contains_key(cid))
766 }
767
768 fn allocate_vm_context(
769 &mut self,
Jiyong Park18ceddc2025-03-18 13:30:02 +0900770 name: &str,
David Brazdilafc9a9e2023-01-12 16:08:10 +0000771 requester_uid: uid_t,
772 requester_debug_pid: pid_t,
773 ) -> Result<Strong<dyn IGlobalVmContext>> {
774 // Garbage collect unused VM contexts.
775 self.held_contexts.retain(|_, instance| instance.strong_count() > 0);
776
777 let cid = self.get_next_available_cid()?;
Yi-Yo Chiang2fbf0da2024-06-14 22:56:56 +0800778 let instance = Arc::new(Mutex::new(GlobalVmInstance {
Jiyong Park18ceddc2025-03-18 13:30:02 +0900779 name: name.to_owned(),
Yi-Yo Chiang2fbf0da2024-06-14 22:56:56 +0800780 cid,
781 requester_uid,
782 requester_debug_pid,
783 ..Default::default()
784 }));
785 create_temporary_directory(&instance.lock().unwrap().get_temp_dir(), Some(requester_uid))?;
David Brazdilafc9a9e2023-01-12 16:08:10 +0000786
787 self.held_contexts.insert(cid, Arc::downgrade(&instance));
788 let binder = GlobalVmContext { instance, ..Default::default() };
789 Ok(BnGlobalVmContext::new_binder(binder, BinderFeatures::default()))
790 }
David Brazdil2dfefd12023-11-17 14:07:36 +0000791
792 fn get_dtbo_file(&mut self) -> Result<File> {
793 let mut file = self.dtbo_file.lock().unwrap();
794
795 let fd = if let Some(ref_fd) = &*file {
796 ref_fd.try_clone()?
797 } else {
798 let path = get_or_create_common_dir()?.join("vm.dtbo");
799 if path.exists() {
800 // All temporary files are deleted when the service is started.
801 // If the file exists but the FD is not cached, the file is
802 // likely corrupted.
803 remove_file(&path).context("Failed to clone cached VM DTBO file descriptor")?;
804 }
805
806 // Open a write-only file descriptor for vfio_handler.
807 let write_fd = File::create(&path).context("Failed to create VM DTBO file")?;
Jakob Vukalovicd42aa2c2023-11-09 16:04:00 +0000808 VFIO_SERVICE.writeVmDtbo(&ParcelFileDescriptor::new(write_fd))?;
David Brazdil2dfefd12023-11-17 14:07:36 +0000809
810 // Open read-only. This FD will be cached and returned to clients.
811 let read_fd = File::open(&path).context("Failed to open VM DTBO file")?;
812 let read_fd_clone =
813 read_fd.try_clone().context("Failed to clone VM DTBO file descriptor")?;
814 *file = Some(read_fd);
815 read_fd_clone
816 };
817
818 Ok(fd)
819 }
David Brazdilafc9a9e2023-01-12 16:08:10 +0000820}
821
David Brazdil2dfefd12023-11-17 14:07:36 +0000822fn create_temporary_directory(path: &PathBuf, requester_uid: Option<uid_t>) -> Result<()> {
823 // Directory may exist if previous attempt to create it had failed.
824 // Delete it before trying again.
David Brazdilafc9a9e2023-01-12 16:08:10 +0000825 if path.as_path().exists() {
826 remove_temporary_dir(path).unwrap_or_else(|e| {
827 warn!("Could not delete temporary directory {:?}: {}", path, e);
828 });
829 }
David Brazdil2dfefd12023-11-17 14:07:36 +0000830 // Create directory.
831 create_dir(path).with_context(|| format!("Could not create temporary directory {:?}", path))?;
832 // If provided, change ownership to client's UID but system's GID, and permissions 0700.
David Brazdilafc9a9e2023-01-12 16:08:10 +0000833 // If the chown() fails, this will leave behind an empty directory that will get removed
834 // at the next attempt, or if virtualizationservice is restarted.
David Brazdil2dfefd12023-11-17 14:07:36 +0000835 if let Some(uid) = requester_uid {
836 chown(path, Some(Uid::from_raw(uid)), None).with_context(|| {
837 format!("Could not set ownership of temporary directory {:?}", path)
838 })?;
839 }
David Brazdilafc9a9e2023-01-12 16:08:10 +0000840 Ok(())
841}
842
843/// Removes a directory owned by a different user by first changing its owner back
844/// to VirtualizationService.
845pub fn remove_temporary_dir(path: &PathBuf) -> Result<()> {
Alice Wangd1b11a02023-04-18 12:30:20 +0000846 ensure!(path.as_path().is_dir(), "Path {:?} is not a directory", path);
David Brazdilafc9a9e2023-01-12 16:08:10 +0000847 chown(path, Some(Uid::current()), None)?;
848 set_permissions(path, Permissions::from_mode(0o700))?;
Alice Wangd1b11a02023-04-18 12:30:20 +0000849 remove_dir_all(path)?;
David Brazdilafc9a9e2023-01-12 16:08:10 +0000850 Ok(())
851}
852
David Brazdil2dfefd12023-11-17 14:07:36 +0000853fn get_or_create_common_dir() -> Result<PathBuf> {
854 let path = Path::new(TEMPORARY_DIRECTORY).join("common");
855 if !path.exists() {
856 create_temporary_directory(&path, None)?;
857 }
858 Ok(path)
859}
860
David Brazdilafc9a9e2023-01-12 16:08:10 +0000861/// Implementation of the AIDL `IGlobalVmContext` interface.
862#[derive(Debug, Default)]
863struct GlobalVmContext {
864 /// Strong reference to the context's instance data structure.
Yi-Yo Chiang2fbf0da2024-06-14 22:56:56 +0800865 instance: Arc<Mutex<GlobalVmInstance>>,
David Brazdilafc9a9e2023-01-12 16:08:10 +0000866 /// Keeps our service process running as long as this VM context exists.
867 #[allow(dead_code)]
868 lazy_service_guard: LazyServiceGuard,
869}
870
871impl Interface for GlobalVmContext {}
872
873impl IGlobalVmContext for GlobalVmContext {
874 fn getCid(&self) -> binder::Result<i32> {
Yi-Yo Chiang2fbf0da2024-06-14 22:56:56 +0800875 Ok(self.instance.lock().unwrap().cid as i32)
David Brazdilafc9a9e2023-01-12 16:08:10 +0000876 }
877
878 fn getTemporaryDirectory(&self) -> binder::Result<String> {
Yi-Yo Chiang2fbf0da2024-06-14 22:56:56 +0800879 Ok(self.instance.lock().unwrap().get_temp_dir().to_string_lossy().to_string())
880 }
881
882 fn setHostConsoleName(&self, pathname: &str) -> binder::Result<()> {
883 self.instance.lock().unwrap().host_console_name = Some(pathname.to_string());
884 Ok(())
David Brazdilafc9a9e2023-01-12 16:08:10 +0000885 }
886}
887
888fn handle_stream_connection_tombstoned() -> Result<()> {
889 // Should not listen for tombstones on a guest VM's port.
890 assert!(!is_valid_guest_cid(VM_TOMBSTONES_SERVICE_PORT as Cid));
891 let listener =
892 VsockListener::bind_with_cid_port(VMADDR_CID_HOST, VM_TOMBSTONES_SERVICE_PORT as Cid)?;
893 for incoming_stream in listener.incoming() {
894 let mut incoming_stream = match incoming_stream {
895 Err(e) => {
Alan Stokes8508bac2024-06-17 15:33:21 +0100896 warn!("invalid incoming connection: {e:?}");
David Brazdilafc9a9e2023-01-12 16:08:10 +0000897 continue;
898 }
899 Ok(s) => s,
900 };
Alan Stokes8508bac2024-06-17 15:33:21 +0100901 if let Ok(addr) = incoming_stream.peer_addr() {
902 let cid = addr.cid();
903 match cid {
904 VMADDR_CID_LOCAL | VMADDR_CID_HOST | VMADDR_CID_HYPERVISOR => {
905 warn!("Rejecting non-guest tombstone vsock connection from cid={cid}");
906 continue;
907 }
908 _ => info!("Vsock Stream connected to cid={cid} for tombstones"),
909 }
910 }
David Brazdilafc9a9e2023-01-12 16:08:10 +0000911 std::thread::spawn(move || {
912 if let Err(e) = handle_tombstone(&mut incoming_stream) {
913 error!("Failed to write tombstone- {:?}", e);
914 }
915 });
916 }
917 Ok(())
918}
919
920fn handle_tombstone(stream: &mut VsockStream) -> Result<()> {
David Brazdilafc9a9e2023-01-12 16:08:10 +0000921 let tb_connection =
922 TombstonedConnection::connect(std::process::id() as i32, DebuggerdDumpType::Tombstone)
923 .context("Failed to connect to tombstoned")?;
924 let mut text_output = tb_connection
925 .text_output
926 .as_ref()
927 .ok_or_else(|| anyhow!("Could not get file to write the tombstones on"))?;
928 let mut num_bytes_read = 0;
929 loop {
930 let mut chunk_recv = [0; CHUNK_RECV_MAX_LEN];
931 let n = stream
932 .read(&mut chunk_recv)
933 .context("Failed to read tombstone data from Vsock stream")?;
934 if n == 0 {
935 break;
936 }
937 num_bytes_read += n;
938 text_output.write_all(&chunk_recv[0..n]).context("Failed to write guests tombstones")?;
939 }
940 info!("Received {} bytes from guest & wrote to tombstone file", num_bytes_read);
941 tb_connection.notify_completion()?;
942 Ok(())
943}
944
Alice Wang6c6535d2024-05-31 06:45:31 +0000945/// Returns true if the AVF remotely provisioned component service is declared in the
946/// VINTF manifest.
947pub(crate) fn is_remote_provisioning_hal_declared() -> binder::Result<bool> {
Alice Wang0dcab552024-03-20 14:42:30 +0000948 Ok(binder::is_declared(REMOTELY_PROVISIONED_COMPONENT_SERVICE_NAME)?)
949}
950
David Brazdilafc9a9e2023-01-12 16:08:10 +0000951/// Checks whether the caller has a specific permission
952fn check_permission(perm: &str) -> binder::Result<()> {
953 let calling_pid = get_calling_pid();
954 let calling_uid = get_calling_uid();
955 // Root can do anything
956 if calling_uid == 0 {
957 return Ok(());
958 }
959 let perm_svc: Strong<dyn IPermissionController::IPermissionController> =
Frederick Mayleb2a02872024-05-08 13:35:12 -0700960 binder::wait_for_interface("permission")?;
David Brazdilafc9a9e2023-01-12 16:08:10 +0000961 if perm_svc.checkPermission(perm, calling_pid, calling_uid as i32)? {
962 Ok(())
963 } else {
Jiyong Park2227eaa2023-08-04 11:59:18 +0900964 Err(anyhow!("does not have the {} permission", perm))
965 .or_binder_exception(ExceptionCode::SECURITY)
David Brazdilafc9a9e2023-01-12 16:08:10 +0000966 }
967}
968
969/// Check whether the caller of the current Binder method is allowed to call debug methods.
970fn check_debug_access() -> binder::Result<()> {
971 check_permission("android.permission.DEBUG_VIRTUAL_MACHINE")
972}
973
974/// Check whether the caller of the current Binder method is allowed to manage VMs
975fn check_manage_access() -> binder::Result<()> {
976 check_permission("android.permission.MANAGE_VIRTUAL_MACHINE")
977}
Inseob Kim53d0b212023-07-20 16:58:37 +0900978
979/// Check whether the caller of the current Binder method is allowed to use custom VMs
980fn check_use_custom_virtual_machine() -> binder::Result<()> {
981 check_permission("android.permission.USE_CUSTOM_VIRTUAL_MACHINE")
982}
Alice Wang4c6c5582023-11-23 15:07:18 +0000983
Seungjae Yooa6589bd2024-06-11 10:14:07 +0900984/// Check whether the caller of the current Binder method is allowed to create socket and
985/// establish connection between the VM and the Internet.
986fn check_internet_permission() -> binder::Result<()> {
987 check_permission("android.permission.INTERNET")
988}
989
Alice Wang4c6c5582023-11-23 15:07:18 +0000990#[cfg(test)]
991mod tests {
992 use super::*;
Alice Wang4c6c5582023-11-23 15:07:18 +0000993
994 const TEST_RKP_CERT_CHAIN_PATH: &str = "testdata/rkp_cert_chain.der";
995
996 #[test]
997 fn splitting_x509_certificate_chain_succeeds() -> Result<()> {
998 let bytes = fs::read(TEST_RKP_CERT_CHAIN_PATH)?;
999 let cert_chain = split_x509_certificate_chain(&bytes)?;
1000
1001 assert_eq!(4, cert_chain.len());
1002 for cert in cert_chain {
Alice Wangfc5a44a2023-12-21 12:22:40 +00001003 let x509_cert = X509::from_der(&cert.encodedCertificate)?;
1004 assert_eq!(x509_cert.to_der()?.len(), cert.encodedCertificate.len());
Alice Wang4c6c5582023-11-23 15:07:18 +00001005 }
1006 Ok(())
1007 }
1008}