1 // 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
17 use crate::atom::{forward_vm_booted_atom, forward_vm_creation_atom, forward_vm_exited_atom};
18 use crate::maintenance;
19 use crate::remote_provisioning;
20 use crate::rkpvm::{generate_ecdsa_p256_key_pair, request_attestation};
21 use crate::{get_calling_pid, get_calling_uid, REMOTELY_PROVISIONED_COMPONENT_SERVICE_NAME};
22 use android_os_permissions_aidl::aidl::android::os::IPermissionController;
23 use android_system_virtualizationcommon::aidl::android::system::virtualizationcommon;
24 use android_system_virtualizationmaintenance::aidl::android::system::virtualizationmaintenance;
25 use android_system_virtualizationservice::aidl::android::system::virtualizationservice;
26 use android_system_virtualizationservice_internal as android_vs_internal;
27 use android_system_virtualmachineservice::aidl::android::system::virtualmachineservice;
28 use android_vs_internal::aidl::android::system::virtualizationservice_internal;
29 use anyhow::{anyhow, ensure, Context, Result};
30 use avflog::LogResult;
31 use binder::{
32 self, wait_for_interface, BinderFeatures, ExceptionCode, Interface, IntoBinderResult,
33 LazyServiceGuard, ParcelFileDescriptor, Status, Strong,
34 };
35 use lazy_static::lazy_static;
36 use libc::VMADDR_CID_HOST;
37 use log::{error, info, warn};
38 use nix::unistd::{chown, Uid};
39 use openssl::x509::X509;
40 use rand::Fill;
41 use rkpd_client::get_rkpd_attestation_key;
42 use rustutils::{
43 system_properties,
44 users::{multiuser_get_app_id, multiuser_get_user_id},
45 };
46 use serde::Deserialize;
47 use service_vm_comm::Response;
48 use std::collections::{HashMap, HashSet};
49 use std::fs::{self, create_dir, remove_dir_all, remove_file, set_permissions, File, Permissions};
50 use std::io::{Read, Write};
51 use std::os::unix::fs::PermissionsExt;
52 use std::os::unix::raw::{pid_t, uid_t};
53 use std::path::{Path, PathBuf};
54 use std::sync::{Arc, Condvar, Mutex, Weak};
55 use tombstoned_client::{DebuggerdDumpType, TombstonedConnection};
56 use virtualizationcommon::Certificate::Certificate;
57 use virtualizationmaintenance::{
58 IVirtualizationMaintenance::IVirtualizationMaintenance,
59 IVirtualizationReconciliationCallback::IVirtualizationReconciliationCallback,
60 };
61 use virtualizationservice::{
62 AssignableDevice::AssignableDevice, VirtualMachineDebugInfo::VirtualMachineDebugInfo,
63 };
64 use 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},
72 IVirtualizationServiceInternal::IVirtualizationServiceInternal,
73 IVmnic::{BpVmnic, IVmnic},
74 };
75 use virtualmachineservice::IVirtualMachineService::VM_TOMBSTONES_SERVICE_PORT;
76 use vsock::{VsockListener, VsockStream};
77
78 /// The unique ID of a VM used (together with a port number) for vsock communication.
79 pub type Cid = u32;
80
81 /// Directory in which to write disk image files used while running VMs.
82 pub const TEMPORARY_DIRECTORY: &str = "/data/misc/virtualizationservice";
83
84 /// The first CID to assign to a guest VM managed by the VirtualizationService. CIDs lower than this
85 /// are reserved for the host or other usage.
86 const GUEST_CID_MIN: Cid = 2048;
87 const GUEST_CID_MAX: Cid = 65535;
88
89 const SYSPROP_LAST_CID: &str = "virtualizationservice.state.last_cid";
90
91 const CHUNK_RECV_MAX_LEN: usize = 1024;
92
93 /// The fake certificate is used for testing only when a client VM requests attestation in test
94 /// mode, it is a single certificate extracted on an unregistered device for testing.
95 /// Here is the snapshot of the certificate:
96 ///
97 /// ```
98 /// Certificate:
99 /// Data:
100 /// Version: 3 (0x2)
101 /// Serial Number:
102 /// 59:ae:50:98:95:e1:34:25:f1:21:93:c0:4c:e5:24:66
103 /// Signature Algorithm: ecdsa-with-SHA256
104 /// Issuer: CN = Droid Unregistered Device CA, O = Google Test LLC
105 /// Validity
106 /// Not Before: Feb 5 14:39:39 2024 GMT
107 /// Not After : Feb 14 14:39:39 2024 GMT
108 /// Subject: CN = 59ae509895e13425f12193c04ce52466, O = TEE
109 /// Subject Public Key Info:
110 /// Public Key Algorithm: id-ecPublicKey
111 /// Public-Key: (256 bit)
112 /// pub:
113 /// 04:30:32:cd:95:12:b0:71:8b:b7:14:44:26:58:d5:
114 /// 82:8c:25:55:2c:6d:ef:98:e3:4f:88:d0:74:82:09:
115 /// 3e:8d:6c:f0:f2:18:d5:83:0e:0d:f2:ce:c5:15:38:
116 /// e5:6a:e6:4d:4d:95:15:b7:24:e7:cb:4b:63:42:21:
117 /// bc:36:c6:0a:d8
118 /// ASN1 OID: prime256v1
119 /// NIST CURVE: P-256
120 /// X509v3 extensions:
121 /// ...
122 /// ```
123 const FAKE_CERTIFICATE_FOR_TESTING: &[u8] = &[
124 0x30, 0x82, 0x01, 0xee, 0x30, 0x82, 0x01, 0x94, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x10, 0x59,
125 0xae, 0x50, 0x98, 0x95, 0xe1, 0x34, 0x25, 0xf1, 0x21, 0x93, 0xc0, 0x4c, 0xe5, 0x24, 0x66, 0x30,
126 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x30, 0x41, 0x31, 0x25, 0x30,
127 0x23, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x1c, 0x44, 0x72, 0x6f, 0x69, 0x64, 0x20, 0x55, 0x6e,
128 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x65, 0x64, 0x20, 0x44, 0x65, 0x76, 0x69, 0x63,
129 0x65, 0x20, 0x43, 0x41, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0f, 0x47,
130 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x20, 0x54, 0x65, 0x73, 0x74, 0x20, 0x4c, 0x4c, 0x43, 0x30, 0x1e,
131 0x17, 0x0d, 0x32, 0x34, 0x30, 0x32, 0x30, 0x35, 0x31, 0x34, 0x33, 0x39, 0x33, 0x39, 0x5a, 0x17,
132 0x0d, 0x32, 0x34, 0x30, 0x32, 0x31, 0x34, 0x31, 0x34, 0x33, 0x39, 0x33, 0x39, 0x5a, 0x30, 0x39,
133 0x31, 0x29, 0x30, 0x27, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x20, 0x35, 0x39, 0x61, 0x65, 0x35,
134 0x30, 0x39, 0x38, 0x39, 0x35, 0x65, 0x31, 0x33, 0x34, 0x32, 0x35, 0x66, 0x31, 0x32, 0x31, 0x39,
135 0x33, 0x63, 0x30, 0x34, 0x63, 0x65, 0x35, 0x32, 0x34, 0x36, 0x36, 0x31, 0x0c, 0x30, 0x0a, 0x06,
136 0x03, 0x55, 0x04, 0x0a, 0x13, 0x03, 0x54, 0x45, 0x45, 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a,
137 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07,
138 0x03, 0x42, 0x00, 0x04, 0x30, 0x32, 0xcd, 0x95, 0x12, 0xb0, 0x71, 0x8b, 0xb7, 0x14, 0x44, 0x26,
139 0x58, 0xd5, 0x82, 0x8c, 0x25, 0x55, 0x2c, 0x6d, 0xef, 0x98, 0xe3, 0x4f, 0x88, 0xd0, 0x74, 0x82,
140 0x09, 0x3e, 0x8d, 0x6c, 0xf0, 0xf2, 0x18, 0xd5, 0x83, 0x0e, 0x0d, 0xf2, 0xce, 0xc5, 0x15, 0x38,
141 0xe5, 0x6a, 0xe6, 0x4d, 0x4d, 0x95, 0x15, 0xb7, 0x24, 0xe7, 0xcb, 0x4b, 0x63, 0x42, 0x21, 0xbc,
142 0x36, 0xc6, 0x0a, 0xd8, 0xa3, 0x76, 0x30, 0x74, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04,
143 0x16, 0x04, 0x14, 0x39, 0x81, 0x41, 0x0a, 0xb9, 0xf3, 0xf4, 0x5b, 0x75, 0x97, 0x4a, 0x46, 0xd6,
144 0x30, 0x9e, 0x1d, 0x7a, 0x3b, 0xec, 0xa8, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18,
145 0x30, 0x16, 0x80, 0x14, 0x82, 0xbd, 0x00, 0xde, 0xcb, 0xc5, 0xe7, 0x72, 0x87, 0x3d, 0x1c, 0x0a,
146 0x1e, 0x78, 0x4f, 0xf5, 0xd3, 0xc1, 0x3e, 0xb8, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01,
147 0x01, 0xff, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f,
148 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x02, 0x04, 0x30, 0x11, 0x06, 0x0a, 0x2b, 0x06, 0x01,
149 0x04, 0x01, 0xd6, 0x79, 0x02, 0x01, 0x1e, 0x04, 0x03, 0xa1, 0x01, 0x08, 0x30, 0x0a, 0x06, 0x08,
150 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x03, 0x48, 0x00, 0x30, 0x45, 0x02, 0x21, 0x00,
151 0xae, 0xd8, 0x40, 0x9e, 0x37, 0x3e, 0x5c, 0x9c, 0xe2, 0x93, 0x3d, 0x8c, 0xf7, 0x05, 0x10, 0xe7,
152 0xd1, 0x2b, 0x87, 0x8a, 0xee, 0xd6, 0x1e, 0x6c, 0x3b, 0xd2, 0x91, 0x3e, 0xa5, 0xdf, 0x91, 0x20,
153 0x02, 0x20, 0x7f, 0x0f, 0x29, 0x54, 0x60, 0x80, 0x07, 0x50, 0x5f, 0x56, 0x6b, 0x9f, 0xe0, 0x94,
154 0xb4, 0x3f, 0x3b, 0x0f, 0x61, 0xa0, 0x33, 0x40, 0xe6, 0x1a, 0x42, 0xda, 0x4b, 0xa4, 0xfd, 0x92,
155 0xb9, 0x0f,
156 ];
157
158 lazy_static! {
159 static ref FAKE_PROVISIONED_KEY_BLOB_FOR_TESTING: Mutex<Option<Vec<u8>>> = Mutex::new(None);
160 static ref VFIO_SERVICE: Strong<dyn IVfioHandler> =
161 wait_for_interface(<BpVfioHandler as IVfioHandler>::get_descriptor())
162 .expect("Could not connect to VfioHandler");
163 static ref NETWORK_SERVICE: Strong<dyn IVmnic> =
164 wait_for_interface(<BpVmnic as IVmnic>::get_descriptor())
165 .expect("Could not connect to Vmnic");
166 }
167
is_valid_guest_cid(cid: Cid) -> bool168 fn is_valid_guest_cid(cid: Cid) -> bool {
169 (GUEST_CID_MIN..=GUEST_CID_MAX).contains(&cid)
170 }
171
172 /// Singleton service for allocating globally-unique VM resources, such as the CID, and running
173 /// singleton servers, like tombstone receiver.
174 #[derive(Clone)]
175 pub struct VirtualizationServiceInternal {
176 state: Arc<Mutex<GlobalState>>,
177 display_service_set: Arc<Condvar>,
178 }
179
180 impl VirtualizationServiceInternal {
init() -> VirtualizationServiceInternal181 pub fn init() -> VirtualizationServiceInternal {
182 let service = VirtualizationServiceInternal {
183 state: Arc::new(Mutex::new(GlobalState::new())),
184 display_service_set: Arc::new(Condvar::new()),
185 };
186
187 std::thread::spawn(|| {
188 if let Err(e) = handle_stream_connection_tombstoned() {
189 warn!("Error receiving tombstone from guest or writing them. Error: {:?}", e);
190 }
191 });
192
193 service
194 }
195 }
196
197 impl Interface for VirtualizationServiceInternal {}
198
199 impl IVirtualizationServiceInternal for VirtualizationServiceInternal {
setDisplayService( &self, ibinder: &binder::SpIBinder, ) -> std::result::Result<(), binder::Status>200 fn setDisplayService(
201 &self,
202 ibinder: &binder::SpIBinder,
203 ) -> std::result::Result<(), binder::Status> {
204 check_manage_access()?;
205 check_use_custom_virtual_machine()?;
206 let state = &mut *self.state.lock().unwrap();
207 state.display_service = Some(ibinder.clone());
208 self.display_service_set.notify_all();
209 Ok(())
210 }
211
clearDisplayService(&self) -> std::result::Result<(), binder::Status>212 fn clearDisplayService(&self) -> std::result::Result<(), binder::Status> {
213 check_manage_access()?;
214 check_use_custom_virtual_machine()?;
215 let state = &mut *self.state.lock().unwrap();
216 state.display_service = None;
217 self.display_service_set.notify_all();
218 Ok(())
219 }
220
waitDisplayService(&self) -> std::result::Result<binder::SpIBinder, binder::Status>221 fn waitDisplayService(&self) -> std::result::Result<binder::SpIBinder, binder::Status> {
222 check_manage_access()?;
223 check_use_custom_virtual_machine()?;
224 let state = self
225 .display_service_set
226 .wait_while(self.state.lock().unwrap(), |state| state.display_service.is_none())
227 .unwrap();
228 Ok((state.display_service)
229 .as_ref()
230 .cloned()
231 .expect("Display service cannot be None in this context"))
232 }
removeMemlockRlimit(&self) -> binder::Result<()>233 fn removeMemlockRlimit(&self) -> binder::Result<()> {
234 let pid = get_calling_pid();
235 let lim = libc::rlimit { rlim_cur: libc::RLIM_INFINITY, rlim_max: libc::RLIM_INFINITY };
236
237 // SAFETY: borrowing the new limit struct only
238 let ret = unsafe { libc::prlimit(pid, libc::RLIMIT_MEMLOCK, &lim, std::ptr::null_mut()) };
239
240 match ret {
241 0 => Ok(()),
242 -1 => Err(std::io::Error::last_os_error().into()),
243 n => Err(anyhow!("Unexpected return value from prlimit(): {n}")),
244 }
245 .or_binder_exception(ExceptionCode::ILLEGAL_STATE)
246 }
247
allocateGlobalVmContext( &self, requester_debug_pid: i32, ) -> binder::Result<Strong<dyn IGlobalVmContext>>248 fn allocateGlobalVmContext(
249 &self,
250 requester_debug_pid: i32,
251 ) -> binder::Result<Strong<dyn IGlobalVmContext>> {
252 check_manage_access()?;
253
254 let requester_uid = get_calling_uid();
255 let requester_debug_pid = requester_debug_pid as pid_t;
256 let state = &mut *self.state.lock().unwrap();
257 state
258 .allocate_vm_context(requester_uid, requester_debug_pid)
259 .or_binder_exception(ExceptionCode::ILLEGAL_STATE)
260 }
261
atomVmBooted(&self, atom: &AtomVmBooted) -> Result<(), Status>262 fn atomVmBooted(&self, atom: &AtomVmBooted) -> Result<(), Status> {
263 forward_vm_booted_atom(atom);
264 Ok(())
265 }
266
atomVmCreationRequested(&self, atom: &AtomVmCreationRequested) -> Result<(), Status>267 fn atomVmCreationRequested(&self, atom: &AtomVmCreationRequested) -> Result<(), Status> {
268 forward_vm_creation_atom(atom);
269 Ok(())
270 }
271
atomVmExited(&self, atom: &AtomVmExited) -> Result<(), Status>272 fn atomVmExited(&self, atom: &AtomVmExited) -> Result<(), Status> {
273 forward_vm_exited_atom(atom);
274 Ok(())
275 }
276
debugListVms(&self) -> binder::Result<Vec<VirtualMachineDebugInfo>>277 fn debugListVms(&self) -> binder::Result<Vec<VirtualMachineDebugInfo>> {
278 check_debug_access()?;
279
280 let state = &mut *self.state.lock().unwrap();
281 let cids = state
282 .held_contexts
283 .iter()
284 .filter_map(|(_, inst)| Weak::upgrade(inst))
285 .map(|vm| VirtualMachineDebugInfo {
286 cid: vm.cid as i32,
287 temporaryDirectory: vm.get_temp_dir().to_string_lossy().to_string(),
288 requesterUid: vm.requester_uid as i32,
289 requesterPid: vm.requester_debug_pid,
290 })
291 .collect();
292 Ok(cids)
293 }
294
enableTestAttestation(&self) -> binder::Result<()>295 fn enableTestAttestation(&self) -> binder::Result<()> {
296 check_manage_access()?;
297 check_use_custom_virtual_machine()?;
298 if !cfg!(remote_attestation) {
299 return Err(Status::new_exception_str(
300 ExceptionCode::UNSUPPORTED_OPERATION,
301 Some(
302 "enableTestAttestation is not supported with the remote_attestation \
303 feature disabled",
304 ),
305 ))
306 .with_log();
307 }
308 let res = generate_ecdsa_p256_key_pair()
309 .context("Failed to generate ECDSA P-256 key pair for testing")
310 .with_log()
311 .or_service_specific_exception(-1)?;
312 // Wait until the service VM shuts down, so that the Service VM will be restarted when
313 // the key generated in the current session will be used for attestation.
314 // This ensures that different Service VM sessions have the same KEK for the key blob.
315 service_vm_manager::wait_until_service_vm_shuts_down()
316 .context("Failed to wait until the service VM shuts down")
317 .with_log()
318 .or_service_specific_exception(-1)?;
319 match res {
320 Response::GenerateEcdsaP256KeyPair(key_pair) => {
321 FAKE_PROVISIONED_KEY_BLOB_FOR_TESTING
322 .lock()
323 .unwrap()
324 .replace(key_pair.key_blob.to_vec());
325 Ok(())
326 }
327 _ => Err(remote_provisioning::to_service_specific_error(res)),
328 }
329 .with_log()
330 }
331
requestAttestation( &self, csr: &[u8], requester_uid: i32, test_mode: bool, ) -> binder::Result<Vec<Certificate>>332 fn requestAttestation(
333 &self,
334 csr: &[u8],
335 requester_uid: i32,
336 test_mode: bool,
337 ) -> binder::Result<Vec<Certificate>> {
338 check_manage_access()?;
339 if !cfg!(remote_attestation) {
340 return Err(Status::new_exception_str(
341 ExceptionCode::UNSUPPORTED_OPERATION,
342 Some(
343 "requestAttestation is not supported with the remote_attestation feature \
344 disabled",
345 ),
346 ))
347 .with_log();
348 }
349 if !is_remote_provisioning_hal_declared()? {
350 return Err(Status::new_exception_str(
351 ExceptionCode::UNSUPPORTED_OPERATION,
352 Some("AVF remotely provisioned component service is not declared"),
353 ))
354 .with_log();
355 }
356 remote_provisioning::check_remote_attestation_is_supported()?;
357 info!("Received csr. Requestting attestation...");
358 let (key_blob, certificate_chain) = if test_mode {
359 check_use_custom_virtual_machine()?;
360 info!("Using the fake key blob for testing...");
361 (
362 FAKE_PROVISIONED_KEY_BLOB_FOR_TESTING
363 .lock()
364 .unwrap()
365 .clone()
366 .ok_or_else(|| anyhow!("No key blob for testing"))
367 .with_log()
368 .or_service_specific_exception(-1)?,
369 FAKE_CERTIFICATE_FOR_TESTING.to_vec(),
370 )
371 } else {
372 info!("Retrieving the remotely provisioned keys from RKPD...");
373 let attestation_key = get_rkpd_attestation_key(
374 REMOTELY_PROVISIONED_COMPONENT_SERVICE_NAME,
375 requester_uid as u32,
376 )
377 .context("Failed to retrieve the remotely provisioned keys")
378 .with_log()
379 .or_service_specific_exception(-1)?;
380 (attestation_key.keyBlob, attestation_key.encodedCertChain)
381 };
382 let mut certificate_chain = split_x509_certificate_chain(&certificate_chain)
383 .context("Failed to split the remotely provisioned certificate chain")
384 .with_log()
385 .or_service_specific_exception(-1)?;
386 if certificate_chain.is_empty() {
387 return Err(Status::new_service_specific_error_str(
388 -1,
389 Some("The certificate chain should contain at least 1 certificate"),
390 ))
391 .with_log();
392 }
393 let certificate = request_attestation(
394 csr.to_vec(),
395 key_blob,
396 certificate_chain[0].encodedCertificate.clone(),
397 )
398 .context("Failed to request attestation")
399 .with_log()
400 .or_service_specific_exception(-1)?;
401 certificate_chain.insert(0, Certificate { encodedCertificate: certificate });
402
403 Ok(certificate_chain)
404 }
405
isRemoteAttestationSupported(&self) -> binder::Result<bool>406 fn isRemoteAttestationSupported(&self) -> binder::Result<bool> {
407 Ok(is_remote_provisioning_hal_declared()?
408 && remote_provisioning::is_remote_attestation_supported())
409 }
410
getAssignableDevices(&self) -> binder::Result<Vec<AssignableDevice>>411 fn getAssignableDevices(&self) -> binder::Result<Vec<AssignableDevice>> {
412 check_use_custom_virtual_machine()?;
413
414 Ok(get_assignable_devices()?
415 .device
416 .into_iter()
417 .map(|x| AssignableDevice { node: x.sysfs_path, dtbo_label: x.dtbo_label })
418 .collect::<Vec<_>>())
419 }
420
bindDevicesToVfioDriver( &self, devices: &[String], ) -> binder::Result<Vec<Strong<dyn IBoundDevice>>>421 fn bindDevicesToVfioDriver(
422 &self,
423 devices: &[String],
424 ) -> binder::Result<Vec<Strong<dyn IBoundDevice>>> {
425 check_use_custom_virtual_machine()?;
426
427 let devices = get_assignable_devices()?
428 .device
429 .into_iter()
430 .filter_map(|x| {
431 if devices.contains(&x.sysfs_path) {
432 Some(VfioDev { sysfsPath: x.sysfs_path, dtboLabel: x.dtbo_label })
433 } else {
434 warn!("device {} is not assignable", x.sysfs_path);
435 None
436 }
437 })
438 .collect::<Vec<VfioDev>>();
439
440 VFIO_SERVICE.bindDevicesToVfioDriver(devices.as_slice())
441 }
442
getDtboFile(&self) -> binder::Result<ParcelFileDescriptor>443 fn getDtboFile(&self) -> binder::Result<ParcelFileDescriptor> {
444 check_use_custom_virtual_machine()?;
445
446 let state = &mut *self.state.lock().unwrap();
447 let file = state.get_dtbo_file().or_service_specific_exception(-1)?;
448 Ok(ParcelFileDescriptor::new(file))
449 }
450
allocateInstanceId(&self) -> binder::Result<[u8; 64]>451 fn allocateInstanceId(&self) -> binder::Result<[u8; 64]> {
452 let mut id = [0u8; 64];
453 id.try_fill(&mut rand::thread_rng())
454 .context("Failed to allocate instance_id")
455 .or_service_specific_exception(-1)?;
456 let uid = get_calling_uid();
457 info!("Allocated a VM's instance_id: {:?}..., for uid: {:?}", &hex::encode(id)[..8], uid);
458 let state = &mut *self.state.lock().unwrap();
459 if let Some(sk_state) = &mut state.sk_state {
460 let user_id = multiuser_get_user_id(uid);
461 let app_id = multiuser_get_app_id(uid);
462 info!("Recording possible existence of state for (user_id={user_id}, app_id={app_id})");
463 if let Err(e) = sk_state.add_id(&id, user_id, app_id) {
464 error!("Failed to record the instance_id: {e:?}");
465 }
466 }
467
468 Ok(id)
469 }
470
removeVmInstance(&self, instance_id: &[u8; 64]) -> binder::Result<()>471 fn removeVmInstance(&self, instance_id: &[u8; 64]) -> binder::Result<()> {
472 let state = &mut *self.state.lock().unwrap();
473 if let Some(sk_state) = &mut state.sk_state {
474 let uid = get_calling_uid();
475 info!(
476 "Removing a VM's instance_id: {:?}, for uid: {:?}",
477 hex::encode(instance_id),
478 uid
479 );
480
481 let user_id = multiuser_get_user_id(uid);
482 let app_id = multiuser_get_app_id(uid);
483 sk_state.delete_id(instance_id, user_id, app_id);
484 } else {
485 info!("ignoring removeVmInstance() as no ISecretkeeper");
486 }
487 Ok(())
488 }
489
claimVmInstance(&self, instance_id: &[u8; 64]) -> binder::Result<()>490 fn claimVmInstance(&self, instance_id: &[u8; 64]) -> binder::Result<()> {
491 let state = &mut *self.state.lock().unwrap();
492 if let Some(sk_state) = &mut state.sk_state {
493 let uid = get_calling_uid();
494 info!(
495 "Claiming a VM's instance_id: {:?}, for uid: {:?}",
496 hex::encode(instance_id),
497 uid
498 );
499
500 let user_id = multiuser_get_user_id(uid);
501 let app_id = multiuser_get_app_id(uid);
502 info!("Recording possible new owner of state for (user_id={user_id}, app_id={app_id})");
503 if let Err(e) = sk_state.add_id(instance_id, user_id, app_id) {
504 error!("Failed to update the instance_id owner: {e:?}");
505 }
506 } else {
507 info!("ignoring claimVmInstance() as no ISecretkeeper");
508 }
509 Ok(())
510 }
511
createTapInterface(&self, iface_name_suffix: &str) -> binder::Result<ParcelFileDescriptor>512 fn createTapInterface(&self, iface_name_suffix: &str) -> binder::Result<ParcelFileDescriptor> {
513 check_internet_permission()?;
514 check_use_custom_virtual_machine()?;
515 if !cfg!(network) {
516 return Err(Status::new_exception_str(
517 ExceptionCode::UNSUPPORTED_OPERATION,
518 Some("createTapInterface is not supported with the network feature disabled"),
519 ))
520 .with_log();
521 }
522 NETWORK_SERVICE.createTapInterface(iface_name_suffix)
523 }
524
deleteTapInterface(&self, tap_fd: &ParcelFileDescriptor) -> binder::Result<()>525 fn deleteTapInterface(&self, tap_fd: &ParcelFileDescriptor) -> binder::Result<()> {
526 check_internet_permission()?;
527 check_use_custom_virtual_machine()?;
528 if !cfg!(network) {
529 return Err(Status::new_exception_str(
530 ExceptionCode::UNSUPPORTED_OPERATION,
531 Some("deleteTapInterface is not supported with the network feature disabled"),
532 ))
533 .with_log();
534 }
535 NETWORK_SERVICE.deleteTapInterface(tap_fd)
536 }
537 }
538
539 impl IVirtualizationMaintenance for VirtualizationServiceInternal {
appRemoved(&self, user_id: i32, app_id: i32) -> binder::Result<()>540 fn appRemoved(&self, user_id: i32, app_id: i32) -> binder::Result<()> {
541 let state = &mut *self.state.lock().unwrap();
542 if let Some(sk_state) = &mut state.sk_state {
543 info!("packageRemoved(user_id={user_id}, app_id={app_id})");
544 sk_state.delete_ids_for_app(user_id, app_id).or_service_specific_exception(-1)?;
545 } else {
546 info!("ignoring packageRemoved(user_id={user_id}, app_id={app_id})");
547 }
548 Ok(())
549 }
550
userRemoved(&self, user_id: i32) -> binder::Result<()>551 fn userRemoved(&self, user_id: i32) -> binder::Result<()> {
552 let state = &mut *self.state.lock().unwrap();
553 if let Some(sk_state) = &mut state.sk_state {
554 info!("userRemoved({user_id})");
555 sk_state.delete_ids_for_user(user_id).or_service_specific_exception(-1)?;
556 } else {
557 info!("ignoring userRemoved(user_id={user_id})");
558 }
559 Ok(())
560 }
561
performReconciliation( &self, callback: &Strong<dyn IVirtualizationReconciliationCallback>, ) -> binder::Result<()>562 fn performReconciliation(
563 &self,
564 callback: &Strong<dyn IVirtualizationReconciliationCallback>,
565 ) -> binder::Result<()> {
566 let state = &mut *self.state.lock().unwrap();
567 if let Some(sk_state) = &mut state.sk_state {
568 info!("performReconciliation()");
569 sk_state.reconcile(callback).or_service_specific_exception(-1)?;
570 } else {
571 info!("ignoring performReconciliation()");
572 }
573 Ok(())
574 }
575 }
576
577 #[derive(Debug, Deserialize)]
578 struct Device {
579 dtbo_label: String,
580 sysfs_path: String,
581 }
582
583 #[derive(Debug, Default, Deserialize)]
584 struct Devices {
585 device: Vec<Device>,
586 }
587
get_assignable_devices() -> binder::Result<Devices>588 fn get_assignable_devices() -> binder::Result<Devices> {
589 let xml_path = Path::new("/vendor/etc/avf/assignable_devices.xml");
590 if !xml_path.exists() {
591 return Ok(Devices { ..Default::default() });
592 }
593
594 let xml = fs::read(xml_path)
595 .context("Failed to read assignable_devices.xml")
596 .with_log()
597 .or_service_specific_exception(-1)?;
598
599 let xml = String::from_utf8(xml)
600 .context("assignable_devices.xml is not a valid UTF-8 file")
601 .with_log()
602 .or_service_specific_exception(-1)?;
603
604 let mut devices: Devices = serde_xml_rs::from_str(&xml)
605 .context("can't parse assignable_devices.xml")
606 .with_log()
607 .or_service_specific_exception(-1)?;
608
609 let mut device_set = HashSet::new();
610 devices.device.retain(move |device| {
611 if device_set.contains(&device.sysfs_path) {
612 warn!("duplicated assignable device {device:?}; ignoring...");
613 return false;
614 }
615
616 if !Path::new(&device.sysfs_path).exists() {
617 warn!("assignable device {device:?} doesn't exist; ignoring...");
618 return false;
619 }
620
621 device_set.insert(device.sysfs_path.clone());
622 true
623 });
624 Ok(devices)
625 }
626
split_x509_certificate_chain(mut cert_chain: &[u8]) -> Result<Vec<Certificate>>627 fn split_x509_certificate_chain(mut cert_chain: &[u8]) -> Result<Vec<Certificate>> {
628 let mut out = Vec::new();
629 while !cert_chain.is_empty() {
630 let cert = X509::from_der(cert_chain)?;
631 let end = cert.to_der()?.len();
632 out.push(Certificate { encodedCertificate: cert_chain[..end].to_vec() });
633 cert_chain = &cert_chain[end..];
634 }
635 Ok(out)
636 }
637
638 #[derive(Debug, Default)]
639 struct GlobalVmInstance {
640 /// The unique CID assigned to the VM for vsock communication.
641 cid: Cid,
642 /// UID of the client who requested this VM instance.
643 requester_uid: uid_t,
644 /// PID of the client who requested this VM instance.
645 requester_debug_pid: pid_t,
646 }
647
648 impl GlobalVmInstance {
get_temp_dir(&self) -> PathBuf649 fn get_temp_dir(&self) -> PathBuf {
650 let cid = self.cid;
651 format!("{TEMPORARY_DIRECTORY}/{cid}").into()
652 }
653 }
654
655 /// The mutable state of the VirtualizationServiceInternal. There should only be one instance
656 /// of this struct.
657 struct GlobalState {
658 /// VM contexts currently allocated to running VMs. A CID is never recycled as long
659 /// as there is a strong reference held by a GlobalVmContext.
660 held_contexts: HashMap<Cid, Weak<GlobalVmInstance>>,
661
662 /// Cached read-only FD of VM DTBO file. Also serves as a lock for creating the file.
663 dtbo_file: Mutex<Option<File>>,
664
665 /// State relating to secrets held by (optional) Secretkeeper instance on behalf of VMs.
666 sk_state: Option<maintenance::State>,
667
668 display_service: Option<binder::SpIBinder>,
669 }
670
671 impl GlobalState {
new() -> Self672 fn new() -> Self {
673 Self {
674 held_contexts: HashMap::new(),
675 dtbo_file: Mutex::new(None),
676 sk_state: maintenance::State::new(),
677 display_service: None,
678 }
679 }
680
681 /// Get the next available CID, or an error if we have run out. The last CID used is stored in
682 /// a system property so that restart of virtualizationservice doesn't reuse CID while the host
683 /// Android is up.
get_next_available_cid(&mut self) -> Result<Cid>684 fn get_next_available_cid(&mut self) -> Result<Cid> {
685 // Start trying to find a CID from the last used CID + 1. This ensures
686 // that we do not eagerly recycle CIDs. It makes debugging easier but
687 // also means that retrying to allocate a CID, eg. because it is
688 // erroneously occupied by a process, will not recycle the same CID.
689 let last_cid_prop =
690 system_properties::read(SYSPROP_LAST_CID)?.and_then(|val| match val.parse::<Cid>() {
691 Ok(num) => {
692 if is_valid_guest_cid(num) {
693 Some(num)
694 } else {
695 error!("Invalid value '{}' of property '{}'", num, SYSPROP_LAST_CID);
696 None
697 }
698 }
699 Err(_) => {
700 error!("Invalid value '{}' of property '{}'", val, SYSPROP_LAST_CID);
701 None
702 }
703 });
704
705 let first_cid = if let Some(last_cid) = last_cid_prop {
706 if last_cid == GUEST_CID_MAX {
707 GUEST_CID_MIN
708 } else {
709 last_cid + 1
710 }
711 } else {
712 GUEST_CID_MIN
713 };
714
715 let cid = self
716 .find_available_cid(first_cid..=GUEST_CID_MAX)
717 .or_else(|| self.find_available_cid(GUEST_CID_MIN..first_cid))
718 .ok_or_else(|| anyhow!("Could not find an available CID."))?;
719
720 system_properties::write(SYSPROP_LAST_CID, &format!("{}", cid))?;
721 Ok(cid)
722 }
723
find_available_cid<I>(&self, mut range: I) -> Option<Cid> where I: Iterator<Item = Cid>,724 fn find_available_cid<I>(&self, mut range: I) -> Option<Cid>
725 where
726 I: Iterator<Item = Cid>,
727 {
728 range.find(|cid| !self.held_contexts.contains_key(cid))
729 }
730
allocate_vm_context( &mut self, requester_uid: uid_t, requester_debug_pid: pid_t, ) -> Result<Strong<dyn IGlobalVmContext>>731 fn allocate_vm_context(
732 &mut self,
733 requester_uid: uid_t,
734 requester_debug_pid: pid_t,
735 ) -> Result<Strong<dyn IGlobalVmContext>> {
736 // Garbage collect unused VM contexts.
737 self.held_contexts.retain(|_, instance| instance.strong_count() > 0);
738
739 let cid = self.get_next_available_cid()?;
740 let instance = Arc::new(GlobalVmInstance { cid, requester_uid, requester_debug_pid });
741 create_temporary_directory(&instance.get_temp_dir(), Some(requester_uid))?;
742
743 self.held_contexts.insert(cid, Arc::downgrade(&instance));
744 let binder = GlobalVmContext { instance, ..Default::default() };
745 Ok(BnGlobalVmContext::new_binder(binder, BinderFeatures::default()))
746 }
747
get_dtbo_file(&mut self) -> Result<File>748 fn get_dtbo_file(&mut self) -> Result<File> {
749 let mut file = self.dtbo_file.lock().unwrap();
750
751 let fd = if let Some(ref_fd) = &*file {
752 ref_fd.try_clone()?
753 } else {
754 let path = get_or_create_common_dir()?.join("vm.dtbo");
755 if path.exists() {
756 // All temporary files are deleted when the service is started.
757 // If the file exists but the FD is not cached, the file is
758 // likely corrupted.
759 remove_file(&path).context("Failed to clone cached VM DTBO file descriptor")?;
760 }
761
762 // Open a write-only file descriptor for vfio_handler.
763 let write_fd = File::create(&path).context("Failed to create VM DTBO file")?;
764 VFIO_SERVICE.writeVmDtbo(&ParcelFileDescriptor::new(write_fd))?;
765
766 // Open read-only. This FD will be cached and returned to clients.
767 let read_fd = File::open(&path).context("Failed to open VM DTBO file")?;
768 let read_fd_clone =
769 read_fd.try_clone().context("Failed to clone VM DTBO file descriptor")?;
770 *file = Some(read_fd);
771 read_fd_clone
772 };
773
774 Ok(fd)
775 }
776 }
777
create_temporary_directory(path: &PathBuf, requester_uid: Option<uid_t>) -> Result<()>778 fn create_temporary_directory(path: &PathBuf, requester_uid: Option<uid_t>) -> Result<()> {
779 // Directory may exist if previous attempt to create it had failed.
780 // Delete it before trying again.
781 if path.as_path().exists() {
782 remove_temporary_dir(path).unwrap_or_else(|e| {
783 warn!("Could not delete temporary directory {:?}: {}", path, e);
784 });
785 }
786 // Create directory.
787 create_dir(path).with_context(|| format!("Could not create temporary directory {:?}", path))?;
788 // If provided, change ownership to client's UID but system's GID, and permissions 0700.
789 // If the chown() fails, this will leave behind an empty directory that will get removed
790 // at the next attempt, or if virtualizationservice is restarted.
791 if let Some(uid) = requester_uid {
792 chown(path, Some(Uid::from_raw(uid)), None).with_context(|| {
793 format!("Could not set ownership of temporary directory {:?}", path)
794 })?;
795 }
796 Ok(())
797 }
798
799 /// Removes a directory owned by a different user by first changing its owner back
800 /// to VirtualizationService.
remove_temporary_dir(path: &PathBuf) -> Result<()>801 pub fn remove_temporary_dir(path: &PathBuf) -> Result<()> {
802 ensure!(path.as_path().is_dir(), "Path {:?} is not a directory", path);
803 chown(path, Some(Uid::current()), None)?;
804 set_permissions(path, Permissions::from_mode(0o700))?;
805 remove_dir_all(path)?;
806 Ok(())
807 }
808
get_or_create_common_dir() -> Result<PathBuf>809 fn get_or_create_common_dir() -> Result<PathBuf> {
810 let path = Path::new(TEMPORARY_DIRECTORY).join("common");
811 if !path.exists() {
812 create_temporary_directory(&path, None)?;
813 }
814 Ok(path)
815 }
816
817 /// Implementation of the AIDL `IGlobalVmContext` interface.
818 #[derive(Debug, Default)]
819 struct GlobalVmContext {
820 /// Strong reference to the context's instance data structure.
821 instance: Arc<GlobalVmInstance>,
822 /// Keeps our service process running as long as this VM context exists.
823 #[allow(dead_code)]
824 lazy_service_guard: LazyServiceGuard,
825 }
826
827 impl Interface for GlobalVmContext {}
828
829 impl IGlobalVmContext for GlobalVmContext {
getCid(&self) -> binder::Result<i32>830 fn getCid(&self) -> binder::Result<i32> {
831 Ok(self.instance.cid as i32)
832 }
833
getTemporaryDirectory(&self) -> binder::Result<String>834 fn getTemporaryDirectory(&self) -> binder::Result<String> {
835 Ok(self.instance.get_temp_dir().to_string_lossy().to_string())
836 }
837 }
838
handle_stream_connection_tombstoned() -> Result<()>839 fn handle_stream_connection_tombstoned() -> Result<()> {
840 // Should not listen for tombstones on a guest VM's port.
841 assert!(!is_valid_guest_cid(VM_TOMBSTONES_SERVICE_PORT as Cid));
842 let listener =
843 VsockListener::bind_with_cid_port(VMADDR_CID_HOST, VM_TOMBSTONES_SERVICE_PORT as Cid)?;
844 for incoming_stream in listener.incoming() {
845 let mut incoming_stream = match incoming_stream {
846 Err(e) => {
847 warn!("invalid incoming connection: {:?}", e);
848 continue;
849 }
850 Ok(s) => s,
851 };
852 std::thread::spawn(move || {
853 if let Err(e) = handle_tombstone(&mut incoming_stream) {
854 error!("Failed to write tombstone- {:?}", e);
855 }
856 });
857 }
858 Ok(())
859 }
860
handle_tombstone(stream: &mut VsockStream) -> Result<()>861 fn handle_tombstone(stream: &mut VsockStream) -> Result<()> {
862 if let Ok(addr) = stream.peer_addr() {
863 info!("Vsock Stream connected to cid={} for tombstones", addr.cid());
864 }
865 let tb_connection =
866 TombstonedConnection::connect(std::process::id() as i32, DebuggerdDumpType::Tombstone)
867 .context("Failed to connect to tombstoned")?;
868 let mut text_output = tb_connection
869 .text_output
870 .as_ref()
871 .ok_or_else(|| anyhow!("Could not get file to write the tombstones on"))?;
872 let mut num_bytes_read = 0;
873 loop {
874 let mut chunk_recv = [0; CHUNK_RECV_MAX_LEN];
875 let n = stream
876 .read(&mut chunk_recv)
877 .context("Failed to read tombstone data from Vsock stream")?;
878 if n == 0 {
879 break;
880 }
881 num_bytes_read += n;
882 text_output.write_all(&chunk_recv[0..n]).context("Failed to write guests tombstones")?;
883 }
884 info!("Received {} bytes from guest & wrote to tombstone file", num_bytes_read);
885 tb_connection.notify_completion()?;
886 Ok(())
887 }
888
889 /// Returns true if the AVF remotely provisioned component service is declared in the
890 /// VINTF manifest.
is_remote_provisioning_hal_declared() -> binder::Result<bool>891 pub(crate) fn is_remote_provisioning_hal_declared() -> binder::Result<bool> {
892 Ok(binder::is_declared(REMOTELY_PROVISIONED_COMPONENT_SERVICE_NAME)?)
893 }
894
895 /// Checks whether the caller has a specific permission
check_permission(perm: &str) -> binder::Result<()>896 fn check_permission(perm: &str) -> binder::Result<()> {
897 let calling_pid = get_calling_pid();
898 let calling_uid = get_calling_uid();
899 // Root can do anything
900 if calling_uid == 0 {
901 return Ok(());
902 }
903 let perm_svc: Strong<dyn IPermissionController::IPermissionController> =
904 binder::wait_for_interface("permission")?;
905 if perm_svc.checkPermission(perm, calling_pid, calling_uid as i32)? {
906 Ok(())
907 } else {
908 Err(anyhow!("does not have the {} permission", perm))
909 .or_binder_exception(ExceptionCode::SECURITY)
910 }
911 }
912
913 /// Check whether the caller of the current Binder method is allowed to call debug methods.
check_debug_access() -> binder::Result<()>914 fn check_debug_access() -> binder::Result<()> {
915 check_permission("android.permission.DEBUG_VIRTUAL_MACHINE")
916 }
917
918 /// Check whether the caller of the current Binder method is allowed to manage VMs
check_manage_access() -> binder::Result<()>919 fn check_manage_access() -> binder::Result<()> {
920 check_permission("android.permission.MANAGE_VIRTUAL_MACHINE")
921 }
922
923 /// Check whether the caller of the current Binder method is allowed to use custom VMs
check_use_custom_virtual_machine() -> binder::Result<()>924 fn check_use_custom_virtual_machine() -> binder::Result<()> {
925 check_permission("android.permission.USE_CUSTOM_VIRTUAL_MACHINE")
926 }
927
928 /// Check whether the caller of the current Binder method is allowed to create socket and
929 /// establish connection between the VM and the Internet.
check_internet_permission() -> binder::Result<()>930 fn check_internet_permission() -> binder::Result<()> {
931 check_permission("android.permission.INTERNET")
932 }
933
934 #[cfg(test)]
935 mod tests {
936 use super::*;
937
938 const TEST_RKP_CERT_CHAIN_PATH: &str = "testdata/rkp_cert_chain.der";
939
940 #[test]
splitting_x509_certificate_chain_succeeds() -> Result<()>941 fn splitting_x509_certificate_chain_succeeds() -> Result<()> {
942 let bytes = fs::read(TEST_RKP_CERT_CHAIN_PATH)?;
943 let cert_chain = split_x509_certificate_chain(&bytes)?;
944
945 assert_eq!(4, cert_chain.len());
946 for cert in cert_chain {
947 let x509_cert = X509::from_der(&cert.encodedCertificate)?;
948 assert_eq!(x509_cert.to_der()?.len(), cert.encodedCertificate.len());
949 }
950 Ok(())
951 }
952 }
953