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