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 pub(crate) fn take_oneway_node(&mut self) -> Option<DArc<Node>> { 161 if let Some(info) = self.allocation_info.as_mut() { 162 info.oneway_node.take() 163 } else { 164 None 165 } 166 } 167 168 /// Reserve enough space to push at least `num_fds` fds. 169 pub(crate) fn info_add_fd_reserve(&mut self, num_fds: usize) -> Result { 170 self.get_or_init_info() 171 .file_list 172 .files_to_translate 173 .reserve(num_fds, GFP_KERNEL)?; 174 175 Ok(()) 176 } 177 178 pub(crate) fn info_add_fd( 179 &mut self, 180 file: ARef<File>, 181 buffer_offset: usize, 182 close_on_free: bool, 183 ) -> Result { 184 self.get_or_init_info().file_list.files_to_translate.push( 185 FileEntry { 186 file, 187 buffer_offset, 188 close_on_free, 189 }, 190 GFP_KERNEL, 191 )?; 192 193 Ok(()) 194 } 195 196 pub(crate) fn set_info_close_on_free(&mut self, cof: FdsCloseOnFree) { 197 self.get_or_init_info().file_list.close_on_free = cof.0; 198 } 199 200 pub(crate) fn translate_fds(&mut self) -> Result<TranslatedFds> { 201 let file_list = match self.allocation_info.as_mut() { 202 Some(info) => &mut info.file_list, 203 None => return Ok(TranslatedFds::new()), 204 }; 205 206 let files = core::mem::take(&mut file_list.files_to_translate); 207 208 let num_close_on_free = files.iter().filter(|entry| entry.close_on_free).count(); 209 let mut close_on_free = KVec::with_capacity(num_close_on_free, GFP_KERNEL)?; 210 211 let mut reservations = KVec::with_capacity(files.len(), GFP_KERNEL)?; 212 for file_info in files { 213 let res = FileDescriptorReservation::get_unused_fd_flags(bindings::O_CLOEXEC)?; 214 let fd = res.reserved_fd(); 215 self.write::<u32>(file_info.buffer_offset, &fd)?; 216 crate::trace::trace_transaction_fd_recv(self.debug_id, fd, file_info.buffer_offset); 217 218 reservations.push( 219 Reservation { 220 res, 221 file: file_info.file, 222 }, 223 GFP_KERNEL, 224 )?; 225 if file_info.close_on_free { 226 close_on_free.push(fd, GFP_KERNEL)?; 227 } 228 } 229 230 Ok(TranslatedFds { 231 reservations, 232 close_on_free: FdsCloseOnFree(close_on_free), 233 }) 234 } 235 236 /// Should the looper return to userspace when freeing this allocation? 237 pub(crate) fn looper_need_return_on_free(&self) -> bool { 238 // Closing fds involves pushing task_work for execution when we return to userspace. Hence, 239 // we should return to userspace asap if we are closing fds. 240 match self.allocation_info { 241 Some(ref info) => !info.file_list.close_on_free.is_empty(), 242 None => false, 243 } 244 } 245 } 246 247 impl Drop for Allocation { 248 fn drop(&mut self) { 249 if !self.free_on_drop { 250 return; 251 } 252 253 if let Some(mut info) = self.allocation_info.take() { 254 if let Some(oneway_node) = info.oneway_node.as_ref() { 255 oneway_node.pending_oneway_finished(); 256 } 257 258 info.target_node = None; 259 260 if let Some(offsets) = info.offsets.clone() { 261 let view = AllocationView::new(self, offsets.start); 262 for i in offsets.step_by(size_of::<usize>()) { 263 if view.cleanup_object(i).is_err() { 264 pr_warn!("Error cleaning up object at offset {}\n", i) 265 } 266 } 267 } 268 269 if self.process.task == kernel::current!().group_leader() { 270 for &fd in &info.file_list.close_on_free { 271 let closer = match DeferredFdCloser::new(GFP_KERNEL) { 272 Ok(closer) => closer, 273 Err(kernel::alloc::AllocError) => { 274 // Ignore allocation failures. 275 break; 276 } 277 }; 278 279 // Here, we ignore errors. The operation can fail if the fd is not valid, or if 280 // the method is called from a kthread. However, this is always called from a 281 // syscall, so the latter case cannot happen, and we don't care about the first 282 // case. 283 let _ = closer.close_fd(fd); 284 } 285 } 286 287 if info.clear_on_free { 288 if let Err(e) = self.fill_zero() { 289 pr_warn!("Failed to clear data on free: {:?}", e); 290 } 291 } 292 } 293 294 self.process.buffer_raw_free(self.ptr); 295 } 296 } 297 298 /// A wrapper around `Allocation` that is being created. 299 /// 300 /// If the allocation is destroyed while wrapped in this wrapper, then the allocation will be 301 /// considered to be part of a failed transaction. Successful transactions avoid that by calling 302 /// `success`, which skips the destructor. 303 #[repr(transparent)] 304 pub(crate) struct NewAllocation(pub(crate) Allocation); 305 306 impl NewAllocation { 307 pub(crate) fn success(self) -> Allocation { 308 // This skips the destructor. 309 // 310 // SAFETY: This type is `#[repr(transparent)]`, so the layout matches. 311 unsafe { core::mem::transmute(self) } 312 } 313 } 314 315 impl core::ops::Deref for NewAllocation { 316 type Target = Allocation; 317 fn deref(&self) -> &Allocation { 318 &self.0 319 } 320 } 321 322 impl core::ops::DerefMut for NewAllocation { 323 fn deref_mut(&mut self) -> &mut Allocation { 324 &mut self.0 325 } 326 } 327 328 /// A view into the beginning of an allocation. 329 /// 330 /// All attempts to read or write outside of the view will fail. To intentionally access outside of 331 /// this view, use the `alloc` field of this struct directly. 332 pub(crate) struct AllocationView<'a> { 333 pub(crate) alloc: &'a mut Allocation, 334 limit: usize, 335 } 336 337 impl<'a> AllocationView<'a> { 338 pub(crate) fn new(alloc: &'a mut Allocation, limit: usize) -> Self { 339 AllocationView { alloc, limit } 340 } 341 342 pub(crate) fn read<T: FromBytes>(&self, offset: usize) -> Result<T> { 343 if offset.checked_add(size_of::<T>()).ok_or(EINVAL)? > self.limit { 344 return Err(EINVAL); 345 } 346 self.alloc.read(offset) 347 } 348 349 pub(crate) fn write<T: AsBytes>(&self, offset: usize, obj: &T) -> Result { 350 if offset.checked_add(size_of::<T>()).ok_or(EINVAL)? > self.limit { 351 return Err(EINVAL); 352 } 353 self.alloc.write(offset, obj) 354 } 355 356 pub(crate) fn copy_into( 357 &self, 358 reader: &mut UserSliceReader, 359 offset: usize, 360 size: usize, 361 ) -> Result { 362 if offset.checked_add(size).ok_or(EINVAL)? > self.limit { 363 return Err(EINVAL); 364 } 365 self.alloc.copy_into(reader, offset, size) 366 } 367 368 pub(crate) fn transfer_binder_object( 369 &self, 370 offset: usize, 371 obj: &uapi::flat_binder_object, 372 strong: bool, 373 node_ref: NodeRef, 374 ) -> Result { 375 let mut newobj = FlatBinderObject::default(); 376 let node = node_ref.node.clone(); 377 if Arc::ptr_eq(&node_ref.node.owner, &self.alloc.process) { 378 // The receiving process is the owner of the node, so send it a binder object (instead 379 // of a handle). 380 let (ptr, cookie) = node.get_id(); 381 newobj.hdr.type_ = if strong { 382 BINDER_TYPE_BINDER 383 } else { 384 BINDER_TYPE_WEAK_BINDER 385 }; 386 newobj.flags = obj.flags; 387 newobj.__bindgen_anon_1.binder = ptr as _; 388 newobj.cookie = cookie as _; 389 self.write(offset, &newobj)?; 390 // Increment the user ref count on the node. It will be decremented as part of the 391 // destruction of the buffer, when we see a binder or weak-binder object. 392 node.update_refcount(true, 1, strong); 393 } else { 394 // The receiving process is different from the owner, so we need to insert a handle to 395 // the binder object. 396 let handle = self 397 .alloc 398 .process 399 .as_arc_borrow() 400 .insert_or_update_handle(node_ref, false)?; 401 newobj.hdr.type_ = if strong { 402 BINDER_TYPE_HANDLE 403 } else { 404 BINDER_TYPE_WEAK_HANDLE 405 }; 406 newobj.flags = obj.flags; 407 newobj.__bindgen_anon_1.handle = handle; 408 if self.write(offset, &newobj).is_err() { 409 // Decrement ref count on the handle we just created. 410 let _ = self 411 .alloc 412 .process 413 .as_arc_borrow() 414 .update_ref(handle, false, strong); 415 return Err(EINVAL); 416 } 417 } 418 419 Ok(()) 420 } 421 422 fn cleanup_object(&self, index_offset: usize) -> Result { 423 let offset = self.alloc.read(index_offset)?; 424 let header = self.read::<BinderObjectHeader>(offset)?; 425 match header.type_ { 426 BINDER_TYPE_WEAK_BINDER | BINDER_TYPE_BINDER => { 427 let obj = self.read::<FlatBinderObject>(offset)?; 428 let strong = header.type_ == BINDER_TYPE_BINDER; 429 // SAFETY: The type is `BINDER_TYPE_{WEAK_}BINDER`, so the `binder` field is 430 // populated. 431 let ptr = unsafe { obj.__bindgen_anon_1.binder }; 432 let cookie = obj.cookie; 433 self.alloc.process.update_node(ptr, cookie, strong); 434 Ok(()) 435 } 436 BINDER_TYPE_WEAK_HANDLE | BINDER_TYPE_HANDLE => { 437 let obj = self.read::<FlatBinderObject>(offset)?; 438 let strong = header.type_ == BINDER_TYPE_HANDLE; 439 // SAFETY: The type is `BINDER_TYPE_{WEAK_}HANDLE`, so the `handle` field is 440 // populated. 441 let handle = unsafe { obj.__bindgen_anon_1.handle }; 442 self.alloc 443 .process 444 .as_arc_borrow() 445 .update_ref(handle, false, strong) 446 } 447 _ => Ok(()), 448 } 449 } 450 } 451 452 /// A binder object as it is serialized. 453 /// 454 /// # Invariants 455 /// 456 /// All bytes must be initialized, and the value of `self.hdr.type_` must be one of the allowed 457 /// types. 458 #[repr(C)] 459 pub(crate) union BinderObject { 460 hdr: uapi::binder_object_header, 461 fbo: uapi::flat_binder_object, 462 fdo: uapi::binder_fd_object, 463 bbo: uapi::binder_buffer_object, 464 fdao: uapi::binder_fd_array_object, 465 } 466 467 /// A view into a `BinderObject` that can be used in a match statement. 468 pub(crate) enum BinderObjectRef<'a> { 469 Binder(&'a mut uapi::flat_binder_object), 470 Handle(&'a mut uapi::flat_binder_object), 471 Fd(&'a mut uapi::binder_fd_object), 472 Ptr(&'a mut uapi::binder_buffer_object), 473 Fda(&'a mut uapi::binder_fd_array_object), 474 } 475 476 impl BinderObject { 477 pub(crate) fn read_from(reader: &mut UserSliceReader) -> Result<BinderObject> { 478 let object = Self::read_from_inner(|slice| { 479 let read_len = usize::min(slice.len(), reader.len()); 480 reader.clone_reader().read_slice(&mut slice[..read_len])?; 481 Ok(()) 482 })?; 483 484 // If we used a object type smaller than the largest object size, then we've read more 485 // bytes than we needed to. However, we used `.clone_reader()` to avoid advancing the 486 // original reader. Now, we call `skip` so that the caller's reader is advanced by the 487 // right amount. 488 // 489 // The `skip` call fails if the reader doesn't have `size` bytes available. This could 490 // happen if the type header corresponds to an object type that is larger than the rest of 491 // the reader. 492 // 493 // Any extra bytes beyond the size of the object are inaccessible after this call, so 494 // reading them again from the `reader` later does not result in TOCTOU bugs. 495 reader.skip(object.size())?; 496 497 Ok(object) 498 } 499 500 /// Use the provided reader closure to construct a `BinderObject`. 501 /// 502 /// The closure should write the bytes for the object into the provided slice. 503 pub(crate) fn read_from_inner<R>(reader: R) -> Result<BinderObject> 504 where 505 R: FnOnce(&mut [u8; size_of::<BinderObject>()]) -> Result<()>, 506 { 507 let mut obj = MaybeUninit::<BinderObject>::zeroed(); 508 509 // SAFETY: The lengths of `BinderObject` and `[u8; size_of::<BinderObject>()]` are equal, 510 // and the byte array has an alignment requirement of one, so the pointer cast is okay. 511 // Additionally, `obj` was initialized to zeros, so the byte array will not be 512 // uninitialized. 513 (reader)(unsafe { &mut *obj.as_mut_ptr().cast() })?; 514 515 // SAFETY: The entire object is initialized, so accessing this field is safe. 516 let type_ = unsafe { obj.assume_init_ref().hdr.type_ }; 517 if Self::type_to_size(type_).is_none() { 518 // The value of `obj.hdr_type_` was invalid. 519 return Err(EINVAL); 520 } 521 522 // SAFETY: All bytes are initialized (since we zeroed them at the start) and we checked 523 // that `self.hdr.type_` is one of the allowed types, so the type invariants are satisfied. 524 unsafe { Ok(obj.assume_init()) } 525 } 526 527 pub(crate) fn as_ref(&mut self) -> BinderObjectRef<'_> { 528 use BinderObjectRef::*; 529 // SAFETY: The constructor ensures that all bytes of `self` are initialized, and all 530 // variants of this union accept all initialized bit patterns. 531 unsafe { 532 match self.hdr.type_ { 533 BINDER_TYPE_WEAK_BINDER | BINDER_TYPE_BINDER => Binder(&mut self.fbo), 534 BINDER_TYPE_WEAK_HANDLE | BINDER_TYPE_HANDLE => Handle(&mut self.fbo), 535 BINDER_TYPE_FD => Fd(&mut self.fdo), 536 BINDER_TYPE_PTR => Ptr(&mut self.bbo), 537 BINDER_TYPE_FDA => Fda(&mut self.fdao), 538 // SAFETY: By the type invariant, the value of `self.hdr.type_` cannot have any 539 // other value than the ones checked above. 540 _ => core::hint::unreachable_unchecked(), 541 } 542 } 543 } 544 545 pub(crate) fn size(&self) -> usize { 546 // SAFETY: The entire object is initialized, so accessing this field is safe. 547 let type_ = unsafe { self.hdr.type_ }; 548 549 // SAFETY: The type invariants guarantee that the type field is correct. 550 unsafe { Self::type_to_size(type_).unwrap_unchecked() } 551 } 552 553 fn type_to_size(type_: u32) -> Option<usize> { 554 match type_ { 555 BINDER_TYPE_WEAK_BINDER => Some(size_of::<uapi::flat_binder_object>()), 556 BINDER_TYPE_BINDER => Some(size_of::<uapi::flat_binder_object>()), 557 BINDER_TYPE_WEAK_HANDLE => Some(size_of::<uapi::flat_binder_object>()), 558 BINDER_TYPE_HANDLE => Some(size_of::<uapi::flat_binder_object>()), 559 BINDER_TYPE_FD => Some(size_of::<uapi::binder_fd_object>()), 560 BINDER_TYPE_PTR => Some(size_of::<uapi::binder_buffer_object>()), 561 BINDER_TYPE_FDA => Some(size_of::<uapi::binder_fd_array_object>()), 562 _ => None, 563 } 564 } 565 } 566 567 #[derive(Default)] 568 struct FileList { 569 files_to_translate: KVec<FileEntry>, 570 close_on_free: KVec<u32>, 571 } 572 573 struct FileEntry { 574 /// The file for which a descriptor will be created in the recipient process. 575 file: ARef<File>, 576 /// The offset in the buffer where the file descriptor is stored. 577 buffer_offset: usize, 578 /// Whether this fd should be closed when the allocation is freed. 579 close_on_free: bool, 580 } 581 582 pub(crate) struct TranslatedFds { 583 reservations: KVec<Reservation>, 584 /// If commit is called, then these fds should be closed. (If commit is not called, then they 585 /// shouldn't be closed.) 586 close_on_free: FdsCloseOnFree, 587 } 588 589 struct Reservation { 590 res: FileDescriptorReservation, 591 file: ARef<File>, 592 } 593 594 impl TranslatedFds { 595 pub(crate) fn new() -> Self { 596 Self { 597 reservations: KVec::new(), 598 close_on_free: FdsCloseOnFree(KVec::new()), 599 } 600 } 601 602 pub(crate) fn commit(self) -> FdsCloseOnFree { 603 for entry in self.reservations { 604 entry.res.fd_install(entry.file); 605 } 606 607 self.close_on_free 608 } 609 } 610 611 pub(crate) struct FdsCloseOnFree(KVec<u32>); 612