blob: 62cede84c63be2a55569289344b063e206bba958 [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,
276 requester_debug_pid: i32,
277 ) -> binder::Result<Strong<dyn IGlobalVmContext>> {
278 check_manage_access()?;
279
280 let requester_uid = get_calling_uid();
281 let requester_debug_pid = requester_debug_pid as pid_t;
282 let state = &mut *self.state.lock().unwrap();
Jiyong Park2227eaa2023-08-04 11:59:18 +0900283 state
284 .allocate_vm_context(requester_uid, requester_debug_pid)
285 .or_binder_exception(ExceptionCode::ILLEGAL_STATE)
David Brazdilafc9a9e2023-01-12 16:08:10 +0000286 }
287
288 fn atomVmBooted(&self, atom: &AtomVmBooted) -> Result<(), Status> {
289 forward_vm_booted_atom(atom);
290 Ok(())
291 }
292
293 fn atomVmCreationRequested(&self, atom: &AtomVmCreationRequested) -> Result<(), Status> {
294 forward_vm_creation_atom(atom);
295 Ok(())
296 }
297
298 fn atomVmExited(&self, atom: &AtomVmExited) -> Result<(), Status> {
299 forward_vm_exited_atom(atom);
300 Ok(())
301 }
302
303 fn debugListVms(&self) -> binder::Result<Vec<VirtualMachineDebugInfo>> {
304 check_debug_access()?;
305
306 let state = &mut *self.state.lock().unwrap();
307 let cids = state
308 .held_contexts
309 .iter()
310 .filter_map(|(_, inst)| Weak::upgrade(inst))
Yi-Yo Chiang2fbf0da2024-06-14 22:56:56 +0800311 .map(|vm| {
312 let vm = vm.lock().unwrap();
313 VirtualMachineDebugInfo {
314 cid: vm.cid as i32,
315 temporaryDirectory: vm.get_temp_dir().to_string_lossy().to_string(),
316 requesterUid: vm.requester_uid as i32,
317 requesterPid: vm.requester_debug_pid,
318 hostConsoleName: vm.host_console_name.clone(),
319 }
David Brazdilafc9a9e2023-01-12 16:08:10 +0000320 })
321 .collect();
322 Ok(cids)
323 }
Alice Wangc2fec932023-02-23 16:24:02 +0000324
Alice Wange64dd182024-01-17 15:57:55 +0000325 fn enableTestAttestation(&self) -> binder::Result<()> {
326 check_manage_access()?;
327 check_use_custom_virtual_machine()?;
328 if !cfg!(remote_attestation) {
329 return Err(Status::new_exception_str(
330 ExceptionCode::UNSUPPORTED_OPERATION,
331 Some(
332 "enableTestAttestation is not supported with the remote_attestation \
333 feature disabled",
334 ),
335 ))
336 .with_log();
337 }
338 let res = generate_ecdsa_p256_key_pair()
339 .context("Failed to generate ECDSA P-256 key pair for testing")
340 .with_log()
341 .or_service_specific_exception(-1)?;
Alice Wang5daec072024-03-15 15:31:17 +0000342 // Wait until the service VM shuts down, so that the Service VM will be restarted when
343 // the key generated in the current session will be used for attestation.
344 // This ensures that different Service VM sessions have the same KEK for the key blob.
345 service_vm_manager::wait_until_service_vm_shuts_down()
346 .context("Failed to wait until the service VM shuts down")
347 .with_log()
348 .or_service_specific_exception(-1)?;
Alice Wange64dd182024-01-17 15:57:55 +0000349 match res {
350 Response::GenerateEcdsaP256KeyPair(key_pair) => {
351 FAKE_PROVISIONED_KEY_BLOB_FOR_TESTING
352 .lock()
353 .unwrap()
354 .replace(key_pair.key_blob.to_vec());
355 Ok(())
356 }
357 _ => Err(remote_provisioning::to_service_specific_error(res)),
358 }
359 .with_log()
360 }
361
Alice Wangbff017f2023-11-09 14:43:28 +0000362 fn requestAttestation(
363 &self,
364 csr: &[u8],
365 requester_uid: i32,
Alice Wange64dd182024-01-17 15:57:55 +0000366 test_mode: bool,
Alice Wangbff017f2023-11-09 14:43:28 +0000367 ) -> binder::Result<Vec<Certificate>> {
Alice Wangc2fec932023-02-23 16:24:02 +0000368 check_manage_access()?;
Alice Wang4c6c5582023-11-23 15:07:18 +0000369 if !cfg!(remote_attestation) {
370 return Err(Status::new_exception_str(
Alice Wange9ac2db2023-09-08 15:13:13 +0000371 ExceptionCode::UNSUPPORTED_OPERATION,
372 Some(
Alice Wanga410b642023-10-18 09:05:15 +0000373 "requestAttestation is not supported with the remote_attestation feature \
374 disabled",
Alice Wange9ac2db2023-09-08 15:13:13 +0000375 ),
376 ))
Alice Wang4c6c5582023-11-23 15:07:18 +0000377 .with_log();
Alice Wange9ac2db2023-09-08 15:13:13 +0000378 }
Alice Wang6c6535d2024-05-31 06:45:31 +0000379 if !is_remote_provisioning_hal_declared()? {
Alice Wang0dcab552024-03-20 14:42:30 +0000380 return Err(Status::new_exception_str(
381 ExceptionCode::UNSUPPORTED_OPERATION,
382 Some("AVF remotely provisioned component service is not declared"),
383 ))
384 .with_log();
385 }
Alice Wangeec580d2024-06-07 08:48:06 +0000386 remote_provisioning::check_remote_attestation_is_supported()?;
Alice Wang4c6c5582023-11-23 15:07:18 +0000387 info!("Received csr. Requestting attestation...");
Alice Wange64dd182024-01-17 15:57:55 +0000388 let (key_blob, certificate_chain) = if test_mode {
389 check_use_custom_virtual_machine()?;
390 info!("Using the fake key blob for testing...");
391 (
392 FAKE_PROVISIONED_KEY_BLOB_FOR_TESTING
393 .lock()
394 .unwrap()
395 .clone()
396 .ok_or_else(|| anyhow!("No key blob for testing"))
397 .with_log()
398 .or_service_specific_exception(-1)?,
399 FAKE_CERTIFICATE_FOR_TESTING.to_vec(),
400 )
401 } else {
402 info!("Retrieving the remotely provisioned keys from RKPD...");
403 let attestation_key = get_rkpd_attestation_key(
404 REMOTELY_PROVISIONED_COMPONENT_SERVICE_NAME,
405 requester_uid as u32,
406 )
407 .context("Failed to retrieve the remotely provisioned keys")
408 .with_log()
409 .or_service_specific_exception(-1)?;
410 (attestation_key.keyBlob, attestation_key.encodedCertChain)
411 };
412 let mut certificate_chain = split_x509_certificate_chain(&certificate_chain)
Alice Wang4c6c5582023-11-23 15:07:18 +0000413 .context("Failed to split the remotely provisioned certificate chain")
414 .with_log()
415 .or_service_specific_exception(-1)?;
416 if certificate_chain.is_empty() {
417 return Err(Status::new_service_specific_error_str(
418 -1,
419 Some("The certificate chain should contain at least 1 certificate"),
420 ))
421 .with_log();
422 }
Alice Wang20b8ebc2023-11-17 09:54:47 +0000423 let certificate = request_attestation(
424 csr.to_vec(),
Alice Wange64dd182024-01-17 15:57:55 +0000425 key_blob,
Alice Wang20b8ebc2023-11-17 09:54:47 +0000426 certificate_chain[0].encodedCertificate.clone(),
427 )
428 .context("Failed to request attestation")
429 .with_log()
430 .or_service_specific_exception(-1)?;
Alice Wang4c6c5582023-11-23 15:07:18 +0000431 certificate_chain.insert(0, Certificate { encodedCertificate: certificate });
432
433 Ok(certificate_chain)
Alice Wangc2fec932023-02-23 16:24:02 +0000434 }
Inseob Kim53d0b212023-07-20 16:58:37 +0900435
Alice Wang0362f7f2024-03-21 08:16:26 +0000436 fn isRemoteAttestationSupported(&self) -> binder::Result<bool> {
Alice Wang801eb752025-02-19 00:48:31 +0000437 if is_remote_provisioning_hal_declared()? {
438 Ok(remote_provisioning::is_remote_attestation_supported())
439 } else {
440 warn!("AVF IRemotelyProvisionedComponent HAL is not declared");
441 Ok(false)
442 }
Alice Wang0362f7f2024-03-21 08:16:26 +0000443 }
444
Inseob Kim53d0b212023-07-20 16:58:37 +0900445 fn getAssignableDevices(&self) -> binder::Result<Vec<AssignableDevice>> {
446 check_use_custom_virtual_machine()?;
447
Inseob Kim7307a892023-09-14 13:37:58 +0900448 Ok(get_assignable_devices()?
449 .device
450 .into_iter()
Jaewan Kim0c99c612024-03-23 00:44:14 +0900451 .map(|x| AssignableDevice { node: x.sysfs_path, dtbo_label: x.dtbo_label })
Inseob Kim7307a892023-09-14 13:37:58 +0900452 .collect::<Vec<_>>())
Inseob Kim53d0b212023-07-20 16:58:37 +0900453 }
Inseob Kim1ca0f652023-07-20 17:18:12 +0900454
Jakob Vukalovicd42aa2c2023-11-09 16:04:00 +0000455 fn bindDevicesToVfioDriver(
456 &self,
457 devices: &[String],
458 ) -> binder::Result<Vec<Strong<dyn IBoundDevice>>> {
Inseob Kim1ca0f652023-07-20 17:18:12 +0900459 check_use_custom_virtual_machine()?;
460
Jakob Vukalovicd42aa2c2023-11-09 16:04:00 +0000461 let devices = get_assignable_devices()?
Inseob Kim7307a892023-09-14 13:37:58 +0900462 .device
463 .into_iter()
464 .filter_map(|x| {
465 if devices.contains(&x.sysfs_path) {
Jakob Vukalovicd42aa2c2023-11-09 16:04:00 +0000466 Some(VfioDev { sysfsPath: x.sysfs_path, dtboLabel: x.dtbo_label })
Inseob Kim7307a892023-09-14 13:37:58 +0900467 } else {
Jakob Vukalovicd42aa2c2023-11-09 16:04:00 +0000468 warn!("device {} is not assignable", x.sysfs_path);
Inseob Kim7307a892023-09-14 13:37:58 +0900469 None
470 }
471 })
Jakob Vukalovicd42aa2c2023-11-09 16:04:00 +0000472 .collect::<Vec<VfioDev>>();
473
474 VFIO_SERVICE.bindDevicesToVfioDriver(devices.as_slice())
Inseob Kim1ca0f652023-07-20 17:18:12 +0900475 }
David Brazdil2dfefd12023-11-17 14:07:36 +0000476
477 fn getDtboFile(&self) -> binder::Result<ParcelFileDescriptor> {
478 check_use_custom_virtual_machine()?;
479
480 let state = &mut *self.state.lock().unwrap();
481 let file = state.get_dtbo_file().or_service_specific_exception(-1)?;
482 Ok(ParcelFileDescriptor::new(file))
483 }
Shikha Panwar61a74b52024-02-16 13:17:01 +0000484
Shikha Panwar61a74b52024-02-16 13:17:01 +0000485 fn allocateInstanceId(&self) -> binder::Result<[u8; 64]> {
486 let mut id = [0u8; 64];
487 id.try_fill(&mut rand::thread_rng())
488 .context("Failed to allocate instance_id")
489 .or_service_specific_exception(-1)?;
490 let uid = get_calling_uid();
Shikha Panwar75e920b2024-06-14 06:12:37 +0000491 info!("Allocated a VM's instance_id: {:?}..., for uid: {:?}", &hex::encode(id)[..8], uid);
Shikha Panwareeae6402025-02-06 19:05:31 +0000492 self.try_updating_sk_state(&id);
Shikha Panwar61a74b52024-02-16 13:17:01 +0000493 Ok(id)
494 }
David Drysdale79af2662024-02-19 14:50:31 +0000495
496 fn removeVmInstance(&self, instance_id: &[u8; 64]) -> binder::Result<()> {
497 let state = &mut *self.state.lock().unwrap();
498 if let Some(sk_state) = &mut state.sk_state {
Alan Stokesde40e642024-06-04 13:36:05 +0100499 let uid = get_calling_uid();
500 info!(
501 "Removing a VM's instance_id: {:?}, for uid: {:?}",
502 hex::encode(instance_id),
503 uid
504 );
505
506 let user_id = multiuser_get_user_id(uid);
507 let app_id = multiuser_get_app_id(uid);
508 sk_state.delete_id(instance_id, user_id, app_id);
David Drysdale79af2662024-02-19 14:50:31 +0000509 } else {
510 info!("ignoring removeVmInstance() as no ISecretkeeper");
511 }
512 Ok(())
513 }
David Drysdale3aa62b32024-03-25 12:31:48 +0000514
515 fn claimVmInstance(&self, instance_id: &[u8; 64]) -> binder::Result<()> {
Shikha Panwareeae6402025-02-06 19:05:31 +0000516 info!("Claiming a VM's instance_id: {:?}", hex::encode(instance_id));
517 self.try_updating_sk_state(instance_id);
David Drysdale3aa62b32024-03-25 12:31:48 +0000518 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 }
Seungjae Yooa442e672024-06-19 16:18:07 +0900553
554 // TODO(340377643): Disabling tethering should be for bridge interface, not TAP interface.
555 TETHERING_SERVICE.disableVmTethering()?;
556
Seungjae Yoo3271f172024-06-11 10:14:07 +0900557 NETWORK_SERVICE.deleteTapInterface(tap_fd)
558 }
Shikha Panwareeae6402025-02-06 19:05:31 +0000559
560 fn claimSecretkeeperEntry(&self, id: &[u8; 64]) -> binder::Result<()> {
561 info!("Claiming Secretkeeper entry: {:?}", hex::encode(id));
562 self.try_updating_sk_state(id);
563 Ok(())
564 }
David Drysdale79af2662024-02-19 14:50:31 +0000565}
566
567impl IVirtualizationMaintenance for VirtualizationServiceInternal {
568 fn appRemoved(&self, user_id: i32, app_id: i32) -> binder::Result<()> {
569 let state = &mut *self.state.lock().unwrap();
570 if let Some(sk_state) = &mut state.sk_state {
571 info!("packageRemoved(user_id={user_id}, app_id={app_id})");
572 sk_state.delete_ids_for_app(user_id, app_id).or_service_specific_exception(-1)?;
573 } else {
574 info!("ignoring packageRemoved(user_id={user_id}, app_id={app_id})");
575 }
576 Ok(())
577 }
578
579 fn userRemoved(&self, user_id: i32) -> binder::Result<()> {
580 let state = &mut *self.state.lock().unwrap();
581 if let Some(sk_state) = &mut state.sk_state {
582 info!("userRemoved({user_id})");
583 sk_state.delete_ids_for_user(user_id).or_service_specific_exception(-1)?;
584 } else {
585 info!("ignoring userRemoved(user_id={user_id})");
586 }
587 Ok(())
588 }
Alan Stokes30ccacb2024-02-20 14:59:02 +0000589
590 fn performReconciliation(
591 &self,
David Drysdale1138fa02024-03-19 13:06:23 +0000592 callback: &Strong<dyn IVirtualizationReconciliationCallback>,
Alan Stokes30ccacb2024-02-20 14:59:02 +0000593 ) -> binder::Result<()> {
David Drysdale1138fa02024-03-19 13:06:23 +0000594 let state = &mut *self.state.lock().unwrap();
595 if let Some(sk_state) = &mut state.sk_state {
596 info!("performReconciliation()");
597 sk_state.reconcile(callback).or_service_specific_exception(-1)?;
598 } else {
599 info!("ignoring performReconciliation()");
600 }
601 Ok(())
Alan Stokes30ccacb2024-02-20 14:59:02 +0000602 }
Inseob Kim1ca0f652023-07-20 17:18:12 +0900603}
604
Inseob Kimc4a774d2023-08-30 12:48:43 +0900605#[derive(Debug, Deserialize)]
606struct Device {
Jaewan Kim35e818d2023-10-18 05:36:38 +0000607 dtbo_label: String,
Inseob Kimc4a774d2023-08-30 12:48:43 +0900608 sysfs_path: String,
609}
610
Inseob Kim7307a892023-09-14 13:37:58 +0900611#[derive(Debug, Default, Deserialize)]
Inseob Kimc4a774d2023-08-30 12:48:43 +0900612struct Devices {
613 device: Vec<Device>,
614}
615
Inseob Kim7307a892023-09-14 13:37:58 +0900616fn get_assignable_devices() -> binder::Result<Devices> {
617 let xml_path = Path::new("/vendor/etc/avf/assignable_devices.xml");
618 if !xml_path.exists() {
619 return Ok(Devices { ..Default::default() });
620 }
621
622 let xml = fs::read(xml_path)
623 .context("Failed to read assignable_devices.xml")
624 .with_log()
625 .or_service_specific_exception(-1)?;
626
627 let xml = String::from_utf8(xml)
628 .context("assignable_devices.xml is not a valid UTF-8 file")
629 .with_log()
630 .or_service_specific_exception(-1)?;
631
632 let mut devices: Devices = serde_xml_rs::from_str(&xml)
633 .context("can't parse assignable_devices.xml")
634 .with_log()
635 .or_service_specific_exception(-1)?;
636
637 let mut device_set = HashSet::new();
638 devices.device.retain(move |device| {
639 if device_set.contains(&device.sysfs_path) {
640 warn!("duplicated assignable device {device:?}; ignoring...");
641 return false;
642 }
643
644 if !Path::new(&device.sysfs_path).exists() {
645 warn!("assignable device {device:?} doesn't exist; ignoring...");
646 return false;
647 }
648
649 device_set.insert(device.sysfs_path.clone());
650 true
651 });
652 Ok(devices)
653}
654
Alice Wang4c6c5582023-11-23 15:07:18 +0000655fn split_x509_certificate_chain(mut cert_chain: &[u8]) -> Result<Vec<Certificate>> {
656 let mut out = Vec::new();
657 while !cert_chain.is_empty() {
Alice Wangfc5a44a2023-12-21 12:22:40 +0000658 let cert = X509::from_der(cert_chain)?;
659 let end = cert.to_der()?.len();
Alice Wang4c6c5582023-11-23 15:07:18 +0000660 out.push(Certificate { encodedCertificate: cert_chain[..end].to_vec() });
Alice Wangfc5a44a2023-12-21 12:22:40 +0000661 cert_chain = &cert_chain[end..];
Alice Wang4c6c5582023-11-23 15:07:18 +0000662 }
663 Ok(out)
664}
665
David Brazdilafc9a9e2023-01-12 16:08:10 +0000666#[derive(Debug, Default)]
667struct GlobalVmInstance {
668 /// The unique CID assigned to the VM for vsock communication.
669 cid: Cid,
670 /// UID of the client who requested this VM instance.
671 requester_uid: uid_t,
672 /// PID of the client who requested this VM instance.
673 requester_debug_pid: pid_t,
Yi-Yo Chiang2fbf0da2024-06-14 22:56:56 +0800674 /// Name of the host console.
675 host_console_name: Option<String>,
David Brazdilafc9a9e2023-01-12 16:08:10 +0000676}
677
678impl GlobalVmInstance {
679 fn get_temp_dir(&self) -> PathBuf {
680 let cid = self.cid;
681 format!("{TEMPORARY_DIRECTORY}/{cid}").into()
682 }
683}
684
685/// The mutable state of the VirtualizationServiceInternal. There should only be one instance
686/// of this struct.
David Brazdilafc9a9e2023-01-12 16:08:10 +0000687struct GlobalState {
688 /// VM contexts currently allocated to running VMs. A CID is never recycled as long
689 /// as there is a strong reference held by a GlobalVmContext.
Yi-Yo Chiang2fbf0da2024-06-14 22:56:56 +0800690 held_contexts: HashMap<Cid, Weak<Mutex<GlobalVmInstance>>>,
David Brazdil2dfefd12023-11-17 14:07:36 +0000691
692 /// Cached read-only FD of VM DTBO file. Also serves as a lock for creating the file.
693 dtbo_file: Mutex<Option<File>>,
David Drysdale79af2662024-02-19 14:50:31 +0000694
695 /// State relating to secrets held by (optional) Secretkeeper instance on behalf of VMs.
696 sk_state: Option<maintenance::State>,
Jeongik Cha7add2a42024-04-02 14:52:39 +0900697
698 display_service: Option<binder::SpIBinder>,
David Brazdilafc9a9e2023-01-12 16:08:10 +0000699}
700
701impl GlobalState {
David Drysdale79af2662024-02-19 14:50:31 +0000702 fn new() -> Self {
703 Self {
704 held_contexts: HashMap::new(),
705 dtbo_file: Mutex::new(None),
706 sk_state: maintenance::State::new(),
Jeongik Cha7add2a42024-04-02 14:52:39 +0900707 display_service: None,
David Drysdale79af2662024-02-19 14:50:31 +0000708 }
709 }
710
David Brazdilafc9a9e2023-01-12 16:08:10 +0000711 /// Get the next available CID, or an error if we have run out. The last CID used is stored in
712 /// a system property so that restart of virtualizationservice doesn't reuse CID while the host
713 /// Android is up.
714 fn get_next_available_cid(&mut self) -> Result<Cid> {
715 // Start trying to find a CID from the last used CID + 1. This ensures
716 // that we do not eagerly recycle CIDs. It makes debugging easier but
717 // also means that retrying to allocate a CID, eg. because it is
718 // erroneously occupied by a process, will not recycle the same CID.
719 let last_cid_prop =
720 system_properties::read(SYSPROP_LAST_CID)?.and_then(|val| match val.parse::<Cid>() {
721 Ok(num) => {
722 if is_valid_guest_cid(num) {
723 Some(num)
724 } else {
725 error!("Invalid value '{}' of property '{}'", num, SYSPROP_LAST_CID);
726 None
727 }
728 }
729 Err(_) => {
730 error!("Invalid value '{}' of property '{}'", val, SYSPROP_LAST_CID);
731 None
732 }
733 });
734
735 let first_cid = if let Some(last_cid) = last_cid_prop {
736 if last_cid == GUEST_CID_MAX {
737 GUEST_CID_MIN
738 } else {
739 last_cid + 1
740 }
741 } else {
742 GUEST_CID_MIN
743 };
744
745 let cid = self
746 .find_available_cid(first_cid..=GUEST_CID_MAX)
747 .or_else(|| self.find_available_cid(GUEST_CID_MIN..first_cid))
748 .ok_or_else(|| anyhow!("Could not find an available CID."))?;
749
750 system_properties::write(SYSPROP_LAST_CID, &format!("{}", cid))?;
751 Ok(cid)
752 }
753
754 fn find_available_cid<I>(&self, mut range: I) -> Option<Cid>
755 where
756 I: Iterator<Item = Cid>,
757 {
758 range.find(|cid| !self.held_contexts.contains_key(cid))
759 }
760
761 fn allocate_vm_context(
762 &mut self,
763 requester_uid: uid_t,
764 requester_debug_pid: pid_t,
765 ) -> Result<Strong<dyn IGlobalVmContext>> {
766 // Garbage collect unused VM contexts.
767 self.held_contexts.retain(|_, instance| instance.strong_count() > 0);
768
769 let cid = self.get_next_available_cid()?;
Yi-Yo Chiang2fbf0da2024-06-14 22:56:56 +0800770 let instance = Arc::new(Mutex::new(GlobalVmInstance {
771 cid,
772 requester_uid,
773 requester_debug_pid,
774 ..Default::default()
775 }));
776 create_temporary_directory(&instance.lock().unwrap().get_temp_dir(), Some(requester_uid))?;
David Brazdilafc9a9e2023-01-12 16:08:10 +0000777
778 self.held_contexts.insert(cid, Arc::downgrade(&instance));
779 let binder = GlobalVmContext { instance, ..Default::default() };
780 Ok(BnGlobalVmContext::new_binder(binder, BinderFeatures::default()))
781 }
David Brazdil2dfefd12023-11-17 14:07:36 +0000782
783 fn get_dtbo_file(&mut self) -> Result<File> {
784 let mut file = self.dtbo_file.lock().unwrap();
785
786 let fd = if let Some(ref_fd) = &*file {
787 ref_fd.try_clone()?
788 } else {
789 let path = get_or_create_common_dir()?.join("vm.dtbo");
790 if path.exists() {
791 // All temporary files are deleted when the service is started.
792 // If the file exists but the FD is not cached, the file is
793 // likely corrupted.
794 remove_file(&path).context("Failed to clone cached VM DTBO file descriptor")?;
795 }
796
797 // Open a write-only file descriptor for vfio_handler.
798 let write_fd = File::create(&path).context("Failed to create VM DTBO file")?;
Jakob Vukalovicd42aa2c2023-11-09 16:04:00 +0000799 VFIO_SERVICE.writeVmDtbo(&ParcelFileDescriptor::new(write_fd))?;
David Brazdil2dfefd12023-11-17 14:07:36 +0000800
801 // Open read-only. This FD will be cached and returned to clients.
802 let read_fd = File::open(&path).context("Failed to open VM DTBO file")?;
803 let read_fd_clone =
804 read_fd.try_clone().context("Failed to clone VM DTBO file descriptor")?;
805 *file = Some(read_fd);
806 read_fd_clone
807 };
808
809 Ok(fd)
810 }
David Brazdilafc9a9e2023-01-12 16:08:10 +0000811}
812
David Brazdil2dfefd12023-11-17 14:07:36 +0000813fn create_temporary_directory(path: &PathBuf, requester_uid: Option<uid_t>) -> Result<()> {
814 // Directory may exist if previous attempt to create it had failed.
815 // Delete it before trying again.
David Brazdilafc9a9e2023-01-12 16:08:10 +0000816 if path.as_path().exists() {
817 remove_temporary_dir(path).unwrap_or_else(|e| {
818 warn!("Could not delete temporary directory {:?}: {}", path, e);
819 });
820 }
David Brazdil2dfefd12023-11-17 14:07:36 +0000821 // Create directory.
822 create_dir(path).with_context(|| format!("Could not create temporary directory {:?}", path))?;
823 // If provided, change ownership to client's UID but system's GID, and permissions 0700.
David Brazdilafc9a9e2023-01-12 16:08:10 +0000824 // If the chown() fails, this will leave behind an empty directory that will get removed
825 // at the next attempt, or if virtualizationservice is restarted.
David Brazdil2dfefd12023-11-17 14:07:36 +0000826 if let Some(uid) = requester_uid {
827 chown(path, Some(Uid::from_raw(uid)), None).with_context(|| {
828 format!("Could not set ownership of temporary directory {:?}", path)
829 })?;
830 }
David Brazdilafc9a9e2023-01-12 16:08:10 +0000831 Ok(())
832}
833
834/// Removes a directory owned by a different user by first changing its owner back
835/// to VirtualizationService.
836pub fn remove_temporary_dir(path: &PathBuf) -> Result<()> {
Alice Wangd1b11a02023-04-18 12:30:20 +0000837 ensure!(path.as_path().is_dir(), "Path {:?} is not a directory", path);
David Brazdilafc9a9e2023-01-12 16:08:10 +0000838 chown(path, Some(Uid::current()), None)?;
839 set_permissions(path, Permissions::from_mode(0o700))?;
Alice Wangd1b11a02023-04-18 12:30:20 +0000840 remove_dir_all(path)?;
David Brazdilafc9a9e2023-01-12 16:08:10 +0000841 Ok(())
842}
843
David Brazdil2dfefd12023-11-17 14:07:36 +0000844fn get_or_create_common_dir() -> Result<PathBuf> {
845 let path = Path::new(TEMPORARY_DIRECTORY).join("common");
846 if !path.exists() {
847 create_temporary_directory(&path, None)?;
848 }
849 Ok(path)
850}
851
David Brazdilafc9a9e2023-01-12 16:08:10 +0000852/// Implementation of the AIDL `IGlobalVmContext` interface.
853#[derive(Debug, Default)]
854struct GlobalVmContext {
855 /// Strong reference to the context's instance data structure.
Yi-Yo Chiang2fbf0da2024-06-14 22:56:56 +0800856 instance: Arc<Mutex<GlobalVmInstance>>,
David Brazdilafc9a9e2023-01-12 16:08:10 +0000857 /// Keeps our service process running as long as this VM context exists.
858 #[allow(dead_code)]
859 lazy_service_guard: LazyServiceGuard,
860}
861
862impl Interface for GlobalVmContext {}
863
864impl IGlobalVmContext for GlobalVmContext {
865 fn getCid(&self) -> binder::Result<i32> {
Yi-Yo Chiang2fbf0da2024-06-14 22:56:56 +0800866 Ok(self.instance.lock().unwrap().cid as i32)
David Brazdilafc9a9e2023-01-12 16:08:10 +0000867 }
868
869 fn getTemporaryDirectory(&self) -> binder::Result<String> {
Yi-Yo Chiang2fbf0da2024-06-14 22:56:56 +0800870 Ok(self.instance.lock().unwrap().get_temp_dir().to_string_lossy().to_string())
871 }
872
873 fn setHostConsoleName(&self, pathname: &str) -> binder::Result<()> {
874 self.instance.lock().unwrap().host_console_name = Some(pathname.to_string());
875 Ok(())
David Brazdilafc9a9e2023-01-12 16:08:10 +0000876 }
877}
878
879fn handle_stream_connection_tombstoned() -> Result<()> {
880 // Should not listen for tombstones on a guest VM's port.
881 assert!(!is_valid_guest_cid(VM_TOMBSTONES_SERVICE_PORT as Cid));
882 let listener =
883 VsockListener::bind_with_cid_port(VMADDR_CID_HOST, VM_TOMBSTONES_SERVICE_PORT as Cid)?;
884 for incoming_stream in listener.incoming() {
885 let mut incoming_stream = match incoming_stream {
886 Err(e) => {
Alan Stokes8508bac2024-06-17 15:33:21 +0100887 warn!("invalid incoming connection: {e:?}");
David Brazdilafc9a9e2023-01-12 16:08:10 +0000888 continue;
889 }
890 Ok(s) => s,
891 };
Alan Stokes8508bac2024-06-17 15:33:21 +0100892 if let Ok(addr) = incoming_stream.peer_addr() {
893 let cid = addr.cid();
894 match cid {
895 VMADDR_CID_LOCAL | VMADDR_CID_HOST | VMADDR_CID_HYPERVISOR => {
896 warn!("Rejecting non-guest tombstone vsock connection from cid={cid}");
897 continue;
898 }
899 _ => info!("Vsock Stream connected to cid={cid} for tombstones"),
900 }
901 }
David Brazdilafc9a9e2023-01-12 16:08:10 +0000902 std::thread::spawn(move || {
903 if let Err(e) = handle_tombstone(&mut incoming_stream) {
904 error!("Failed to write tombstone- {:?}", e);
905 }
906 });
907 }
908 Ok(())
909}
910
911fn handle_tombstone(stream: &mut VsockStream) -> Result<()> {
David Brazdilafc9a9e2023-01-12 16:08:10 +0000912 let tb_connection =
913 TombstonedConnection::connect(std::process::id() as i32, DebuggerdDumpType::Tombstone)
914 .context("Failed to connect to tombstoned")?;
915 let mut text_output = tb_connection
916 .text_output
917 .as_ref()
918 .ok_or_else(|| anyhow!("Could not get file to write the tombstones on"))?;
919 let mut num_bytes_read = 0;
920 loop {
921 let mut chunk_recv = [0; CHUNK_RECV_MAX_LEN];
922 let n = stream
923 .read(&mut chunk_recv)
924 .context("Failed to read tombstone data from Vsock stream")?;
925 if n == 0 {
926 break;
927 }
928 num_bytes_read += n;
929 text_output.write_all(&chunk_recv[0..n]).context("Failed to write guests tombstones")?;
930 }
931 info!("Received {} bytes from guest & wrote to tombstone file", num_bytes_read);
932 tb_connection.notify_completion()?;
933 Ok(())
934}
935
Alice Wang6c6535d2024-05-31 06:45:31 +0000936/// Returns true if the AVF remotely provisioned component service is declared in the
937/// VINTF manifest.
938pub(crate) fn is_remote_provisioning_hal_declared() -> binder::Result<bool> {
Alice Wang0dcab552024-03-20 14:42:30 +0000939 Ok(binder::is_declared(REMOTELY_PROVISIONED_COMPONENT_SERVICE_NAME)?)
940}
941
David Brazdilafc9a9e2023-01-12 16:08:10 +0000942/// Checks whether the caller has a specific permission
943fn check_permission(perm: &str) -> binder::Result<()> {
944 let calling_pid = get_calling_pid();
945 let calling_uid = get_calling_uid();
946 // Root can do anything
947 if calling_uid == 0 {
948 return Ok(());
949 }
950 let perm_svc: Strong<dyn IPermissionController::IPermissionController> =
Frederick Mayleb2a02872024-05-08 13:35:12 -0700951 binder::wait_for_interface("permission")?;
David Brazdilafc9a9e2023-01-12 16:08:10 +0000952 if perm_svc.checkPermission(perm, calling_pid, calling_uid as i32)? {
953 Ok(())
954 } else {
Jiyong Park2227eaa2023-08-04 11:59:18 +0900955 Err(anyhow!("does not have the {} permission", perm))
956 .or_binder_exception(ExceptionCode::SECURITY)
David Brazdilafc9a9e2023-01-12 16:08:10 +0000957 }
958}
959
960/// Check whether the caller of the current Binder method is allowed to call debug methods.
961fn check_debug_access() -> binder::Result<()> {
962 check_permission("android.permission.DEBUG_VIRTUAL_MACHINE")
963}
964
965/// Check whether the caller of the current Binder method is allowed to manage VMs
966fn check_manage_access() -> binder::Result<()> {
967 check_permission("android.permission.MANAGE_VIRTUAL_MACHINE")
968}
Inseob Kim53d0b212023-07-20 16:58:37 +0900969
970/// Check whether the caller of the current Binder method is allowed to use custom VMs
971fn check_use_custom_virtual_machine() -> binder::Result<()> {
972 check_permission("android.permission.USE_CUSTOM_VIRTUAL_MACHINE")
973}
Alice Wang4c6c5582023-11-23 15:07:18 +0000974
Seungjae Yooa6589bd2024-06-11 10:14:07 +0900975/// Check whether the caller of the current Binder method is allowed to create socket and
976/// establish connection between the VM and the Internet.
977fn check_internet_permission() -> binder::Result<()> {
978 check_permission("android.permission.INTERNET")
979}
980
Alice Wang4c6c5582023-11-23 15:07:18 +0000981#[cfg(test)]
982mod tests {
983 use super::*;
Alice Wang4c6c5582023-11-23 15:07:18 +0000984
985 const TEST_RKP_CERT_CHAIN_PATH: &str = "testdata/rkp_cert_chain.der";
986
987 #[test]
988 fn splitting_x509_certificate_chain_succeeds() -> Result<()> {
989 let bytes = fs::read(TEST_RKP_CERT_CHAIN_PATH)?;
990 let cert_chain = split_x509_certificate_chain(&bytes)?;
991
992 assert_eq!(4, cert_chain.len());
993 for cert in cert_chain {
Alice Wangfc5a44a2023-12-21 12:22:40 +0000994 let x509_cert = X509::from_der(&cert.encodedCertificate)?;
995 assert_eq!(x509_cert.to_der()?.len(), cert.encodedCertificate.len());
Alice Wang4c6c5582023-11-23 15:07:18 +0000996 }
997 Ok(())
998 }
999}