optee_utee/object/object_handle.rs
1// Licensed to the Apache Software Foundation (ASF) under one
2// or more contributor license agreements. See the NOTICE file
3// distributed with this work for additional information
4// regarding copyright ownership. The ASF licenses this file
5// to you under the Apache License, Version 2.0 (the
6// "License"); you may not use this file except in compliance
7// with the License. You may obtain a copy of the License at
8//
9// http://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing,
12// software distributed under the License is distributed on an
13// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14// KIND, either express or implied. See the License for the
15// specific language governing permissions and limitations
16// under the License.
17
18use optee_utee_sys as raw;
19
20use super::GenericObject;
21
22/// An opaque handle on an object.
23#[derive(Debug)]
24pub struct ObjectHandle(raw::TEE_ObjectHandle);
25
26impl ObjectHandle {
27 pub fn from_raw(raw: raw::TEE_ObjectHandle) -> crate::Result<ObjectHandle> {
28 if raw.is_null() {
29 return Err(crate::ErrorKind::BadParameters.into());
30 }
31 Ok(Self(raw))
32 }
33
34 /// Forget the inner handle to prevent a double-free, this function would be
35 /// called when the inner handle is(or will be) freed externally.
36 ///
37 /// Example:
38 /// ``` rust,no_run
39 /// # use optee_utee::ObjectHandle;
40 /// # use optee_utee_sys as raw;
41 /// # let external_handle: raw::TEE_ObjectHandle = core::ptr::null_mut();
42 /// # fn main() -> optee_utee::Result<()> {
43 /// # let external_handle = core::ptr::null_mut();
44 /// // `external_handle` is a handle that is constructed and controlled
45 /// // externally.
46 /// // `handle` is valid, and will call TEE_CloseObject on
47 /// // `external_handle` when it is dropping, which is not allowed
48 /// // as the `external_handle` is externally controlled.
49 /// let mut handle = ObjectHandle::from_raw(external_handle)?;
50 /// // ... Some operation
51 /// // forget the inner handle, so it won't call TEE_CloseObject on
52 /// // `external_handle`
53 /// handle.forget();
54 /// # Ok(())
55 /// # }
56 /// ```
57 pub fn forget(mut self) {
58 self.0 = core::ptr::null_mut();
59 }
60}
61
62// functions for internal usage
63impl ObjectHandle {
64 pub(crate) fn new_null() -> Self {
65 Self(core::ptr::null_mut())
66 }
67
68 pub(crate) fn is_null(&self) -> bool {
69 self.0.is_null()
70 }
71}
72
73impl Drop for ObjectHandle {
74 fn drop(&mut self) {
75 if !self.is_null() {
76 unsafe { raw::TEE_CloseObject(self.0) }
77 }
78 }
79}
80
81impl GenericObject for ObjectHandle {
82 unsafe fn as_raw_ref(&self) -> &raw::TEE_ObjectHandle {
83 &self.0
84 }
85}
86
87#[cfg(test)]
88mod tests {
89 extern crate std;
90
91 use optee_utee_sys::{
92 mock_api,
93 mock_utils::{SERIAL_TEST_LOCK, object::MockHandle},
94 };
95
96 use super::*;
97
98 /// Ensures `ObjectHandle` can be safely constructed from a raw handle
99 /// and automatically calls `TEE_CloseObject` when dropped.
100 #[test]
101 fn test_from_raw() {
102 let _lock = SERIAL_TEST_LOCK.lock().expect("should get the lock");
103
104 let mut raw_handle = MockHandle::new();
105 let handle = raw_handle.as_handle();
106 let fn1 = mock_api::TEE_CloseObject_context();
107
108 fn1.expect().return_once_st(move |obj| {
109 debug_assert_eq!(obj, handle.clone());
110 });
111
112 let obj = ObjectHandle::from_raw(handle.clone()).expect("it should be ok");
113 assert_eq!(unsafe { *obj.as_raw_ref() }, handle);
114 }
115
116 /// Ensures `ObjectHandle` can call `forget` to prevent automatically
117 /// calls `TEE_CloseObject` when dropped.
118 #[test]
119 fn test_forget() {
120 let _lock = SERIAL_TEST_LOCK.lock().expect("should get the lock");
121
122 let mut raw_handle = MockHandle::new();
123 let handle = raw_handle.as_handle();
124
125 let obj = ObjectHandle::from_raw(handle.clone()).expect("it should be ok");
126 assert_eq!(unsafe { *obj.as_raw_ref() }, handle);
127
128 obj.forget();
129 }
130
131 #[test]
132 fn test_new_null() {
133 let obj = ObjectHandle::new_null();
134 assert!(obj.is_null());
135 }
136}