The Linux Kernel Mailing List
 help / color / mirror / Atom feed
* [PATCH v2 0/7] rust_binder : Implement dynamic debug logging mask
@ 2026-07-10 14:32 Jahnavi MN via B4 Relay
  2026-07-10 14:32 ` [PATCH v2 1/7] rust_binder: Add " Jahnavi MN via B4 Relay
                   ` (8 more replies)
  0 siblings, 9 replies; 25+ messages in thread
From: Jahnavi MN via B4 Relay @ 2026-07-10 14:32 UTC (permalink / raw)
  To: Greg Kroah-Hartman, Arve Hjønnevåg, Todd Kjos,
	Christian Brauner, Carlos Llamas, Alice Ryhl, Miguel Ojeda,
	Boqun Feng, Gary Guo, Björn Roy Baron, Benno Lossin,
	Andreas Hindborg, Trevor Gross, Danilo Krummrich, Daniel Almeida,
	Tamir Duberstein, Alexandre Courbot, Onur Özkan
  Cc: linux-kernel, rust-for-linux, Jahnavi MN

When a user-space application sends malformed data or makes a
lifecycle mistake, the driver rejects it with a generic error code
(like -EINVAL). Without internal logs, the driver acts as a
"black box," forcing developers to guess which check failed.

In the legacy C Binder driver, this issue is solved using a dynamic
debug_mask module parameter that toggles verbose logs for specific
subsystems. This series brings the same critical capability to the
Rust Binder driver to provide developers with clear, real-time
feedback.

Instead of rebuilds, reboots, or guessing:
- Developers can enable logs instantly on a running device by writing to 
  `/sys/module/rust_binder/parameters/debug_mask`.
- It prints the exact reason for failures (such as alignment errors, 
  mismatched call stacks, or invalid handle references) directly into 
  `dmesg`, reducing debugging time from hours to seconds.
- It protects system logs by keeping logging off by default and only 
  enabling it when developers are actively troubleshooting.

Based on top of:
https://lore.kernel.org/rust-for-linux/20260707-upgrade-poll-v6-0-4b8fae7bf1d9@google.com/

Signed-off-by: Jahnavi MN <jahnavimn@google.com>
---
Changes in v2:
- Defined the debug mask categories using bitflags (impl_flags) to
  resolve potential Undefined Behavior and match Rust idioms.
- Added a tgid helper to rust/kernel/task.rs to expose the task
  group ID and optimize default "PID:TID" prefixing.
- Implemented the BINDER_DEBUG_DEATH_NOTIFICATION mask to log OOM
  failures, lifecycle updates, and async delivery to user-space.
- Added pid fields to ThreadError, DeliverCode, and FreezeMessage
  to ensure cancellation logs show the correct process PID instead
  of background kworker PIDs.
- Removed duplicate PID printing across workqueue, transaction
  failure, and stack unwinding logs.
- Refactored log formatting (e.g. formatted BinderError with {:?},
  used "strong"/"weak" strings, and improved message wording).
- Fixed logic bugs (restored missing update_ref block, moved manager
  lookup warnings).
- Cleaned up spurious newlines, corrected indentations, and adjusted
  all commit titles to be shorter and more meaningful.
- Link to v1: https://lore.kernel.org/r/20260703-rust_binder_debug_mask-v1-0-9bdf12b5325c@google.com

---
Jahnavi MN (7):
      rust_binder: Add dynamic debug logging mask
      rust_binder: Implement BINDER_DEBUG_USER_ERROR for freezer-related operation
      rust_binder: Implement BINDER_DEBUG_USER_ERROR for refcounting and death notifications
      rust_binder: Implement BINDER_DEBUG_USER_ERROR for transaction parsing failures
      rust_binder: Implement BINDER_DEBUG_FAILED_TRANSACTION
      rust_binder: Implement BINDER_DEBUG_DEATH_NOTIFICATION
      rust_binder: Implement BINDER_DEBUG_DEAD_TRANSACTION

 drivers/android/binder/debug.rs            |  80 ++++++++++++++++
 drivers/android/binder/freeze.rs           |  70 ++++++++++----
 drivers/android/binder/node.rs             |  30 +++++-
 drivers/android/binder/process.rs          |  62 ++++++++++--
 drivers/android/binder/rust_binder_main.rs |  16 +++-
 drivers/android/binder/rust_binderfs.c     |   3 +
 drivers/android/binder/thread.rs           | 149 ++++++++++++++++++++++-------
 drivers/android/binder/transaction.rs      |  15 +++
 rust/kernel/task.rs                        |   7 ++
 9 files changed, 363 insertions(+), 69 deletions(-)
---
base-commit: bf694eb01b1313f5510645ca34be4ed034ae08de
change-id: 20260702-rust_binder_debug_mask-636737015624

Best regards,
-- 
Jahnavi MN <jahnavimn@google.com>



^ permalink raw reply	[flat|nested] 25+ messages in thread

* [PATCH v2 1/7] rust_binder: Add dynamic debug logging mask
  2026-07-10 14:32 [PATCH v2 0/7] rust_binder : Implement dynamic debug logging mask Jahnavi MN via B4 Relay
@ 2026-07-10 14:32 ` Jahnavi MN via B4 Relay
  2026-07-10 14:59   ` Greg Kroah-Hartman
                     ` (2 more replies)
  2026-07-10 14:32 ` [PATCH v2 2/7] rust_binder: Implement BINDER_DEBUG_USER_ERROR for freezer-related operation Jahnavi MN via B4 Relay
                   ` (7 subsequent siblings)
  8 siblings, 3 replies; 25+ messages in thread
From: Jahnavi MN via B4 Relay @ 2026-07-10 14:32 UTC (permalink / raw)
  To: Greg Kroah-Hartman, Arve Hjønnevåg, Todd Kjos,
	Christian Brauner, Carlos Llamas, Alice Ryhl, Miguel Ojeda,
	Boqun Feng, Gary Guo, Björn Roy Baron, Benno Lossin,
	Andreas Hindborg, Trevor Gross, Danilo Krummrich, Daniel Almeida,
	Tamir Duberstein, Alexandre Courbot, Onur Özkan
  Cc: linux-kernel, rust-for-linux, Jahnavi MN

From: Jahnavi MN <jahnavimn@google.com>

Implement a dynamic debug logging mask (`debug_mask`) for the
`rust_binder` module to allow dynamic runtime configuration of log
levels. This enables parity with the legacy C driver's debug mask.

Since the Rust `module!` macro in the current kernel build does not yet
support declaring module parameters directly in Rust, we define the
`debug_mask` variable in a C companion file to expose it to the kernel
runtime and import it using FFI with volatile reads.

To verify the setup, instrument process lifecycle events (open, flush,
and release) in `process.rs` under the new `BINDER_DEBUG_OPEN_CLOSE`
logging mask. These entry-point events are chosen for initial validation
because they represent the start of the Binder lifecycle and occur
at low frequency, allowing simple runtime verification of the dynamic
toggle without log noise.

Signed-off-by: Jahnavi MN <jahnavimn@google.com>
---
 drivers/android/binder/debug.rs            | 80 ++++++++++++++++++++++++++++++
 drivers/android/binder/process.rs          |  7 ++-
 drivers/android/binder/rust_binder_main.rs |  2 +
 drivers/android/binder/rust_binderfs.c     |  3 ++
 rust/kernel/task.rs                        |  7 +++
 5 files changed, 98 insertions(+), 1 deletion(-)

diff --git a/drivers/android/binder/debug.rs b/drivers/android/binder/debug.rs
new file mode 100644
index 000000000000..da48bce3df54
--- /dev/null
+++ b/drivers/android/binder/debug.rs
@@ -0,0 +1,80 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (C) 2026 Google LLC.
+
+//! Binder debugging helpers.
+
+#![allow(dead_code)]
+
+kernel::impl_flags!(
+    /// Represents multiple debug mask flags.
+    #[derive(Debug, Clone, Default, Copy, PartialEq, Eq)]
+    pub struct DebugMasks(u32);
+
+    /// Represents a single debug mask category.
+    #[derive(Debug, Clone, Copy, PartialEq, Eq)]
+    pub enum DebugMask {
+        UserError = 1 << 0,
+        FailedTransaction = 1 << 1,
+        DeadTransaction = 1 << 2,
+        OpenClose = 1 << 3,
+        DeadBinder = 1 << 4,
+        DeathNotification = 1 << 5,
+        ReadWrite = 1 << 6,
+        UserRefs = 1 << 7,
+        Threads = 1 << 8,
+        Transaction = 1 << 9,
+        TransactionComplete = 1 << 10,
+        FreeBuffer = 1 << 11,
+        InternalRefs = 1 << 12,
+        PriorityCap = 1 << 13,
+        Spinlocks = 1 << 14,
+    }
+);
+
+extern "C" {
+    // Declared as static mut because the value is mutated dynamically by C sysfs.
+    static mut rust_binder_debug_mask: u32;
+}
+
+/// Checks if the given debug logging category is enabled in the mask.
+pub(crate) fn debug_mask_enabled(mask: DebugMask) -> bool {
+    // SAFETY: `rust_binder_debug_mask` is defined in C and can be mutated at any time.
+    // We read it via volatile to ensure we fetch the current value from memory.
+    let current_mask = unsafe { core::ptr::read_volatile(&raw const rust_binder_debug_mask) };
+    (current_mask & (mask as u32)) != 0
+}
+
+/// Prints a debug log if the specified mask category is enabled.
+#[macro_export]
+macro_rules! binder_debug {
+    // 1. Internal helper rule to do the raw print.
+    (raw, $($arg:tt)*) => {
+        kernel::pr_info!($($arg)*);
+    };
+
+    // 2. Rule to explicitly specify a PID (used in kworkers).
+    (pid=$pid:expr, $mask:ident, $($arg:tt)*) => {
+        if $crate::debug::debug_mask_enabled($crate::debug::DebugMask::$mask) {
+            $crate::binder_debug!(
+                raw,
+                "{}: {}\n",
+                $pid,
+                kernel::prelude::fmt!($($arg)*)
+            );
+        }
+    };
+
+    // 3. Default rule (automatically prepends "PID:TID" of the current calling thread).
+    ($mask:ident, $($arg:tt)*) => {
+        if $crate::debug::debug_mask_enabled($crate::debug::DebugMask::$mask) {
+            let thread = kernel::current!();
+            $crate::binder_debug!(
+                raw,
+                "{}:{} {}\n",
+                thread.tgid(),
+                thread.pid(),
+                kernel::prelude::fmt!($($arg)*)
+            );
+        }
+    };
+}
diff --git a/drivers/android/binder/process.rs b/drivers/android/binder/process.rs
index f855d8d9818c..836a0db92354 100644
--- a/drivers/android/binder/process.rs
+++ b/drivers/android/binder/process.rs
@@ -1349,6 +1349,7 @@ pub(crate) fn lock_with_nodes(&self) -> WithNodes<'_> {
     }
 
     fn deferred_flush(&self) {
+        binder_debug!(pid=self.task.pid(), OpenClose, "flushing process");
         let inner = self.inner.lock();
         for thread in inner.threads.values() {
             thread.exit_looper();
@@ -1356,6 +1357,8 @@ fn deferred_flush(&self) {
     }
 
     fn deferred_release(self: Arc<Self>) {
+        binder_debug!(pid=self.task.pid(), OpenClose, "releasing process");
+
         let is_manager = {
             let mut inner = self.inner.lock();
             inner.is_dead = true;
@@ -1658,7 +1661,9 @@ fn ioctl_write_read(
 /// The file operations supported by `Process`.
 impl Process {
     pub(crate) fn open(ctx: ArcBorrow<'_, Context>, file: &File) -> Result<Arc<Process>> {
-        Self::new(ctx.into(), ARef::from(file.cred()))
+        let proc = Self::new(ctx.into(), ARef::from(file.cred()))?;
+        binder_debug!(OpenClose, "opened process");
+        Ok(proc)
     }
 
     pub(crate) fn release(this: Arc<Process>, _file: &File) {
diff --git a/drivers/android/binder/rust_binder_main.rs b/drivers/android/binder/rust_binder_main.rs
index df47aba05133..995e6131bb77 100644
--- a/drivers/android/binder/rust_binder_main.rs
+++ b/drivers/android/binder/rust_binder_main.rs
@@ -31,6 +31,8 @@
 mod context;
 mod deferred_close;
 mod defs;
+#[macro_use]
+mod debug;
 mod error;
 mod netlink;
 mod node;
diff --git a/drivers/android/binder/rust_binderfs.c b/drivers/android/binder/rust_binderfs.c
index ade1c4d92499..fa8b38465550 100644
--- a/drivers/android/binder/rust_binderfs.c
+++ b/drivers/android/binder/rust_binderfs.c
@@ -51,6 +51,9 @@ DEFINE_SHOW_ATTRIBUTE(rust_binder_proc);
 char *rust_binder_devices_param = CONFIG_ANDROID_BINDER_DEVICES;
 module_param_named(rust_devices, rust_binder_devices_param, charp, 0444);
 
+u32 rust_binder_debug_mask = 7;
+module_param_named(debug_mask, rust_binder_debug_mask, uint, 0644);
+
 static dev_t binderfs_dev;
 static DEFINE_MUTEX(binderfs_minors_mutex);
 static DEFINE_IDA(binderfs_minors);
diff --git a/rust/kernel/task.rs b/rust/kernel/task.rs
index 38273f4eedb5..1b290c61714d 100644
--- a/rust/kernel/task.rs
+++ b/rust/kernel/task.rs
@@ -210,6 +210,13 @@ pub fn pid(&self) -> Pid {
         unsafe { *ptr::addr_of!((*self.as_ptr()).pid) }
     }
 
+    /// Returns the TGID (Thread Group ID / Process ID) of the given task.
+    pub fn tgid(&self) -> Pid {
+        // SAFETY: The tgid of a task never changes after initialization, so reading this field is
+        // not a data race.
+        unsafe { *ptr::addr_of!((*self.as_ptr()).tgid) }
+    }
+
     /// Returns the UID of the given task.
     #[inline]
     pub fn uid(&self) -> Kuid {

-- 
2.55.0.795.g602f6c329a-goog



^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH v2 2/7] rust_binder: Implement BINDER_DEBUG_USER_ERROR for freezer-related operation
  2026-07-10 14:32 [PATCH v2 0/7] rust_binder : Implement dynamic debug logging mask Jahnavi MN via B4 Relay
  2026-07-10 14:32 ` [PATCH v2 1/7] rust_binder: Add " Jahnavi MN via B4 Relay
@ 2026-07-10 14:32 ` Jahnavi MN via B4 Relay
  2026-07-10 19:55   ` Carlos Llamas
  2026-07-10 14:32 ` [PATCH v2 3/7] rust_binder: Implement BINDER_DEBUG_USER_ERROR for refcounting and death notifications Jahnavi MN via B4 Relay
                   ` (6 subsequent siblings)
  8 siblings, 1 reply; 25+ messages in thread
From: Jahnavi MN via B4 Relay @ 2026-07-10 14:32 UTC (permalink / raw)
  To: Greg Kroah-Hartman, Arve Hjønnevåg, Todd Kjos,
	Christian Brauner, Carlos Llamas, Alice Ryhl, Miguel Ojeda,
	Boqun Feng, Gary Guo, Björn Roy Baron, Benno Lossin,
	Andreas Hindborg, Trevor Gross, Danilo Krummrich, Daniel Almeida,
	Tamir Duberstein, Alexandre Courbot, Onur Özkan
  Cc: linux-kernel, rust-for-linux, Jahnavi MN

From: Jahnavi MN <jahnavimn@google.com>

This adds dynamic debug logs for:
- Requesting freeze notifications on invalid references, duplicate
  cookies, or already active registrations.
- Completing freeze notifications that are not pending or not found.
- Clearing freeze notifications on invalid references, inactive
  notifications, or cookie mismatches.

Signed-off-by: Jahnavi MN <jahnavimn@google.com>
---
 drivers/android/binder/freeze.rs | 46 +++++++++++++++++++++++++++++++---------
 1 file changed, 36 insertions(+), 10 deletions(-)

diff --git a/drivers/android/binder/freeze.rs b/drivers/android/binder/freeze.rs
index f43388ed6ae2..70b192ec199a 100644
--- a/drivers/android/binder/freeze.rs
+++ b/drivers/android/binder/freeze.rs
@@ -189,12 +189,18 @@ pub(crate) fn request_freeze_notif(
             info = match node_refs.by_handle.get_mut(&handle) {
                 Some(info) => info,
                 None => {
-                    pr_warn!("BC_REQUEST_FREEZE_NOTIFICATION invalid ref {}\n", handle);
+                    binder_debug!(
+                        UserError,
+                        "BC_REQUEST_FREEZE_NOTIFICATION invalid ref {handle}"
+                    );
                     return Err(EINVAL);
                 }
             };
             if info.freeze().is_some() {
-                pr_warn!("BC_REQUEST_FREEZE_NOTIFICATION already set\n");
+                binder_debug!(
+                    UserError,
+                    "BC_REQUEST_FREEZE_NOTIFICATION already set"
+                );
                 return Err(EINVAL);
             }
             let node_ref = info.node_ref();
@@ -202,7 +208,10 @@ pub(crate) fn request_freeze_notif(
 
             if let rbtree::Entry::Occupied(ref dupe) = freeze_entry {
                 if !dupe.get().allow_duplicate(&node_ref.node) {
-                    pr_warn!("BC_REQUEST_FREEZE_NOTIFICATION duplicate cookie\n");
+                    binder_debug!(
+                        UserError,
+                        "BC_REQUEST_FREEZE_NOTIFICATION duplicate cookie"
+                    );
                     return Err(EINVAL);
                 }
             }
@@ -267,7 +276,11 @@ pub(crate) fn freeze_notif_done(self: &Arc<Self>, reader: &mut UserSliceReader)
         let mut node_refs_guard = self.node_refs.lock();
         let node_refs = &mut *node_refs_guard;
         let Some(freeze) = node_refs.freeze_listeners.get_mut(&cookie) else {
-            pr_warn!("BC_FREEZE_NOTIFICATION_DONE {:016x} not found\n", cookie.0);
+            binder_debug!(
+                UserError,
+                "BC_FREEZE_NOTIFICATION_DONE {:016x} not found",
+                cookie.0
+            );
             return Err(EINVAL);
         };
         let mut clear_msg = None;
@@ -277,8 +290,9 @@ pub(crate) fn freeze_notif_done(self: &Arc<Self>, reader: &mut UserSliceReader)
             freeze.num_cleared_duplicates += 1;
         } else {
             if !freeze.is_pending {
-                pr_warn!(
-                    "BC_FREEZE_NOTIFICATION_DONE {:016x} not pending\n",
+                binder_debug!(
+                    UserError,
+                    "BC_FREEZE_NOTIFICATION_DONE {:016x} not pending",
                     cookie.0
                 );
                 return Err(EINVAL);
@@ -307,19 +321,31 @@ pub(crate) fn clear_freeze_notif(self: &Arc<Self>, reader: &mut UserSliceReader)
         let mut node_refs_guard = self.node_refs.lock();
         let node_refs = &mut *node_refs_guard;
         let Some(info) = node_refs.by_handle.get_mut(&handle) else {
-            pr_warn!("BC_CLEAR_FREEZE_NOTIFICATION invalid ref {}\n", handle);
+            binder_debug!(
+                UserError,
+                "BC_CLEAR_FREEZE_NOTIFICATION invalid ref {handle}"
+            );
             return Err(EINVAL);
         };
         let Some(info_cookie) = info.freeze() else {
-            pr_warn!("BC_CLEAR_FREEZE_NOTIFICATION freeze notification not active\n");
+            binder_debug!(
+                UserError,
+                "BC_CLEAR_FREEZE_NOTIFICATION freeze notification not active"
+            );
             return Err(EINVAL);
         };
         if *info_cookie != cookie {
-            pr_warn!("BC_CLEAR_FREEZE_NOTIFICATION freeze notification cookie mismatch\n");
+            binder_debug!(
+                UserError,
+                "BC_CLEAR_FREEZE_NOTIFICATION freeze notification cookie mismatch"
+            );
             return Err(EINVAL);
         }
         let Some(listener) = node_refs.freeze_listeners.get_mut(&cookie) else {
-            pr_warn!("BC_CLEAR_FREEZE_NOTIFICATION invalid cookie {}\n", handle);
+            binder_debug!(
+                UserError,
+                "BC_CLEAR_FREEZE_NOTIFICATION invalid cookie {handle}"
+            );
             return Err(EINVAL);
         };
         listener.is_clearing = true;

-- 
2.55.0.795.g602f6c329a-goog



^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH v2 3/7] rust_binder: Implement BINDER_DEBUG_USER_ERROR for refcounting and death notifications
  2026-07-10 14:32 [PATCH v2 0/7] rust_binder : Implement dynamic debug logging mask Jahnavi MN via B4 Relay
  2026-07-10 14:32 ` [PATCH v2 1/7] rust_binder: Add " Jahnavi MN via B4 Relay
  2026-07-10 14:32 ` [PATCH v2 2/7] rust_binder: Implement BINDER_DEBUG_USER_ERROR for freezer-related operation Jahnavi MN via B4 Relay
@ 2026-07-10 14:32 ` Jahnavi MN via B4 Relay
  2026-07-10 19:56   ` Carlos Llamas
  2026-07-10 19:58   ` Carlos Llamas
  2026-07-10 14:32 ` [PATCH v2 4/7] rust_binder: Implement BINDER_DEBUG_USER_ERROR for transaction parsing failures Jahnavi MN via B4 Relay
                   ` (5 subsequent siblings)
  8 siblings, 2 replies; 25+ messages in thread
From: Jahnavi MN via B4 Relay @ 2026-07-10 14:32 UTC (permalink / raw)
  To: Greg Kroah-Hartman, Arve Hjønnevåg, Todd Kjos,
	Christian Brauner, Carlos Llamas, Alice Ryhl, Miguel Ojeda,
	Boqun Feng, Gary Guo, Björn Roy Baron, Benno Lossin,
	Andreas Hindborg, Trevor Gross, Danilo Krummrich, Daniel Almeida,
	Tamir Duberstein, Alexandre Courbot, Onur Özkan
  Cc: linux-kernel, rust-for-linux, Jahnavi MN

From: Jahnavi MN <jahnavimn@google.com>

This adds dynamic debug logs for:
- Decrementing handle reference counts that are already zero.
- Mismatched reference states (calling inc_ref_done with no active
  inc_refs, or using a weak reference as a strong reference).
- Requesting or clearing death notifications on invalid references,
  already active notifications, or with mismatched cookies.

Signed-off-by: Jahnavi MN <jahnavimn@google.com>
---
 drivers/android/binder/node.rs    | 16 +++++++++++----
 drivers/android/binder/process.rs | 41 ++++++++++++++++++++++++++++++++-------
 2 files changed, 46 insertions(+), 11 deletions(-)

diff --git a/drivers/android/binder/node.rs b/drivers/android/binder/node.rs
index 2b0618938a0a..dfad3697f672 100644
--- a/drivers/android/binder/node.rs
+++ b/drivers/android/binder/node.rs
@@ -345,7 +345,10 @@ pub(crate) fn inc_ref_done_locked(
     ) -> Option<DLArc<Node>> {
         let inner = self.inner.access_mut(owner_inner);
         if inner.active_inc_refs == 0 {
-            pr_err!("inc_ref_done called when no active inc_refs");
+            binder_debug!(
+                UserError,
+                "inc_ref_done called when no active inc_refs"
+            );
             return None;
         }
 
@@ -821,6 +824,10 @@ pub(crate) fn get_count(&self) -> (usize, usize) {
 
     pub(crate) fn clone(&self, strong: bool) -> Result<NodeRef> {
         if strong && self.strong_count == 0 {
+            binder_debug!(
+                UserError,
+                "tried to use weak ref as strong ref"
+            );
             return Err(EINVAL);
         }
         Ok(self
@@ -861,9 +868,10 @@ pub(crate) fn update(&mut self, inc: bool, strong: bool) -> bool {
             *count += 1;
         } else {
             if *count == 0 {
-                pr_warn!(
-                    "pid {} performed invalid decrement on ref\n",
-                    kernel::current!().pid()
+                binder_debug!(
+                    UserError,
+                    "performed invalid {} decrement on ref",
+                    if strong { "strong" } else { "weak" }
                 );
                 return false;
             }
diff --git a/drivers/android/binder/process.rs b/drivers/android/binder/process.rs
index 836a0db92354..db2b0230d19f 100644
--- a/drivers/android/binder/process.rs
+++ b/drivers/android/binder/process.rs
@@ -920,7 +920,16 @@ pub(crate) fn get_transaction_node(&self, handle: u32) -> BinderResult<NodeRef>
             }
             Ok(node_ref)
         } else {
-            Ok(self.get_node_from_handle(handle, true)?)
+            match self.get_node_from_handle(handle, true) {
+                Ok(node_ref) => Ok(node_ref),
+                Err(err) => {
+                    binder_debug!(
+                        UserError,
+                        "got transaction to invalid handle {handle}"
+                    );
+                    Err(err.into())
+                }
+            }
         }
     }
 
@@ -1005,7 +1014,10 @@ pub(crate) fn update_ref(
         } else {
             // All refs are cleared in process exit, so this warning is expected in that case.
             if !self.inner.lock().is_dead {
-                pr_warn!("{}: no such ref {handle}\n", self.pid_in_current_ns());
+                binder_debug!(
+                    UserError,
+                    "no such ref {handle}"
+                );
             }
         }
         Ok(())
@@ -1258,13 +1270,19 @@ pub(crate) fn request_death(
         })?;
         let mut refs = self.node_refs.lock();
         let Some(info) = refs.by_handle.get_mut(&handle) else {
-            pr_warn!("BC_REQUEST_DEATH_NOTIFICATION invalid ref {handle}\n");
+            binder_debug!(
+                UserError,
+                "BC_REQUEST_DEATH_NOTIFICATION invalid ref {handle}"
+            );
             return Ok(());
         };
 
         // Nothing to do if there is already a death notification request for this handle.
         if info.death().is_some() {
-            pr_warn!("BC_REQUEST_DEATH_NOTIFICATION death notification already set\n");
+            binder_debug!(
+                UserError,
+                "BC_REQUEST_DEATH_NOTIFICATION death notification already set"
+            );
             return Ok(());
         }
 
@@ -1301,17 +1319,26 @@ pub(crate) fn clear_death(&self, reader: &mut UserSliceReader, thread: &Thread)
 
         let mut refs = self.node_refs.lock();
         let Some(info) = refs.by_handle.get_mut(&handle) else {
-            pr_warn!("BC_CLEAR_DEATH_NOTIFICATION invalid ref {handle}\n");
+            binder_debug!(
+                UserError,
+                "BC_CLEAR_DEATH_NOTIFICATION invalid ref {handle}"
+            );
             return Ok(());
         };
 
         let Some(death) = info.death().take() else {
-            pr_warn!("BC_CLEAR_DEATH_NOTIFICATION death notification not active\n");
+            binder_debug!(
+                UserError,
+                "BC_CLEAR_DEATH_NOTIFICATION death notification not active"
+            );
             return Ok(());
         };
         if death.cookie != cookie {
             *info.death() = Some(death);
-            pr_warn!("BC_CLEAR_DEATH_NOTIFICATION death notification cookie mismatch\n");
+            binder_debug!(
+                UserError,
+                "BC_CLEAR_DEATH_NOTIFICATION death notification cookie mismatch"
+            );
             return Ok(());
         }
 

-- 
2.55.0.795.g602f6c329a-goog



^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH v2 4/7] rust_binder: Implement BINDER_DEBUG_USER_ERROR for transaction parsing failures
  2026-07-10 14:32 [PATCH v2 0/7] rust_binder : Implement dynamic debug logging mask Jahnavi MN via B4 Relay
                   ` (2 preceding siblings ...)
  2026-07-10 14:32 ` [PATCH v2 3/7] rust_binder: Implement BINDER_DEBUG_USER_ERROR for refcounting and death notifications Jahnavi MN via B4 Relay
@ 2026-07-10 14:32 ` Jahnavi MN via B4 Relay
  2026-07-10 20:07   ` Carlos Llamas
  2026-07-10 14:32 ` [PATCH v2 5/7] rust_binder: Implement BINDER_DEBUG_FAILED_TRANSACTION Jahnavi MN via B4 Relay
                   ` (4 subsequent siblings)
  8 siblings, 1 reply; 25+ messages in thread
From: Jahnavi MN via B4 Relay @ 2026-07-10 14:32 UTC (permalink / raw)
  To: Greg Kroah-Hartman, Arve Hjønnevåg, Todd Kjos,
	Christian Brauner, Carlos Llamas, Alice Ryhl, Miguel Ojeda,
	Boqun Feng, Gary Guo, Björn Roy Baron, Benno Lossin,
	Andreas Hindborg, Trevor Gross, Danilo Krummrich, Daniel Almeida,
	Tamir Duberstein, Alexandre Courbot, Onur Özkan
  Cc: linux-kernel, rust-for-linux, Jahnavi MN

From: Jahnavi MN <jahnavimn@google.com>

This adds dynamic debug logs in `thread.rs` for:
- File descriptor array (FDA) parent offset and parent buffer address
  alignment misalignments.
- Memory copy, write, and translation failures during transaction
  serialization (including out-of-bounds pointer fixups).
- Incoming transactions or replies that do not match the expected
  thread calling stack (such as out-of-order replies).

Signed-off-by: Jahnavi MN <jahnavimn@google.com>
---
 drivers/android/binder/thread.rs | 84 +++++++++++++++++++++++++++++-----------
 1 file changed, 62 insertions(+), 22 deletions(-)

diff --git a/drivers/android/binder/thread.rs b/drivers/android/binder/thread.rs
index 541ca947cc52..54b98efdd0ec 100644
--- a/drivers/android/binder/thread.rs
+++ b/drivers/android/binder/thread.rs
@@ -743,11 +743,12 @@ fn translate_object(
                 let alloc_offset = match sg_state.unused_buffer_space.claim_next(obj_length) {
                     Ok(alloc_offset) => alloc_offset,
                     Err(err) => {
-                        pr_warn!(
-                            "Failed to claim space for a BINDER_TYPE_PTR. (offset: {}, limit: {}, size: {})",
+                        binder_debug!(
+                            UserError,
+                            "failed to claim space for a BINDER_TYPE_PTR (offset: {}, limit: {}, size: {})",
                             sg_state.unused_buffer_space.offset,
                             sg_state.unused_buffer_space.limit,
-                            obj_length,
+                            obj_length
                         );
                         return Err(err.into());
                     }
@@ -826,6 +827,10 @@ fn translate_object(
                 let fds_len = num_fds.checked_mul(size_of::<u32>()).ok_or(EINVAL)?;
 
                 if !is_aligned(parent_offset, size_of::<u32>()) {
+                    binder_debug!(
+                        UserError,
+                        "FDA parent offset not aligned correctly"
+                    );
                     return Err(EINVAL.into());
                 }
 
@@ -844,6 +849,10 @@ fn translate_object(
                 };
 
                 if !is_aligned(parent_entry.sender_uaddr, size_of::<u32>()) {
+                    binder_debug!(
+                        UserError,
+                        "FDA parent buffer not aligned correctly"
+                    );
                     return Err(EINVAL.into());
                 }
 
@@ -927,12 +936,9 @@ fn apply_sg(&self, alloc: &mut Allocation, sg_state: &mut ScatterGatherState) ->
 
                 let target_offset_end = fixup_offset.checked_add(fixup_len).ok_or(EINVAL)?;
                 if fixup_offset < end_of_previous_fixup || offset_end < target_offset_end {
-                    pr_warn!(
-                        "Fixups oob {} {} {} {}",
-                        fixup_offset,
-                        end_of_previous_fixup,
-                        offset_end,
-                        target_offset_end
+                    binder_debug!(
+                        UserError,
+                        "fixups oob {fixup_offset} {end_of_previous_fixup} {offset_end} {target_offset_end}"
                     );
                     return Err(EINVAL.into());
                 }
@@ -940,18 +946,27 @@ fn apply_sg(&self, alloc: &mut Allocation, sg_state: &mut ScatterGatherState) ->
                 let copy_off = end_of_previous_fixup;
                 let copy_len = fixup_offset - end_of_previous_fixup;
                 if let Err(err) = alloc.copy_into(&mut reader, copy_off, copy_len) {
-                    pr_warn!("Failed copying into alloc: {:?}", err);
+                    binder_debug!(
+                        UserError,
+                        "failed copying into alloc: {err:?}"
+                    );
                     return Err(err.into());
                 }
                 if let PointerFixupEntry::Fixup { pointer_value, .. } = fixup {
                     let res = alloc.write::<u64>(fixup_offset, pointer_value);
                     if let Err(err) = res {
-                        pr_warn!("Failed copying ptr into alloc: {:?}", err);
+                        binder_debug!(
+                            UserError,
+                            "failed copying ptr into alloc: {err:?}"
+                        );
                         return Err(err.into());
                     }
                 }
                 if let Err(err) = reader.skip(fixup_len) {
-                    pr_warn!("Failed skipping {} from reader: {:?}", fixup_len, err);
+                    binder_debug!(
+                        UserError,
+                        "failed skipping {fixup_len} from reader: {err:?}"
+                    );
                     return Err(err.into());
                 }
                 end_of_previous_fixup = target_offset_end;
@@ -959,7 +974,10 @@ fn apply_sg(&self, alloc: &mut Allocation, sg_state: &mut ScatterGatherState) ->
             let copy_off = end_of_previous_fixup;
             let copy_len = offset_end - end_of_previous_fixup;
             if let Err(err) = alloc.copy_into(&mut reader, copy_off, copy_len) {
-                pr_warn!("Failed copying remainder into alloc: {:?}", err);
+                binder_debug!(
+                    UserError,
+                    "failed copying remainder into alloc: {err:?}"
+                );
                 return Err(err.into());
             }
         }
@@ -1063,7 +1081,10 @@ pub(crate) fn copy_transaction_data(
                 let offset: usize = offset.try_into().map_err(|_| EINVAL)?;
 
                 if offset < end_of_previous_object || !is_aligned(offset, size_of::<u32>()) {
-                    pr_warn!("Got transaction with invalid offset.");
+                    binder_debug!(
+                        UserError,
+                        "got transaction with invalid offset"
+                    );
                     return Err(EINVAL.into());
                 }
 
@@ -1088,7 +1109,10 @@ pub(crate) fn copy_transaction_data(
                 ) {
                     Ok(()) => end_of_previous_object = offset + object.size(),
                     Err(err) => {
-                        pr_warn!("Error while translating object.");
+                        binder_debug!(
+                            UserError,
+                            "error while translating object: {err:?}"
+                        );
                         return Err(err);
                     }
                 }
@@ -1108,15 +1132,15 @@ pub(crate) fn copy_transaction_data(
         )?;
 
         if let Some(sg_state) = sg_state.as_mut() {
-            if let Err(err) = self.apply_sg(&mut alloc, sg_state) {
-                pr_warn!("Failure in apply_sg: {:?}", err);
-                return Err(err);
-            }
+            self.apply_sg(&mut alloc, sg_state)?;
         }
 
         if let Some((off_out, secctx)) = secctx.as_mut() {
             if let Err(err) = alloc.write(secctx_off, secctx.as_bytes()) {
-                pr_warn!("Failed to write security context: {:?}", err);
+                binder_debug!(
+                    UserError,
+                    "failed to write security context: {err:?}"
+                );
                 return Err(err.into());
             }
             **off_out = secctx_off;
@@ -1328,7 +1352,10 @@ fn transaction_inner(self: &Arc<Self>, info: &mut TransactionInfo) -> BinderResu
         {
             let mut inner = self.inner.lock();
             if !transaction.is_stacked_on(&inner.current_transaction) {
-                pr_warn!("Transaction stack changed during transaction!");
+                binder_debug!(
+                    UserError,
+                    "got new transaction with bad transaction stack"
+                );
                 return Err(EINVAL.into());
             }
             inner.current_transaction = Some(transaction.clone_arc());
@@ -1351,8 +1378,21 @@ fn transaction_inner(self: &Arc<Self>, info: &mut TransactionInfo) -> BinderResu
     }
 
     fn reply_inner(self: &Arc<Self>, info: &mut TransactionInfo) -> BinderResult {
-        let orig = self.inner.lock().pop_transaction_to_reply(self)?;
+        let orig = match self.inner.lock().pop_transaction_to_reply(self) {
+            Ok(orig) => orig,
+            Err(err) => {
+                binder_debug!(
+                    UserError,
+                    "got reply transaction with no transaction stack"
+                );
+                return Err(err.into());
+            }
+        };
         if !orig.from.is_current_transaction(&orig) {
+            binder_debug!(
+                UserError,
+                "got reply transaction with bad transaction stack"
+            );
             return Err(EINVAL.into());
         }
 

-- 
2.55.0.795.g602f6c329a-goog



^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH v2 5/7] rust_binder: Implement BINDER_DEBUG_FAILED_TRANSACTION
  2026-07-10 14:32 [PATCH v2 0/7] rust_binder : Implement dynamic debug logging mask Jahnavi MN via B4 Relay
                   ` (3 preceding siblings ...)
  2026-07-10 14:32 ` [PATCH v2 4/7] rust_binder: Implement BINDER_DEBUG_USER_ERROR for transaction parsing failures Jahnavi MN via B4 Relay
@ 2026-07-10 14:32 ` Jahnavi MN via B4 Relay
  2026-07-10 20:15   ` Carlos Llamas
  2026-07-10 14:32 ` [PATCH v2 6/7] rust_binder: Implement BINDER_DEBUG_DEATH_NOTIFICATION Jahnavi MN via B4 Relay
                   ` (3 subsequent siblings)
  8 siblings, 1 reply; 25+ messages in thread
From: Jahnavi MN via B4 Relay @ 2026-07-10 14:32 UTC (permalink / raw)
  To: Greg Kroah-Hartman, Arve Hjønnevåg, Todd Kjos,
	Christian Brauner, Carlos Llamas, Alice Ryhl, Miguel Ojeda,
	Boqun Feng, Gary Guo, Björn Roy Baron, Benno Lossin,
	Andreas Hindborg, Trevor Gross, Danilo Krummrich, Daniel Almeida,
	Tamir Duberstein, Alexandre Courbot, Onur Özkan
  Cc: linux-kernel, rust-for-linux, Jahnavi MN

From: Jahnavi MN <jahnavimn@google.com>

This adds dynamic debug logs for:
- Failed replies, target process deaths, and error code deliveries.
- Detailed transaction failure diagnostics (including sender/receiver
  PIDs, TIDs, transaction IDs, buffer sizes, and error codes).

Signed-off-by: Jahnavi MN <jahnavimn@google.com>
---
 drivers/android/binder/thread.rs      | 21 ++++++++++++++++-----
 drivers/android/binder/transaction.rs |  8 ++++++++
 2 files changed, 24 insertions(+), 5 deletions(-)

diff --git a/drivers/android/binder/thread.rs b/drivers/android/binder/thread.rs
index 54b98efdd0ec..d7038b58c2ad 100644
--- a/drivers/android/binder/thread.rs
+++ b/drivers/android/binder/thread.rs
@@ -1315,11 +1315,22 @@ fn transaction(self: &Arc<Self>, cmd: u32, reader: &mut UserSliceReader) -> Resu
                     }
                 }
 
-                pr_warn!(
-                    "{}:{} transaction to {} failed: {err:?}",
-                    info.from_pid,
-                    info.from_tid,
-                    info.to_pid
+                binder_debug!(
+                    FailedTransaction,
+                    "transaction {} to {}:{} failed {:?}, code {} size {}-{}",
+                    if info.is_reply {
+                        "reply"
+                    } else if info.is_oneway() {
+                        "async"
+                    } else {
+                        "call"
+                    },
+                    info.to_pid,
+                    info.to_tid,
+                    err,
+                    info.code,
+                    info.data_size,
+                    info.offsets_size
                 );
             }
         }
diff --git a/drivers/android/binder/transaction.rs b/drivers/android/binder/transaction.rs
index 2643cca4a7d6..f058d3d50eb7 100644
--- a/drivers/android/binder/transaction.rs
+++ b/drivers/android/binder/transaction.rs
@@ -448,6 +448,14 @@ fn do_work(
         } else {
             // On failure to process the list, we send a reply back to the sender and ignore the
             // transaction on the recipient.
+            binder_debug!(
+                FailedTransaction,
+                "transaction {} to {} failed, fd fixups failed, size {}-{}",
+                self.debug_id,
+                self.to.task.pid(),
+                self.data_size,
+                self.offsets_size
+            );
             return Ok(true);
         };
 

-- 
2.55.0.795.g602f6c329a-goog



^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH v2 6/7] rust_binder: Implement BINDER_DEBUG_DEATH_NOTIFICATION
  2026-07-10 14:32 [PATCH v2 0/7] rust_binder : Implement dynamic debug logging mask Jahnavi MN via B4 Relay
                   ` (4 preceding siblings ...)
  2026-07-10 14:32 ` [PATCH v2 5/7] rust_binder: Implement BINDER_DEBUG_FAILED_TRANSACTION Jahnavi MN via B4 Relay
@ 2026-07-10 14:32 ` Jahnavi MN via B4 Relay
  2026-07-10 20:20   ` Carlos Llamas
  2026-07-10 14:32 ` [PATCH v2 7/7] rust_binder: Implement BINDER_DEBUG_DEAD_TRANSACTION Jahnavi MN via B4 Relay
                   ` (2 subsequent siblings)
  8 siblings, 1 reply; 25+ messages in thread
From: Jahnavi MN via B4 Relay @ 2026-07-10 14:32 UTC (permalink / raw)
  To: Greg Kroah-Hartman, Arve Hjønnevåg, Todd Kjos,
	Christian Brauner, Carlos Llamas, Alice Ryhl, Miguel Ojeda,
	Boqun Feng, Gary Guo, Björn Roy Baron, Benno Lossin,
	Andreas Hindborg, Trevor Gross, Danilo Krummrich, Daniel Almeida,
	Tamir Duberstein, Alexandre Courbot, Onur Özkan
  Cc: linux-kernel, rust-for-linux, Jahnavi MN

From: Jahnavi MN <jahnavimn@google.com>

This adds dynamic debug logs for:
- Memory allocation (OOM) failures when requesting
  death notifications
- Registration and cancellation lifecycle events
  (BC_REQUEST / BC_CLEAR)
- Delivery of death notification events to userspace
  (BR_DEAD_BINDER)

Signed-off-by: Jahnavi MN <jahnavimn@google.com>
---
 drivers/android/binder/node.rs    |  5 +++++
 drivers/android/binder/process.rs | 14 ++++++++++++++
 2 files changed, 19 insertions(+)

diff --git a/drivers/android/binder/node.rs b/drivers/android/binder/node.rs
index dfad3697f672..898412cfddd9 100644
--- a/drivers/android/binder/node.rs
+++ b/drivers/android/binder/node.rs
@@ -1113,6 +1113,11 @@ fn do_work(
             // We're still holding the inner lock, so it cannot be aborted while we insert it into
             // the delivered list.
             process_inner.death_delivered(self.clone());
+            binder_debug!(
+                DeathNotification,
+                "sending death notification, cookie {:016x}",
+                cookie
+            );
             BR_DEAD_BINDER
         };
 
diff --git a/drivers/android/binder/process.rs b/drivers/android/binder/process.rs
index db2b0230d19f..b1f1207ee868 100644
--- a/drivers/android/binder/process.rs
+++ b/drivers/android/binder/process.rs
@@ -1267,6 +1267,10 @@ pub(crate) fn request_death(
         // Queue BR_ERROR if we can't allocate memory for the death notification.
         let death = UniqueArc::new_uninit(GFP_KERNEL).inspect_err(|_| {
             thread.push_return_work(BR_ERROR);
+            binder_debug!(
+                DeathNotification,
+                "BC_REQUEST_DEATH_NOTIFICATION failed due to memory allocation failure"
+            );
         })?;
         let mut refs = self.node_refs.lock();
         let Some(info) = refs.by_handle.get_mut(&handle) else {
@@ -1310,6 +1314,11 @@ pub(crate) fn request_death(
                 info.node_ref().node.add_death(death, &mut owner_inner);
             }
         }
+        binder_debug!(
+            DeathNotification,
+            "BC_REQUEST_DEATH_NOTIFICATION handle {handle} cookie {:016x}",
+            cookie
+        );
         Ok(())
     }
 
@@ -1353,6 +1362,11 @@ pub(crate) fn clear_death(&self, reader: &mut UserSliceReader, thread: &Thread)
             }
         }
 
+        binder_debug!(
+            DeathNotification,
+            "BC_CLEAR_DEATH_NOTIFICATION handle {handle} cookie {:016x}",
+            cookie
+        );
         Ok(())
     }
 

-- 
2.55.0.795.g602f6c329a-goog



^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH v2 7/7] rust_binder: Implement BINDER_DEBUG_DEAD_TRANSACTION
  2026-07-10 14:32 [PATCH v2 0/7] rust_binder : Implement dynamic debug logging mask Jahnavi MN via B4 Relay
                   ` (5 preceding siblings ...)
  2026-07-10 14:32 ` [PATCH v2 6/7] rust_binder: Implement BINDER_DEBUG_DEATH_NOTIFICATION Jahnavi MN via B4 Relay
@ 2026-07-10 14:32 ` Jahnavi MN via B4 Relay
  2026-07-10 14:35 ` [PATCH v2 0/7] rust_binder : Implement dynamic debug logging mask Alice Ryhl
  2026-07-10 15:01 ` Greg Kroah-Hartman
  8 siblings, 0 replies; 25+ messages in thread
From: Jahnavi MN via B4 Relay @ 2026-07-10 14:32 UTC (permalink / raw)
  To: Greg Kroah-Hartman, Arve Hjønnevåg, Todd Kjos,
	Christian Brauner, Carlos Llamas, Alice Ryhl, Miguel Ojeda,
	Boqun Feng, Gary Guo, Björn Roy Baron, Benno Lossin,
	Andreas Hindborg, Trevor Gross, Danilo Krummrich, Daniel Almeida,
	Tamir Duberstein, Alexandre Courbot, Onur Özkan
  Cc: linux-kernel, rust-for-linux, Jahnavi MN

From: Jahnavi MN <jahnavimn@google.com>

This adds dynamic debug logs for:
- Releasing active transactions during thread stack unwinding.
- Discarded transaction error codes when a thread exits.
- Undelivered transaction acknowledgments (TRANSACTION_COMPLETE)
  upon thread exit.
- Undelivered process death and freeze notifications when processes
  exit or die.
- Undelivered transactions canceled due to target process death.

We now store the process PID in `ThreadError`, `DeliverCode`, and
`FreezeMessage` to ensure the correct PID is logged on cancellation.
This is necessary because `cancel()` runs from background `kworkers`,
which would otherwise print the wrong PID.

Signed-off-by: Jahnavi MN <jahnavimn@google.com>
---
 drivers/android/binder/freeze.rs           | 24 ++++++++++------
 drivers/android/binder/node.rs             |  9 +++++-
 drivers/android/binder/rust_binder_main.rs | 14 ++++++++--
 drivers/android/binder/thread.rs           | 44 ++++++++++++++++++++++++------
 drivers/android/binder/transaction.rs      |  7 +++++
 5 files changed, 78 insertions(+), 20 deletions(-)

diff --git a/drivers/android/binder/freeze.rs b/drivers/android/binder/freeze.rs
index 70b192ec199a..8bc0bff54d81 100644
--- a/drivers/android/binder/freeze.rs
+++ b/drivers/android/binder/freeze.rs
@@ -60,6 +60,7 @@ fn allow_duplicate(&self, node: &DArc<Node>) -> bool {
 /// Represents a notification that the freeze state has changed.
 pub(crate) struct FreezeMessage {
     cookie: FreezeCookie,
+    pid: i32,
 }
 
 kernel::list::impl_list_arc_safe! {
@@ -73,8 +74,8 @@ fn new(flags: kernel::alloc::Flags) -> Result<UninitFM, AllocError> {
         UniqueArc::new_uninit(flags)
     }
 
-    fn init(ua: UninitFM, cookie: FreezeCookie) -> DLArc<FreezeMessage> {
-        match ua.pin_init_with(DTRWrap::new(FreezeMessage { cookie })) {
+    fn init(ua: UninitFM, cookie: FreezeCookie, pid: i32) -> DLArc<FreezeMessage> {
+        match ua.pin_init_with(DTRWrap::new(FreezeMessage { cookie, pid })) {
             Ok(msg) => ListArc::from(msg),
             Err(err) => match err {},
         }
@@ -140,7 +141,14 @@ fn do_work(
         }
     }
 
-    fn cancel(self: DArc<Self>) {}
+    fn cancel(self: DArc<Self>) {
+        binder_debug!(
+            pid=self.pid,
+            DeadTransaction,
+            "undelivered freeze notification, {:016x}",
+            self.cookie.0
+        );
+    }
 
     fn should_sync_wakeup(&self) -> bool {
         false
@@ -264,7 +272,7 @@ pub(crate) fn request_freeze_notif(
         }
 
         *info.freeze() = Some(cookie);
-        let msg = FreezeMessage::init(msg, cookie);
+        let msg = FreezeMessage::init(msg, cookie, self.task.pid());
         drop(node_refs_guard);
         let _ = self.push_work(msg);
         Ok(())
@@ -285,7 +293,7 @@ pub(crate) fn freeze_notif_done(self: &Arc<Self>, reader: &mut UserSliceReader)
         };
         let mut clear_msg = None;
         if freeze.num_pending_duplicates > 0 {
-            clear_msg = Some(FreezeMessage::init(alloc, cookie));
+            clear_msg = Some(FreezeMessage::init(alloc, cookie, self.task.pid()));
             freeze.num_pending_duplicates -= 1;
             freeze.num_cleared_duplicates += 1;
         } else {
@@ -300,7 +308,7 @@ pub(crate) fn freeze_notif_done(self: &Arc<Self>, reader: &mut UserSliceReader)
             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));
+                clear_msg = Some(FreezeMessage::init(alloc, cookie, self.task.pid()));
             }
             freeze.is_pending = false;
         }
@@ -353,7 +361,7 @@ pub(crate) fn clear_freeze_notif(self: &Arc<Self>, reader: &mut UserSliceReader)
         *info.freeze() = None;
         let mut msg = None;
         if !listener.is_pending {
-            msg = Some(FreezeMessage::init(alloc, cookie));
+            msg = Some(FreezeMessage::init(alloc, cookie, self.task.pid()));
         }
         drop(node_refs_guard);
 
@@ -433,7 +441,7 @@ pub(crate) fn prepare_freeze_messages(&self) -> Result<FreezeMessages, AllocErro
                 continue;
             };
             let msg_alloc = FreezeMessage::new(GFP_KERNEL)?;
-            let msg = FreezeMessage::init(msg_alloc, cookie);
+            let msg = FreezeMessage::init(msg_alloc, cookie, proc.task.pid());
             batch.push((proc, msg), GFP_KERNEL)?;
         }
 
diff --git a/drivers/android/binder/node.rs b/drivers/android/binder/node.rs
index 898412cfddd9..b2d9d518e32b 100644
--- a/drivers/android/binder/node.rs
+++ b/drivers/android/binder/node.rs
@@ -1128,7 +1128,14 @@ fn do_work(
         Ok(cmd != BR_DEAD_BINDER)
     }
 
-    fn cancel(self: DArc<Self>) {}
+    fn cancel(self: DArc<Self>) {
+        binder_debug!(
+            pid=self.process.task.pid(),
+            DeadTransaction,
+            "undelivered death notification, {:016x}",
+            self.cookie
+        );
+    }
 
     fn should_sync_wakeup(&self) -> bool {
         false
diff --git a/drivers/android/binder/rust_binder_main.rs b/drivers/android/binder/rust_binder_main.rs
index 995e6131bb77..31213b67b206 100644
--- a/drivers/android/binder/rust_binder_main.rs
+++ b/drivers/android/binder/rust_binder_main.rs
@@ -222,6 +222,7 @@ fn arc_pin_init(init: impl PinInit<T>) -> Result<DLArc<T>, kernel::error::Error>
 struct DeliverCode {
     code: u32,
     skip: Atomic<bool>,
+    pid: i32,
 }
 
 kernel::list::impl_list_arc_safe! {
@@ -229,10 +230,11 @@ struct DeliverCode {
 }
 
 impl DeliverCode {
-    fn new(code: u32) -> Self {
+    fn new(code: u32, pid: i32) -> Self {
         Self {
             code,
             skip: Atomic::new(false),
+            pid,
         }
     }
 
@@ -257,7 +259,15 @@ fn do_work(
         Ok(true)
     }
 
-    fn cancel(self: DArc<Self>) {}
+    fn cancel(self: DArc<Self>) {
+        if !self.skip.load(Relaxed) {
+            binder_debug!(
+                pid=self.pid,
+                DeadTransaction,
+                "undelivered TRANSACTION_COMPLETE"
+            );
+        }
+    }
 
     fn should_sync_wakeup(&self) -> bool {
         false
diff --git a/drivers/android/binder/thread.rs b/drivers/android/binder/thread.rs
index d7038b58c2ad..b93c37ad6845 100644
--- a/drivers/android/binder/thread.rs
+++ b/drivers/android/binder/thread.rs
@@ -281,7 +281,7 @@ struct InnerThread {
 const LOOPER_POLL: u32 = 0x40;
 
 impl InnerThread {
-    fn new() -> Result<Self> {
+    fn new(pid: i32) -> Result<Self> {
         fn next_err_id() -> u32 {
             static EE_ID: Atomic<u32> = Atomic::new(0);
             EE_ID.fetch_add(1, Relaxed)
@@ -292,8 +292,8 @@ fn next_err_id() -> u32 {
             looper_need_return: false,
             is_dead: false,
             process_work_list: false,
-            reply_work: ThreadError::try_new()?,
-            return_work: ThreadError::try_new()?,
+            reply_work: ThreadError::try_new(pid)?,
+            return_work: ThreadError::try_new(pid)?,
             work_list: List::new(),
             current_transaction: None,
             extended_error: ExtendedError::new(next_err_id(), BR_OK, 0),
@@ -452,7 +452,7 @@ impl ListItem<0> for Thread {
 
 impl Thread {
     pub(crate) fn new(id: i32, process: Arc<Process>) -> Result<Arc<Self>> {
-        let inner = InnerThread::new()?;
+        let inner = InnerThread::new(process.task.pid())?;
 
         Arc::pin_init(
             try_pin_init!(Thread {
@@ -1154,6 +1154,12 @@ fn unwind_transaction_stack(self: &Arc<Self>) {
             let mut inner = thread.inner.lock();
             inner.pop_transaction_to_reply(thread.as_ref())
         } {
+            binder_debug!(
+                DeadTransaction,
+                "release transaction {} in, still active",
+                transaction.debug_id
+            );
+
             let reply = Err(BR_DEAD_REPLY);
             if !transaction
                 .from
@@ -1354,7 +1360,10 @@ fn transaction_inner(self: &Arc<Self>, info: &mut TransactionInfo) -> BinderResu
         // TODO: We need to ensure that there isn't a pending transaction in the work queue. How
         // could this happen?
         let top = self.top_of_transaction_stack()?;
-        let list_completion = DTRWrap::arc_try_new(DeliverCode::new(BR_TRANSACTION_COMPLETE))?;
+        let list_completion = DTRWrap::arc_try_new(DeliverCode::new(
+            BR_TRANSACTION_COMPLETE,
+            self.process.task.pid(),
+        ))?;
         let completion = list_completion.clone_arc();
         let transaction = Transaction::new(node_ref, top, self, info)?;
 
@@ -1412,7 +1421,10 @@ fn reply_inner(self: &Arc<Self>, info: &mut TransactionInfo) -> BinderResult {
 
         // We need to complete the transaction even if we cannot complete building the reply.
         let out = (|| -> BinderResult<_> {
-            let completion = DTRWrap::arc_try_new(DeliverCode::new(BR_TRANSACTION_COMPLETE))?;
+            let completion = DTRWrap::arc_try_new(DeliverCode::new(
+                BR_TRANSACTION_COMPLETE,
+                self.process.task.pid(),
+            ))?;
             let process = orig.from.process.clone();
             let allow_fds = orig.flags & TF_ACCEPT_FDS != 0;
             let reply = Transaction::new_reply(self, process, info, allow_fds)?;
@@ -1453,7 +1465,10 @@ fn oneway_transaction_inner(self: &Arc<Self>, info: &mut TransactionInfo) -> Bin
         } else {
             BR_TRANSACTION_COMPLETE
         };
-        let list_completion = DTRWrap::arc_try_new(DeliverCode::new(code))?;
+        let list_completion = DTRWrap::arc_try_new(DeliverCode::new(
+            code,
+            self.process.task.pid(),
+        ))?;
         let completion = list_completion.clone_arc();
         // Not notifying: Reply to current thread.
         let _ = self.inner.lock().push_work(list_completion);
@@ -1692,14 +1707,16 @@ pub(crate) fn release(self: &Arc<Self>) {
 #[pin_data]
 struct ThreadError {
     error_code: Atomic<u32>,
+    pid: i32,
     #[pin]
     links_track: AtomicTracker,
 }
 
 impl ThreadError {
-    fn try_new() -> Result<DArc<Self>> {
+    fn try_new(pid: i32) -> Result<DArc<Self>> {
         DTRWrap::arc_pin_init(pin_init!(Self {
             error_code: Atomic::new(BR_OK),
+            pid,
             links_track <- AtomicTracker::new(),
         }))
         .map(ListArc::into_arc)
@@ -1726,7 +1743,16 @@ fn do_work(
         Ok(true)
     }
 
-    fn cancel(self: DArc<Self>) {}
+    fn cancel(self: DArc<Self>) {
+        let code = self.error_code.load(Relaxed);
+        if code != BR_OK {
+            binder_debug!(
+                pid=self.pid,
+                DeadTransaction,
+                "undelivered TRANSACTION_ERROR: {code}"
+            );
+        }
+    }
 
     fn should_sync_wakeup(&self) -> bool {
         false
diff --git a/drivers/android/binder/transaction.rs b/drivers/android/binder/transaction.rs
index f058d3d50eb7..c8f2b3e2ef57 100644
--- a/drivers/android/binder/transaction.rs
+++ b/drivers/android/binder/transaction.rs
@@ -532,6 +532,13 @@ fn cancel(self: DArc<Self>) {
         if self.target_node.is_some() && self.flags & TF_ONE_WAY == 0 {
             let reply = Err(BR_DEAD_REPLY);
             self.from.deliver_reply(reply, &self, None);
+        } else {
+            binder_debug!(
+                pid=self.to.task.pid(),
+                DeadTransaction,
+                "undelivered transaction {}, process died",
+                self.debug_id
+            );
         }
 
         self.drop_outstanding_txn();

-- 
2.55.0.795.g602f6c329a-goog



^ permalink raw reply related	[flat|nested] 25+ messages in thread

* Re: [PATCH v2 0/7] rust_binder : Implement dynamic debug logging mask
  2026-07-10 14:32 [PATCH v2 0/7] rust_binder : Implement dynamic debug logging mask Jahnavi MN via B4 Relay
                   ` (6 preceding siblings ...)
  2026-07-10 14:32 ` [PATCH v2 7/7] rust_binder: Implement BINDER_DEBUG_DEAD_TRANSACTION Jahnavi MN via B4 Relay
@ 2026-07-10 14:35 ` Alice Ryhl
  2026-07-10 15:01 ` Greg Kroah-Hartman
  8 siblings, 0 replies; 25+ messages in thread
From: Alice Ryhl @ 2026-07-10 14:35 UTC (permalink / raw)
  To: jahnavimn
  Cc: Greg Kroah-Hartman, Arve Hjønnevåg, Todd Kjos,
	Christian Brauner, Carlos Llamas, Miguel Ojeda, Boqun Feng,
	Gary Guo, Björn Roy Baron, Benno Lossin, Andreas Hindborg,
	Trevor Gross, Danilo Krummrich, Daniel Almeida, Tamir Duberstein,
	Alexandre Courbot, Onur Özkan, linux-kernel, rust-for-linux

On Fri, Jul 10, 2026 at 4:33 PM Jahnavi MN via B4 Relay
<devnull+jahnavimn.google.com@kernel.org> wrote:
>
> When a user-space application sends malformed data or makes a
> lifecycle mistake, the driver rejects it with a generic error code
> (like -EINVAL). Without internal logs, the driver acts as a
> "black box," forcing developers to guess which check failed.
>
> In the legacy C Binder driver, this issue is solved using a dynamic
> debug_mask module parameter that toggles verbose logs for specific
> subsystems. This series brings the same critical capability to the
> Rust Binder driver to provide developers with clear, real-time
> feedback.
>
> Instead of rebuilds, reboots, or guessing:
> - Developers can enable logs instantly on a running device by writing to
>   `/sys/module/rust_binder/parameters/debug_mask`.
> - It prints the exact reason for failures (such as alignment errors,
>   mismatched call stacks, or invalid handle references) directly into
>   `dmesg`, reducing debugging time from hours to seconds.
> - It protects system logs by keeping logging off by default and only
>   enabling it when developers are actively troubleshooting.
>
> Based on top of:
> https://lore.kernel.org/rust-for-linux/20260707-upgrade-poll-v6-0-4b8fae7bf1d9@google.com/
>
> Signed-off-by: Jahnavi MN <jahnavimn@google.com>

Reviewed-by: Alice Ryhl <aliceryhl@google.com>

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH v2 1/7] rust_binder: Add dynamic debug logging mask
  2026-07-10 14:32 ` [PATCH v2 1/7] rust_binder: Add " Jahnavi MN via B4 Relay
@ 2026-07-10 14:59   ` Greg Kroah-Hartman
  2026-07-10 16:37     ` Miguel Ojeda
  2026-07-10 16:51   ` Gary Guo
  2026-07-10 19:47   ` Carlos Llamas
  2 siblings, 1 reply; 25+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-10 14:59 UTC (permalink / raw)
  To: jahnavimn
  Cc: Arve Hjønnevåg, Todd Kjos, Christian Brauner,
	Carlos Llamas, Alice Ryhl, Miguel Ojeda, Boqun Feng, Gary Guo,
	Björn Roy Baron, Benno Lossin, Andreas Hindborg,
	Trevor Gross, Danilo Krummrich, Daniel Almeida, Tamir Duberstein,
	Alexandre Courbot, Onur Özkan, linux-kernel, rust-for-linux

On Fri, Jul 10, 2026 at 02:32:52PM +0000, Jahnavi MN via B4 Relay wrote:
> From: Jahnavi MN <jahnavimn@google.com>
> 
> Implement a dynamic debug logging mask (`debug_mask`) for the
> `rust_binder` module to allow dynamic runtime configuration of log
> levels. This enables parity with the legacy C driver's debug mask.
> 
> Since the Rust `module!` macro in the current kernel build does not yet
> support declaring module parameters directly in Rust, we define the
> `debug_mask` variable in a C companion file to expose it to the kernel
> runtime and import it using FFI with volatile reads.
> 
> To verify the setup, instrument process lifecycle events (open, flush,
> and release) in `process.rs` under the new `BINDER_DEBUG_OPEN_CLOSE`
> logging mask. These entry-point events are chosen for initial validation
> because they represent the start of the Binder lifecycle and occur
> at low frequency, allowing simple runtime verification of the dynamic
> toggle without log noise.
> 
> Signed-off-by: Jahnavi MN <jahnavimn@google.com>
> ---
>  drivers/android/binder/debug.rs            | 80 ++++++++++++++++++++++++++++++
>  drivers/android/binder/process.rs          |  7 ++-
>  drivers/android/binder/rust_binder_main.rs |  2 +
>  drivers/android/binder/rust_binderfs.c     |  3 ++
>  rust/kernel/task.rs                        |  7 +++
>  5 files changed, 98 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/android/binder/debug.rs b/drivers/android/binder/debug.rs
> new file mode 100644
> index 000000000000..da48bce3df54
> --- /dev/null
> +++ b/drivers/android/binder/debug.rs
> @@ -0,0 +1,80 @@
> +// SPDX-License-Identifier: GPL-2.0
> +// Copyright (C) 2026 Google LLC.
> +
> +//! Binder debugging helpers.
> +
> +#![allow(dead_code)]
> +
> +kernel::impl_flags!(
> +    /// Represents multiple debug mask flags.
> +    #[derive(Debug, Clone, Default, Copy, PartialEq, Eq)]
> +    pub struct DebugMasks(u32);
> +
> +    /// Represents a single debug mask category.
> +    #[derive(Debug, Clone, Copy, PartialEq, Eq)]
> +    pub enum DebugMask {
> +        UserError = 1 << 0,
> +        FailedTransaction = 1 << 1,
> +        DeadTransaction = 1 << 2,
> +        OpenClose = 1 << 3,
> +        DeadBinder = 1 << 4,
> +        DeathNotification = 1 << 5,
> +        ReadWrite = 1 << 6,
> +        UserRefs = 1 << 7,
> +        Threads = 1 << 8,
> +        Transaction = 1 << 9,
> +        TransactionComplete = 1 << 10,
> +        FreeBuffer = 1 << 11,
> +        InternalRefs = 1 << 12,
> +        PriorityCap = 1 << 13,
> +        Spinlocks = 1 << 14,

Not an objection, but don't we have the equivalent of the BIT() macro in
rust?  I think that's what this should be using if we do...

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH v2 0/7] rust_binder : Implement dynamic debug logging mask
  2026-07-10 14:32 [PATCH v2 0/7] rust_binder : Implement dynamic debug logging mask Jahnavi MN via B4 Relay
                   ` (7 preceding siblings ...)
  2026-07-10 14:35 ` [PATCH v2 0/7] rust_binder : Implement dynamic debug logging mask Alice Ryhl
@ 2026-07-10 15:01 ` Greg Kroah-Hartman
  2026-07-11 10:28   ` Jahnavi Nitheesha Mandava
  8 siblings, 1 reply; 25+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-10 15:01 UTC (permalink / raw)
  To: jahnavimn
  Cc: Arve Hjønnevåg, Todd Kjos, Christian Brauner,
	Carlos Llamas, Alice Ryhl, Miguel Ojeda, Boqun Feng, Gary Guo,
	Björn Roy Baron, Benno Lossin, Andreas Hindborg,
	Trevor Gross, Danilo Krummrich, Daniel Almeida, Tamir Duberstein,
	Alexandre Courbot, Onur Özkan, linux-kernel, rust-for-linux

On Fri, Jul 10, 2026 at 02:32:51PM +0000, Jahnavi MN via B4 Relay wrote:
> When a user-space application sends malformed data or makes a
> lifecycle mistake, the driver rejects it with a generic error code
> (like -EINVAL). Without internal logs, the driver acts as a
> "black box," forcing developers to guess which check failed.
> 
> In the legacy C Binder driver, this issue is solved using a dynamic
> debug_mask module parameter that toggles verbose logs for specific
> subsystems. This series brings the same critical capability to the
> Rust Binder driver to provide developers with clear, real-time
> feedback.
> 
> Instead of rebuilds, reboots, or guessing:
> - Developers can enable logs instantly on a running device by writing to 
>   `/sys/module/rust_binder/parameters/debug_mask`.
> - It prints the exact reason for failures (such as alignment errors, 
>   mismatched call stacks, or invalid handle references) directly into 
>   `dmesg`, reducing debugging time from hours to seconds.
> - It protects system logs by keeping logging off by default and only 
>   enabling it when developers are actively troubleshooting.
> 
> Based on top of:
> https://lore.kernel.org/rust-for-linux/20260707-upgrade-poll-v6-0-4b8fae7bf1d9@google.com/
> 
> Signed-off-by: Jahnavi MN <jahnavimn@google.com>

Patches 5 and 7 did not apply to my tree, can you rebase against the
char-misc-testing branch and send just those?  Other ones are now all
queued up, nice work!

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH v2 1/7] rust_binder: Add dynamic debug logging mask
  2026-07-10 14:59   ` Greg Kroah-Hartman
@ 2026-07-10 16:37     ` Miguel Ojeda
  2026-07-10 17:03       ` Miguel Ojeda
  0 siblings, 1 reply; 25+ messages in thread
From: Miguel Ojeda @ 2026-07-10 16:37 UTC (permalink / raw)
  To: Greg Kroah-Hartman
  Cc: jahnavimn, Arve Hjønnevåg, Todd Kjos, Christian Brauner,
	Carlos Llamas, Alice Ryhl, Miguel Ojeda, Boqun Feng, Gary Guo,
	Björn Roy Baron, Benno Lossin, Andreas Hindborg,
	Trevor Gross, Danilo Krummrich, Daniel Almeida, Tamir Duberstein,
	Alexandre Courbot, Onur Özkan, linux-kernel, rust-for-linux

On Fri, Jul 10, 2026 at 4:59 PM Greg Kroah-Hartman
<gregkh@linuxfoundation.org> wrote:
>
> Not an objection, but don't we have the equivalent of the BIT() macro in
> rust?  I think that's what this should be using if we do...

Yeah:

  https://rust.docs.kernel.org/kernel/bits/

We should probably update the example in the `impl_flags!` macro so
that people use it here too -- the macro already takes an expression
so it works.

Cheers,
Miguel

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH v2 1/7] rust_binder: Add dynamic debug logging mask
  2026-07-10 14:32 ` [PATCH v2 1/7] rust_binder: Add " Jahnavi MN via B4 Relay
  2026-07-10 14:59   ` Greg Kroah-Hartman
@ 2026-07-10 16:51   ` Gary Guo
  2026-07-10 19:47   ` Carlos Llamas
  2 siblings, 0 replies; 25+ messages in thread
From: Gary Guo @ 2026-07-10 16:51 UTC (permalink / raw)
  To: jahnavimn, Greg Kroah-Hartman, Arve Hjønnevåg,
	Todd Kjos, Christian Brauner, Carlos Llamas, Alice Ryhl,
	Miguel Ojeda, Boqun Feng, Gary Guo, Björn Roy Baron,
	Benno Lossin, Andreas Hindborg, Trevor Gross, Danilo Krummrich,
	Daniel Almeida, Tamir Duberstein, Alexandre Courbot,
	Onur Özkan
  Cc: linux-kernel, rust-for-linux

On Fri Jul 10, 2026 at 3:32 PM BST, Jahnavi MN via B4 Relay wrote:
> From: Jahnavi MN <jahnavimn@google.com>
>
> Implement a dynamic debug logging mask (`debug_mask`) for the
> `rust_binder` module to allow dynamic runtime configuration of log
> levels. This enables parity with the legacy C driver's debug mask.
>
> Since the Rust `module!` macro in the current kernel build does not yet
> support declaring module parameters directly in Rust, we define the
> `debug_mask` variable in a C companion file to expose it to the kernel
> runtime and import it using FFI with volatile reads.
>
> To verify the setup, instrument process lifecycle events (open, flush,
> and release) in `process.rs` under the new `BINDER_DEBUG_OPEN_CLOSE`
> logging mask. These entry-point events are chosen for initial validation
> because they represent the start of the Binder lifecycle and occur
> at low frequency, allowing simple runtime verification of the dynamic
> toggle without log noise.
>
> Signed-off-by: Jahnavi MN <jahnavimn@google.com>
> ---
>  drivers/android/binder/debug.rs            | 80 ++++++++++++++++++++++++++++++
>  drivers/android/binder/process.rs          |  7 ++-
>  drivers/android/binder/rust_binder_main.rs |  2 +
>  drivers/android/binder/rust_binderfs.c     |  3 ++
>  rust/kernel/task.rs                        |  7 +++
>  5 files changed, 98 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/android/binder/debug.rs b/drivers/android/binder/debug.rs
> new file mode 100644
> index 000000000000..da48bce3df54
> --- /dev/null
> +++ b/drivers/android/binder/debug.rs
> @@ -0,0 +1,80 @@
> +// SPDX-License-Identifier: GPL-2.0
> +// Copyright (C) 2026 Google LLC.
> +
> +//! Binder debugging helpers.
> +
> +#![allow(dead_code)]
> +
> +kernel::impl_flags!(
> +    /// Represents multiple debug mask flags.
> +    #[derive(Debug, Clone, Default, Copy, PartialEq, Eq)]
> +    pub struct DebugMasks(u32);
> +
> +    /// Represents a single debug mask category.
> +    #[derive(Debug, Clone, Copy, PartialEq, Eq)]
> +    pub enum DebugMask {
> +        UserError = 1 << 0,
> +        FailedTransaction = 1 << 1,
> +        DeadTransaction = 1 << 2,
> +        OpenClose = 1 << 3,
> +        DeadBinder = 1 << 4,
> +        DeathNotification = 1 << 5,
> +        ReadWrite = 1 << 6,
> +        UserRefs = 1 << 7,
> +        Threads = 1 << 8,
> +        Transaction = 1 << 9,
> +        TransactionComplete = 1 << 10,
> +        FreeBuffer = 1 << 11,
> +        InternalRefs = 1 << 12,
> +        PriorityCap = 1 << 13,
> +        Spinlocks = 1 << 14,
> +    }
> +);
> +
> +extern "C" {
> +    // Declared as static mut because the value is mutated dynamically by C sysfs.
> +    static mut rust_binder_debug_mask: u32;
> +}

This should be `Atomic<u32>` so the read_volatile below is avoided.

> +
> +/// Checks if the given debug logging category is enabled in the mask.
> +pub(crate) fn debug_mask_enabled(mask: DebugMask) -> bool {
> +    // SAFETY: `rust_binder_debug_mask` is defined in C and can be mutated at any time.
> +    // We read it via volatile to ensure we fetch the current value from memory.
> +    let current_mask = unsafe { core::ptr::read_volatile(&raw const rust_binder_debug_mask) };
> +    (current_mask & (mask as u32)) != 0
> +}
> +
> +/// Prints a debug log if the specified mask category is enabled.
> +#[macro_export]
> +macro_rules! binder_debug {
> +    // 1. Internal helper rule to do the raw print.

This 1, 2, 3 numbering is very strange.

> +    (raw, $($arg:tt)*) => {
> +        kernel::pr_info!($($arg)*);
> +    };

Why is this needed instead of just calling `pr_info!`?

Best,
Gary

> +
> +    // 2. Rule to explicitly specify a PID (used in kworkers).
> +    (pid=$pid:expr, $mask:ident, $($arg:tt)*) => {
> +        if $crate::debug::debug_mask_enabled($crate::debug::DebugMask::$mask) {
> +            $crate::binder_debug!(
> +                raw,
> +                "{}: {}\n",
> +                $pid,
> +                kernel::prelude::fmt!($($arg)*)
> +            );
> +        }
> +    };
> +
> +    // 3. Default rule (automatically prepends "PID:TID" of the current calling thread).
> +    ($mask:ident, $($arg:tt)*) => {
> +        if $crate::debug::debug_mask_enabled($crate::debug::DebugMask::$mask) {
> +            let thread = kernel::current!();
> +            $crate::binder_debug!(
> +                raw,
> +                "{}:{} {}\n",
> +                thread.tgid(),
> +                thread.pid(),
> +                kernel::prelude::fmt!($($arg)*)
> +            );
> +        }
> +    };
> +}


^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH v2 1/7] rust_binder: Add dynamic debug logging mask
  2026-07-10 16:37     ` Miguel Ojeda
@ 2026-07-10 17:03       ` Miguel Ojeda
  0 siblings, 0 replies; 25+ messages in thread
From: Miguel Ojeda @ 2026-07-10 17:03 UTC (permalink / raw)
  To: Greg Kroah-Hartman
  Cc: jahnavimn, Arve Hjønnevåg, Todd Kjos, Christian Brauner,
	Carlos Llamas, Alice Ryhl, Miguel Ojeda, Boqun Feng, Gary Guo,
	Björn Roy Baron, Benno Lossin, Andreas Hindborg,
	Trevor Gross, Danilo Krummrich, Daniel Almeida, Tamir Duberstein,
	Alexandre Courbot, Onur Özkan, linux-kernel, rust-for-linux

On Fri, Jul 10, 2026 at 6:37 PM Miguel Ojeda
<miguel.ojeda.sandonis@gmail.com> wrote:
>
> We should probably update the example in the `impl_flags!` macro so
> that people use it here too -- the macro already takes an expression
> so it works.

Filled "good first issue":

  https://github.com/Rust-for-Linux/linux/issues/1244

Cheers,
Miguel

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH v2 1/7] rust_binder: Add dynamic debug logging mask
  2026-07-10 14:32 ` [PATCH v2 1/7] rust_binder: Add " Jahnavi MN via B4 Relay
  2026-07-10 14:59   ` Greg Kroah-Hartman
  2026-07-10 16:51   ` Gary Guo
@ 2026-07-10 19:47   ` Carlos Llamas
  2026-07-10 20:27     ` Gary Guo
  2 siblings, 1 reply; 25+ messages in thread
From: Carlos Llamas @ 2026-07-10 19:47 UTC (permalink / raw)
  To: jahnavimn
  Cc: Greg Kroah-Hartman, Arve Hjønnevåg, Todd Kjos,
	Christian Brauner, Alice Ryhl, Miguel Ojeda, Boqun Feng, Gary Guo,
	Björn Roy Baron, Benno Lossin, Andreas Hindborg,
	Trevor Gross, Danilo Krummrich, Daniel Almeida, Tamir Duberstein,
	Alexandre Courbot, Onur Özkan, linux-kernel, rust-for-linux

On Fri, Jul 10, 2026 at 02:32:52PM +0000, Jahnavi MN via B4 Relay wrote:
> From: Jahnavi MN <jahnavimn@google.com>
> 
> Implement a dynamic debug logging mask (`debug_mask`) for the
> `rust_binder` module to allow dynamic runtime configuration of log
> levels. This enables parity with the legacy C driver's debug mask.
> 
> Since the Rust `module!` macro in the current kernel build does not yet
> support declaring module parameters directly in Rust, we define the
> `debug_mask` variable in a C companion file to expose it to the kernel
> runtime and import it using FFI with volatile reads.

Yeah, declaring it under rust_binderfs.c is not great but I guess we
don't have any other alternative for now. So this is fine.

> 
> To verify the setup, instrument process lifecycle events (open, flush,
> and release) in `process.rs` under the new `BINDER_DEBUG_OPEN_CLOSE`
> logging mask. These entry-point events are chosen for initial validation
> because they represent the start of the Binder lifecycle and occur
> at low frequency, allowing simple runtime verification of the dynamic
> toggle without log noise.
> 
> Signed-off-by: Jahnavi MN <jahnavimn@google.com>
> ---
>  drivers/android/binder/debug.rs            | 80 ++++++++++++++++++++++++++++++
>  drivers/android/binder/process.rs          |  7 ++-
>  drivers/android/binder/rust_binder_main.rs |  2 +
>  drivers/android/binder/rust_binderfs.c     |  3 ++
>  rust/kernel/task.rs                        |  7 +++
>  5 files changed, 98 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/android/binder/debug.rs b/drivers/android/binder/debug.rs
> new file mode 100644
> index 000000000000..da48bce3df54
> --- /dev/null
> +++ b/drivers/android/binder/debug.rs
> @@ -0,0 +1,80 @@
> +// SPDX-License-Identifier: GPL-2.0
> +// Copyright (C) 2026 Google LLC.
> +
> +//! Binder debugging helpers.
> +
> +#![allow(dead_code)]
> +
> +kernel::impl_flags!(
> +    /// Represents multiple debug mask flags.
> +    #[derive(Debug, Clone, Default, Copy, PartialEq, Eq)]
> +    pub struct DebugMasks(u32);

Where is this being used? I can't find it on subsequent patches.
Maybe leftover from previous implementation?

> +
> +    /// Represents a single debug mask category.
> +    #[derive(Debug, Clone, Copy, PartialEq, Eq)]
> +    pub enum DebugMask {
> +        UserError = 1 << 0,
> +        FailedTransaction = 1 << 1,
> +        DeadTransaction = 1 << 2,
> +        OpenClose = 1 << 3,
> +        DeadBinder = 1 << 4,
> +        DeathNotification = 1 << 5,
> +        ReadWrite = 1 << 6,
> +        UserRefs = 1 << 7,
> +        Threads = 1 << 8,
> +        Transaction = 1 << 9,
> +        TransactionComplete = 1 << 10,
> +        FreeBuffer = 1 << 11,
> +        InternalRefs = 1 << 12,
> +        PriorityCap = 1 << 13,
> +        Spinlocks = 1 << 14,
> +    }
> +);
> +
> +extern "C" {
> +    // Declared as static mut because the value is mutated dynamically by C sysfs.
> +    static mut rust_binder_debug_mask: u32;
> +}
> +
> +/// Checks if the given debug logging category is enabled in the mask.
> +pub(crate) fn debug_mask_enabled(mask: DebugMask) -> bool {
> +    // SAFETY: `rust_binder_debug_mask` is defined in C and can be mutated at any time.
> +    // We read it via volatile to ensure we fetch the current value from memory.
> +    let current_mask = unsafe { core::ptr::read_volatile(&raw const rust_binder_debug_mask) };
> +    (current_mask & (mask as u32)) != 0
> +}
> +
> +/// Prints a debug log if the specified mask category is enabled.
> +#[macro_export]
> +macro_rules! binder_debug {
> +    // 1. Internal helper rule to do the raw print.
> +    (raw, $($arg:tt)*) => {
> +        kernel::pr_info!($($arg)*);
> +    };
> +
> +    // 2. Rule to explicitly specify a PID (used in kworkers).
> +    (pid=$pid:expr, $mask:ident, $($arg:tt)*) => {
> +        if $crate::debug::debug_mask_enabled($crate::debug::DebugMask::$mask) {
> +            $crate::binder_debug!(
> +                raw,
> +                "{}: {}\n",
> +                $pid,
> +                kernel::prelude::fmt!($($arg)*)
> +            );
> +        }
> +    };
> +
> +    // 3. Default rule (automatically prepends "PID:TID" of the current calling thread).

Adding the pid:tid implicitly is a good idea. Nice!


> +    ($mask:ident, $($arg:tt)*) => {
> +        if $crate::debug::debug_mask_enabled($crate::debug::DebugMask::$mask) {
> +            let thread = kernel::current!();
> +            $crate::binder_debug!(
> +                raw,
> +                "{}:{} {}\n",
> +                thread.tgid(),
> +                thread.pid(),
> +                kernel::prelude::fmt!($($arg)*)
> +            );
> +        }
> +    };
> +}
> diff --git a/drivers/android/binder/process.rs b/drivers/android/binder/process.rs
> index f855d8d9818c..836a0db92354 100644
> --- a/drivers/android/binder/process.rs
> +++ b/drivers/android/binder/process.rs
> @@ -1349,6 +1349,7 @@ pub(crate) fn lock_with_nodes(&self) -> WithNodes<'_> {
>      }
>  
>      fn deferred_flush(&self) {
> +        binder_debug!(pid=self.task.pid(), OpenClose, "flushing process");
>          let inner = self.inner.lock();
>          for thread in inner.threads.values() {
>              thread.exit_looper();
> @@ -1356,6 +1357,8 @@ fn deferred_flush(&self) {
>      }
>  
>      fn deferred_release(self: Arc<Self>) {
> +        binder_debug!(pid=self.task.pid(), OpenClose, "releasing process");
> +
>          let is_manager = {
>              let mut inner = self.inner.lock();
>              inner.is_dead = true;
> @@ -1658,7 +1661,9 @@ fn ioctl_write_read(
>  /// The file operations supported by `Process`.
>  impl Process {
>      pub(crate) fn open(ctx: ArcBorrow<'_, Context>, file: &File) -> Result<Arc<Process>> {
> -        Self::new(ctx.into(), ARef::from(file.cred()))
> +        let proc = Self::new(ctx.into(), ARef::from(file.cred()))?;
> +        binder_debug!(OpenClose, "opened process");
> +        Ok(proc)
>      }
>  
>      pub(crate) fn release(this: Arc<Process>, _file: &File) {
> diff --git a/drivers/android/binder/rust_binder_main.rs b/drivers/android/binder/rust_binder_main.rs
> index df47aba05133..995e6131bb77 100644
> --- a/drivers/android/binder/rust_binder_main.rs
> +++ b/drivers/android/binder/rust_binder_main.rs
> @@ -31,6 +31,8 @@
>  mod context;
>  mod deferred_close;
>  mod defs;
> +#[macro_use]
> +mod debug;
>  mod error;
>  mod netlink;
>  mod node;
> diff --git a/drivers/android/binder/rust_binderfs.c b/drivers/android/binder/rust_binderfs.c
> index ade1c4d92499..fa8b38465550 100644
> --- a/drivers/android/binder/rust_binderfs.c
> +++ b/drivers/android/binder/rust_binderfs.c
> @@ -51,6 +51,9 @@ DEFINE_SHOW_ATTRIBUTE(rust_binder_proc);
>  char *rust_binder_devices_param = CONFIG_ANDROID_BINDER_DEVICES;
>  module_param_named(rust_devices, rust_binder_devices_param, charp, 0444);
>  
> +u32 rust_binder_debug_mask = 7;

hmm, I'm not sure about this magic number. Do you think we can
initialize on the rust end at init()? Or at least a comment about what
flags we are setting as default here?

> +module_param_named(debug_mask, rust_binder_debug_mask, uint, 0644);
> +
>  static dev_t binderfs_dev;
>  static DEFINE_MUTEX(binderfs_minors_mutex);
>  static DEFINE_IDA(binderfs_minors);
> diff --git a/rust/kernel/task.rs b/rust/kernel/task.rs
> index 38273f4eedb5..1b290c61714d 100644
> --- a/rust/kernel/task.rs
> +++ b/rust/kernel/task.rs
> @@ -210,6 +210,13 @@ pub fn pid(&self) -> Pid {
>          unsafe { *ptr::addr_of!((*self.as_ptr()).pid) }
>      }
>  
> +    /// Returns the TGID (Thread Group ID / Process ID) of the given task.
> +    pub fn tgid(&self) -> Pid {
> +        // SAFETY: The tgid of a task never changes after initialization, so reading this field is
> +        // not a data race.
> +        unsafe { *ptr::addr_of!((*self.as_ptr()).tgid) }
> +    }
> +
>      /// Returns the UID of the given task.
>      #[inline]
>      pub fn uid(&self) -> Kuid {
> 
> -- 

Only a few optional suggestions so...

Reviewed-by: Carlos Llamas <cmllamas@google.com>

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH v2 2/7] rust_binder: Implement BINDER_DEBUG_USER_ERROR for freezer-related operation
  2026-07-10 14:32 ` [PATCH v2 2/7] rust_binder: Implement BINDER_DEBUG_USER_ERROR for freezer-related operation Jahnavi MN via B4 Relay
@ 2026-07-10 19:55   ` Carlos Llamas
  0 siblings, 0 replies; 25+ messages in thread
From: Carlos Llamas @ 2026-07-10 19:55 UTC (permalink / raw)
  To: jahnavimn
  Cc: Greg Kroah-Hartman, Arve Hjønnevåg, Todd Kjos,
	Christian Brauner, Alice Ryhl, Miguel Ojeda, Boqun Feng, Gary Guo,
	Björn Roy Baron, Benno Lossin, Andreas Hindborg,
	Trevor Gross, Danilo Krummrich, Daniel Almeida, Tamir Duberstein,
	Alexandre Courbot, Onur Özkan, linux-kernel, rust-for-linux

On Fri, Jul 10, 2026 at 02:32:53PM +0000, Jahnavi MN via B4 Relay wrote:
> From: Jahnavi MN <jahnavimn@google.com>
> 
> This adds dynamic debug logs for:
> - Requesting freeze notifications on invalid references, duplicate
>   cookies, or already active registrations.
> - Completing freeze notifications that are not pending or not found.
> - Clearing freeze notifications on invalid references, inactive
>   notifications, or cookie mismatches.
> 
> Signed-off-by: Jahnavi MN <jahnavimn@google.com>
> ---

LGTM, thanks!

Reviewed-by: Carlos Llamas <cmllamas@google.com>

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH v2 3/7] rust_binder: Implement BINDER_DEBUG_USER_ERROR for refcounting and death notifications
  2026-07-10 14:32 ` [PATCH v2 3/7] rust_binder: Implement BINDER_DEBUG_USER_ERROR for refcounting and death notifications Jahnavi MN via B4 Relay
@ 2026-07-10 19:56   ` Carlos Llamas
  2026-07-10 19:58   ` Carlos Llamas
  1 sibling, 0 replies; 25+ messages in thread
From: Carlos Llamas @ 2026-07-10 19:56 UTC (permalink / raw)
  To: jahnavimn
  Cc: Greg Kroah-Hartman, Arve Hjønnevåg, Todd Kjos,
	Christian Brauner, Alice Ryhl, Miguel Ojeda, Boqun Feng, Gary Guo,
	Björn Roy Baron, Benno Lossin, Andreas Hindborg,
	Trevor Gross, Danilo Krummrich, Daniel Almeida, Tamir Duberstein,
	Alexandre Courbot, Onur Özkan, linux-kernel, rust-for-linux

On Fri, Jul 10, 2026 at 02:32:54PM +0000, Jahnavi MN via B4 Relay wrote:
> From: Jahnavi MN <jahnavimn@google.com>
> 
> This adds dynamic debug logs for:
> - Decrementing handle reference counts that are already zero.
> - Mismatched reference states (calling inc_ref_done with no active
>   inc_refs, or using a weak reference as a strong reference).
> - Requesting or clearing death notifications on invalid references,
>   already active notifications, or with mismatched cookies.
> 
> Signed-off-by: Jahnavi MN <jahnavimn@google.com>
> ---

LGTM, thanks!

Reviewed-by: Carlos Llamas <cmllamas@google.com>

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH v2 3/7] rust_binder: Implement BINDER_DEBUG_USER_ERROR for refcounting and death notifications
  2026-07-10 14:32 ` [PATCH v2 3/7] rust_binder: Implement BINDER_DEBUG_USER_ERROR for refcounting and death notifications Jahnavi MN via B4 Relay
  2026-07-10 19:56   ` Carlos Llamas
@ 2026-07-10 19:58   ` Carlos Llamas
  1 sibling, 0 replies; 25+ messages in thread
From: Carlos Llamas @ 2026-07-10 19:58 UTC (permalink / raw)
  To: jahnavimn
  Cc: Greg Kroah-Hartman, Arve Hjønnevåg, Todd Kjos,
	Christian Brauner, Alice Ryhl, Miguel Ojeda, Boqun Feng, Gary Guo,
	Björn Roy Baron, Benno Lossin, Andreas Hindborg,
	Trevor Gross, Danilo Krummrich, Daniel Almeida, Tamir Duberstein,
	Alexandre Courbot, Onur Özkan, linux-kernel, rust-for-linux

On Fri, Jul 10, 2026 at 02:32:54PM +0000, Jahnavi MN via B4 Relay wrote:
> From: Jahnavi MN <jahnavimn@google.com>
> 
> This adds dynamic debug logs for:
> - Decrementing handle reference counts that are already zero.
> - Mismatched reference states (calling inc_ref_done with no active
>   inc_refs, or using a weak reference as a strong reference).
> - Requesting or clearing death notifications on invalid references,
>   already active notifications, or with mismatched cookies.
> 
> Signed-off-by: Jahnavi MN <jahnavimn@google.com>
> ---

LGTM, thanks!

Reviewed-by: Carlos Llamas <cmllamas@google.com>

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH v2 4/7] rust_binder: Implement BINDER_DEBUG_USER_ERROR for transaction parsing failures
  2026-07-10 14:32 ` [PATCH v2 4/7] rust_binder: Implement BINDER_DEBUG_USER_ERROR for transaction parsing failures Jahnavi MN via B4 Relay
@ 2026-07-10 20:07   ` Carlos Llamas
  0 siblings, 0 replies; 25+ messages in thread
From: Carlos Llamas @ 2026-07-10 20:07 UTC (permalink / raw)
  To: jahnavimn
  Cc: Greg Kroah-Hartman, Arve Hjønnevåg, Todd Kjos,
	Christian Brauner, Alice Ryhl, Miguel Ojeda, Boqun Feng, Gary Guo,
	Björn Roy Baron, Benno Lossin, Andreas Hindborg,
	Trevor Gross, Danilo Krummrich, Daniel Almeida, Tamir Duberstein,
	Alexandre Courbot, Onur Özkan, linux-kernel, rust-for-linux

On Fri, Jul 10, 2026 at 02:32:55PM +0000, Jahnavi MN via B4 Relay wrote:
> From: Jahnavi MN <jahnavimn@google.com>
> 
> This adds dynamic debug logs in `thread.rs` for:
> - File descriptor array (FDA) parent offset and parent buffer address
>   alignment misalignments.
> - Memory copy, write, and translation failures during transaction
>   serialization (including out-of-bounds pointer fixups).
> - Incoming transactions or replies that do not match the expected
>   thread calling stack (such as out-of-order replies).
> 
> Signed-off-by: Jahnavi MN <jahnavimn@google.com>
> ---

LGTM, thanks!

Reviewed-by: Carlos Llamas <cmllamas@google.com>

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH v2 5/7] rust_binder: Implement BINDER_DEBUG_FAILED_TRANSACTION
  2026-07-10 14:32 ` [PATCH v2 5/7] rust_binder: Implement BINDER_DEBUG_FAILED_TRANSACTION Jahnavi MN via B4 Relay
@ 2026-07-10 20:15   ` Carlos Llamas
  0 siblings, 0 replies; 25+ messages in thread
From: Carlos Llamas @ 2026-07-10 20:15 UTC (permalink / raw)
  To: jahnavimn
  Cc: Greg Kroah-Hartman, Arve Hjønnevåg, Todd Kjos,
	Christian Brauner, Alice Ryhl, Miguel Ojeda, Boqun Feng, Gary Guo,
	Björn Roy Baron, Benno Lossin, Andreas Hindborg,
	Trevor Gross, Danilo Krummrich, Daniel Almeida, Tamir Duberstein,
	Alexandre Courbot, Onur Özkan, linux-kernel, rust-for-linux

On Fri, Jul 10, 2026 at 02:32:56PM +0000, Jahnavi MN via B4 Relay wrote:
> From: Jahnavi MN <jahnavimn@google.com>
> 
> This adds dynamic debug logs for:
> - Failed replies, target process deaths, and error code deliveries.
> - Detailed transaction failure diagnostics (including sender/receiver
>   PIDs, TIDs, transaction IDs, buffer sizes, and error codes).
> 
> Signed-off-by: Jahnavi MN <jahnavimn@google.com>
> ---

LGTM, thanks!

Reviewed-by: Carlos Llamas <cmllamas@google.com>

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH v2 6/7] rust_binder: Implement BINDER_DEBUG_DEATH_NOTIFICATION
  2026-07-10 14:32 ` [PATCH v2 6/7] rust_binder: Implement BINDER_DEBUG_DEATH_NOTIFICATION Jahnavi MN via B4 Relay
@ 2026-07-10 20:20   ` Carlos Llamas
  0 siblings, 0 replies; 25+ messages in thread
From: Carlos Llamas @ 2026-07-10 20:20 UTC (permalink / raw)
  To: jahnavimn
  Cc: Greg Kroah-Hartman, Arve Hjønnevåg, Todd Kjos,
	Christian Brauner, Alice Ryhl, Miguel Ojeda, Boqun Feng, Gary Guo,
	Björn Roy Baron, Benno Lossin, Andreas Hindborg,
	Trevor Gross, Danilo Krummrich, Daniel Almeida, Tamir Duberstein,
	Alexandre Courbot, Onur Özkan, linux-kernel, rust-for-linux

On Fri, Jul 10, 2026 at 02:32:57PM +0000, Jahnavi MN via B4 Relay wrote:
> From: Jahnavi MN <jahnavimn@google.com>
> 
> This adds dynamic debug logs for:
> - Memory allocation (OOM) failures when requesting
>   death notifications
> - Registration and cancellation lifecycle events
>   (BC_REQUEST / BC_CLEAR)
> - Delivery of death notification events to userspace
>   (BR_DEAD_BINDER)
> 
> Signed-off-by: Jahnavi MN <jahnavimn@google.com>
> ---

LGTM, thanks!

Reviewed-by: Carlos Llamas <cmllamas@google.com>

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH v2 1/7] rust_binder: Add dynamic debug logging mask
  2026-07-10 19:47   ` Carlos Llamas
@ 2026-07-10 20:27     ` Gary Guo
  2026-07-10 22:12       ` Carlos Llamas
  0 siblings, 1 reply; 25+ messages in thread
From: Gary Guo @ 2026-07-10 20:27 UTC (permalink / raw)
  To: Carlos Llamas, jahnavimn
  Cc: Greg Kroah-Hartman, Arve Hjønnevåg, Todd Kjos,
	Christian Brauner, Alice Ryhl, Miguel Ojeda, Boqun Feng, Gary Guo,
	Björn Roy Baron, Benno Lossin, Andreas Hindborg,
	Trevor Gross, Danilo Krummrich, Daniel Almeida, Tamir Duberstein,
	Alexandre Courbot, Onur Özkan, linux-kernel, rust-for-linux

On Fri Jul 10, 2026 at 8:47 PM BST, Carlos Llamas wrote:
> On Fri, Jul 10, 2026 at 02:32:52PM +0000, Jahnavi MN via B4 Relay wrote:
>> From: Jahnavi MN <jahnavimn@google.com>
>> 
>> Implement a dynamic debug logging mask (`debug_mask`) for the
>> `rust_binder` module to allow dynamic runtime configuration of log
>> levels. This enables parity with the legacy C driver's debug mask.
>> 
>> Since the Rust `module!` macro in the current kernel build does not yet
>> support declaring module parameters directly in Rust, we define the
>> `debug_mask` variable in a C companion file to expose it to the kernel
>> runtime and import it using FFI with volatile reads.
>> 
>> To verify the setup, instrument process lifecycle events (open, flush,
>> and release) in `process.rs` under the new `BINDER_DEBUG_OPEN_CLOSE`
>> logging mask. These entry-point events are chosen for initial validation
>> because they represent the start of the Binder lifecycle and occur
>> at low frequency, allowing simple runtime verification of the dynamic
>> toggle without log noise.
>> 
>> Signed-off-by: Jahnavi MN <jahnavimn@google.com>
>> ---
>>  drivers/android/binder/debug.rs            | 80 ++++++++++++++++++++++++++++++
>>  drivers/android/binder/process.rs          |  7 ++-
>>  drivers/android/binder/rust_binder_main.rs |  2 +
>>  drivers/android/binder/rust_binderfs.c     |  3 ++
>>  rust/kernel/task.rs                        |  7 +++
>>  5 files changed, 98 insertions(+), 1 deletion(-)
>> 
>> diff --git a/drivers/android/binder/debug.rs b/drivers/android/binder/debug.rs
>> new file mode 100644
>> index 000000000000..da48bce3df54
>> --- /dev/null
>> +++ b/drivers/android/binder/debug.rs
>> @@ -0,0 +1,80 @@
>> +// SPDX-License-Identifier: GPL-2.0
>> +// Copyright (C) 2026 Google LLC.
>> +
>> +//! Binder debugging helpers.
>> +
>> +#![allow(dead_code)]
>> +
>> +kernel::impl_flags!(
>> +    /// Represents multiple debug mask flags.
>> +    #[derive(Debug, Clone, Default, Copy, PartialEq, Eq)]
>> +    pub struct DebugMasks(u32);
>
> Where is this being used? I can't find it on subsequent patches.
> Maybe leftover from previous implementation?

impl_flags macro requires a type for a single flag and a type for flag masks.

>
>> +
>> +    /// Represents a single debug mask category.
>> +    #[derive(Debug, Clone, Copy, PartialEq, Eq)]
>> +    pub enum DebugMask {
>> +        UserError = 1 << 0,
>> +        FailedTransaction = 1 << 1,
>> +        DeadTransaction = 1 << 2,
>> +        OpenClose = 1 << 3,
>> +        DeadBinder = 1 << 4,
>> +        DeathNotification = 1 << 5,
>> +        ReadWrite = 1 << 6,
>> +        UserRefs = 1 << 7,
>> +        Threads = 1 << 8,
>> +        Transaction = 1 << 9,
>> +        TransactionComplete = 1 << 10,
>> +        FreeBuffer = 1 << 11,
>> +        InternalRefs = 1 << 12,
>> +        PriorityCap = 1 << 13,
>> +        Spinlocks = 1 << 14,
>> +    }
>> +);
>> diff --git a/drivers/android/binder/rust_binder_main.rs b/drivers/android/binder/rust_binder_main.rs
>> index df47aba05133..995e6131bb77 100644
>> --- a/drivers/android/binder/rust_binder_main.rs
>> +++ b/drivers/android/binder/rust_binder_main.rs
>> @@ -31,6 +31,8 @@
>>  mod context;
>>  mod deferred_close;
>>  mod defs;
>> +#[macro_use]
>> +mod debug;
>>  mod error;
>>  mod netlink;
>>  mod node;
>> diff --git a/drivers/android/binder/rust_binderfs.c b/drivers/android/binder/rust_binderfs.c
>> index ade1c4d92499..fa8b38465550 100644
>> --- a/drivers/android/binder/rust_binderfs.c
>> +++ b/drivers/android/binder/rust_binderfs.c
>> @@ -51,6 +51,9 @@ DEFINE_SHOW_ATTRIBUTE(rust_binder_proc);
>>  char *rust_binder_devices_param = CONFIG_ANDROID_BINDER_DEVICES;
>>  module_param_named(rust_devices, rust_binder_devices_param, charp, 0444);
>>  
>> +u32 rust_binder_debug_mask = 7;
>
> hmm, I'm not sure about this magic number. Do you think we can
> initialize on the rust end at init()? Or at least a comment about what
> flags we are setting as default here?

It doesn't even need that, just a

static rust_binder_debug_mask: Atomic<u32> = Atomic::new((FLAG_A as u32) | (FLAG_B as u32) | ...);

and a `extern u32` on C side should do.

would do. Unfortunately this has to be integer bit-or with casts (and cannot use
DebugMasks due to lack of const trait impl).

Best,
Gary

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH v2 1/7] rust_binder: Add dynamic debug logging mask
  2026-07-10 20:27     ` Gary Guo
@ 2026-07-10 22:12       ` Carlos Llamas
  0 siblings, 0 replies; 25+ messages in thread
From: Carlos Llamas @ 2026-07-10 22:12 UTC (permalink / raw)
  To: Gary Guo
  Cc: jahnavimn, Greg Kroah-Hartman, Arve Hjønnevåg,
	Todd Kjos, Christian Brauner, Alice Ryhl, Miguel Ojeda,
	Boqun Feng, Björn Roy Baron, Benno Lossin, Andreas Hindborg,
	Trevor Gross, Danilo Krummrich, Daniel Almeida, Tamir Duberstein,
	Alexandre Courbot, Onur Özkan, linux-kernel, rust-for-linux

On Fri, Jul 10, 2026 at 09:27:37PM +0100, Gary Guo wrote:
> On Fri Jul 10, 2026 at 8:47 PM BST, Carlos Llamas wrote:
> > On Fri, Jul 10, 2026 at 02:32:52PM +0000, Jahnavi MN via B4 Relay wrote:
> >> From: Jahnavi MN <jahnavimn@google.com>
> >> 
> >> Implement a dynamic debug logging mask (`debug_mask`) for the
> >> `rust_binder` module to allow dynamic runtime configuration of log
> >> levels. This enables parity with the legacy C driver's debug mask.
> >> 
> >> Since the Rust `module!` macro in the current kernel build does not yet
> >> support declaring module parameters directly in Rust, we define the
> >> `debug_mask` variable in a C companion file to expose it to the kernel
> >> runtime and import it using FFI with volatile reads.
> >> 
> >> To verify the setup, instrument process lifecycle events (open, flush,
> >> and release) in `process.rs` under the new `BINDER_DEBUG_OPEN_CLOSE`
> >> logging mask. These entry-point events are chosen for initial validation
> >> because they represent the start of the Binder lifecycle and occur
> >> at low frequency, allowing simple runtime verification of the dynamic
> >> toggle without log noise.
> >> 
> >> Signed-off-by: Jahnavi MN <jahnavimn@google.com>
> >> ---
> >>  drivers/android/binder/debug.rs            | 80 ++++++++++++++++++++++++++++++
> >>  drivers/android/binder/process.rs          |  7 ++-
> >>  drivers/android/binder/rust_binder_main.rs |  2 +
> >>  drivers/android/binder/rust_binderfs.c     |  3 ++
> >>  rust/kernel/task.rs                        |  7 +++
> >>  5 files changed, 98 insertions(+), 1 deletion(-)
> >> 
> >> diff --git a/drivers/android/binder/debug.rs b/drivers/android/binder/debug.rs
> >> new file mode 100644
> >> index 000000000000..da48bce3df54
> >> --- /dev/null
> >> +++ b/drivers/android/binder/debug.rs
> >> @@ -0,0 +1,80 @@
> >> +// SPDX-License-Identifier: GPL-2.0
> >> +// Copyright (C) 2026 Google LLC.
> >> +
> >> +//! Binder debugging helpers.
> >> +
> >> +#![allow(dead_code)]
> >> +
> >> +kernel::impl_flags!(
> >> +    /// Represents multiple debug mask flags.
> >> +    #[derive(Debug, Clone, Default, Copy, PartialEq, Eq)]
> >> +    pub struct DebugMasks(u32);
> >
> > Where is this being used? I can't find it on subsequent patches.
> > Maybe leftover from previous implementation?
> 
> impl_flags macro requires a type for a single flag and a type for flag masks.

Oh I see. I was expecting the bitops to be peformed on this type
somewhere. I guess the reason it wasn't is because of the issue with
module parameters and their C macros.

> 
> >
> >> +
> >> +    /// Represents a single debug mask category.
> >> +    #[derive(Debug, Clone, Copy, PartialEq, Eq)]
> >> +    pub enum DebugMask {
> >> +        UserError = 1 << 0,
> >> +        FailedTransaction = 1 << 1,
> >> +        DeadTransaction = 1 << 2,
> >> +        OpenClose = 1 << 3,
> >> +        DeadBinder = 1 << 4,
> >> +        DeathNotification = 1 << 5,
> >> +        ReadWrite = 1 << 6,
> >> +        UserRefs = 1 << 7,
> >> +        Threads = 1 << 8,
> >> +        Transaction = 1 << 9,
> >> +        TransactionComplete = 1 << 10,
> >> +        FreeBuffer = 1 << 11,
> >> +        InternalRefs = 1 << 12,
> >> +        PriorityCap = 1 << 13,
> >> +        Spinlocks = 1 << 14,
> >> +    }
> >> +);
> >> diff --git a/drivers/android/binder/rust_binder_main.rs b/drivers/android/binder/rust_binder_main.rs
> >> index df47aba05133..995e6131bb77 100644
> >> --- a/drivers/android/binder/rust_binder_main.rs
> >> +++ b/drivers/android/binder/rust_binder_main.rs
> >> @@ -31,6 +31,8 @@
> >>  mod context;
> >>  mod deferred_close;
> >>  mod defs;
> >> +#[macro_use]
> >> +mod debug;
> >>  mod error;
> >>  mod netlink;
> >>  mod node;
> >> diff --git a/drivers/android/binder/rust_binderfs.c b/drivers/android/binder/rust_binderfs.c
> >> index ade1c4d92499..fa8b38465550 100644
> >> --- a/drivers/android/binder/rust_binderfs.c
> >> +++ b/drivers/android/binder/rust_binderfs.c
> >> @@ -51,6 +51,9 @@ DEFINE_SHOW_ATTRIBUTE(rust_binder_proc);
> >>  char *rust_binder_devices_param = CONFIG_ANDROID_BINDER_DEVICES;
> >>  module_param_named(rust_devices, rust_binder_devices_param, charp, 0444);
> >>  
> >> +u32 rust_binder_debug_mask = 7;
> >
> > hmm, I'm not sure about this magic number. Do you think we can
> > initialize on the rust end at init()? Or at least a comment about what
> > flags we are setting as default here?
> 
> It doesn't even need that, just a
> 
> static rust_binder_debug_mask: Atomic<u32> = Atomic::new((FLAG_A as u32) | (FLAG_B as u32) | ...);
> 
> and a `extern u32` on C side should do.

ha sure, reversing the declaration and extern would also work.

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH v2 0/7] rust_binder : Implement dynamic debug logging mask
  2026-07-10 15:01 ` Greg Kroah-Hartman
@ 2026-07-11 10:28   ` Jahnavi Nitheesha Mandava
  2026-07-11 10:42     ` Alice Ryhl
  0 siblings, 1 reply; 25+ messages in thread
From: Jahnavi Nitheesha Mandava @ 2026-07-11 10:28 UTC (permalink / raw)
  To: Greg Kroah-Hartman
  Cc: Arve Hjønnevåg, Todd Kjos, Christian Brauner,
	Carlos Llamas, Alice Ryhl, Miguel Ojeda, Boqun Feng, Gary Guo,
	Björn Roy Baron, Benno Lossin, Andreas Hindborg,
	Trevor Gross, Danilo Krummrich, Daniel Almeida, Tamir Duberstein,
	Alexandre Courbot, Onur Özkan, linux-kernel, rust-for-linux

On Fri, Jul 10, 2026 at 8:31 PM Greg Kroah-Hartman
<gregkh@linuxfoundation.org> wrote:
>
> On Fri, Jul 10, 2026 at 02:32:51PM +0000, Jahnavi MN via B4 Relay wrote:
> > When a user-space application sends malformed data or makes a
> > lifecycle mistake, the driver rejects it with a generic error code
> > (like -EINVAL). Without internal logs, the driver acts as a
> > "black box," forcing developers to guess which check failed.
> >
> > In the legacy C Binder driver, this issue is solved using a dynamic
> > debug_mask module parameter that toggles verbose logs for specific
> > subsystems. This series brings the same critical capability to the
> > Rust Binder driver to provide developers with clear, real-time
> > feedback.
> >
> > Instead of rebuilds, reboots, or guessing:
> > - Developers can enable logs instantly on a running device by writing to
> >   `/sys/module/rust_binder/parameters/debug_mask`.
> > - It prints the exact reason for failures (such as alignment errors,
> >   mismatched call stacks, or invalid handle references) directly into
> >   `dmesg`, reducing debugging time from hours to seconds.
> > - It protects system logs by keeping logging off by default and only
> >   enabling it when developers are actively troubleshooting.
> >
> > Based on top of:
> > https://lore.kernel.org/rust-for-linux/20260707-upgrade-poll-v6-0-4b8fae7bf1d9@google.com/
> >
> > Signed-off-by: Jahnavi MN <jahnavimn@google.com>
>
> Patches 5 and 7 did not apply to my tree, can you rebase against the
> char-misc-testing branch and send just those?  Other ones are now all
> queued up, nice work!
>
> thanks,
>
> greg k-h

Hi Greg,

Thanks! I will rebase and resubmit only patches 5 and 7 as a new
version (v3) of this series shortly.

Regarding the feedback I received on Patch 1 (using the BIT macro
and Atomic<u32>), since Patch 1 is already queued, I will send those
cleanups as a separate, follow-up patch. Does that sound good?

Thanks,
Jahnavi

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH v2 0/7] rust_binder : Implement dynamic debug logging mask
  2026-07-11 10:28   ` Jahnavi Nitheesha Mandava
@ 2026-07-11 10:42     ` Alice Ryhl
  0 siblings, 0 replies; 25+ messages in thread
From: Alice Ryhl @ 2026-07-11 10:42 UTC (permalink / raw)
  To: Jahnavi Nitheesha Mandava
  Cc: Greg Kroah-Hartman, Arve Hjønnevåg, Todd Kjos,
	Christian Brauner, Carlos Llamas, Miguel Ojeda, Boqun Feng,
	Gary Guo, Björn Roy Baron, Benno Lossin, Andreas Hindborg,
	Trevor Gross, Danilo Krummrich, Daniel Almeida, Tamir Duberstein,
	Alexandre Courbot, Onur Özkan, linux-kernel, rust-for-linux

On Sat, Jul 11, 2026 at 12:29 PM Jahnavi Nitheesha Mandava
<jahnavimn@google.com> wrote:
>
> On Fri, Jul 10, 2026 at 8:31 PM Greg Kroah-Hartman
> <gregkh@linuxfoundation.org> wrote:
> >
> > On Fri, Jul 10, 2026 at 02:32:51PM +0000, Jahnavi MN via B4 Relay wrote:
> > > When a user-space application sends malformed data or makes a
> > > lifecycle mistake, the driver rejects it with a generic error code
> > > (like -EINVAL). Without internal logs, the driver acts as a
> > > "black box," forcing developers to guess which check failed.
> > >
> > > In the legacy C Binder driver, this issue is solved using a dynamic
> > > debug_mask module parameter that toggles verbose logs for specific
> > > subsystems. This series brings the same critical capability to the
> > > Rust Binder driver to provide developers with clear, real-time
> > > feedback.
> > >
> > > Instead of rebuilds, reboots, or guessing:
> > > - Developers can enable logs instantly on a running device by writing to
> > >   `/sys/module/rust_binder/parameters/debug_mask`.
> > > - It prints the exact reason for failures (such as alignment errors,
> > >   mismatched call stacks, or invalid handle references) directly into
> > >   `dmesg`, reducing debugging time from hours to seconds.
> > > - It protects system logs by keeping logging off by default and only
> > >   enabling it when developers are actively troubleshooting.
> > >
> > > Based on top of:
> > > https://lore.kernel.org/rust-for-linux/20260707-upgrade-poll-v6-0-4b8fae7bf1d9@google.com/
> > >
> > > Signed-off-by: Jahnavi MN <jahnavimn@google.com>
> >
> > Patches 5 and 7 did not apply to my tree, can you rebase against the
> > char-misc-testing branch and send just those?  Other ones are now all
> > queued up, nice work!
> >
> > thanks,
> >
> > greg k-h
>
> Hi Greg,
>
> Thanks! I will rebase and resubmit only patches 5 and 7 as a new
> version (v3) of this series shortly.
>
> Regarding the feedback I received on Patch 1 (using the BIT macro
> and Atomic<u32>), since Patch 1 is already queued, I will send those
> cleanups as a separate, follow-up patch. Does that sound good?

Since it's only queued in char-misc-testing and not char-misc-next, I
don't think it's too late to change the patches themselves. So I guess
you could also resend the entire series based on top of commit
f8d269390cd2 ("rust_binder: update Process::node_refs to use
SpinLock") from testing?

Alice

^ permalink raw reply	[flat|nested] 25+ messages in thread

end of thread, other threads:[~2026-07-11 10:42 UTC | newest]

Thread overview: 25+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-10 14:32 [PATCH v2 0/7] rust_binder : Implement dynamic debug logging mask Jahnavi MN via B4 Relay
2026-07-10 14:32 ` [PATCH v2 1/7] rust_binder: Add " Jahnavi MN via B4 Relay
2026-07-10 14:59   ` Greg Kroah-Hartman
2026-07-10 16:37     ` Miguel Ojeda
2026-07-10 17:03       ` Miguel Ojeda
2026-07-10 16:51   ` Gary Guo
2026-07-10 19:47   ` Carlos Llamas
2026-07-10 20:27     ` Gary Guo
2026-07-10 22:12       ` Carlos Llamas
2026-07-10 14:32 ` [PATCH v2 2/7] rust_binder: Implement BINDER_DEBUG_USER_ERROR for freezer-related operation Jahnavi MN via B4 Relay
2026-07-10 19:55   ` Carlos Llamas
2026-07-10 14:32 ` [PATCH v2 3/7] rust_binder: Implement BINDER_DEBUG_USER_ERROR for refcounting and death notifications Jahnavi MN via B4 Relay
2026-07-10 19:56   ` Carlos Llamas
2026-07-10 19:58   ` Carlos Llamas
2026-07-10 14:32 ` [PATCH v2 4/7] rust_binder: Implement BINDER_DEBUG_USER_ERROR for transaction parsing failures Jahnavi MN via B4 Relay
2026-07-10 20:07   ` Carlos Llamas
2026-07-10 14:32 ` [PATCH v2 5/7] rust_binder: Implement BINDER_DEBUG_FAILED_TRANSACTION Jahnavi MN via B4 Relay
2026-07-10 20:15   ` Carlos Llamas
2026-07-10 14:32 ` [PATCH v2 6/7] rust_binder: Implement BINDER_DEBUG_DEATH_NOTIFICATION Jahnavi MN via B4 Relay
2026-07-10 20:20   ` Carlos Llamas
2026-07-10 14:32 ` [PATCH v2 7/7] rust_binder: Implement BINDER_DEBUG_DEAD_TRANSACTION Jahnavi MN via B4 Relay
2026-07-10 14:35 ` [PATCH v2 0/7] rust_binder : Implement dynamic debug logging mask Alice Ryhl
2026-07-10 15:01 ` Greg Kroah-Hartman
2026-07-11 10:28   ` Jahnavi Nitheesha Mandava
2026-07-11 10:42     ` Alice Ryhl

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox