1 /* 2 * Copyright (C) 2022 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16 pub mod parcelable; 17 pub mod types; 18 19 pub use types::on_string16_writer; 20 pub use types::vec_u16_to_string; 21 pub use types::vec_to_string; 22 pub use parcelable::allocate_vec_with_buffer; 23 24 use crate::{ipc_binding, IpcResult, IpcStatusCode}; 25 use crate::ipc_binding::CParcel; 26 use std::marker::PhantomData; 27 use std::mem::{ManuallyDrop, MaybeUninit}; 28 use std::ops::Drop; 29 use std::ptr::NonNull; 30 use std::slice; 31 use crate::AsRawPtr; 32 use crate::parcel::parcelable::{Serialize, Deserialize}; 33 34 /// This trait implements the common function for MsgParcel 35 /// and BorrowedMsgParcel 36 pub trait IMsgParcel: AsRawPtr<CParcel> { 37 /// Get current data size in parcel get_data_size(&self) -> u3238 fn get_data_size(&self) -> u32 { 39 // SAFETY: 40 // The self reference must be valid and point to a properly allocated CParcel object 41 unsafe { 42 ipc_binding::CParcelGetDataSize(self.as_raw()) 43 } 44 } 45 46 /// Set current data size in parcel set_data_size(&mut self, new_size: u32) -> bool47 fn set_data_size(&mut self, new_size: u32) -> bool { 48 // SAFETY: 49 // The self reference must be valid and point to a properly allocated CParcel object. 50 // Calling this function with an invalid self reference can lead to undefined behavior, 51 // including memory access violations and data corruption. 52 unsafe { 53 ipc_binding::CParcelSetDataSize(self.as_mut_raw(), new_size) 54 } 55 } 56 57 /// Get current data capacity in parcel get_data_capacity(&self) -> u3258 fn get_data_capacity(&self) -> u32 { 59 // SAFETY: 60 unsafe { 61 ipc_binding::CParcelGetDataCapacity(self.as_raw()) 62 } 63 } 64 65 /// Set current data capacity in parcel set_data_capacity(&mut self, new_size: u32) -> bool66 fn set_data_capacity(&mut self, new_size: u32) -> bool { 67 // SAFETY: 68 unsafe { 69 ipc_binding::CParcelSetDataCapacity(self.as_mut_raw(), new_size) 70 } 71 } 72 73 /// Get maximum capacity in parcel get_max_capacity(&self) -> u3274 fn get_max_capacity(&self) -> u32 { 75 // SAFETY: 76 unsafe { 77 ipc_binding::CParcelGetMaxCapacity(self.as_raw()) 78 } 79 } 80 81 /// Set maximum capacity in parcel set_max_capacity(&mut self, new_size: u32) -> bool82 fn set_max_capacity(&mut self, new_size: u32) -> bool { 83 // SAFETY: 84 unsafe { 85 ipc_binding::CParcelSetMaxCapacity(self.as_mut_raw(), new_size) 86 } 87 } 88 89 /// Get current writalbe bytes in parcel get_writable_bytes(&self) -> u3290 fn get_writable_bytes(&self) -> u32 { 91 // SAFETY: 92 unsafe { 93 ipc_binding::CParcelGetWritableBytes(self.as_raw()) 94 } 95 } 96 97 /// Get current readable bytes in parcel get_readable_bytes(&self) -> u3298 fn get_readable_bytes(&self) -> u32 { 99 // SAFETY: 100 unsafe { 101 ipc_binding::CParcelGetReadableBytes(self.as_raw()) 102 } 103 } 104 105 /// Get current read position of parcel get_read_position(&self) -> u32106 fn get_read_position(&self) -> u32 { 107 // SAFETY: 108 unsafe { 109 ipc_binding::CParcelGetReadPosition(self.as_raw()) 110 } 111 } 112 113 /// Get current write position of parcel get_write_position(&self) -> u32114 fn get_write_position(&self) -> u32 { 115 // SAFETY: 116 unsafe { 117 ipc_binding::CParcelGetWritePosition(self.as_raw()) 118 } 119 } 120 121 /// Rewind the read position to a new position of parcel rewind_read(&mut self, new_pos: u32) -> bool122 fn rewind_read(&mut self, new_pos: u32) -> bool { 123 // SAFETY: 124 unsafe { 125 ipc_binding::CParcelRewindRead(self.as_mut_raw(), new_pos) 126 } 127 } 128 129 /// Rewind the write position to a new position of parcel rewind_write(&mut self, new_pos: u32) -> bool130 fn rewind_write(&mut self, new_pos: u32) -> bool { 131 // SAFETY: 132 unsafe { 133 ipc_binding::CParcelRewindWrite(self.as_mut_raw(), new_pos) 134 } 135 } 136 137 /// Write a bytes stream into parcel write_buffer(&mut self, data: &[u8]) -> bool138 fn write_buffer(&mut self, data: &[u8]) -> bool { 139 // SAFETY: 140 unsafe { 141 ipc_binding::CParcelWriteBuffer(self.as_mut_raw(), 142 data.as_ptr(), data.len() as u32) 143 } 144 } 145 146 /// Read a sized bytes stream from parcel read_buffer(&self, len: u32) -> IpcResult<Vec<u8>>147 fn read_buffer(&self, len: u32) -> IpcResult<Vec<u8>> { 148 let mut buffer: Vec<MaybeUninit<u8>> = Vec::with_capacity(len as usize); 149 // SAFETY: this is safe because the vector contains MaybeUninit elements which can be uninitialized 150 unsafe{ 151 buffer.set_len(len as usize); 152 } 153 // SAFETY: 154 let ok_status = unsafe { 155 ipc_binding::CParcelReadBuffer( 156 self.as_raw(), 157 buffer.as_mut_ptr() as *mut u8, 158 len 159 ) 160 }; 161 // SAFETY: MaybeUninit has been initialized, this should be safe 162 // since MaybeUninit should have same layout as inner type 163 unsafe fn transmute_vec(v: Vec<std::mem::MaybeUninit<u8>>) -> Vec<u8> { 164 std::mem::transmute(v) 165 } 166 // SAFETY: 167 let buffer = unsafe { transmute_vec(buffer) }; 168 if ok_status { Ok(buffer) } else { Err(IpcStatusCode::Failed) } 169 } 170 171 /// Write a large bytes stream into parcel write_raw_data(&mut self, data: &[u8]) -> bool172 fn write_raw_data(&mut self, data: &[u8]) -> bool { 173 // SAFETY: 174 unsafe { 175 ipc_binding::CParcelWriteRawData(self.as_mut_raw(), 176 data.as_ptr(), data.len() as u32) 177 } 178 } 179 180 /// Read a big bytes stream from parcel read_raw_data(&self, len: u32) -> IpcResult<RawData>181 fn read_raw_data(&self, len: u32) -> IpcResult<RawData> { 182 // SAFETY: 183 let raw_data_ptr = unsafe { 184 ipc_binding::CParcelReadRawData(self.as_raw(), len) 185 }; 186 if raw_data_ptr.is_null() { 187 Err(IpcStatusCode::Failed) 188 } else { 189 Ok(RawData::new(raw_data_ptr, len)) 190 } 191 } 192 193 /// contain file descriptors has_fd(&self) -> bool194 fn has_fd(&self) -> bool { 195 // SAFETY: 196 unsafe { 197 ipc_binding::CParcelContainFileDescriptors(self.as_raw()) 198 } 199 } 200 201 /// clear file descriptor clear_fd(&mut self)202 fn clear_fd(&mut self) { 203 // SAFETY: 204 unsafe { 205 ipc_binding::CParcelClearFileDescriptor(self.as_mut_raw()); 206 } 207 } 208 209 /// get raw data size get_raw_data_size(&self) -> usize210 fn get_raw_data_size(&self) -> usize { 211 // SAFETY: 212 unsafe { 213 ipc_binding::CParcelGetRawDataSize(self.as_raw()) 214 } 215 } 216 217 /// get raw data capacity get_raw_data_capacity(&self) -> usize218 fn get_raw_data_capacity(&self) -> usize { 219 // SAFETY: 220 unsafe { 221 ipc_binding::CParcelGetRawDataCapacity(self.as_raw()) 222 } 223 } 224 225 /// set clear fd flag set_clear_fd_flag(&mut self)226 fn set_clear_fd_flag(&mut self) { 227 // SAFETY: 228 unsafe { 229 ipc_binding::CParcelSetClearFdFlag(self.as_mut_raw()); 230 } 231 } 232 233 /// append a MsgParcel append(&mut self, data: &mut MsgParcel) -> bool234 fn append(&mut self, data: &mut MsgParcel) -> bool { 235 let data_parcel = data.as_mut_raw(); 236 // SAFETY: 237 unsafe { 238 ipc_binding::CParcelAppend(self.as_mut_raw(), data_parcel) 239 } 240 } 241 } 242 243 /// Rust RawData type which just for fetch data from C++ MssageParcel::ReadRawData() 244 #[repr(C)] 245 pub struct RawData{ 246 raw_ptr: *const u8, 247 len: u32, 248 } 249 250 impl RawData{ 251 /// Create RawData object new(raw_ptr: *const u8, len: u32) -> Self252 pub fn new(raw_ptr: *const u8, len: u32) -> Self { 253 RawData { 254 raw_ptr, 255 len, 256 } 257 } 258 259 /// The caller should ensure that the u8 slice can be 260 /// correctly converted to other rust types read(&self, start: u32, len: u32) -> IpcResult<&[u8]>261 pub fn read(&self, start: u32, len: u32) -> IpcResult<&[u8]> { 262 if (len == 0) || (len > self.len) || (start >= self.len) || ((start + len) > self.len) { 263 return Err(IpcStatusCode::Failed); 264 } 265 // SAFETY: 266 // raw_ptr is valid in [0..len], the memory is matained by C++ Parcel. 267 let data_ptr = unsafe { 268 self.raw_ptr.add(start as usize) 269 }; 270 if data_ptr.is_null() { 271 Err(IpcStatusCode::Failed) 272 } else { 273 // SAFETY: 274 // 1. data is valid for reads for `len * mem::size_of::<u8>() ` 275 // 2. The entire memory range of this slice be contained within a single allocated object (From Cpp) 276 // 3. data_ptr point to len consecutive properly initialized values of `u8` 277 // 4. The total size `len * mem::size_of::<u8>()` of the slice is no larger than `isize::MAX` 278 unsafe { 279 Ok(slice::from_raw_parts::<u8>(data_ptr, len as usize)) 280 } 281 } 282 } 283 } 284 285 286 /// Container for a message (data and object references) that can be sent 287 /// through Binder. 288 /// 289 /// This type represents a parcel that is owned by Rust code. 290 #[repr(transparent)] 291 pub struct MsgParcel { 292 ptr: NonNull<CParcel>, 293 } 294 /// # Safety 295 /// 296 /// An `MsgParcel` is an immutable handle to CParcel, which is thread-safe 297 unsafe impl Send for MsgParcel {} 298 299 /// # Safety 300 /// 301 /// An `MsgParcel` is an immutable handle to CParcel, which is thread-safe 302 unsafe impl Sync for MsgParcel {} 303 304 impl IMsgParcel for MsgParcel {} 305 306 impl MsgParcel { 307 /// Create a MsgParcel object new() -> Option<Self>308 pub fn new() -> Option<Self> { 309 // SAFETY: 310 let cparcel: *mut CParcel = unsafe { 311 ipc_binding::CParcelObtain() 312 }; 313 314 NonNull::new(cparcel).map(|x| MsgParcel{ptr: x}) 315 } 316 317 /// # Safety from_raw(ptr: *mut CParcel) -> Option<MsgParcel>318 pub unsafe fn from_raw(ptr: *mut CParcel) -> Option<MsgParcel> { 319 NonNull::new(ptr).map(|ptr| Self { ptr }) 320 } 321 322 /// Get a raw CParcel pointer and MsgParcel dropped its ownership into_raw(self) -> *mut CParcel323 pub fn into_raw(self) -> *mut CParcel { 324 let ptr = self.ptr.as_ptr(); 325 let _ = ManuallyDrop::new(self); 326 ptr 327 } 328 329 /// Get a borrowed view into the contents of this `MsgParcel`. borrowed(&mut self) -> BorrowedMsgParcel<'_>330 pub fn borrowed(&mut self) -> BorrowedMsgParcel<'_> { 331 // SAFETY: The raw pointer is a valid pointer 332 BorrowedMsgParcel { 333 ptr: self.ptr, 334 _mark: PhantomData, 335 } 336 } 337 338 /// Get an immutable borrowed view into the contents of this `MsgParcel`. borrowed_ref(&self) -> &BorrowedMsgParcel<'_>339 pub fn borrowed_ref(&self) -> &BorrowedMsgParcel<'_> { 340 // Safety: MsgParcel and BorrowedParcel are both represented in the same 341 // way as a NonNull<CParcel> due to their use of repr(transparent), 342 // so casting references as done here is valid. 343 unsafe { 344 &*(self as *const MsgParcel as *const BorrowedMsgParcel<'_>) 345 } 346 } 347 } 348 349 /// # Safety 350 /// 351 /// The `MsgParcel` constructors guarantee that a `MsgParcel` object will always 352 /// contain a valid pointer to an `CParcel`. 353 unsafe impl AsRawPtr<CParcel> for MsgParcel { as_raw(&self) -> *const CParcel354 fn as_raw(&self) -> *const CParcel { 355 self.ptr.as_ptr() 356 } 357 as_mut_raw(&mut self) -> *mut CParcel358 fn as_mut_raw(&mut self) -> *mut CParcel { 359 self.ptr.as_ptr() 360 } 361 } 362 363 impl Drop for MsgParcel { drop(&mut self)364 fn drop(&mut self) { 365 // Safety: 366 unsafe { 367 ipc_binding::CParcelDecStrongRef(self.as_mut_raw()) 368 } 369 } 370 } 371 372 /// Container for a message (data and object references) that can be sent 373 /// through Binder. 374 /// 375 /// This object is a borrowed variant of [`MsgParcel`] 376 #[repr(transparent)] 377 pub struct BorrowedMsgParcel<'a> { 378 ptr: NonNull<CParcel>, 379 _mark: PhantomData<&'a mut MsgParcel>, 380 } 381 382 impl<'a> IMsgParcel for BorrowedMsgParcel<'a> {} 383 384 impl<'a> BorrowedMsgParcel<'a> { 385 /// # Safety 386 /// 387 /// `*mut CParcel` must be a valid pointer from_raw(ptr: *mut CParcel) -> Option<BorrowedMsgParcel<'a>>388 pub unsafe fn from_raw(ptr: *mut CParcel) -> Option<BorrowedMsgParcel<'a>> { 389 Some(Self { 390 ptr: NonNull::new(ptr)?, 391 _mark: PhantomData, 392 }) 393 } 394 395 /// Get a sub-reference to this reference to the parcel. reborrow(&mut self) -> BorrowedMsgParcel<'_>396 pub fn reborrow(&mut self) -> BorrowedMsgParcel<'_> { 397 BorrowedMsgParcel { 398 ptr: self.ptr, 399 _mark: PhantomData, 400 } 401 } 402 } 403 404 /// # Safety 405 /// 406 /// The `BorrowedMsgParcel` constructors guarantee that a `BorrowedMsgParcel` object 407 /// will always contain a valid pointer to an `CParcel`. 408 unsafe impl<'a> AsRawPtr<CParcel> for BorrowedMsgParcel<'a> { as_raw(&self) -> *const CParcel409 fn as_raw(&self) -> *const CParcel { 410 self.ptr.as_ptr() 411 } 412 as_mut_raw(&mut self) -> *mut CParcel413 fn as_mut_raw(&mut self) -> *mut CParcel { 414 self.ptr.as_ptr() 415 } 416 } 417 418 impl MsgParcel { 419 /// Read a data object which implements the Deserialize trait from MsgParcel read<D: Deserialize>(&self) -> IpcResult<D>420 pub fn read<D: Deserialize>(&self) -> IpcResult<D> { 421 self.borrowed_ref().read() 422 } 423 424 /// Write a data object which implements the Serialize trait to MsgParcel write<S: Serialize + ?Sized>(&mut self, parcelable: &S) -> IpcResult<()>425 pub fn write<S: Serialize + ?Sized>(&mut self, parcelable: &S) -> IpcResult<()> { 426 self.borrowed().write(parcelable) 427 } 428 } 429 430 impl<'a> BorrowedMsgParcel<'a> { 431 /// Read a data object which implements the Deserialize trait from BorrowedMsgParcel read<D: Deserialize>(&self) -> IpcResult<D>432 pub fn read<D: Deserialize>(&self) -> IpcResult<D> { 433 D::deserialize(self) 434 } 435 436 /// Write a data object which implements the Serialize trait to BorrowedMsgParcel write<S: Serialize + ?Sized>(&mut self, parcelable: &S) -> IpcResult<()>437 pub fn write<S: Serialize + ?Sized>(&mut self, parcelable: &S) -> IpcResult<()> { 438 parcelable.serialize(self) 439 } 440 }