• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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