1 // SPDX-License-Identifier: GPL-2.0 2 3 // Copyright (C) 2025 Google LLC. 4 5 use core::mem::{size_of, size_of_val, MaybeUninit}; 6 use core::ops::Range; 7 8 use kernel::{ 9 bindings, 10 fs::file::{File, FileDescriptorReservation}, 11 prelude::*, 12 sync::{aref::ARef, Arc}, 13 transmute::{AsBytes, FromBytes}, 14 uaccess::UserSliceReader, 15 uapi, 16 }; 17 18 use crate::{ 19 deferred_close::DeferredFdCloser, 20 defs::*, 21 node::{Node, NodeRef}, 22 process::Process, 23 DArc, 24 }; 25 26 #[derive(Default)] 27 pub(crate) struct AllocationInfo { 28 /// Range within the allocation where we can find the offsets to the object descriptors. 29 pub(crate) offsets: Option<Range<usize>>, 30 /// The target node of the transaction this allocation is associated to. 31 /// Not set for replies. 32 pub(crate) target_node: Option<NodeRef>, 33 /// When this allocation is dropped, call `pending_oneway_finished` on the node. 34 /// 35 /// This is used to serialize oneway transaction on the same node. Binder guarantees that 36 /// oneway transactions to the same node are delivered sequentially in the order they are sent. 37 pub(crate) oneway_node: Option<DArc<Node>>, 38 /// Zero the data in the buffer on free. 39 pub(crate) clear_on_free: bool, 40 /// List of files embedded in this transaction. 41 file_list: FileList, 42 } 43 44 /// Represents an allocation that the kernel is currently using. 45 /// 46 /// When allocations are idle, the range allocator holds the data related to them. 47 /// 48 /// # Invariants 49 /// 50 /// This allocation corresponds to an allocation in the range allocator, so the relevant pages are 51 /// marked in use in the page range. 52 pub(crate) struct Allocation { 53 pub(crate) offset: usize, 54 size: usize, 55 pub(crate) ptr: usize, 56 pub(crate) process: Arc<Process>, 57 allocation_info: Option<AllocationInfo>, 58 free_on_drop: bool, 59 #[allow(dead_code)] 60 pub(crate) debug_id: usize, 61 } 62 63 impl Allocation { 64 pub(crate) fn new( 65 process: Arc<Process>, 66 debug_id: usize, 67 offset: usize, 68 size: usize, 69 ptr: usize, 70 ) -> Self { 71 Self { 72 process, 73 offset, 74 size, 75 ptr, 76 debug_id, 77 allocation_info: None, 78 free_on_drop: true, 79 } 80 } 81 82 fn size_check(&self, offset: usize, size: usize) -> Result { 83 let overflow_fail = offset.checked_add(size).is_none(); 84 let cmp_size_fail = offset.wrapping_add(size) > self.size; 85 if overflow_fail || cmp_size_fail { 86 return Err(EFAULT); 87 } 88 Ok(()) 89 } 90 91 pub(crate) fn copy_into( 92 &self, 93 reader: &mut UserSliceReader, 94 offset: usize, 95 size: usize, 96 ) -> Result { 97 self.size_check(offset, size)?; 98 99 // SAFETY: While this object exists, the range allocator will keep the range allocated, and 100 // in turn, the pages will be marked as in use. 101 unsafe { 102 self.process 103 .pages 104 .copy_from_user_slice(reader, self.offset + offset, size) 105 } 106 } 107 108 pub(crate) fn read<T: FromBytes>(&self, offset: usize) -> Result<T> { 109 self.size_check(offset, size_of::<T>())?; 110 111 // SAFETY: While this object exists, the range allocator will keep the range allocated, and 112 // in turn, the pages will be marked as in use. 113 unsafe { self.process.pages.read(self.offset + offset) } 114 } 115 116 pub(crate) fn write<T: ?Sized>(&self, offset: usize, obj: &T) -> Result { 117 self.size_check(offset, size_of_val::<T>(obj))?; 118 119 // SAFETY: While this object exists, the range allocator will keep the range allocated, and 120 // in turn, the pages will be marked as in use. 121 unsafe { self.process.pages.write(self.offset + offset, obj) } 122 } 123 124 pub(crate) fn fill_zero(&self) -> Result { 125 // SAFETY: While this object exists, the range allocator will keep the range allocated, and 126 // in turn, the pages will be marked as in use. 127 unsafe { self.process.pages.fill_zero(self.offset, self.size) } 128 } 129 130 pub(crate) fn keep_alive(mut self) { 131 self.process 132 .buffer_make_freeable(self.offset, self.allocation_info.take()); 133 self.free_on_drop = false; 134 } 135 136 pub(crate) fn set_info(&mut self, info: AllocationInfo) { 137 self.allocation_info = Some(info); 138 } 139 140 pub(crate) fn get_or_init_info(&mut self) -> &mut AllocationInfo { 141 self.allocation_info.get_or_insert_with(Default::default) 142 } 143 144 pub(crate) fn set_info_offsets(&mut self, offsets: Range<usize>) { 145 self.get_or_init_info().offsets = Some(offsets); 146 } 147 148 pub(crate) fn set_info_oneway_node(&mut self, oneway_node: DArc<Node>) { 149 self.get_or_init_info().oneway_node = Some(oneway_node); 150 } 151 152 pub(crate) fn set_info_clear_on_drop(&mut self) { 153 self.get_or_init_info().clear_on_free = true; 154 } 155 156 pub(crate) fn set_info_target_node(&mut self, target_node: NodeRef) { 157 self.get_or_init_info().target_node = Some(target_node); 158 } 159 160 /// Reserve enough space to push at least `num_fds` fds. 161 pub(crate) fn info_add_fd_reserve(&mut self, num_fds: usize) -> Result { 162 self.get_or_init_info() 163 .file_list 164 .files_to_translate 165 .reserve(num_fds, GFP_KERNEL)?; 166 167 Ok(()) 168 } 169 170 pub(crate) fn info_add_fd( 171 &mut self, 172 file: ARef<File>, 173 buffer_offset: usize, 174 close_on_free: bool, 175 ) -> Result { 176 self.get_or_init_info().file_list.files_to_translate.push( 177 FileEntry { 178 file, 179 buffer_offset, 180 close_on_free, 181 }, 182 GFP_KERNEL, 183 )?; 184 185 Ok(()) 186 } 187 188 pub(crate) fn set_info_close_on_free(&mut self, cof: FdsCloseOnFree) { 189 self.get_or_init_info().file_list.close_on_free = cof.0; 190 } 191 192 pub(crate) fn translate_fds(&mut self) -> Result<TranslatedFds> { 193 let file_list = match self.allocation_info.as_mut() { 194 Some(info) => &mut info.file_list, 195 None => return Ok(TranslatedFds::new()), 196 }; 197 198 let files = core::mem::take(&mut file_list.files_to_translate); 199 200 let num_close_on_free = files.iter().filter(|entry| entry.close_on_free).count(); 201 let mut close_on_free = KVec::with_capacity(num_close_on_free, GFP_KERNEL)?; 202 203 let mut reservations = KVec::with_capacity(files.len(), GFP_KERNEL)?; 204 for file_info in files { 205 let res = FileDescriptorReservation::get_unused_fd_flags(bindings::O_CLOEXEC)?; 206 let fd = res.reserved_fd(); 207 self.write::<u32>(file_info.buffer_offset, &fd)?; 208 crate::trace::trace_transaction_fd_recv(self.debug_id, fd, file_info.buffer_offset); 209 210 reservations.push( 211 Reservation { 212 res, 213 file: file_info.file, 214 }, 215 GFP_KERNEL, 216 )?; 217 if file_info.close_on_free { 218 close_on_free.push(fd, GFP_KERNEL)?; 219 } 220 } 221 222 Ok(TranslatedFds { 223 reservations, 224 close_on_free: FdsCloseOnFree(close_on_free), 225 }) 226 } 227 228 /// Should the looper return to userspace when freeing this allocation? 229 pub(crate) fn looper_need_return_on_free(&self) -> bool { 230 // Closing fds involves pushing task_work for execution when we return to userspace. Hence, 231 // we should return to userspace asap if we are closing fds. 232 match self.allocation_info { 233 Some(ref info) => !info.file_list.close_on_free.is_empty(), 234 None => false, 235 } 236 } 237 } 238 239 impl Drop for Allocation { 240 fn drop(&mut self) { 241 if !self.free_on_drop { 242 return; 243 } 244 245 if let Some(mut info) = self.allocation_info.take() { 246 if let Some(oneway_node) = info.oneway_node.as_ref() { 247 oneway_node.pending_oneway_finished(); 248 } 249 250 info.target_node = None; 251 252 if let Some(offsets) = info.offsets.clone() { 253 let view = AllocationView::new(self, offsets.start); 254 for i in offsets.step_by(size_of::<usize>()) { 255 if view.cleanup_object(i).is_err() { 256 pr_warn!("Error cleaning up object at offset {}\n", i) 257 } 258 } 259 } 260 261 if self.process.task == kernel::current!().group_leader() { 262 for &fd in &info.file_list.close_on_free { 263 let closer = match DeferredFdCloser::new(GFP_KERNEL) { 264 Ok(closer) => closer, 265 Err(kernel::alloc::AllocError) => { 266 // Ignore allocation failures. 267 break; 268 } 269 }; 270 271 // Here, we ignore errors. The operation can fail if the fd is not valid, or if 272 // the method is called from a kthread. However, this is always called from a 273 // syscall, so the latter case cannot happen, and we don't care about the first 274 // case. 275 let _ = closer.close_fd(fd); 276 } 277 } 278 279 if info.clear_on_free { 280 if let Err(e) = self.fill_zero() { 281 pr_warn!("Failed to clear data on free: {:?}", e); 282 } 283 } 284 } 285 286 self.process.buffer_raw_free(self.ptr); 287 } 288 } 289 290 /// A wrapper around `Allocation` that is being created. 291 /// 292 /// If the allocation is destroyed while wrapped in this wrapper, then the allocation will be 293 /// considered to be part of a failed transaction. Successful transactions avoid that by calling 294 /// `success`, which skips the destructor. 295 #[repr(transparent)] 296 pub(crate) struct NewAllocation(pub(crate) Allocation); 297 298 impl NewAllocation { 299 pub(crate) fn success(self) -> Allocation { 300 // This skips the destructor. 301 // 302 // SAFETY: This type is `#[repr(transparent)]`, so the layout matches. 303 unsafe { core::mem::transmute(self) } 304 } 305 } 306 307 impl core::ops::Deref for NewAllocation { 308 type Target = Allocation; 309 fn deref(&self) -> &Allocation { 310 &self.0 311 } 312 } 313 314 impl core::ops::DerefMut for NewAllocation { 315 fn deref_mut(&mut self) -> &mut Allocation { 316 &mut self.0 317 } 318 } 319 320 /// A view into the beginning of an allocation. 321 /// 322 /// All attempts to read or write outside of the view will fail. To intentionally access outside of 323 /// this view, use the `alloc` field of this struct directly. 324 pub(crate) struct AllocationView<'a> { 325 pub(crate) alloc: &'a mut Allocation, 326 limit: usize, 327 } 328 329 impl<'a> AllocationView<'a> { 330 pub(crate) fn new(alloc: &'a mut Allocation, limit: usize) -> Self { 331 AllocationView { alloc, limit } 332 } 333 334 pub(crate) fn read<T: FromBytes>(&self, offset: usize) -> Result<T> { 335 if offset.checked_add(size_of::<T>()).ok_or(EINVAL)? > self.limit { 336 return Err(EINVAL); 337 } 338 self.alloc.read(offset) 339 } 340 341 pub(crate) fn write<T: AsBytes>(&self, offset: usize, obj: &T) -> Result { 342 if offset.checked_add(size_of::<T>()).ok_or(EINVAL)? > self.limit { 343 return Err(EINVAL); 344 } 345 self.alloc.write(offset, obj) 346 } 347 348 pub(crate) fn copy_into( 349 &self, 350 reader: &mut UserSliceReader, 351 offset: usize, 352 size: usize, 353 ) -> Result { 354 if offset.checked_add(size).ok_or(EINVAL)? > self.limit { 355 return Err(EINVAL); 356 } 357 self.alloc.copy_into(reader, offset, size) 358 } 359 360 pub(crate) fn transfer_binder_object( 361 &self, 362 offset: usize, 363 obj: &uapi::flat_binder_object, 364 strong: bool, 365 node_ref: NodeRef, 366 ) -> Result { 367 let mut newobj = FlatBinderObject::default(); 368 let node = node_ref.node.clone(); 369 if Arc::ptr_eq(&node_ref.node.owner, &self.alloc.process) { 370 // The receiving process is the owner of the node, so send it a binder object (instead 371 // of a handle). 372 let (ptr, cookie) = node.get_id(); 373 newobj.hdr.type_ = if strong { 374 BINDER_TYPE_BINDER 375 } else { 376 BINDER_TYPE_WEAK_BINDER 377 }; 378 newobj.flags = obj.flags; 379 newobj.__bindgen_anon_1.binder = ptr as _; 380 newobj.cookie = cookie as _; 381 self.write(offset, &newobj)?; 382 // Increment the user ref count on the node. It will be decremented as part of the 383 // destruction of the buffer, when we see a binder or weak-binder object. 384 node.update_refcount(true, 1, strong); 385 } else { 386 // The receiving process is different from the owner, so we need to insert a handle to 387 // the binder object. 388 let handle = self 389 .alloc 390 .process 391 .as_arc_borrow() 392 .insert_or_update_handle(node_ref, false)?; 393 newobj.hdr.type_ = if strong { 394 BINDER_TYPE_HANDLE 395 } else { 396 BINDER_TYPE_WEAK_HANDLE 397 }; 398 newobj.flags = obj.flags; 399 newobj.__bindgen_anon_1.handle = handle; 400 if self.write(offset, &newobj).is_err() { 401 // Decrement ref count on the handle we just created. 402 let _ = self 403 .alloc 404 .process 405 .as_arc_borrow() 406 .update_ref(handle, false, strong); 407 return Err(EINVAL); 408 } 409 } 410 411 Ok(()) 412 } 413 414 fn cleanup_object(&self, index_offset: usize) -> Result { 415 let offset = self.alloc.read(index_offset)?; 416 let header = self.read::<BinderObjectHeader>(offset)?; 417 match header.type_ { 418 BINDER_TYPE_WEAK_BINDER | BINDER_TYPE_BINDER => { 419 let obj = self.read::<FlatBinderObject>(offset)?; 420 let strong = header.type_ == BINDER_TYPE_BINDER; 421 // SAFETY: The type is `BINDER_TYPE_{WEAK_}BINDER`, so the `binder` field is 422 // populated. 423 let ptr = unsafe { obj.__bindgen_anon_1.binder }; 424 let cookie = obj.cookie; 425 self.alloc.process.update_node(ptr, cookie, strong); 426 Ok(()) 427 } 428 BINDER_TYPE_WEAK_HANDLE | BINDER_TYPE_HANDLE => { 429 let obj = self.read::<FlatBinderObject>(offset)?; 430 let strong = header.type_ == BINDER_TYPE_HANDLE; 431 // SAFETY: The type is `BINDER_TYPE_{WEAK_}HANDLE`, so the `handle` field is 432 // populated. 433 let handle = unsafe { obj.__bindgen_anon_1.handle }; 434 self.alloc 435 .process 436 .as_arc_borrow() 437 .update_ref(handle, false, strong) 438 } 439 _ => Ok(()), 440 } 441 } 442 } 443 444 /// A binder object as it is serialized. 445 /// 446 /// # Invariants 447 /// 448 /// All bytes must be initialized, and the value of `self.hdr.type_` must be one of the allowed 449 /// types. 450 #[repr(C)] 451 pub(crate) union BinderObject { 452 hdr: uapi::binder_object_header, 453 fbo: uapi::flat_binder_object, 454 fdo: uapi::binder_fd_object, 455 bbo: uapi::binder_buffer_object, 456 fdao: uapi::binder_fd_array_object, 457 } 458 459 /// A view into a `BinderObject` that can be used in a match statement. 460 pub(crate) enum BinderObjectRef<'a> { 461 Binder(&'a mut uapi::flat_binder_object), 462 Handle(&'a mut uapi::flat_binder_object), 463 Fd(&'a mut uapi::binder_fd_object), 464 Ptr(&'a mut uapi::binder_buffer_object), 465 Fda(&'a mut uapi::binder_fd_array_object), 466 } 467 468 impl BinderObject { 469 pub(crate) fn read_from(reader: &mut UserSliceReader) -> Result<BinderObject> { 470 let object = Self::read_from_inner(|slice| { 471 let read_len = usize::min(slice.len(), reader.len()); 472 reader.clone_reader().read_slice(&mut slice[..read_len])?; 473 Ok(()) 474 })?; 475 476 // If we used a object type smaller than the largest object size, then we've read more 477 // bytes than we needed to. However, we used `.clone_reader()` to avoid advancing the 478 // original reader. Now, we call `skip` so that the caller's reader is advanced by the 479 // right amount. 480 // 481 // The `skip` call fails if the reader doesn't have `size` bytes available. This could 482 // happen if the type header corresponds to an object type that is larger than the rest of 483 // the reader. 484 // 485 // Any extra bytes beyond the size of the object are inaccessible after this call, so 486 // reading them again from the `reader` later does not result in TOCTOU bugs. 487 reader.skip(object.size())?; 488 489 Ok(object) 490 } 491 492 /// Use the provided reader closure to construct a `BinderObject`. 493 /// 494 /// The closure should write the bytes for the object into the provided slice. 495 pub(crate) fn read_from_inner<R>(reader: R) -> Result<BinderObject> 496 where 497 R: FnOnce(&mut [u8; size_of::<BinderObject>()]) -> Result<()>, 498 { 499 let mut obj = MaybeUninit::<BinderObject>::zeroed(); 500 501 // SAFETY: The lengths of `BinderObject` and `[u8; size_of::<BinderObject>()]` are equal, 502 // and the byte array has an alignment requirement of one, so the pointer cast is okay. 503 // Additionally, `obj` was initialized to zeros, so the byte array will not be 504 // uninitialized. 505 (reader)(unsafe { &mut *obj.as_mut_ptr().cast() })?; 506 507 // SAFETY: The entire object is initialized, so accessing this field is safe. 508 let type_ = unsafe { obj.assume_init_ref().hdr.type_ }; 509 if Self::type_to_size(type_).is_none() { 510 // The value of `obj.hdr_type_` was invalid. 511 return Err(EINVAL); 512 } 513 514 // SAFETY: All bytes are initialized (since we zeroed them at the start) and we checked 515 // that `self.hdr.type_` is one of the allowed types, so the type invariants are satisfied. 516 unsafe { Ok(obj.assume_init()) } 517 } 518 519 pub(crate) fn as_ref(&mut self) -> BinderObjectRef<'_> { 520 use BinderObjectRef::*; 521 // SAFETY: The constructor ensures that all bytes of `self` are initialized, and all 522 // variants of this union accept all initialized bit patterns. 523 unsafe { 524 match self.hdr.type_ { 525 BINDER_TYPE_WEAK_BINDER | BINDER_TYPE_BINDER => Binder(&mut self.fbo), 526 BINDER_TYPE_WEAK_HANDLE | BINDER_TYPE_HANDLE => Handle(&mut self.fbo), 527 BINDER_TYPE_FD => Fd(&mut self.fdo), 528 BINDER_TYPE_PTR => Ptr(&mut self.bbo), 529 BINDER_TYPE_FDA => Fda(&mut self.fdao), 530 // SAFETY: By the type invariant, the value of `self.hdr.type_` cannot have any 531 // other value than the ones checked above. 532 _ => core::hint::unreachable_unchecked(), 533 } 534 } 535 } 536 537 pub(crate) fn size(&self) -> usize { 538 // SAFETY: The entire object is initialized, so accessing this field is safe. 539 let type_ = unsafe { self.hdr.type_ }; 540 541 // SAFETY: The type invariants guarantee that the type field is correct. 542 unsafe { Self::type_to_size(type_).unwrap_unchecked() } 543 } 544 545 fn type_to_size(type_: u32) -> Option<usize> { 546 match type_ { 547 BINDER_TYPE_WEAK_BINDER => Some(size_of::<uapi::flat_binder_object>()), 548 BINDER_TYPE_BINDER => Some(size_of::<uapi::flat_binder_object>()), 549 BINDER_TYPE_WEAK_HANDLE => Some(size_of::<uapi::flat_binder_object>()), 550 BINDER_TYPE_HANDLE => Some(size_of::<uapi::flat_binder_object>()), 551 BINDER_TYPE_FD => Some(size_of::<uapi::binder_fd_object>()), 552 BINDER_TYPE_PTR => Some(size_of::<uapi::binder_buffer_object>()), 553 BINDER_TYPE_FDA => Some(size_of::<uapi::binder_fd_array_object>()), 554 _ => None, 555 } 556 } 557 } 558 559 #[derive(Default)] 560 struct FileList { 561 files_to_translate: KVec<FileEntry>, 562 close_on_free: KVec<u32>, 563 } 564 565 struct FileEntry { 566 /// The file for which a descriptor will be created in the recipient process. 567 file: ARef<File>, 568 /// The offset in the buffer where the file descriptor is stored. 569 buffer_offset: usize, 570 /// Whether this fd should be closed when the allocation is freed. 571 close_on_free: bool, 572 } 573 574 pub(crate) struct TranslatedFds { 575 reservations: KVec<Reservation>, 576 /// If commit is called, then these fds should be closed. (If commit is not called, then they 577 /// shouldn't be closed.) 578 close_on_free: FdsCloseOnFree, 579 } 580 581 struct Reservation { 582 res: FileDescriptorReservation, 583 file: ARef<File>, 584 } 585 586 impl TranslatedFds { 587 pub(crate) fn new() -> Self { 588 Self { 589 reservations: KVec::new(), 590 close_on_free: FdsCloseOnFree(KVec::new()), 591 } 592 } 593 594 pub(crate) fn commit(self) -> FdsCloseOnFree { 595 for entry in self.reservations { 596 entry.res.fd_install(entry.file); 597 } 598 599 self.close_on_free 600 } 601 } 602 603 pub(crate) struct FdsCloseOnFree(KVec<u32>); 604