diff options
Diffstat (limited to 'drivers/android')
| -rw-r--r-- | drivers/android/binder.c | 38 | ||||
| -rw-r--r-- | drivers/android/binder/error.rs | 5 | ||||
| -rw-r--r-- | drivers/android/binder/freeze.rs | 22 | ||||
| -rw-r--r-- | drivers/android/binder/node.rs | 2 | ||||
| -rw-r--r-- | drivers/android/binder/process.rs | 54 | ||||
| -rw-r--r-- | drivers/android/binder/range_alloc/tree.rs | 2 | ||||
| -rw-r--r-- | drivers/android/binder/stats.rs | 6 | ||||
| -rw-r--r-- | drivers/android/binder/transaction.rs | 6 | ||||
| -rw-r--r-- | drivers/android/binder_netlink.c | 1 | ||||
| -rw-r--r-- | drivers/android/binder_netlink.h | 1 |
10 files changed, 83 insertions, 54 deletions
diff --git a/drivers/android/binder.c b/drivers/android/binder.c index 8c99ceaa303b..a3a1b5c33ba3 100644 --- a/drivers/android/binder.c +++ b/drivers/android/binder.c @@ -851,17 +851,8 @@ static int binder_inc_node_nilocked(struct binder_node *node, int strong, } else { if (!internal) node->local_weak_refs++; - if (!node->has_weak_ref && list_empty(&node->work.entry)) { - if (target_list == NULL) { - pr_err("invalid inc weak node for %d\n", - node->debug_id); - return -EINVAL; - } - /* - * See comment above - */ + if (!node->has_weak_ref && target_list && list_empty(&node->work.entry)) binder_enqueue_work_ilocked(&node->work, target_list); - } } return 0; } @@ -2418,10 +2409,10 @@ err_fd_not_accepted: /** * struct binder_ptr_fixup - data to be fixed-up in target buffer - * @offset offset in target buffer to fixup - * @skip_size bytes to skip in copy (fixup will be written later) - * @fixup_data data to write at fixup offset - * @node list node + * @offset: offset in target buffer to fixup + * @skip_size: bytes to skip in copy (fixup will be written later) + * @fixup_data: data to write at fixup offset + * @node: list node * * This is used for the pointer fixup list (pf) which is created and consumed * during binder_transaction() and is only accessed locally. No @@ -2438,10 +2429,10 @@ struct binder_ptr_fixup { /** * struct binder_sg_copy - scatter-gather data to be copied - * @offset offset in target buffer - * @sender_uaddr user address in source buffer - * @length bytes to copy - * @node list node + * @offset: offset in target buffer + * @sender_uaddr: user address in source buffer + * @length: bytes to copy + * @node: list node * * This is used for the sg copy list (sgc) which is created and consumed * during binder_transaction() and is only accessed locally. No @@ -4063,14 +4054,15 @@ binder_freeze_notification_done(struct binder_proc *proc, /** * binder_free_buf() - free the specified buffer - * @proc: binder proc that owns buffer - * @buffer: buffer to be freed - * @is_failure: failed to send transaction + * @proc: binder proc that owns buffer + * @thread: binder thread performing the buffer release + * @buffer: buffer to be freed + * @is_failure: failed to send transaction * - * If buffer for an async transaction, enqueue the next async + * If the buffer is for an async transaction, enqueue the next async * transaction from the node. * - * Cleanup buffer and free it. + * Cleanup the buffer and free it. */ static void binder_free_buf(struct binder_proc *proc, diff --git a/drivers/android/binder/error.rs b/drivers/android/binder/error.rs index 9921827267d0..b24497cfa292 100644 --- a/drivers/android/binder/error.rs +++ b/drivers/android/binder/error.rs @@ -2,6 +2,7 @@ // Copyright (C) 2025 Google LLC. +use kernel::fmt; use kernel::prelude::*; use crate::defs::*; @@ -76,8 +77,8 @@ impl From<kernel::alloc::AllocError> for BinderError { } } -impl core::fmt::Debug for BinderError { - fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { +impl fmt::Debug for BinderError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self.reply { BR_FAILED_REPLY => match self.source.as_ref() { Some(source) => f diff --git a/drivers/android/binder/freeze.rs b/drivers/android/binder/freeze.rs index e68c3c8bc55a..53b60035639a 100644 --- a/drivers/android/binder/freeze.rs +++ b/drivers/android/binder/freeze.rs @@ -106,13 +106,22 @@ impl DeliverToRead for FreezeMessage { return Ok(true); } if freeze.is_clearing { - _removed_listener = freeze_entry.remove_node(); + kernel::warn_on!(freeze.num_cleared_duplicates != 0); + if freeze.num_pending_duplicates > 0 { + // The primary freeze listener was deleted, so convert a pending duplicate back + // into the primary one. + freeze.num_pending_duplicates -= 1; + freeze.is_pending = true; + freeze.is_clearing = true; + } else { + _removed_listener = freeze_entry.remove_node(); + } drop(node_refs); writer.write_code(BR_CLEAR_FREEZE_NOTIFICATION_DONE)?; writer.write_payload(&self.cookie.0)?; Ok(true) } else { - let is_frozen = freeze.node.owner.inner.lock().is_frozen; + let is_frozen = freeze.node.owner.inner.lock().is_frozen.is_fully_frozen(); if freeze.last_is_frozen == Some(is_frozen) { return Ok(true); } @@ -245,8 +254,9 @@ impl Process { ); return Err(EINVAL); } - if freeze.is_clearing { - // Immediately send another FreezeMessage for BR_CLEAR_FREEZE_NOTIFICATION_DONE. + let is_frozen = freeze.node.owner.inner.lock().is_frozen.is_fully_frozen(); + if freeze.is_clearing || freeze.last_is_frozen != Some(is_frozen) { + // Immediately send another FreezeMessage. clear_msg = Some(FreezeMessage::init(alloc, cookie)); } freeze.is_pending = false; @@ -321,7 +331,7 @@ impl Process { KVVec::with_capacity(8, GFP_KERNEL).unwrap_or_else(|_err| KVVec::new()); let mut inner = self.lock_with_nodes(); - let mut curr = inner.nodes.cursor_front(); + let mut curr = inner.nodes.cursor_front_mut(); while let Some(cursor) = curr { let (key, node) = cursor.current(); let key = *key; @@ -335,7 +345,7 @@ impl Process { // Find the node we were looking at and try again. If the set of nodes was changed, // then just proceed to the next node. This is ok because we don't guarantee the // inclusion of nodes that are added or removed in parallel with this operation. - curr = inner.nodes.cursor_lower_bound(&key); + curr = inner.nodes.cursor_lower_bound_mut(&key); continue; } diff --git a/drivers/android/binder/node.rs b/drivers/android/binder/node.rs index ade895ef791e..08d362deaf61 100644 --- a/drivers/android/binder/node.rs +++ b/drivers/android/binder/node.rs @@ -687,7 +687,7 @@ impl Node { ); } if inner.freeze_list.is_empty() { - _unused_capacity = mem::replace(&mut inner.freeze_list, KVVec::new()); + _unused_capacity = mem::take(&mut inner.freeze_list); } } diff --git a/drivers/android/binder/process.rs b/drivers/android/binder/process.rs index f13a747e784c..e5237e9ec552 100644 --- a/drivers/android/binder/process.rs +++ b/drivers/android/binder/process.rs @@ -72,6 +72,33 @@ impl Mapping { const PROC_DEFER_FLUSH: u8 = 1; const PROC_DEFER_RELEASE: u8 = 2; +#[derive(Copy, Clone)] +pub(crate) enum IsFrozen { + Yes, + No, + InProgress, +} + +impl IsFrozen { + /// Whether incoming transactions should be rejected due to freeze. + pub(crate) fn is_frozen(self) -> bool { + match self { + IsFrozen::Yes => true, + IsFrozen::No => false, + IsFrozen::InProgress => true, + } + } + + /// Whether freeze notifications consider this process frozen. + pub(crate) fn is_fully_frozen(self) -> bool { + match self { + IsFrozen::Yes => true, + IsFrozen::No => false, + IsFrozen::InProgress => false, + } + } +} + /// The fields of `Process` protected by the spinlock. pub(crate) struct ProcessInner { is_manager: bool, @@ -98,7 +125,7 @@ pub(crate) struct ProcessInner { /// are woken up. outstanding_txns: u32, /// Process is frozen and unable to service binder transactions. - pub(crate) is_frozen: bool, + pub(crate) is_frozen: IsFrozen, /// Process received sync transactions since last frozen. pub(crate) sync_recv: bool, /// Process received async transactions since last frozen. @@ -124,7 +151,7 @@ impl ProcessInner { started_thread_count: 0, defer_work: 0, outstanding_txns: 0, - is_frozen: false, + is_frozen: IsFrozen::No, sync_recv: false, async_recv: false, binderfs_file: None, @@ -596,7 +623,7 @@ impl Process { " ref {}: desc {} {}node {debug_id} s {strong} w {weak}", r.debug_id, r.handle, - if dead { "dead " } else { "" }, + if dead { "dead " } else { "" } ); } } @@ -1260,7 +1287,7 @@ impl Process { let is_manager = { let mut inner = self.inner.lock(); inner.is_dead = true; - inner.is_frozen = false; + inner.is_frozen = IsFrozen::No; inner.sync_recv = false; inner.async_recv = false; inner.is_manager @@ -1293,7 +1320,7 @@ impl Process { { while let Some(node) = { let mut lock = self.inner.lock(); - lock.nodes.cursor_front().map(|c| c.remove_current().1) + lock.nodes.cursor_front_mut().map(|c| c.remove_current().1) } { node.to_key_value().1.release(); } @@ -1346,10 +1373,6 @@ impl Process { .alloc .take_for_each(|offset, size, debug_id, odata| { let ptr = offset + address; - pr_warn!( - "{}: removing orphan mapping {offset}:{size}\n", - self.pid_in_current_ns() - ); let mut alloc = Allocation::new(self.clone(), debug_id, offset, size, ptr, false); if let Some(data) = odata { @@ -1371,7 +1394,7 @@ impl Process { return; } inner.outstanding_txns -= 1; - inner.is_frozen && inner.outstanding_txns == 0 + inner.is_frozen.is_frozen() && inner.outstanding_txns == 0 }; if wake { @@ -1385,7 +1408,7 @@ impl Process { let mut inner = self.inner.lock(); inner.sync_recv = false; inner.async_recv = false; - inner.is_frozen = false; + inner.is_frozen = IsFrozen::No; drop(inner); msgs.send_messages(); return Ok(()); @@ -1394,7 +1417,7 @@ impl Process { let mut inner = self.inner.lock(); inner.sync_recv = false; inner.async_recv = false; - inner.is_frozen = true; + inner.is_frozen = IsFrozen::InProgress; if info.timeout_ms > 0 { let mut jiffies = kernel::time::msecs_to_jiffies(info.timeout_ms); @@ -1408,7 +1431,7 @@ impl Process { .wait_interruptible_timeout(&mut inner, jiffies) { CondVarTimeoutResult::Signal { .. } => { - inner.is_frozen = false; + inner.is_frozen = IsFrozen::No; return Err(ERESTARTSYS); } CondVarTimeoutResult::Woken { jiffies: remaining } => { @@ -1422,17 +1445,18 @@ impl Process { } if inner.txns_pending_locked() { - inner.is_frozen = false; + inner.is_frozen = IsFrozen::No; Err(EAGAIN) } else { drop(inner); match self.prepare_freeze_messages() { Ok(batch) => { + self.inner.lock().is_frozen = IsFrozen::Yes; batch.send_messages(); Ok(()) } Err(kernel::alloc::AllocError) => { - self.inner.lock().is_frozen = false; + self.inner.lock().is_frozen = IsFrozen::No; Err(ENOMEM) } } diff --git a/drivers/android/binder/range_alloc/tree.rs b/drivers/android/binder/range_alloc/tree.rs index 7b1a248fcb02..838fdd2b47ea 100644 --- a/drivers/android/binder/range_alloc/tree.rs +++ b/drivers/android/binder/range_alloc/tree.rs @@ -207,7 +207,7 @@ impl<T> TreeRangeAllocator<T> { } pub(crate) fn reservation_abort(&mut self, offset: usize) -> Result<FreedRange> { - let mut cursor = self.tree.cursor_lower_bound(&offset).ok_or_else(|| { + let mut cursor = self.tree.cursor_lower_bound_mut(&offset).ok_or_else(|| { pr_warn!( "EINVAL from range_alloc.reservation_abort - offset: {}", offset diff --git a/drivers/android/binder/stats.rs b/drivers/android/binder/stats.rs index a83ec111d2cb..037002651941 100644 --- a/drivers/android/binder/stats.rs +++ b/drivers/android/binder/stats.rs @@ -61,7 +61,7 @@ impl BinderStats { mod strings { use core::str::from_utf8_unchecked; - use kernel::str::CStr; + use kernel::str::{CStr, CStrExt as _}; extern "C" { static binder_command_strings: [*const u8; super::BC_COUNT]; @@ -72,7 +72,7 @@ mod strings { // SAFETY: Accessing `binder_command_strings` is always safe. let c_str_ptr = unsafe { binder_command_strings[i] }; // SAFETY: The `binder_command_strings` array only contains nul-terminated strings. - let bytes = unsafe { CStr::from_char_ptr(c_str_ptr) }.as_bytes(); + let bytes = unsafe { CStr::from_char_ptr(c_str_ptr) }.to_bytes(); // SAFETY: The `binder_command_strings` array only contains strings with ascii-chars. unsafe { from_utf8_unchecked(bytes) } } @@ -81,7 +81,7 @@ mod strings { // SAFETY: Accessing `binder_return_strings` is always safe. let c_str_ptr = unsafe { binder_return_strings[i] }; // SAFETY: The `binder_command_strings` array only contains nul-terminated strings. - let bytes = unsafe { CStr::from_char_ptr(c_str_ptr) }.as_bytes(); + let bytes = unsafe { CStr::from_char_ptr(c_str_ptr) }.to_bytes(); // SAFETY: The `binder_command_strings` array only contains strings with ascii-chars. unsafe { from_utf8_unchecked(bytes) } } diff --git a/drivers/android/binder/transaction.rs b/drivers/android/binder/transaction.rs index 02512175d622..4bd3c0e417eb 100644 --- a/drivers/android/binder/transaction.rs +++ b/drivers/android/binder/transaction.rs @@ -249,7 +249,7 @@ impl Transaction { if oneway { if let Some(target_node) = self.target_node.clone() { - if process_inner.is_frozen { + if process_inner.is_frozen.is_frozen() { process_inner.async_recv = true; if self.flags & TF_UPDATE_TXN != 0 { if let Some(t_outdated) = @@ -270,7 +270,7 @@ impl Transaction { } } - if process_inner.is_frozen { + if process_inner.is_frozen.is_frozen() { return Err(BinderError::new_frozen_oneway()); } else { return Ok(()); @@ -280,7 +280,7 @@ impl Transaction { } } - if process_inner.is_frozen { + if process_inner.is_frozen.is_frozen() { process_inner.sync_recv = true; return Err(BinderError::new_frozen()); } diff --git a/drivers/android/binder_netlink.c b/drivers/android/binder_netlink.c index d05397a50ca6..81e8432b5904 100644 --- a/drivers/android/binder_netlink.c +++ b/drivers/android/binder_netlink.c @@ -2,6 +2,7 @@ /* Do not edit directly, auto-generated from: */ /* Documentation/netlink/specs/binder.yaml */ /* YNL-GEN kernel source */ +/* To regenerate run: tools/net/ynl/ynl-regen.sh */ #include <net/netlink.h> #include <net/genetlink.h> diff --git a/drivers/android/binder_netlink.h b/drivers/android/binder_netlink.h index 882c7a6b537e..57399942a5e3 100644 --- a/drivers/android/binder_netlink.h +++ b/drivers/android/binder_netlink.h @@ -2,6 +2,7 @@ /* Do not edit directly, auto-generated from: */ /* Documentation/netlink/specs/binder.yaml */ /* YNL-GEN kernel header */ +/* To regenerate run: tools/net/ynl/ynl-regen.sh */ #ifndef _LINUX_BINDER_GEN_H #define _LINUX_BINDER_GEN_H |
