lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite for Android: free password hash cracker in your pocket
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20251203-binder-trace1-v1-2-22d3ffddb44e@google.com>
Date: Wed, 03 Dec 2025 14:48:09 +0000
From: Alice Ryhl <aliceryhl@...gle.com>
To: Greg Kroah-Hartman <gregkh@...uxfoundation.org>, Carlos Llamas <cmllamas@...gle.com>, 
	Steven Rostedt <rostedt@...dmis.org>
Cc: Masami Hiramatsu <mhiramat@...nel.org>, Mathieu Desnoyers <mathieu.desnoyers@...icios.com>, 
	Miguel Ojeda <ojeda@...nel.org>, Boqun Feng <boqun.feng@...il.com>, Gary Guo <gary@...yguo.net>, 
	"Björn Roy Baron" <bjorn3_gh@...tonmail.com>, Benno Lossin <lossin@...nel.org>, 
	Andreas Hindborg <a.hindborg@...nel.org>, Trevor Gross <tmgross@...ch.edu>, 
	Danilo Krummrich <dakr@...nel.org>, "Arve Hjønnevåg" <arve@...roid.com>, Todd Kjos <tkjos@...roid.com>, 
	Martijn Coenen <maco@...roid.com>, Joel Fernandes <joelagnelf@...dia.com>, 
	Christian Brauner <brauner@...nel.org>, Suren Baghdasaryan <surenb@...gle.com>, rust-for-linux@...r.kernel.org, 
	linux-trace-kernel@...r.kernel.org, linux-kernel@...r.kernel.org, 
	Alice Ryhl <aliceryhl@...gle.com>
Subject: [PATCH 2/2] rust_binder: add binder_transaction tracepoint

This patch adds the binder_transaction tracepoint to Rust Binder. This
was chosen as the next tracepoint to add as it is the most complex
tracepoint. (And it's also an important tracepoint known to perfetto.)

Signed-off-by: Alice Ryhl <aliceryhl@...gle.com>
---
 drivers/android/binder/node.rs              |  8 +++
 drivers/android/binder/process.rs           |  7 +++
 drivers/android/binder/rust_binder.h        | 79 +++++++++++++++++++++++++++++
 drivers/android/binder/rust_binder_events.h | 30 +++++++++++
 drivers/android/binder/rust_binder_main.rs  |  8 +++
 drivers/android/binder/thread.rs            |  1 +
 drivers/android/binder/trace.rs             | 21 ++++++++
 drivers/android/binder/transaction.rs       | 14 +++++
 8 files changed, 168 insertions(+)

diff --git a/drivers/android/binder/node.rs b/drivers/android/binder/node.rs
index ade895ef791ec5746f9f5c1bfc15f47d59829455..7e6c94c7c3373461520d52d0b1fe8c1fc871fbd8 100644
--- a/drivers/android/binder/node.rs
+++ b/drivers/android/binder/node.rs
@@ -178,6 +178,14 @@ struct NodeInner {
     refs: List<NodeRefInfo, { NodeRefInfo::LIST_NODE }>,
 }
 
+use kernel::bindings::rb_node_layout;
+use mem::offset_of;
+pub(crate) const NODE_LAYOUT: rb_node_layout = rb_node_layout {
+    arc_offset: Arc::<Node>::DATA_OFFSET + offset_of!(DTRWrap<Node>, wrapped),
+    debug_id: offset_of!(Node, debug_id),
+    ptr: offset_of!(Node, ptr),
+};
+
 #[pin_data]
 pub(crate) struct Node {
     pub(crate) debug_id: usize,
diff --git a/drivers/android/binder/process.rs b/drivers/android/binder/process.rs
index f13a747e784c84a0fb09cbf47442712106eba07c..c4c8a0ba93366f3e2ec426fb5950f48edb0610ae 100644
--- a/drivers/android/binder/process.rs
+++ b/drivers/android/binder/process.rs
@@ -387,6 +387,13 @@ fn new() -> Self {
     }
 }
 
+use core::mem::offset_of;
+use kernel::bindings::rb_process_layout;
+pub(crate) const PROCESS_LAYOUT: rb_process_layout = rb_process_layout {
+    arc_offset: Arc::<Process>::DATA_OFFSET,
+    task: offset_of!(Process, task),
+};
+
 /// A process using binder.
 ///
 /// Strictly speaking, there can be multiple of these per process. There is one for each binder fd
diff --git a/drivers/android/binder/rust_binder.h b/drivers/android/binder/rust_binder.h
index 31806890ed1a278793ae7178f9d76ca4d591a954..e68ba7a23c34de4688fa7d34341b0585b5dba7e9 100644
--- a/drivers/android/binder/rust_binder.h
+++ b/drivers/android/binder/rust_binder.h
@@ -20,4 +20,83 @@ struct inode;
 struct dentry *rust_binderfs_create_proc_file(struct inode *nodp, int pid);
 void rust_binderfs_remove_file(struct dentry *dentry);
 
+/*
+ * The internal data types in the Rust Binder driver are opaque to C, so we use
+ * void pointer typedefs for these types.
+ */
+
+typedef void *rust_binder_transaction;
+typedef void *rust_binder_process;
+typedef void *rust_binder_node;
+
+struct rb_process_layout {
+	size_t arc_offset;
+	size_t task;
+};
+
+struct rb_transaction_layout {
+	size_t debug_id;
+	size_t code;
+	size_t flags;
+	size_t from_thread;
+	size_t to_proc;
+	size_t target_node;
+};
+
+struct rb_node_layout {
+	size_t arc_offset;
+	size_t debug_id;
+	size_t ptr;
+};
+
+struct rust_binder_layout {
+	struct rb_transaction_layout t;
+	struct rb_process_layout p;
+	struct rb_node_layout n;
+};
+
+extern const struct rust_binder_layout RUST_BINDER_LAYOUT;
+
+static inline size_t rust_binder_transaction_debug_id(rust_binder_transaction t)
+{
+	return *(size_t *) (t + RUST_BINDER_LAYOUT.t.debug_id);
+}
+
+static inline u32 rust_binder_transaction_code(rust_binder_transaction t)
+{
+	return *(u32 *) (t + RUST_BINDER_LAYOUT.t.code);
+}
+
+static inline u32 rust_binder_transaction_flags(rust_binder_transaction t)
+{
+	return *(u32 *) (t + RUST_BINDER_LAYOUT.t.flags);
+}
+
+// Nullable!
+static inline rust_binder_node rust_binder_transaction_target_node(rust_binder_transaction t)
+{
+	void *p = *(void **) (t + RUST_BINDER_LAYOUT.t.target_node);
+
+	if (p)
+		p = p + RUST_BINDER_LAYOUT.n.arc_offset;
+	return NULL;
+}
+
+static inline rust_binder_process rust_binder_transaction_to_proc(rust_binder_transaction t)
+{
+	void *p = *(void **) (t + RUST_BINDER_LAYOUT.t.to_proc);
+
+	return p + RUST_BINDER_LAYOUT.p.arc_offset;
+}
+
+static inline struct task_struct *rust_binder_process_task(rust_binder_process t)
+{
+	return *(struct task_struct **) (t + RUST_BINDER_LAYOUT.p.task);
+}
+
+static inline size_t rust_binder_node_debug_id(rust_binder_node t)
+{
+	return *(size_t *) (t + RUST_BINDER_LAYOUT.n.debug_id);
+}
+
 #endif
diff --git a/drivers/android/binder/rust_binder_events.h b/drivers/android/binder/rust_binder_events.h
index 2f3efbf9dba68e6415f0f09ff5c8255dc5c5bc00..8ad785c6bd0f5783df1e764a8827fed41afbcb00 100644
--- a/drivers/android/binder/rust_binder_events.h
+++ b/drivers/android/binder/rust_binder_events.h
@@ -30,6 +30,36 @@ TRACE_EVENT(rust_binder_ioctl,
 	TP_printk("cmd=0x%x arg=0x%lx", __entry->cmd, __entry->arg)
 );
 
+TRACE_EVENT(rust_binder_transaction,
+	TP_PROTO(bool reply, rust_binder_transaction t, struct task_struct *thread),
+	TP_ARGS(reply, t, thread),
+	TP_STRUCT__entry(
+		__field(int, debug_id)
+		__field(int, target_node)
+		__field(int, to_proc)
+		__field(int, to_thread)
+		__field(int, reply)
+		__field(unsigned int, code)
+		__field(unsigned int, flags)
+	),
+	TP_fast_assign(
+		rust_binder_process to = rust_binder_transaction_to_proc(t);
+		rust_binder_node target_node = rust_binder_transaction_target_node(t);
+
+		__entry->debug_id = rust_binder_transaction_debug_id(t);
+		__entry->target_node = target_node ? rust_binder_node_debug_id(target_node) : 0;
+		__entry->to_proc = rust_binder_process_task(to)->pid;
+		__entry->to_thread = thread ? thread->pid : 0;
+		__entry->reply = reply;
+		__entry->code = rust_binder_transaction_code(t);
+		__entry->flags = rust_binder_transaction_flags(t);
+	),
+	TP_printk("transaction=%d dest_node=%d dest_proc=%d dest_thread=%d reply=%d flags=0x%x code=0x%x",
+		  __entry->debug_id, __entry->target_node,
+		  __entry->to_proc, __entry->to_thread,
+		  __entry->reply, __entry->flags, __entry->code)
+);
+
 #endif /* _RUST_BINDER_TRACE_H */
 
 /* This part must be outside protection */
diff --git a/drivers/android/binder/rust_binder_main.rs b/drivers/android/binder/rust_binder_main.rs
index 6773b7c273ec9634057300954d67b51ca9b54f6f..3799b4707ed4e0505a3d3370e3dd1e74f974b641 100644
--- a/drivers/android/binder/rust_binder_main.rs
+++ b/drivers/android/binder/rust_binder_main.rs
@@ -89,6 +89,14 @@ fn default() -> Self {
     license: "GPL",
 }
 
+use kernel::bindings::rust_binder_layout;
+#[no_mangle]
+static RUST_BINDER_LAYOUT: rust_binder_layout = rust_binder_layout {
+    t: transaction::TRANSACTION_LAYOUT,
+    p: process::PROCESS_LAYOUT,
+    n: node::NODE_LAYOUT,
+};
+
 fn next_debug_id() -> usize {
     static NEXT_DEBUG_ID: AtomicUsize = AtomicUsize::new(0);
 
diff --git a/drivers/android/binder/thread.rs b/drivers/android/binder/thread.rs
index 7e34ccd394f8049bab88562ffb4601739aea670a..0874e2793e276e075802d97ea9bb02a4c2fc8c72 100644
--- a/drivers/android/binder/thread.rs
+++ b/drivers/android/binder/thread.rs
@@ -1117,6 +1117,7 @@ fn deliver_single_reply(
         transaction: &DArc<Transaction>,
     ) -> bool {
         if let Ok(transaction) = &reply {
+            crate::trace::trace_transaction(true, transaction, Some(&self.task));
             transaction.set_outstanding(&mut self.process.inner.lock());
         }
 
diff --git a/drivers/android/binder/trace.rs b/drivers/android/binder/trace.rs
index af0e4392805e7ef2a39b7c1e557ea233dcd810ab..9839901c7151590defed297b091f1339603c09df 100644
--- a/drivers/android/binder/trace.rs
+++ b/drivers/android/binder/trace.rs
@@ -2,11 +2,21 @@
 
 // Copyright (C) 2025 Google LLC.
 
+use crate::transaction::Transaction;
+
+use kernel::bindings::{rust_binder_transaction, task_struct};
 use kernel::ffi::{c_uint, c_ulong};
+use kernel::task::Task;
 use kernel::tracepoint::declare_trace;
 
 declare_trace! {
     unsafe fn rust_binder_ioctl(cmd: c_uint, arg: c_ulong);
+    unsafe fn rust_binder_transaction(reply: bool, t: rust_binder_transaction, thread: *mut task_struct);
+}
+
+#[inline]
+fn raw_transaction(t: &Transaction) -> rust_binder_transaction {
+    t as *const Transaction as rust_binder_transaction
 }
 
 #[inline]
@@ -14,3 +24,14 @@ pub(crate) fn trace_ioctl(cmd: u32, arg: usize) {
     // SAFETY: Always safe to call.
     unsafe { rust_binder_ioctl(cmd, arg as c_ulong) }
 }
+
+#[inline]
+pub(crate) fn trace_transaction(reply: bool, t: &Transaction, thread: Option<&Task>) {
+    let thread = match thread {
+        Some(thread) => thread.as_ptr(),
+        None => core::ptr::null_mut(),
+    };
+    // SAFETY: The raw transaction is valid for the duration of this call. The thread pointer is
+    // valid or null.
+    unsafe { rust_binder_transaction(reply, raw_transaction(t), thread) }
+}
diff --git a/drivers/android/binder/transaction.rs b/drivers/android/binder/transaction.rs
index 02512175d6229535373f2d3e543ba8c91ecd72f0..6a12064a53ad4c477d8b6cb016333f5a10ec399a 100644
--- a/drivers/android/binder/transaction.rs
+++ b/drivers/android/binder/transaction.rs
@@ -24,6 +24,17 @@
     BinderReturnWriter, DArc, DLArc, DTRWrap, DeliverToRead,
 };
 
+use core::mem::offset_of;
+use kernel::bindings::rb_transaction_layout;
+pub(crate) const TRANSACTION_LAYOUT: rb_transaction_layout = rb_transaction_layout {
+    debug_id: offset_of!(Transaction, debug_id),
+    code: offset_of!(Transaction, code),
+    flags: offset_of!(Transaction, flags),
+    from_thread: offset_of!(Transaction, from),
+    to_proc: offset_of!(Transaction, to),
+    target_node: offset_of!(Transaction, target_node),
+};
+
 #[pin_data(PinnedDrop)]
 pub(crate) struct Transaction {
     pub(crate) debug_id: usize,
@@ -249,6 +260,7 @@ pub(crate) fn submit(self: DLArc<Self>) -> BinderResult {
 
         if oneway {
             if let Some(target_node) = self.target_node.clone() {
+                crate::trace::trace_transaction(false, &self, None);
                 if process_inner.is_frozen {
                     process_inner.async_recv = true;
                     if self.flags & TF_UPDATE_TXN != 0 {
@@ -286,11 +298,13 @@ pub(crate) fn submit(self: DLArc<Self>) -> BinderResult {
         }
 
         let res = if let Some(thread) = self.find_target_thread() {
+            crate::trace::trace_transaction(false, &self, Some(&thread.task));
             match thread.push_work(self) {
                 PushWorkRes::Ok => Ok(()),
                 PushWorkRes::FailedDead(me) => Err((BinderError::new_dead(), me)),
             }
         } else {
+            crate::trace::trace_transaction(false, &self, None);
             process_inner.push_work(self)
         };
         drop(process_inner);

-- 
2.52.0.158.g65b55ccf14-goog


Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ