1 /*
2 * Copyright (C) 2024 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 //! # Interface library for communicating with the vmm obj service.
18
19 #![no_std]
20
21 use core::ffi::CStr;
22 use trusty_std::vec::Vec;
23 use trusty_sys::c_void;
24
25 #[allow(non_upper_case_globals)]
26 #[allow(non_camel_case_types)]
27 #[allow(unused)]
28 pub mod sys {
29 include!(env!("BINDGEN_INC_FILE"));
30 }
31
32 #[derive(Debug)]
33 pub enum GetVmmObjFailure {
34 NotFound,
35 BadSize,
36 BadStart,
37 }
38
39 /// A simple wrapper struct to call munmap on `Drop`.
40 struct Mapped<'a>(&'a [u8]);
41
42 impl<'a> Mapped<'_> {
43 /// # Safety
44 /// - `ptr` must be memory mmap-ed in this process and be readable for `sz` bytes while this struct is live.
45 /// - It must be sound to unmap this memory when this struct is dropped.
new(ptr: *const c_void, sz: usize) -> Self46 unsafe fn new(ptr: *const c_void, sz: usize) -> Self {
47 Self(unsafe { core::slice::from_raw_parts(ptr.cast(), sz) })
48 }
49 }
50
51 impl Drop for Mapped<'_> {
drop(&mut self)52 fn drop(&mut self) {
53 // SAFETY: This struct exists specifically to call munmap on mmap-ed memory. new is marked
54 // unsafe to discourage improper construction of this struct and details that ptr must be
55 // mapped in this process with the corresponding size.
56 let res = unsafe { libc::munmap(self.0.as_ptr() as *mut _, self.0.len()) };
57 if res != 0 {
58 log::error!("munmap failed!");
59 }
60 }
61 }
62
get_vmm_obj(name: &CStr) -> Result<Vec<u8>, GetVmmObjFailure>63 pub fn get_vmm_obj(name: &CStr) -> Result<Vec<u8>, GetVmmObjFailure> {
64 let mut ptr: *const c_void = std::ptr::null();
65 let mut sz: usize = 0;
66 // SAFETY:
67 // - `name.as_ptr()` points to as a valid, readable nul-terminated string as promised by CStr
68 // - ptr and sz have been initialized to valid values
69 // - references to name, ptr, and sz are not retained.
70 let rc = unsafe { crate::sys::vmm_obj_map_ro(name.as_ptr().cast(), &mut ptr, &mut sz) };
71 if rc < 0 || ptr.is_null() {
72 return Err(GetVmmObjFailure::NotFound);
73 }
74 // SAFETY: On success, vmm_obj_map_ro sets ptr to point to static immutable memory readable for
75 // sz bytes.
76 let buffer = unsafe { Mapped::new(ptr, sz) };
77 let start = u32::from_ne_bytes(
78 buffer
79 .0
80 .get(..4)
81 .ok_or(GetVmmObjFailure::BadStart)?
82 .try_into()
83 .map_err(|_| GetVmmObjFailure::BadStart)?,
84 ) as usize;
85 let sz = u32::from_ne_bytes(
86 buffer
87 .0
88 .get(4..8)
89 .ok_or(GetVmmObjFailure::BadSize)?
90 .try_into()
91 .map_err(|_| GetVmmObjFailure::BadSize)?,
92 ) as usize;
93 Ok(buffer.0.get(start..start + sz).ok_or(GetVmmObjFailure::BadSize)?.to_vec())
94 }
95