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_system_vmtethering::aidl::android::system::vmtethering;
29 use android_vs_internal::aidl::android::system::virtualizationservice_internal;
30 use anyhow::{anyhow, ensure, Context, Result};
31 use avflog::LogResult;
32 use binder::{
33 self, wait_for_interface, BinderFeatures, ExceptionCode, Interface, IntoBinderResult,
34 LazyServiceGuard, ParcelFileDescriptor, Status, Strong,
35 };
36 use libc::{VMADDR_CID_HOST, VMADDR_CID_HYPERVISOR, VMADDR_CID_LOCAL};
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, LazyLock, 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 vmtethering::IVmTethering::{BpVmTethering, IVmTethering};
77 use vsock::{VsockListener, VsockStream};
78
79 /// The unique ID of a VM used (together with a port number) for vsock communication.
80 pub type Cid = u32;
81
82 /// Directory in which to write disk image files used while running VMs.
83 pub 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.
87 const GUEST_CID_MIN: Cid = 2048;
88 const GUEST_CID_MAX: Cid = 65535;
89
90 const SYSPROP_LAST_CID: &str = "virtualizationservice.state.last_cid";
91
92 const CHUNK_RECV_MAX_LEN: usize = 1024;
93
94 /// 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 /// ```
124 const 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
159 static FAKE_PROVISIONED_KEY_BLOB_FOR_TESTING: Mutex<Option<Vec<u8>>> = Mutex::new(None);
160 static 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 });
164 static NETWORK_SERVICE: LazyLock<Strong<dyn IVmnic>> = LazyLock::new(|| {
165 wait_for_interface(<BpVmnic as IVmnic>::get_descriptor()).expect("Could not connect to Vmnic")
166 });
167 static 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 });
171
is_valid_guest_cid(cid: Cid) -> bool172 fn 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.
178 #[derive(Clone)]
179 pub struct VirtualizationServiceInternal {
180 state: Arc<Mutex<GlobalState>>,
181 display_service_set: Arc<Condvar>,
182 }
183
184 impl VirtualizationServiceInternal {
init() -> VirtualizationServiceInternal185 pub fn init() -> VirtualizationServiceInternal {
186 let service = VirtualizationServiceInternal {
187 state: Arc::new(Mutex::new(GlobalState::new())),
188 display_service_set: Arc::new(Condvar::new()),
189 };
190
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
197 service
198 }
199 }
200
201 impl Interface for VirtualizationServiceInternal {}
202
203 impl IVirtualizationServiceInternal for VirtualizationServiceInternal {
setDisplayService( &self, ibinder: &binder::SpIBinder, ) -> std::result::Result<(), binder::Status>204 fn setDisplayService(
205 &self,
206 ibinder: &binder::SpIBinder,
207 ) -> std::result::Result<(), binder::Status> {
208 check_manage_access()?;
209 check_use_custom_virtual_machine()?;
210 let state = &mut *self.state.lock().unwrap();
211 state.display_service = Some(ibinder.clone());
212 self.display_service_set.notify_all();
213 Ok(())
214 }
215
clearDisplayService(&self) -> std::result::Result<(), binder::Status>216 fn clearDisplayService(&self) -> std::result::Result<(), binder::Status> {
217 check_manage_access()?;
218 check_use_custom_virtual_machine()?;
219 let state = &mut *self.state.lock().unwrap();
220 state.display_service = None;
221 self.display_service_set.notify_all();
222 Ok(())
223 }
224
waitDisplayService(&self) -> std::result::Result<binder::SpIBinder, binder::Status>225 fn waitDisplayService(&self) -> std::result::Result<binder::SpIBinder, binder::Status> {
226 check_manage_access()?;
227 check_use_custom_virtual_machine()?;
228 let state = self
229 .display_service_set
230 .wait_while(self.state.lock().unwrap(), |state| state.display_service.is_none())
231 .unwrap();
232 Ok((state.display_service)
233 .as_ref()
234 .cloned()
235 .expect("Display service cannot be None in this context"))
236 }
removeMemlockRlimit(&self) -> binder::Result<()>237 fn removeMemlockRlimit(&self) -> binder::Result<()> {
238 let pid = get_calling_pid();
239 let lim = libc::rlimit { rlim_cur: libc::RLIM_INFINITY, rlim_max: libc::RLIM_INFINITY };
240
241 // SAFETY: borrowing the new limit struct only
242 let ret = unsafe { libc::prlimit(pid, libc::RLIMIT_MEMLOCK, &lim, std::ptr::null_mut()) };
243
244 match ret {
245 0 => Ok(()),
246 -1 => Err(std::io::Error::last_os_error().into()),
247 n => Err(anyhow!("Unexpected return value from prlimit(): {n}")),
248 }
249 .or_binder_exception(ExceptionCode::ILLEGAL_STATE)
250 }
251
allocateGlobalVmContext( &self, requester_debug_pid: i32, ) -> binder::Result<Strong<dyn IGlobalVmContext>>252 fn allocateGlobalVmContext(
253 &self,
254 requester_debug_pid: i32,
255 ) -> binder::Result<Strong<dyn IGlobalVmContext>> {
256 check_manage_access()?;
257
258 let requester_uid = get_calling_uid();
259 let requester_debug_pid = requester_debug_pid as pid_t;
260 let state = &mut *self.state.lock().unwrap();
261 state
262 .allocate_vm_context(requester_uid, requester_debug_pid)
263 .or_binder_exception(ExceptionCode::ILLEGAL_STATE)
264 }
265
atomVmBooted(&self, atom: &AtomVmBooted) -> Result<(), Status>266 fn atomVmBooted(&self, atom: &AtomVmBooted) -> Result<(), Status> {
267 forward_vm_booted_atom(atom);
268 Ok(())
269 }
270
atomVmCreationRequested(&self, atom: &AtomVmCreationRequested) -> Result<(), Status>271 fn atomVmCreationRequested(&self, atom: &AtomVmCreationRequested) -> Result<(), Status> {
272 forward_vm_creation_atom(atom);
273 Ok(())
274 }
275
atomVmExited(&self, atom: &AtomVmExited) -> Result<(), Status>276 fn atomVmExited(&self, atom: &AtomVmExited) -> Result<(), Status> {
277 forward_vm_exited_atom(atom);
278 Ok(())
279 }
280
debugListVms(&self) -> binder::Result<Vec<VirtualMachineDebugInfo>>281 fn debugListVms(&self) -> binder::Result<Vec<VirtualMachineDebugInfo>> {
282 check_debug_access()?;
283
284 let state = &mut *self.state.lock().unwrap();
285 let cids = state
286 .held_contexts
287 .iter()
288 .filter_map(|(_, inst)| Weak::upgrade(inst))
289 .map(|vm| {
290 let vm = vm.lock().unwrap();
291 VirtualMachineDebugInfo {
292 cid: vm.cid as i32,
293 temporaryDirectory: vm.get_temp_dir().to_string_lossy().to_string(),
294 requesterUid: vm.requester_uid as i32,
295 requesterPid: vm.requester_debug_pid,
296 hostConsoleName: vm.host_console_name.clone(),
297 }
298 })
299 .collect();
300 Ok(cids)
301 }
302
enableTestAttestation(&self) -> binder::Result<()>303 fn enableTestAttestation(&self) -> binder::Result<()> {
304 check_manage_access()?;
305 check_use_custom_virtual_machine()?;
306 if !cfg!(remote_attestation) {
307 return Err(Status::new_exception_str(
308 ExceptionCode::UNSUPPORTED_OPERATION,
309 Some(
310 "enableTestAttestation is not supported with the remote_attestation \
311 feature disabled",
312 ),
313 ))
314 .with_log();
315 }
316 let res = generate_ecdsa_p256_key_pair()
317 .context("Failed to generate ECDSA P-256 key pair for testing")
318 .with_log()
319 .or_service_specific_exception(-1)?;
320 // Wait until the service VM shuts down, so that the Service VM will be restarted when
321 // the key generated in the current session will be used for attestation.
322 // This ensures that different Service VM sessions have the same KEK for the key blob.
323 service_vm_manager::wait_until_service_vm_shuts_down()
324 .context("Failed to wait until the service VM shuts down")
325 .with_log()
326 .or_service_specific_exception(-1)?;
327 match res {
328 Response::GenerateEcdsaP256KeyPair(key_pair) => {
329 FAKE_PROVISIONED_KEY_BLOB_FOR_TESTING
330 .lock()
331 .unwrap()
332 .replace(key_pair.key_blob.to_vec());
333 Ok(())
334 }
335 _ => Err(remote_provisioning::to_service_specific_error(res)),
336 }
337 .with_log()
338 }
339
requestAttestation( &self, csr: &[u8], requester_uid: i32, test_mode: bool, ) -> binder::Result<Vec<Certificate>>340 fn requestAttestation(
341 &self,
342 csr: &[u8],
343 requester_uid: i32,
344 test_mode: bool,
345 ) -> binder::Result<Vec<Certificate>> {
346 check_manage_access()?;
347 if !cfg!(remote_attestation) {
348 return Err(Status::new_exception_str(
349 ExceptionCode::UNSUPPORTED_OPERATION,
350 Some(
351 "requestAttestation is not supported with the remote_attestation feature \
352 disabled",
353 ),
354 ))
355 .with_log();
356 }
357 if !is_remote_provisioning_hal_declared()? {
358 return Err(Status::new_exception_str(
359 ExceptionCode::UNSUPPORTED_OPERATION,
360 Some("AVF remotely provisioned component service is not declared"),
361 ))
362 .with_log();
363 }
364 remote_provisioning::check_remote_attestation_is_supported()?;
365 info!("Received csr. Requestting attestation...");
366 let (key_blob, certificate_chain) = if test_mode {
367 check_use_custom_virtual_machine()?;
368 info!("Using the fake key blob for testing...");
369 (
370 FAKE_PROVISIONED_KEY_BLOB_FOR_TESTING
371 .lock()
372 .unwrap()
373 .clone()
374 .ok_or_else(|| anyhow!("No key blob for testing"))
375 .with_log()
376 .or_service_specific_exception(-1)?,
377 FAKE_CERTIFICATE_FOR_TESTING.to_vec(),
378 )
379 } else {
380 info!("Retrieving the remotely provisioned keys from RKPD...");
381 let attestation_key = get_rkpd_attestation_key(
382 REMOTELY_PROVISIONED_COMPONENT_SERVICE_NAME,
383 requester_uid as u32,
384 )
385 .context("Failed to retrieve the remotely provisioned keys")
386 .with_log()
387 .or_service_specific_exception(-1)?;
388 (attestation_key.keyBlob, attestation_key.encodedCertChain)
389 };
390 let mut certificate_chain = split_x509_certificate_chain(&certificate_chain)
391 .context("Failed to split the remotely provisioned certificate chain")
392 .with_log()
393 .or_service_specific_exception(-1)?;
394 if certificate_chain.is_empty() {
395 return Err(Status::new_service_specific_error_str(
396 -1,
397 Some("The certificate chain should contain at least 1 certificate"),
398 ))
399 .with_log();
400 }
401 let certificate = request_attestation(
402 csr.to_vec(),
403 key_blob,
404 certificate_chain[0].encodedCertificate.clone(),
405 )
406 .context("Failed to request attestation")
407 .with_log()
408 .or_service_specific_exception(-1)?;
409 certificate_chain.insert(0, Certificate { encodedCertificate: certificate });
410
411 Ok(certificate_chain)
412 }
413
isRemoteAttestationSupported(&self) -> binder::Result<bool>414 fn isRemoteAttestationSupported(&self) -> binder::Result<bool> {
415 Ok(is_remote_provisioning_hal_declared()?
416 && remote_provisioning::is_remote_attestation_supported())
417 }
418
getAssignableDevices(&self) -> binder::Result<Vec<AssignableDevice>>419 fn getAssignableDevices(&self) -> binder::Result<Vec<AssignableDevice>> {
420 check_use_custom_virtual_machine()?;
421
422 Ok(get_assignable_devices()?
423 .device
424 .into_iter()
425 .map(|x| AssignableDevice { node: x.sysfs_path, dtbo_label: x.dtbo_label })
426 .collect::<Vec<_>>())
427 }
428
bindDevicesToVfioDriver( &self, devices: &[String], ) -> binder::Result<Vec<Strong<dyn IBoundDevice>>>429 fn bindDevicesToVfioDriver(
430 &self,
431 devices: &[String],
432 ) -> binder::Result<Vec<Strong<dyn IBoundDevice>>> {
433 check_use_custom_virtual_machine()?;
434
435 let devices = get_assignable_devices()?
436 .device
437 .into_iter()
438 .filter_map(|x| {
439 if devices.contains(&x.sysfs_path) {
440 Some(VfioDev { sysfsPath: x.sysfs_path, dtboLabel: x.dtbo_label })
441 } else {
442 warn!("device {} is not assignable", x.sysfs_path);
443 None
444 }
445 })
446 .collect::<Vec<VfioDev>>();
447
448 VFIO_SERVICE.bindDevicesToVfioDriver(devices.as_slice())
449 }
450
getDtboFile(&self) -> binder::Result<ParcelFileDescriptor>451 fn getDtboFile(&self) -> binder::Result<ParcelFileDescriptor> {
452 check_use_custom_virtual_machine()?;
453
454 let state = &mut *self.state.lock().unwrap();
455 let file = state.get_dtbo_file().or_service_specific_exception(-1)?;
456 Ok(ParcelFileDescriptor::new(file))
457 }
458
allocateInstanceId(&self) -> binder::Result<[u8; 64]>459 fn allocateInstanceId(&self) -> binder::Result<[u8; 64]> {
460 let mut id = [0u8; 64];
461 id.try_fill(&mut rand::thread_rng())
462 .context("Failed to allocate instance_id")
463 .or_service_specific_exception(-1)?;
464 let uid = get_calling_uid();
465 info!("Allocated a VM's instance_id: {:?}..., for uid: {:?}", &hex::encode(id)[..8], uid);
466 let state = &mut *self.state.lock().unwrap();
467 if let Some(sk_state) = &mut state.sk_state {
468 let user_id = multiuser_get_user_id(uid);
469 let app_id = multiuser_get_app_id(uid);
470 info!("Recording possible existence of state for (user_id={user_id}, app_id={app_id})");
471 if let Err(e) = sk_state.add_id(&id, user_id, app_id) {
472 error!("Failed to record the instance_id: {e:?}");
473 }
474 }
475
476 Ok(id)
477 }
478
removeVmInstance(&self, instance_id: &[u8; 64]) -> binder::Result<()>479 fn removeVmInstance(&self, instance_id: &[u8; 64]) -> binder::Result<()> {
480 let state = &mut *self.state.lock().unwrap();
481 if let Some(sk_state) = &mut state.sk_state {
482 let uid = get_calling_uid();
483 info!(
484 "Removing a VM's instance_id: {:?}, for uid: {:?}",
485 hex::encode(instance_id),
486 uid
487 );
488
489 let user_id = multiuser_get_user_id(uid);
490 let app_id = multiuser_get_app_id(uid);
491 sk_state.delete_id(instance_id, user_id, app_id);
492 } else {
493 info!("ignoring removeVmInstance() as no ISecretkeeper");
494 }
495 Ok(())
496 }
497
claimVmInstance(&self, instance_id: &[u8; 64]) -> binder::Result<()>498 fn claimVmInstance(&self, instance_id: &[u8; 64]) -> binder::Result<()> {
499 let state = &mut *self.state.lock().unwrap();
500 if let Some(sk_state) = &mut state.sk_state {
501 let uid = get_calling_uid();
502 info!(
503 "Claiming a VM's instance_id: {:?}, for uid: {:?}",
504 hex::encode(instance_id),
505 uid
506 );
507
508 let user_id = multiuser_get_user_id(uid);
509 let app_id = multiuser_get_app_id(uid);
510 info!("Recording possible new owner of state for (user_id={user_id}, app_id={app_id})");
511 if let Err(e) = sk_state.add_id(instance_id, user_id, app_id) {
512 error!("Failed to update the instance_id owner: {e:?}");
513 }
514 } else {
515 info!("ignoring claimVmInstance() as no ISecretkeeper");
516 }
517 Ok(())
518 }
519
createTapInterface(&self, _iface_name_suffix: &str) -> binder::Result<ParcelFileDescriptor>520 fn createTapInterface(&self, _iface_name_suffix: &str) -> binder::Result<ParcelFileDescriptor> {
521 check_internet_permission()?;
522 check_use_custom_virtual_machine()?;
523 if !cfg!(network) {
524 return Err(Status::new_exception_str(
525 ExceptionCode::UNSUPPORTED_OPERATION,
526 Some("createTapInterface is not supported with the network feature disabled"),
527 ))
528 .with_log();
529 }
530 // TODO(340377643): Use iface_name_suffix after introducing bridge interface, not fixed
531 // value.
532 let tap_fd = NETWORK_SERVICE.createTapInterface("fixed")?;
533
534 // TODO(340377643): Due to lack of implementation of creating bridge interface, tethering is
535 // enabled for TAP interface instead of bridge interface. After introducing creation of
536 // bridge interface in AVF, we should modify it.
537 TETHERING_SERVICE.enableVmTethering()?;
538
539 Ok(tap_fd)
540 }
541
deleteTapInterface(&self, tap_fd: &ParcelFileDescriptor) -> binder::Result<()>542 fn deleteTapInterface(&self, tap_fd: &ParcelFileDescriptor) -> binder::Result<()> {
543 check_internet_permission()?;
544 check_use_custom_virtual_machine()?;
545 if !cfg!(network) {
546 return Err(Status::new_exception_str(
547 ExceptionCode::UNSUPPORTED_OPERATION,
548 Some("deleteTapInterface is not supported with the network feature disabled"),
549 ))
550 .with_log();
551 }
552
553 // TODO(340377643): Disabling tethering should be for bridge interface, not TAP interface.
554 TETHERING_SERVICE.disableVmTethering()?;
555
556 NETWORK_SERVICE.deleteTapInterface(tap_fd)
557 }
558 }
559
560 impl IVirtualizationMaintenance for VirtualizationServiceInternal {
appRemoved(&self, user_id: i32, app_id: i32) -> binder::Result<()>561 fn appRemoved(&self, user_id: i32, app_id: i32) -> binder::Result<()> {
562 let state = &mut *self.state.lock().unwrap();
563 if let Some(sk_state) = &mut state.sk_state {
564 info!("packageRemoved(user_id={user_id}, app_id={app_id})");
565 sk_state.delete_ids_for_app(user_id, app_id).or_service_specific_exception(-1)?;
566 } else {
567 info!("ignoring packageRemoved(user_id={user_id}, app_id={app_id})");
568 }
569 Ok(())
570 }
571
userRemoved(&self, user_id: i32) -> binder::Result<()>572 fn userRemoved(&self, user_id: i32) -> binder::Result<()> {
573 let state = &mut *self.state.lock().unwrap();
574 if let Some(sk_state) = &mut state.sk_state {
575 info!("userRemoved({user_id})");
576 sk_state.delete_ids_for_user(user_id).or_service_specific_exception(-1)?;
577 } else {
578 info!("ignoring userRemoved(user_id={user_id})");
579 }
580 Ok(())
581 }
582
performReconciliation( &self, callback: &Strong<dyn IVirtualizationReconciliationCallback>, ) -> binder::Result<()>583 fn performReconciliation(
584 &self,
585 callback: &Strong<dyn IVirtualizationReconciliationCallback>,
586 ) -> binder::Result<()> {
587 let state = &mut *self.state.lock().unwrap();
588 if let Some(sk_state) = &mut state.sk_state {
589 info!("performReconciliation()");
590 sk_state.reconcile(callback).or_service_specific_exception(-1)?;
591 } else {
592 info!("ignoring performReconciliation()");
593 }
594 Ok(())
595 }
596 }
597
598 #[derive(Debug, Deserialize)]
599 struct Device {
600 dtbo_label: String,
601 sysfs_path: String,
602 }
603
604 #[derive(Debug, Default, Deserialize)]
605 struct Devices {
606 device: Vec<Device>,
607 }
608
get_assignable_devices() -> binder::Result<Devices>609 fn get_assignable_devices() -> binder::Result<Devices> {
610 let xml_path = Path::new("/vendor/etc/avf/assignable_devices.xml");
611 if !xml_path.exists() {
612 return Ok(Devices { ..Default::default() });
613 }
614
615 let xml = fs::read(xml_path)
616 .context("Failed to read assignable_devices.xml")
617 .with_log()
618 .or_service_specific_exception(-1)?;
619
620 let xml = String::from_utf8(xml)
621 .context("assignable_devices.xml is not a valid UTF-8 file")
622 .with_log()
623 .or_service_specific_exception(-1)?;
624
625 let mut devices: Devices = serde_xml_rs::from_str(&xml)
626 .context("can't parse assignable_devices.xml")
627 .with_log()
628 .or_service_specific_exception(-1)?;
629
630 let mut device_set = HashSet::new();
631 devices.device.retain(move |device| {
632 if device_set.contains(&device.sysfs_path) {
633 warn!("duplicated assignable device {device:?}; ignoring...");
634 return false;
635 }
636
637 if !Path::new(&device.sysfs_path).exists() {
638 warn!("assignable device {device:?} doesn't exist; ignoring...");
639 return false;
640 }
641
642 device_set.insert(device.sysfs_path.clone());
643 true
644 });
645 Ok(devices)
646 }
647
split_x509_certificate_chain(mut cert_chain: &[u8]) -> Result<Vec<Certificate>>648 fn split_x509_certificate_chain(mut cert_chain: &[u8]) -> Result<Vec<Certificate>> {
649 let mut out = Vec::new();
650 while !cert_chain.is_empty() {
651 let cert = X509::from_der(cert_chain)?;
652 let end = cert.to_der()?.len();
653 out.push(Certificate { encodedCertificate: cert_chain[..end].to_vec() });
654 cert_chain = &cert_chain[end..];
655 }
656 Ok(out)
657 }
658
659 #[derive(Debug, Default)]
660 struct GlobalVmInstance {
661 /// The unique CID assigned to the VM for vsock communication.
662 cid: Cid,
663 /// UID of the client who requested this VM instance.
664 requester_uid: uid_t,
665 /// PID of the client who requested this VM instance.
666 requester_debug_pid: pid_t,
667 /// Name of the host console.
668 host_console_name: Option<String>,
669 }
670
671 impl GlobalVmInstance {
get_temp_dir(&self) -> PathBuf672 fn get_temp_dir(&self) -> PathBuf {
673 let cid = self.cid;
674 format!("{TEMPORARY_DIRECTORY}/{cid}").into()
675 }
676 }
677
678 /// The mutable state of the VirtualizationServiceInternal. There should only be one instance
679 /// of this struct.
680 struct GlobalState {
681 /// VM contexts currently allocated to running VMs. A CID is never recycled as long
682 /// as there is a strong reference held by a GlobalVmContext.
683 held_contexts: HashMap<Cid, Weak<Mutex<GlobalVmInstance>>>,
684
685 /// Cached read-only FD of VM DTBO file. Also serves as a lock for creating the file.
686 dtbo_file: Mutex<Option<File>>,
687
688 /// State relating to secrets held by (optional) Secretkeeper instance on behalf of VMs.
689 sk_state: Option<maintenance::State>,
690
691 display_service: Option<binder::SpIBinder>,
692 }
693
694 impl GlobalState {
new() -> Self695 fn new() -> Self {
696 Self {
697 held_contexts: HashMap::new(),
698 dtbo_file: Mutex::new(None),
699 sk_state: maintenance::State::new(),
700 display_service: None,
701 }
702 }
703
704 /// Get the next available CID, or an error if we have run out. The last CID used is stored in
705 /// a system property so that restart of virtualizationservice doesn't reuse CID while the host
706 /// Android is up.
get_next_available_cid(&mut self) -> Result<Cid>707 fn get_next_available_cid(&mut self) -> Result<Cid> {
708 // Start trying to find a CID from the last used CID + 1. This ensures
709 // that we do not eagerly recycle CIDs. It makes debugging easier but
710 // also means that retrying to allocate a CID, eg. because it is
711 // erroneously occupied by a process, will not recycle the same CID.
712 let last_cid_prop =
713 system_properties::read(SYSPROP_LAST_CID)?.and_then(|val| match val.parse::<Cid>() {
714 Ok(num) => {
715 if is_valid_guest_cid(num) {
716 Some(num)
717 } else {
718 error!("Invalid value '{}' of property '{}'", num, SYSPROP_LAST_CID);
719 None
720 }
721 }
722 Err(_) => {
723 error!("Invalid value '{}' of property '{}'", val, SYSPROP_LAST_CID);
724 None
725 }
726 });
727
728 let first_cid = if let Some(last_cid) = last_cid_prop {
729 if last_cid == GUEST_CID_MAX {
730 GUEST_CID_MIN
731 } else {
732 last_cid + 1
733 }
734 } else {
735 GUEST_CID_MIN
736 };
737
738 let cid = self
739 .find_available_cid(first_cid..=GUEST_CID_MAX)
740 .or_else(|| self.find_available_cid(GUEST_CID_MIN..first_cid))
741 .ok_or_else(|| anyhow!("Could not find an available CID."))?;
742
743 system_properties::write(SYSPROP_LAST_CID, &format!("{}", cid))?;
744 Ok(cid)
745 }
746
find_available_cid<I>(&self, mut range: I) -> Option<Cid> where I: Iterator<Item = Cid>,747 fn find_available_cid<I>(&self, mut range: I) -> Option<Cid>
748 where
749 I: Iterator<Item = Cid>,
750 {
751 range.find(|cid| !self.held_contexts.contains_key(cid))
752 }
753
allocate_vm_context( &mut self, requester_uid: uid_t, requester_debug_pid: pid_t, ) -> Result<Strong<dyn IGlobalVmContext>>754 fn allocate_vm_context(
755 &mut self,
756 requester_uid: uid_t,
757 requester_debug_pid: pid_t,
758 ) -> Result<Strong<dyn IGlobalVmContext>> {
759 // Garbage collect unused VM contexts.
760 self.held_contexts.retain(|_, instance| instance.strong_count() > 0);
761
762 let cid = self.get_next_available_cid()?;
763 let instance = Arc::new(Mutex::new(GlobalVmInstance {
764 cid,
765 requester_uid,
766 requester_debug_pid,
767 ..Default::default()
768 }));
769 create_temporary_directory(&instance.lock().unwrap().get_temp_dir(), Some(requester_uid))?;
770
771 self.held_contexts.insert(cid, Arc::downgrade(&instance));
772 let binder = GlobalVmContext { instance, ..Default::default() };
773 Ok(BnGlobalVmContext::new_binder(binder, BinderFeatures::default()))
774 }
775
get_dtbo_file(&mut self) -> Result<File>776 fn get_dtbo_file(&mut self) -> Result<File> {
777 let mut file = self.dtbo_file.lock().unwrap();
778
779 let fd = if let Some(ref_fd) = &*file {
780 ref_fd.try_clone()?
781 } else {
782 let path = get_or_create_common_dir()?.join("vm.dtbo");
783 if path.exists() {
784 // All temporary files are deleted when the service is started.
785 // If the file exists but the FD is not cached, the file is
786 // likely corrupted.
787 remove_file(&path).context("Failed to clone cached VM DTBO file descriptor")?;
788 }
789
790 // Open a write-only file descriptor for vfio_handler.
791 let write_fd = File::create(&path).context("Failed to create VM DTBO file")?;
792 VFIO_SERVICE.writeVmDtbo(&ParcelFileDescriptor::new(write_fd))?;
793
794 // Open read-only. This FD will be cached and returned to clients.
795 let read_fd = File::open(&path).context("Failed to open VM DTBO file")?;
796 let read_fd_clone =
797 read_fd.try_clone().context("Failed to clone VM DTBO file descriptor")?;
798 *file = Some(read_fd);
799 read_fd_clone
800 };
801
802 Ok(fd)
803 }
804 }
805
create_temporary_directory(path: &PathBuf, requester_uid: Option<uid_t>) -> Result<()>806 fn create_temporary_directory(path: &PathBuf, requester_uid: Option<uid_t>) -> Result<()> {
807 // Directory may exist if previous attempt to create it had failed.
808 // Delete it before trying again.
809 if path.as_path().exists() {
810 remove_temporary_dir(path).unwrap_or_else(|e| {
811 warn!("Could not delete temporary directory {:?}: {}", path, e);
812 });
813 }
814 // Create directory.
815 create_dir(path).with_context(|| format!("Could not create temporary directory {:?}", path))?;
816 // If provided, change ownership to client's UID but system's GID, and permissions 0700.
817 // If the chown() fails, this will leave behind an empty directory that will get removed
818 // at the next attempt, or if virtualizationservice is restarted.
819 if let Some(uid) = requester_uid {
820 chown(path, Some(Uid::from_raw(uid)), None).with_context(|| {
821 format!("Could not set ownership of temporary directory {:?}", path)
822 })?;
823 }
824 Ok(())
825 }
826
827 /// Removes a directory owned by a different user by first changing its owner back
828 /// to VirtualizationService.
remove_temporary_dir(path: &PathBuf) -> Result<()>829 pub fn remove_temporary_dir(path: &PathBuf) -> Result<()> {
830 ensure!(path.as_path().is_dir(), "Path {:?} is not a directory", path);
831 chown(path, Some(Uid::current()), None)?;
832 set_permissions(path, Permissions::from_mode(0o700))?;
833 remove_dir_all(path)?;
834 Ok(())
835 }
836
get_or_create_common_dir() -> Result<PathBuf>837 fn get_or_create_common_dir() -> Result<PathBuf> {
838 let path = Path::new(TEMPORARY_DIRECTORY).join("common");
839 if !path.exists() {
840 create_temporary_directory(&path, None)?;
841 }
842 Ok(path)
843 }
844
845 /// Implementation of the AIDL `IGlobalVmContext` interface.
846 #[derive(Debug, Default)]
847 struct GlobalVmContext {
848 /// Strong reference to the context's instance data structure.
849 instance: Arc<Mutex<GlobalVmInstance>>,
850 /// Keeps our service process running as long as this VM context exists.
851 #[allow(dead_code)]
852 lazy_service_guard: LazyServiceGuard,
853 }
854
855 impl Interface for GlobalVmContext {}
856
857 impl IGlobalVmContext for GlobalVmContext {
getCid(&self) -> binder::Result<i32>858 fn getCid(&self) -> binder::Result<i32> {
859 Ok(self.instance.lock().unwrap().cid as i32)
860 }
861
getTemporaryDirectory(&self) -> binder::Result<String>862 fn getTemporaryDirectory(&self) -> binder::Result<String> {
863 Ok(self.instance.lock().unwrap().get_temp_dir().to_string_lossy().to_string())
864 }
865
setHostConsoleName(&self, pathname: &str) -> binder::Result<()>866 fn setHostConsoleName(&self, pathname: &str) -> binder::Result<()> {
867 self.instance.lock().unwrap().host_console_name = Some(pathname.to_string());
868 Ok(())
869 }
870 }
871
handle_stream_connection_tombstoned() -> Result<()>872 fn handle_stream_connection_tombstoned() -> Result<()> {
873 // Should not listen for tombstones on a guest VM's port.
874 assert!(!is_valid_guest_cid(VM_TOMBSTONES_SERVICE_PORT as Cid));
875 let listener =
876 VsockListener::bind_with_cid_port(VMADDR_CID_HOST, VM_TOMBSTONES_SERVICE_PORT as Cid)?;
877 for incoming_stream in listener.incoming() {
878 let mut incoming_stream = match incoming_stream {
879 Err(e) => {
880 warn!("invalid incoming connection: {e:?}");
881 continue;
882 }
883 Ok(s) => s,
884 };
885 if let Ok(addr) = incoming_stream.peer_addr() {
886 let cid = addr.cid();
887 match cid {
888 VMADDR_CID_LOCAL | VMADDR_CID_HOST | VMADDR_CID_HYPERVISOR => {
889 warn!("Rejecting non-guest tombstone vsock connection from cid={cid}");
890 continue;
891 }
892 _ => info!("Vsock Stream connected to cid={cid} for tombstones"),
893 }
894 }
895 std::thread::spawn(move || {
896 if let Err(e) = handle_tombstone(&mut incoming_stream) {
897 error!("Failed to write tombstone- {:?}", e);
898 }
899 });
900 }
901 Ok(())
902 }
903
handle_tombstone(stream: &mut VsockStream) -> Result<()>904 fn handle_tombstone(stream: &mut VsockStream) -> Result<()> {
905 let tb_connection =
906 TombstonedConnection::connect(std::process::id() as i32, DebuggerdDumpType::Tombstone)
907 .context("Failed to connect to tombstoned")?;
908 let mut text_output = tb_connection
909 .text_output
910 .as_ref()
911 .ok_or_else(|| anyhow!("Could not get file to write the tombstones on"))?;
912 let mut num_bytes_read = 0;
913 loop {
914 let mut chunk_recv = [0; CHUNK_RECV_MAX_LEN];
915 let n = stream
916 .read(&mut chunk_recv)
917 .context("Failed to read tombstone data from Vsock stream")?;
918 if n == 0 {
919 break;
920 }
921 num_bytes_read += n;
922 text_output.write_all(&chunk_recv[0..n]).context("Failed to write guests tombstones")?;
923 }
924 info!("Received {} bytes from guest & wrote to tombstone file", num_bytes_read);
925 tb_connection.notify_completion()?;
926 Ok(())
927 }
928
929 /// Returns true if the AVF remotely provisioned component service is declared in the
930 /// VINTF manifest.
is_remote_provisioning_hal_declared() -> binder::Result<bool>931 pub(crate) fn is_remote_provisioning_hal_declared() -> binder::Result<bool> {
932 Ok(binder::is_declared(REMOTELY_PROVISIONED_COMPONENT_SERVICE_NAME)?)
933 }
934
935 /// Checks whether the caller has a specific permission
check_permission(perm: &str) -> binder::Result<()>936 fn check_permission(perm: &str) -> binder::Result<()> {
937 let calling_pid = get_calling_pid();
938 let calling_uid = get_calling_uid();
939 // Root can do anything
940 if calling_uid == 0 {
941 return Ok(());
942 }
943 let perm_svc: Strong<dyn IPermissionController::IPermissionController> =
944 binder::wait_for_interface("permission")?;
945 if perm_svc.checkPermission(perm, calling_pid, calling_uid as i32)? {
946 Ok(())
947 } else {
948 Err(anyhow!("does not have the {} permission", perm))
949 .or_binder_exception(ExceptionCode::SECURITY)
950 }
951 }
952
953 /// Check whether the caller of the current Binder method is allowed to call debug methods.
check_debug_access() -> binder::Result<()>954 fn check_debug_access() -> binder::Result<()> {
955 check_permission("android.permission.DEBUG_VIRTUAL_MACHINE")
956 }
957
958 /// Check whether the caller of the current Binder method is allowed to manage VMs
check_manage_access() -> binder::Result<()>959 fn check_manage_access() -> binder::Result<()> {
960 check_permission("android.permission.MANAGE_VIRTUAL_MACHINE")
961 }
962
963 /// Check whether the caller of the current Binder method is allowed to use custom VMs
check_use_custom_virtual_machine() -> binder::Result<()>964 fn check_use_custom_virtual_machine() -> binder::Result<()> {
965 check_permission("android.permission.USE_CUSTOM_VIRTUAL_MACHINE")
966 }
967
968 /// Check whether the caller of the current Binder method is allowed to create socket and
969 /// establish connection between the VM and the Internet.
check_internet_permission() -> binder::Result<()>970 fn check_internet_permission() -> binder::Result<()> {
971 check_permission("android.permission.INTERNET")
972 }
973
974 #[cfg(test)]
975 mod tests {
976 use super::*;
977
978 const TEST_RKP_CERT_CHAIN_PATH: &str = "testdata/rkp_cert_chain.der";
979
980 #[test]
splitting_x509_certificate_chain_succeeds() -> Result<()>981 fn splitting_x509_certificate_chain_succeeds() -> Result<()> {
982 let bytes = fs::read(TEST_RKP_CERT_CHAIN_PATH)?;
983 let cert_chain = split_x509_certificate_chain(&bytes)?;
984
985 assert_eq!(4, cert_chain.len());
986 for cert in cert_chain {
987 let x509_cert = X509::from_der(&cert.encodedCertificate)?;
988 assert_eq!(x509_cert.to_der()?.len(), cert.encodedCertificate.len());
989 }
990 Ok(())
991 }
992 }
993