1 // SPDX-License-Identifier: GPL-2.0 2 3 // Copyright (C) 2025 Google LLC. 4 5 use kernel::{ 6 list::{AtomicTracker, List, ListArc, ListLinks, TryNewListArc}, 7 prelude::*, 8 seq_file::SeqFile, 9 seq_print, 10 sync::lock::{spinlock::SpinLockBackend, Guard}, 11 sync::{Arc, LockedBy, SpinLock}, 12 }; 13 14 use crate::{ 15 defs::*, 16 error::BinderError, 17 process::{NodeRefInfo, Process, ProcessInner}, 18 thread::Thread, 19 transaction::Transaction, 20 BinderReturnWriter, DArc, DLArc, DTRWrap, DeliverToRead, 21 }; 22 23 use core::mem; 24 25 mod wrapper; 26 pub(crate) use self::wrapper::CritIncrWrapper; 27 28 #[derive(Debug)] 29 pub(crate) struct CouldNotDeliverCriticalIncrement; 30 31 /// Keeps track of how this node is scheduled. 32 /// 33 /// There are two ways to schedule a node to a work list. Just schedule the node itself, or 34 /// allocate a wrapper that references the node and schedule the wrapper. These wrappers exists to 35 /// make it possible to "move" a node from one list to another - when `do_work` is called directly 36 /// on the `Node`, then it's a no-op if there's also a pending wrapper. 37 /// 38 /// Wrappers are generally only needed for zero-to-one refcount increments, and there are two cases 39 /// of this: weak increments and strong increments. We call such increments "critical" because it 40 /// is critical that they are delivered to the thread doing the increment. Some examples: 41 /// 42 /// * One thread makes a zero-to-one strong increment, and another thread makes a zero-to-one weak 43 /// increment. Delivering the node to the thread doing the weak increment is wrong, since the 44 /// thread doing the strong increment may have ended a long time ago when the command is actually 45 /// processed by userspace. 46 /// 47 /// * We have a weak reference and are about to drop it on one thread. But then another thread does 48 /// a zero-to-one strong increment. If the strong increment gets sent to the thread that was 49 /// about to drop the weak reference, then the strong increment could be processed after the 50 /// other thread has already exited, which would be too late. 51 /// 52 /// Note that trying to create a `ListArc` to the node can succeed even if `has_normal_push` is 53 /// set. This is because another thread might just have popped the node from a todo list, but not 54 /// yet called `do_work`. However, if `has_normal_push` is false, then creating a `ListArc` should 55 /// always succeed. 56 /// 57 /// Like the other fields in `NodeInner`, the delivery state is protected by the process lock. 58 struct DeliveryState { 59 /// Is the `Node` currently scheduled? 60 has_pushed_node: bool, 61 62 /// Is a wrapper currently scheduled? 63 /// 64 /// The wrapper is used only for strong zero2one increments. 65 has_pushed_wrapper: bool, 66 67 /// Is the currently scheduled `Node` scheduled due to a weak zero2one increment? 68 /// 69 /// Weak zero2one operations are always scheduled using the `Node`. 70 has_weak_zero2one: bool, 71 72 /// Is the currently scheduled wrapper/`Node` scheduled due to a strong zero2one increment? 73 /// 74 /// If `has_pushed_wrapper` is set, then the strong zero2one increment was scheduled using the 75 /// wrapper. Otherwise, `has_pushed_node` must be set and it was scheduled using the `Node`. 76 has_strong_zero2one: bool, 77 } 78 79 impl DeliveryState { 80 fn should_normal_push(&self) -> bool { 81 !self.has_pushed_node && !self.has_pushed_wrapper 82 } 83 84 fn did_normal_push(&mut self) { 85 assert!(self.should_normal_push()); 86 self.has_pushed_node = true; 87 } 88 89 fn should_push_weak_zero2one(&self) -> bool { 90 !self.has_weak_zero2one && !self.has_strong_zero2one 91 } 92 93 fn can_push_weak_zero2one_normally(&self) -> bool { 94 !self.has_pushed_node 95 } 96 97 fn did_push_weak_zero2one(&mut self) { 98 assert!(self.should_push_weak_zero2one()); 99 assert!(self.can_push_weak_zero2one_normally()); 100 self.has_pushed_node = true; 101 self.has_weak_zero2one = true; 102 } 103 104 fn should_push_strong_zero2one(&self) -> bool { 105 !self.has_strong_zero2one 106 } 107 108 fn can_push_strong_zero2one_normally(&self) -> bool { 109 !self.has_pushed_node 110 } 111 112 fn did_push_strong_zero2one(&mut self) { 113 assert!(self.should_push_strong_zero2one()); 114 assert!(self.can_push_strong_zero2one_normally()); 115 self.has_pushed_node = true; 116 self.has_strong_zero2one = true; 117 } 118 119 fn did_push_strong_zero2one_wrapper(&mut self) { 120 assert!(self.should_push_strong_zero2one()); 121 assert!(!self.can_push_strong_zero2one_normally()); 122 self.has_pushed_wrapper = true; 123 self.has_strong_zero2one = true; 124 } 125 } 126 127 struct CountState { 128 /// The reference count. 129 count: usize, 130 /// Whether the process that owns this node thinks that we hold a refcount on it. (Note that 131 /// even if count is greater than one, we only increment it once in the owning process.) 132 has_count: bool, 133 } 134 135 impl CountState { 136 fn new() -> Self { 137 Self { 138 count: 0, 139 has_count: false, 140 } 141 } 142 } 143 144 struct NodeInner { 145 /// Strong refcounts held on this node by `NodeRef` objects. 146 strong: CountState, 147 /// Weak refcounts held on this node by `NodeRef` objects. 148 weak: CountState, 149 delivery_state: DeliveryState, 150 /// The binder driver guarantees that oneway transactions sent to the same node are serialized, 151 /// that is, userspace will not be given the next one until it has finished processing the 152 /// previous oneway transaction. This is done to avoid the case where two oneway transactions 153 /// arrive in opposite order from the order in which they were sent. (E.g., they could be 154 /// delivered to two different threads, which could appear as-if they were sent in opposite 155 /// order.) 156 /// 157 /// To fix that, we store pending oneway transactions in a separate list in the node, and don't 158 /// deliver the next oneway transaction until userspace signals that it has finished processing 159 /// the previous oneway transaction by calling the `BC_FREE_BUFFER` ioctl. 160 oneway_todo: List<DTRWrap<Transaction>>, 161 /// Keeps track of whether this node has a pending oneway transaction. 162 /// 163 /// When this is true, incoming oneway transactions are stored in `oneway_todo`, instead of 164 /// being delivered directly to the process. 165 has_oneway_transaction: bool, 166 /// List of processes to deliver a notification to when this node is destroyed (usually due to 167 /// the process dying). 168 death_list: List<DTRWrap<NodeDeath>, 1>, 169 /// List of processes to deliver freeze notifications to. 170 freeze_list: KVVec<Arc<Process>>, 171 /// The number of active BR_INCREFS or BR_ACQUIRE operations. (should be maximum two) 172 /// 173 /// If this is non-zero, then we postpone any BR_RELEASE or BR_DECREFS notifications until the 174 /// active operations have ended. This avoids the situation an increment and decrement get 175 /// reordered from userspace's perspective. 176 active_inc_refs: u8, 177 /// List of `NodeRefInfo` objects that reference this node. 178 refs: List<NodeRefInfo, { NodeRefInfo::LIST_NODE }>, 179 } 180 181 #[pin_data] 182 pub(crate) struct Node { 183 pub(crate) debug_id: usize, 184 ptr: u64, 185 pub(crate) cookie: u64, 186 pub(crate) flags: u32, 187 pub(crate) owner: Arc<Process>, 188 inner: LockedBy<NodeInner, ProcessInner>, 189 #[pin] 190 links_track: AtomicTracker, 191 } 192 193 kernel::list::impl_list_arc_safe! { 194 impl ListArcSafe<0> for Node { 195 tracked_by links_track: AtomicTracker; 196 } 197 } 198 199 // Make `oneway_todo` work. 200 kernel::list::impl_list_item! { 201 impl ListItem<0> for DTRWrap<Transaction> { 202 using ListLinks { self.links.inner }; 203 } 204 } 205 206 impl Node { 207 pub(crate) fn new( 208 ptr: u64, 209 cookie: u64, 210 flags: u32, 211 owner: Arc<Process>, 212 ) -> impl PinInit<Self> { 213 pin_init!(Self { 214 inner: LockedBy::new( 215 &owner.inner, 216 NodeInner { 217 strong: CountState::new(), 218 weak: CountState::new(), 219 delivery_state: DeliveryState { 220 has_pushed_node: false, 221 has_pushed_wrapper: false, 222 has_weak_zero2one: false, 223 has_strong_zero2one: false, 224 }, 225 death_list: List::new(), 226 oneway_todo: List::new(), 227 freeze_list: KVVec::new(), 228 has_oneway_transaction: false, 229 active_inc_refs: 0, 230 refs: List::new(), 231 }, 232 ), 233 debug_id: super::next_debug_id(), 234 ptr, 235 cookie, 236 flags, 237 owner, 238 links_track <- AtomicTracker::new(), 239 }) 240 } 241 242 pub(crate) fn has_oneway_transaction(&self, owner_inner: &mut ProcessInner) -> bool { 243 let inner = self.inner.access_mut(owner_inner); 244 inner.has_oneway_transaction 245 } 246 247 #[inline(never)] 248 pub(crate) fn full_debug_print( 249 &self, 250 m: &SeqFile, 251 owner_inner: &mut ProcessInner, 252 ) -> Result<()> { 253 let inner = self.inner.access_mut(owner_inner); 254 seq_print!( 255 m, 256 " node {}: u{:016x} c{:016x} hs {} hw {} cs {} cw {}", 257 self.debug_id, 258 self.ptr, 259 self.cookie, 260 inner.strong.has_count, 261 inner.weak.has_count, 262 inner.strong.count, 263 inner.weak.count, 264 ); 265 if !inner.refs.is_empty() { 266 seq_print!(m, " proc"); 267 for node_ref in &inner.refs { 268 seq_print!(m, " {}", node_ref.process.task.pid()); 269 } 270 } 271 seq_print!(m, "\n"); 272 for t in &inner.oneway_todo { 273 t.debug_print_inner(m, " pending async transaction "); 274 } 275 Ok(()) 276 } 277 278 /// Insert the `NodeRef` into this `refs` list. 279 /// 280 /// # Safety 281 /// 282 /// It must be the case that `info.node_ref.node` is this node. 283 pub(crate) unsafe fn insert_node_info( 284 &self, 285 info: ListArc<NodeRefInfo, { NodeRefInfo::LIST_NODE }>, 286 ) { 287 self.inner 288 .access_mut(&mut self.owner.inner.lock()) 289 .refs 290 .push_front(info); 291 } 292 293 /// Insert the `NodeRef` into this `refs` list. 294 /// 295 /// # Safety 296 /// 297 /// It must be the case that `info.node_ref.node` is this node. 298 pub(crate) unsafe fn remove_node_info( 299 &self, 300 info: &NodeRefInfo, 301 ) -> Option<ListArc<NodeRefInfo, { NodeRefInfo::LIST_NODE }>> { 302 // SAFETY: We always insert `NodeRefInfo` objects into the `refs` list of the node that it 303 // references in `info.node_ref.node`. That is this node, so `info` cannot possibly be in 304 // the `refs` list of another node. 305 unsafe { 306 self.inner 307 .access_mut(&mut self.owner.inner.lock()) 308 .refs 309 .remove(info) 310 } 311 } 312 313 /// An id that is unique across all binder nodes on the system. Used as the key in the 314 /// `by_node` map. 315 pub(crate) fn global_id(&self) -> usize { 316 self as *const Node as usize 317 } 318 319 pub(crate) fn get_id(&self) -> (u64, u64) { 320 (self.ptr, self.cookie) 321 } 322 323 pub(crate) fn add_death( 324 &self, 325 death: ListArc<DTRWrap<NodeDeath>, 1>, 326 guard: &mut Guard<'_, ProcessInner, SpinLockBackend>, 327 ) { 328 self.inner.access_mut(guard).death_list.push_back(death); 329 } 330 331 pub(crate) fn inc_ref_done_locked( 332 self: &DArc<Node>, 333 _strong: bool, 334 owner_inner: &mut ProcessInner, 335 ) -> Option<DLArc<Node>> { 336 let inner = self.inner.access_mut(owner_inner); 337 if inner.active_inc_refs == 0 { 338 pr_err!("inc_ref_done called when no active inc_refs"); 339 return None; 340 } 341 342 inner.active_inc_refs -= 1; 343 if inner.active_inc_refs == 0 { 344 // Having active inc_refs can inhibit dropping of ref-counts. Calculate whether we 345 // would send a refcount decrement, and if so, tell the caller to schedule us. 346 let strong = inner.strong.count > 0; 347 let has_strong = inner.strong.has_count; 348 let weak = strong || inner.weak.count > 0; 349 let has_weak = inner.weak.has_count; 350 351 let should_drop_weak = !weak && has_weak; 352 let should_drop_strong = !strong && has_strong; 353 354 // If we want to drop the ref-count again, tell the caller to schedule a work node for 355 // that. 356 let need_push = should_drop_weak || should_drop_strong; 357 358 if need_push && inner.delivery_state.should_normal_push() { 359 let list_arc = ListArc::try_from_arc(self.clone()).ok().unwrap(); 360 inner.delivery_state.did_normal_push(); 361 Some(list_arc) 362 } else { 363 None 364 } 365 } else { 366 None 367 } 368 } 369 370 pub(crate) fn update_refcount_locked( 371 self: &DArc<Node>, 372 inc: bool, 373 strong: bool, 374 count: usize, 375 owner_inner: &mut ProcessInner, 376 ) -> Option<DLArc<Node>> { 377 let is_dead = owner_inner.is_dead; 378 let inner = self.inner.access_mut(owner_inner); 379 380 // Get a reference to the state we'll update. 381 let state = if strong { 382 &mut inner.strong 383 } else { 384 &mut inner.weak 385 }; 386 387 // Update the count and determine whether we need to push work. 388 let need_push = if inc { 389 state.count += count; 390 // TODO: This method shouldn't be used for zero-to-one increments. 391 !is_dead && !state.has_count 392 } else { 393 if state.count < count { 394 pr_err!("Failure: refcount underflow!"); 395 return None; 396 } 397 state.count -= count; 398 !is_dead && state.count == 0 && state.has_count 399 }; 400 401 if need_push && inner.delivery_state.should_normal_push() { 402 let list_arc = ListArc::try_from_arc(self.clone()).ok().unwrap(); 403 inner.delivery_state.did_normal_push(); 404 Some(list_arc) 405 } else { 406 None 407 } 408 } 409 410 pub(crate) fn incr_refcount_allow_zero2one( 411 self: &DArc<Self>, 412 strong: bool, 413 owner_inner: &mut ProcessInner, 414 ) -> Result<Option<DLArc<Node>>, CouldNotDeliverCriticalIncrement> { 415 let is_dead = owner_inner.is_dead; 416 let inner = self.inner.access_mut(owner_inner); 417 418 // Get a reference to the state we'll update. 419 let state = if strong { 420 &mut inner.strong 421 } else { 422 &mut inner.weak 423 }; 424 425 // Update the count and determine whether we need to push work. 426 state.count += 1; 427 if is_dead || state.has_count { 428 return Ok(None); 429 } 430 431 // Userspace needs to be notified of this. 432 if !strong && inner.delivery_state.should_push_weak_zero2one() { 433 assert!(inner.delivery_state.can_push_weak_zero2one_normally()); 434 let list_arc = ListArc::try_from_arc(self.clone()).ok().unwrap(); 435 inner.delivery_state.did_push_weak_zero2one(); 436 Ok(Some(list_arc)) 437 } else if strong && inner.delivery_state.should_push_strong_zero2one() { 438 if inner.delivery_state.can_push_strong_zero2one_normally() { 439 let list_arc = ListArc::try_from_arc(self.clone()).ok().unwrap(); 440 inner.delivery_state.did_push_strong_zero2one(); 441 Ok(Some(list_arc)) 442 } else { 443 state.count -= 1; 444 Err(CouldNotDeliverCriticalIncrement) 445 } 446 } else { 447 // Work is already pushed, and we don't need to push again. 448 Ok(None) 449 } 450 } 451 452 pub(crate) fn incr_refcount_allow_zero2one_with_wrapper( 453 self: &DArc<Self>, 454 strong: bool, 455 wrapper: CritIncrWrapper, 456 owner_inner: &mut ProcessInner, 457 ) -> Option<DLArc<dyn DeliverToRead>> { 458 match self.incr_refcount_allow_zero2one(strong, owner_inner) { 459 Ok(Some(node)) => Some(node as _), 460 Ok(None) => None, 461 Err(CouldNotDeliverCriticalIncrement) => { 462 assert!(strong); 463 let inner = self.inner.access_mut(owner_inner); 464 inner.strong.count += 1; 465 inner.delivery_state.did_push_strong_zero2one_wrapper(); 466 Some(wrapper.init(self.clone())) 467 } 468 } 469 } 470 471 pub(crate) fn update_refcount(self: &DArc<Self>, inc: bool, count: usize, strong: bool) { 472 self.owner 473 .inner 474 .lock() 475 .update_node_refcount(self, inc, strong, count, None); 476 } 477 478 pub(crate) fn populate_counts( 479 &self, 480 out: &mut BinderNodeInfoForRef, 481 guard: &Guard<'_, ProcessInner, SpinLockBackend>, 482 ) { 483 let inner = self.inner.access(guard); 484 out.strong_count = inner.strong.count as _; 485 out.weak_count = inner.weak.count as _; 486 } 487 488 pub(crate) fn populate_debug_info( 489 &self, 490 out: &mut BinderNodeDebugInfo, 491 guard: &Guard<'_, ProcessInner, SpinLockBackend>, 492 ) { 493 out.ptr = self.ptr as _; 494 out.cookie = self.cookie as _; 495 let inner = self.inner.access(guard); 496 if inner.strong.has_count { 497 out.has_strong_ref = 1; 498 } 499 if inner.weak.has_count { 500 out.has_weak_ref = 1; 501 } 502 } 503 504 pub(crate) fn force_has_count(&self, guard: &mut Guard<'_, ProcessInner, SpinLockBackend>) { 505 let inner = self.inner.access_mut(guard); 506 inner.strong.has_count = true; 507 inner.weak.has_count = true; 508 } 509 510 fn write(&self, writer: &mut BinderReturnWriter<'_>, code: u32) -> Result { 511 writer.write_code(code)?; 512 writer.write_payload(&self.ptr)?; 513 writer.write_payload(&self.cookie)?; 514 Ok(()) 515 } 516 517 pub(crate) fn submit_oneway( 518 &self, 519 transaction: DLArc<Transaction>, 520 guard: &mut Guard<'_, ProcessInner, SpinLockBackend>, 521 ) -> Result<(), (BinderError, DLArc<dyn DeliverToRead>)> { 522 if guard.is_dead { 523 return Err((BinderError::new_dead(), transaction)); 524 } 525 526 let inner = self.inner.access_mut(guard); 527 if inner.has_oneway_transaction { 528 inner.oneway_todo.push_back(transaction); 529 } else { 530 inner.has_oneway_transaction = true; 531 guard.push_work(transaction)?; 532 } 533 Ok(()) 534 } 535 536 pub(crate) fn release(&self) { 537 let mut guard = self.owner.inner.lock(); 538 while let Some(work) = self.inner.access_mut(&mut guard).oneway_todo.pop_front() { 539 drop(guard); 540 work.into_arc().cancel(); 541 guard = self.owner.inner.lock(); 542 } 543 544 let death_list = core::mem::take(&mut self.inner.access_mut(&mut guard).death_list); 545 drop(guard); 546 for death in death_list { 547 death.into_arc().set_dead(); 548 } 549 } 550 551 pub(crate) fn pending_oneway_finished(&self) { 552 let mut guard = self.owner.inner.lock(); 553 if guard.is_dead { 554 // Cleanup will happen in `Process::deferred_release`. 555 return; 556 } 557 558 let inner = self.inner.access_mut(&mut guard); 559 560 let transaction = inner.oneway_todo.pop_front(); 561 inner.has_oneway_transaction = transaction.is_some(); 562 if let Some(transaction) = transaction { 563 match guard.push_work(transaction) { 564 Ok(()) => {} 565 Err((_err, work)) => { 566 // Process is dead. 567 // This shouldn't happen due to the `is_dead` check, but if it does, just drop 568 // the transaction and return. 569 drop(guard); 570 drop(work); 571 } 572 } 573 } 574 } 575 576 /// Finds an outdated transaction that the given transaction can replace. 577 /// 578 /// If one is found, it is removed from the list and returned. 579 pub(crate) fn take_outdated_transaction( 580 &self, 581 new: &Transaction, 582 guard: &mut Guard<'_, ProcessInner, SpinLockBackend>, 583 ) -> Option<DLArc<Transaction>> { 584 let inner = self.inner.access_mut(guard); 585 let mut cursor = inner.oneway_todo.cursor_front(); 586 while let Some(next) = cursor.peek_next() { 587 if new.can_replace(&next) { 588 return Some(next.remove()); 589 } 590 cursor.move_next(); 591 } 592 None 593 } 594 595 /// This is split into a separate function since it's called by both `Node::do_work` and 596 /// `NodeWrapper::do_work`. 597 fn do_work_locked( 598 &self, 599 writer: &mut BinderReturnWriter<'_>, 600 mut guard: Guard<'_, ProcessInner, SpinLockBackend>, 601 ) -> Result<bool> { 602 let inner = self.inner.access_mut(&mut guard); 603 let strong = inner.strong.count > 0; 604 let has_strong = inner.strong.has_count; 605 let weak = strong || inner.weak.count > 0; 606 let has_weak = inner.weak.has_count; 607 608 if weak && !has_weak { 609 inner.weak.has_count = true; 610 inner.active_inc_refs += 1; 611 } 612 613 if strong && !has_strong { 614 inner.strong.has_count = true; 615 inner.active_inc_refs += 1; 616 } 617 618 let no_active_inc_refs = inner.active_inc_refs == 0; 619 let should_drop_weak = no_active_inc_refs && (!weak && has_weak); 620 let should_drop_strong = no_active_inc_refs && (!strong && has_strong); 621 if should_drop_weak { 622 inner.weak.has_count = false; 623 } 624 if should_drop_strong { 625 inner.strong.has_count = false; 626 } 627 if no_active_inc_refs && !weak { 628 // Remove the node if there are no references to it. 629 guard.remove_node(self.ptr); 630 } 631 drop(guard); 632 633 if weak && !has_weak { 634 self.write(writer, BR_INCREFS)?; 635 } 636 if strong && !has_strong { 637 self.write(writer, BR_ACQUIRE)?; 638 } 639 if should_drop_strong { 640 self.write(writer, BR_RELEASE)?; 641 } 642 if should_drop_weak { 643 self.write(writer, BR_DECREFS)?; 644 } 645 646 Ok(true) 647 } 648 649 pub(crate) fn add_freeze_listener( 650 &self, 651 process: &Arc<Process>, 652 flags: kernel::alloc::Flags, 653 ) -> Result { 654 let mut vec_alloc = KVVec::<Arc<Process>>::new(); 655 loop { 656 let mut guard = self.owner.inner.lock(); 657 // Do not check for `guard.dead`. The `dead` flag that matters here is the owner of the 658 // listener, no the target. 659 let inner = self.inner.access_mut(&mut guard); 660 let len = inner.freeze_list.len(); 661 if len >= inner.freeze_list.capacity() { 662 if len >= vec_alloc.capacity() { 663 drop(guard); 664 vec_alloc = KVVec::with_capacity((1 + len).next_power_of_two(), flags)?; 665 continue; 666 } 667 mem::swap(&mut inner.freeze_list, &mut vec_alloc); 668 for elem in vec_alloc.drain_all() { 669 inner.freeze_list.push_within_capacity(elem)?; 670 } 671 } 672 inner.freeze_list.push_within_capacity(process.clone())?; 673 return Ok(()); 674 } 675 } 676 677 pub(crate) fn remove_freeze_listener(&self, p: &Arc<Process>) { 678 let _unused_capacity; 679 let mut guard = self.owner.inner.lock(); 680 let inner = self.inner.access_mut(&mut guard); 681 let len = inner.freeze_list.len(); 682 inner.freeze_list.retain(|proc| !Arc::ptr_eq(proc, p)); 683 if len == inner.freeze_list.len() { 684 pr_warn!( 685 "Could not remove freeze listener for {}\n", 686 p.pid_in_current_ns() 687 ); 688 } 689 if inner.freeze_list.is_empty() { 690 _unused_capacity = mem::replace(&mut inner.freeze_list, KVVec::new()); 691 } 692 } 693 694 pub(crate) fn freeze_list<'a>(&'a self, guard: &'a ProcessInner) -> &'a [Arc<Process>] { 695 &self.inner.access(guard).freeze_list 696 } 697 } 698 699 impl DeliverToRead for Node { 700 fn do_work( 701 self: DArc<Self>, 702 _thread: &Thread, 703 writer: &mut BinderReturnWriter<'_>, 704 ) -> Result<bool> { 705 let mut owner_inner = self.owner.inner.lock(); 706 let inner = self.inner.access_mut(&mut owner_inner); 707 708 assert!(inner.delivery_state.has_pushed_node); 709 if inner.delivery_state.has_pushed_wrapper { 710 // If the wrapper is scheduled, then we are either a normal push or weak zero2one 711 // increment, and the wrapper is a strong zero2one increment, so the wrapper always 712 // takes precedence over us. 713 assert!(inner.delivery_state.has_strong_zero2one); 714 inner.delivery_state.has_pushed_node = false; 715 inner.delivery_state.has_weak_zero2one = false; 716 return Ok(true); 717 } 718 719 inner.delivery_state.has_pushed_node = false; 720 inner.delivery_state.has_weak_zero2one = false; 721 inner.delivery_state.has_strong_zero2one = false; 722 723 self.do_work_locked(writer, owner_inner) 724 } 725 726 fn cancel(self: DArc<Self>) {} 727 728 fn should_sync_wakeup(&self) -> bool { 729 false 730 } 731 732 #[inline(never)] 733 fn debug_print(&self, m: &SeqFile, prefix: &str, _tprefix: &str) -> Result<()> { 734 seq_print!( 735 m, 736 "{}node work {}: u{:016x} c{:016x}\n", 737 prefix, 738 self.debug_id, 739 self.ptr, 740 self.cookie, 741 ); 742 Ok(()) 743 } 744 } 745 746 /// Represents something that holds one or more ref-counts to a `Node`. 747 /// 748 /// Whenever process A holds a refcount to a node owned by a different process B, then process A 749 /// will store a `NodeRef` that refers to the `Node` in process B. When process A releases the 750 /// refcount, we destroy the NodeRef, which decrements the ref-count in process A. 751 /// 752 /// This type is also used for some other cases. For example, a transaction allocation holds a 753 /// refcount on the target node, and this is implemented by storing a `NodeRef` in the allocation 754 /// so that the destructor of the allocation will drop a refcount of the `Node`. 755 pub(crate) struct NodeRef { 756 pub(crate) node: DArc<Node>, 757 /// How many times does this NodeRef hold a refcount on the Node? 758 strong_node_count: usize, 759 weak_node_count: usize, 760 /// How many times does userspace hold a refcount on this NodeRef? 761 strong_count: usize, 762 weak_count: usize, 763 } 764 765 impl NodeRef { 766 pub(crate) fn new(node: DArc<Node>, strong_count: usize, weak_count: usize) -> Self { 767 Self { 768 node, 769 strong_node_count: strong_count, 770 weak_node_count: weak_count, 771 strong_count, 772 weak_count, 773 } 774 } 775 776 pub(crate) fn absorb(&mut self, mut other: Self) { 777 assert!( 778 Arc::ptr_eq(&self.node, &other.node), 779 "absorb called with differing nodes" 780 ); 781 self.strong_node_count += other.strong_node_count; 782 self.weak_node_count += other.weak_node_count; 783 self.strong_count += other.strong_count; 784 self.weak_count += other.weak_count; 785 other.strong_count = 0; 786 other.weak_count = 0; 787 other.strong_node_count = 0; 788 other.weak_node_count = 0; 789 790 if self.strong_node_count >= 2 || self.weak_node_count >= 2 { 791 let mut guard = self.node.owner.inner.lock(); 792 let inner = self.node.inner.access_mut(&mut guard); 793 794 if self.strong_node_count >= 2 { 795 inner.strong.count -= self.strong_node_count - 1; 796 self.strong_node_count = 1; 797 assert_ne!(inner.strong.count, 0); 798 } 799 if self.weak_node_count >= 2 { 800 inner.weak.count -= self.weak_node_count - 1; 801 self.weak_node_count = 1; 802 assert_ne!(inner.weak.count, 0); 803 } 804 } 805 } 806 807 pub(crate) fn get_count(&self) -> (usize, usize) { 808 (self.strong_count, self.weak_count) 809 } 810 811 pub(crate) fn clone(&self, strong: bool) -> Result<NodeRef> { 812 if strong && self.strong_count == 0 { 813 return Err(EINVAL); 814 } 815 Ok(self 816 .node 817 .owner 818 .inner 819 .lock() 820 .new_node_ref(self.node.clone(), strong, None)) 821 } 822 823 /// Updates (increments or decrements) the number of references held against the node. If the 824 /// count being updated transitions from 0 to 1 or from 1 to 0, the node is notified by having 825 /// its `update_refcount` function called. 826 /// 827 /// Returns whether `self` should be removed (when both counts are zero). 828 pub(crate) fn update(&mut self, inc: bool, strong: bool) -> bool { 829 if strong && self.strong_count == 0 { 830 return false; 831 } 832 let (count, node_count, other_count) = if strong { 833 ( 834 &mut self.strong_count, 835 &mut self.strong_node_count, 836 self.weak_count, 837 ) 838 } else { 839 ( 840 &mut self.weak_count, 841 &mut self.weak_node_count, 842 self.strong_count, 843 ) 844 }; 845 if inc { 846 if *count == 0 { 847 *node_count = 1; 848 self.node.update_refcount(true, 1, strong); 849 } 850 *count += 1; 851 } else { 852 if *count == 0 { 853 pr_warn!( 854 "pid {} performed invalid decrement on ref\n", 855 kernel::current!().pid() 856 ); 857 return false; 858 } 859 *count -= 1; 860 if *count == 0 { 861 self.node.update_refcount(false, *node_count, strong); 862 *node_count = 0; 863 return other_count == 0; 864 } 865 } 866 false 867 } 868 } 869 870 impl Drop for NodeRef { 871 // This destructor is called conditionally from `Allocation::drop`. That branch is often 872 // mispredicted. Inlining this method call reduces the cost of those branch mispredictions. 873 #[inline(always)] 874 fn drop(&mut self) { 875 if self.strong_node_count > 0 { 876 self.node 877 .update_refcount(false, self.strong_node_count, true); 878 } 879 if self.weak_node_count > 0 { 880 self.node 881 .update_refcount(false, self.weak_node_count, false); 882 } 883 } 884 } 885 886 struct NodeDeathInner { 887 dead: bool, 888 cleared: bool, 889 notification_done: bool, 890 /// Indicates whether the normal flow was interrupted by removing the handle. In this case, we 891 /// need behave as if the death notification didn't exist (i.e., we don't deliver anything to 892 /// the user. 893 aborted: bool, 894 } 895 896 /// Used to deliver notifications when a process dies. 897 /// 898 /// A process can request to be notified when a process dies using `BC_REQUEST_DEATH_NOTIFICATION`. 899 /// This will make the driver send a `BR_DEAD_BINDER` to userspace when the process dies (or 900 /// immediately if it is already dead). Userspace is supposed to respond with `BC_DEAD_BINDER_DONE` 901 /// once it has processed the notification. 902 /// 903 /// Userspace can unregister from death notifications using the `BC_CLEAR_DEATH_NOTIFICATION` 904 /// command. In this case, the kernel will respond with `BR_CLEAR_DEATH_NOTIFICATION_DONE` once the 905 /// notification has been removed. Note that if the remote process dies before the kernel has 906 /// responded with `BR_CLEAR_DEATH_NOTIFICATION_DONE`, then the kernel will still send a 907 /// `BR_DEAD_BINDER`, which userspace must be able to process. In this case, the kernel will wait 908 /// for the `BC_DEAD_BINDER_DONE` command before it sends `BR_CLEAR_DEATH_NOTIFICATION_DONE`. 909 /// 910 /// Note that even if the kernel sends a `BR_DEAD_BINDER`, this does not remove the death 911 /// notification. Userspace must still remove it manually using `BC_CLEAR_DEATH_NOTIFICATION`. 912 /// 913 /// If a process uses `BC_RELEASE` to destroy its last refcount on a node that has an active death 914 /// registration, then the death registration is immediately deleted (we implement this using the 915 /// `aborted` field). However, userspace is not supposed to delete a `NodeRef` without first 916 /// deregistering death notifications, so this codepath is not executed under normal circumstances. 917 #[pin_data] 918 pub(crate) struct NodeDeath { 919 node: DArc<Node>, 920 process: Arc<Process>, 921 pub(crate) cookie: u64, 922 #[pin] 923 links_track: AtomicTracker<0>, 924 /// Used by the owner `Node` to store a list of registered death notifications. 925 /// 926 /// # Invariants 927 /// 928 /// Only ever used with the `death_list` list of `self.node`. 929 #[pin] 930 death_links: ListLinks<1>, 931 /// Used by the process to keep track of the death notifications for which we have sent a 932 /// `BR_DEAD_BINDER` but not yet received a `BC_DEAD_BINDER_DONE`. 933 /// 934 /// # Invariants 935 /// 936 /// Only ever used with the `delivered_deaths` list of `self.process`. 937 #[pin] 938 delivered_links: ListLinks<2>, 939 #[pin] 940 delivered_links_track: AtomicTracker<2>, 941 #[pin] 942 inner: SpinLock<NodeDeathInner>, 943 } 944 945 impl NodeDeath { 946 /// Constructs a new node death notification object. 947 pub(crate) fn new( 948 node: DArc<Node>, 949 process: Arc<Process>, 950 cookie: u64, 951 ) -> impl PinInit<DTRWrap<Self>> { 952 DTRWrap::new(pin_init!( 953 Self { 954 node, 955 process, 956 cookie, 957 links_track <- AtomicTracker::new(), 958 death_links <- ListLinks::new(), 959 delivered_links <- ListLinks::new(), 960 delivered_links_track <- AtomicTracker::new(), 961 inner <- kernel::new_spinlock!(NodeDeathInner { 962 dead: false, 963 cleared: false, 964 notification_done: false, 965 aborted: false, 966 }, "NodeDeath::inner"), 967 } 968 )) 969 } 970 971 /// Sets the cleared flag to `true`. 972 /// 973 /// It removes `self` from the node's death notification list if needed. 974 /// 975 /// Returns whether it needs to be queued. 976 pub(crate) fn set_cleared(self: &DArc<Self>, abort: bool) -> bool { 977 let (needs_removal, needs_queueing) = { 978 // Update state and determine if we need to queue a work item. We only need to do it 979 // when the node is not dead or if the user already completed the death notification. 980 let mut inner = self.inner.lock(); 981 if abort { 982 inner.aborted = true; 983 } 984 if inner.cleared { 985 // Already cleared. 986 return false; 987 } 988 inner.cleared = true; 989 (!inner.dead, !inner.dead || inner.notification_done) 990 }; 991 992 // Remove death notification from node. 993 if needs_removal { 994 let mut owner_inner = self.node.owner.inner.lock(); 995 let node_inner = self.node.inner.access_mut(&mut owner_inner); 996 // SAFETY: A `NodeDeath` is never inserted into the death list of any node other than 997 // its owner, so it is either in this death list or in no death list. 998 unsafe { node_inner.death_list.remove(self) }; 999 } 1000 needs_queueing 1001 } 1002 1003 /// Sets the 'notification done' flag to `true`. 1004 pub(crate) fn set_notification_done(self: DArc<Self>, thread: &Thread) { 1005 let needs_queueing = { 1006 let mut inner = self.inner.lock(); 1007 inner.notification_done = true; 1008 inner.cleared 1009 }; 1010 if needs_queueing { 1011 if let Some(death) = ListArc::try_from_arc_or_drop(self) { 1012 let _ = thread.push_work_if_looper(death); 1013 } 1014 } 1015 } 1016 1017 /// Sets the 'dead' flag to `true` and queues work item if needed. 1018 pub(crate) fn set_dead(self: DArc<Self>) { 1019 let needs_queueing = { 1020 let mut inner = self.inner.lock(); 1021 if inner.cleared { 1022 false 1023 } else { 1024 inner.dead = true; 1025 true 1026 } 1027 }; 1028 if needs_queueing { 1029 // Push the death notification to the target process. There is nothing else to do if 1030 // it's already dead. 1031 if let Some(death) = ListArc::try_from_arc_or_drop(self) { 1032 let process = death.process.clone(); 1033 let _ = process.push_work(death); 1034 } 1035 } 1036 } 1037 } 1038 1039 kernel::list::impl_list_arc_safe! { 1040 impl ListArcSafe<0> for NodeDeath { 1041 tracked_by links_track: AtomicTracker; 1042 } 1043 } 1044 1045 kernel::list::impl_list_arc_safe! { 1046 impl ListArcSafe<1> for DTRWrap<NodeDeath> { untracked; } 1047 } 1048 kernel::list::impl_list_item! { 1049 impl ListItem<1> for DTRWrap<NodeDeath> { 1050 using ListLinks { self.wrapped.death_links }; 1051 } 1052 } 1053 1054 kernel::list::impl_list_arc_safe! { 1055 impl ListArcSafe<2> for DTRWrap<NodeDeath> { 1056 tracked_by wrapped: NodeDeath; 1057 } 1058 } 1059 kernel::list::impl_list_arc_safe! { 1060 impl ListArcSafe<2> for NodeDeath { 1061 tracked_by delivered_links_track: AtomicTracker<2>; 1062 } 1063 } 1064 kernel::list::impl_list_item! { 1065 impl ListItem<2> for DTRWrap<NodeDeath> { 1066 using ListLinks { self.wrapped.delivered_links }; 1067 } 1068 } 1069 1070 impl DeliverToRead for NodeDeath { 1071 fn do_work( 1072 self: DArc<Self>, 1073 _thread: &Thread, 1074 writer: &mut BinderReturnWriter<'_>, 1075 ) -> Result<bool> { 1076 let done = { 1077 let inner = self.inner.lock(); 1078 if inner.aborted { 1079 return Ok(true); 1080 } 1081 inner.cleared && (!inner.dead || inner.notification_done) 1082 }; 1083 1084 let cookie = self.cookie; 1085 let cmd = if done { 1086 BR_CLEAR_DEATH_NOTIFICATION_DONE 1087 } else { 1088 let process = self.process.clone(); 1089 let mut process_inner = process.inner.lock(); 1090 let inner = self.inner.lock(); 1091 if inner.aborted { 1092 return Ok(true); 1093 } 1094 // We're still holding the inner lock, so it cannot be aborted while we insert it into 1095 // the delivered list. 1096 process_inner.death_delivered(self.clone()); 1097 BR_DEAD_BINDER 1098 }; 1099 1100 writer.write_code(cmd)?; 1101 writer.write_payload(&cookie)?; 1102 // DEAD_BINDER notifications can cause transactions, so stop processing work items when we 1103 // get to a death notification. 1104 Ok(cmd != BR_DEAD_BINDER) 1105 } 1106 1107 fn cancel(self: DArc<Self>) {} 1108 1109 fn should_sync_wakeup(&self) -> bool { 1110 false 1111 } 1112 1113 #[inline(never)] 1114 fn debug_print(&self, m: &SeqFile, prefix: &str, _tprefix: &str) -> Result<()> { 1115 let inner = self.inner.lock(); 1116 1117 let dead_binder = inner.dead && !inner.notification_done; 1118 1119 if dead_binder { 1120 if inner.cleared { 1121 seq_print!(m, "{}has cleared dead binder\n", prefix); 1122 } else { 1123 seq_print!(m, "{}has dead binder\n", prefix); 1124 } 1125 } else { 1126 seq_print!(m, "{}has cleared death notification\n", prefix); 1127 } 1128 1129 Ok(()) 1130 } 1131 } 1132