• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2025 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 //! Define the raw handle set which registers in and removes from the handle set a given type of a
18 //! handle. It waits on all the registered handles and returns the handle object along with the
19 //! event when an event takes place in any of the handles.
20 use crate::sys;
21 use crate::{Handle, Result, TipcError};
22 use alloc::sync::Arc;
23 use core::ffi::c_void;
24 use core::marker::PhantomData;
25 
26 /// Trait that should be implemented by a handle object that is passed into the `RawHandleSet`.
27 pub trait Handler {
28     // Get the raw file descriptor corresponding to the handle object.
get_raw_fd_id(&self) -> i3229     fn get_raw_fd_id(&self) -> i32;
30 }
31 
32 /// Raw handle set parameterized by the type of the handle stored in the event cookie.
33 pub struct RawHandleSet<H: Handler> {
34     // The handle that represents the handleset
35     handle: Handle,
36     data: PhantomData<H>,
37 }
38 
39 impl<H: Handler> RawHandleSet<H> {
40     /// Constructor
new() -> Result<Self>41     pub fn new() -> Result<Self> {
42         // SAFETY: syscall, return value is either a negative error code or a
43         // valid handle.
44         let rc = unsafe { trusty_sys::handle_set_create() };
45         if rc < 0 {
46             Err(TipcError::from_uapi(rc))
47         } else {
48             let handle = Handle::from_raw(rc as i32)?;
49             Ok(RawHandleSet::<H> { handle, data: PhantomData })
50         }
51     }
52 
53     /// Waits on the handles for events and returns the handle object that was registered in the
54     /// event cookie and the event flags.
wait(&self, timeout: Option<u32>) -> Result<(Arc<H>, u32)>55     pub fn wait(&self, timeout: Option<u32>) -> Result<(Arc<H>, u32)> {
56         let event = self.handle.wait(timeout)?;
57         let ptr = event.cookie;
58         let handle_obj =
59             // SAFETY: the `ptr` is the `Arc` that we registered in `register`. If we receive
60             // an event on a handle with this cookie, we return an `Arc` with a bumped ref count.
61             unsafe {
62                 Arc::increment_strong_count(ptr);
63                 Arc::from_raw(ptr.cast::<H>())
64             };
65         Ok((handle_obj, event.event))
66     }
67 
68     /// Register a handle object as the event cookie along with the corresponding Handle.
register(&self, event_cookie_obj: Arc<H>) -> Result<()>69     pub fn register(&self, event_cookie_obj: Arc<H>) -> Result<()> {
70         let ret = self.do_set_ctrl(
71             sys::HSET_ADD as u32,
72             trusty_sys::uevent::ALL_EVENTS,
73             &event_cookie_obj,
74         );
75         if ret.is_ok() {
76             std::mem::forget(event_cookie_obj);
77         }
78         ret
79     }
80 
81     /// Remove a previously registered handle object.
remove(&self, event_cookie_obj: Arc<H>) -> Result<()>82     pub fn remove(&self, event_cookie_obj: Arc<H>) -> Result<()> {
83         self.remove_raw(event_cookie_obj.get_raw_fd_id()).map(|_| ())
84     }
85 
86     /// Remove a previously registered handle object and return an arc to it.
remove_raw(&self, handle: i32) -> Result<Arc<H>>87     pub fn remove_raw(&self, handle: i32) -> Result<Arc<H>> {
88         let mut uevt = trusty_sys::uevent { handle, event: 0, cookie: std::ptr::null_mut() };
89         // SAFETY: syscall. The uevent pointer points to a correctly initialized
90         // structure that is valid across the call. The handle for the handle set is valid for
91         // the same lifetime as self, so will remain valid at least as long as the handle object
92         // being added/modified.
93         let rc = unsafe {
94             trusty_sys::handle_set_ctrl(
95                 self.handle.as_raw_fd(),
96                 sys::HSET_DEL_GET_COOKIE,
97                 &mut uevt,
98             )
99         };
100 
101         if rc < 0 {
102             Err(TipcError::from_uapi(rc))
103         } else {
104             // SAFETY: the `cookie` is the `Arc` that we registered in `register`. Here, we
105             // successfully deleted the handle from the handle set and are returning its cookie.
106             unsafe { Ok(Arc::from_raw(uevt.cookie.cast::<H>())) }
107         }
108     }
109 
110     // Add, update or remove the handle object (event cookie object) from the kernel handle set.
111     // This function should never be public.
112     // When this is called in the delete path, an arc to the deleted handle object is returned to
113     // caller, without dropping it, because the caller may need it for further processing.
do_set_ctrl(&self, cmd: u32, event: u32, event_cookie_obj: &Arc<H>) -> Result<()>114     fn do_set_ctrl(&self, cmd: u32, event: u32, event_cookie_obj: &Arc<H>) -> Result<()> {
115         let raw_handle_fd: i32 = event_cookie_obj.get_raw_fd_id();
116         let cookie = Arc::as_ptr(event_cookie_obj);
117         let mut uevt =
118             trusty_sys::uevent { handle: raw_handle_fd, event, cookie: cookie as *mut c_void };
119 
120         // SAFETY: syscall. The uevent pointer points to a correctly initialized
121         // structure that is valid across the call. The handle for the handle set is valid for
122         // the same lifetime as self, so will remain valid at least as long as the handle object
123         // being added/modified.
124         let rc = unsafe { trusty_sys::handle_set_ctrl(self.handle.as_raw_fd(), cmd, &mut uevt) };
125 
126         if rc < 0 {
127             Err(TipcError::from_uapi(rc))
128         } else {
129             Ok(())
130         }
131     }
132 }
133