Skip to contentSkip to conversation

FAILED: patch "[PATCH] rust_binder: fix BINDER_GET_EXTENDED_ERROR" failed to apply to 6.18-stable tree

PATCH Applied [email protected] 3 participants 4 messages Jul 13 – Jul 15

Subsystems (2)
lore
Share & tools
lore

[email protected]

author maintainer
#0 lore raw

The patch below does not apply to the 6.18-stable tree.
If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to <[email protected]>.

To reproduce the conflict and resubmit, you may use the following commands:

git fetch https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/ linux-6.18.y
git checkout FETCH_HEAD
git cherry-pick -x 77bfebf110773f5a0d6b5ff8110896adb2c9c335
# <resolve conflicts, build, test, etc.>
git commit -s
git send-email --to '<[email protected]>' --in-reply-to '2026071331-obstruct-sprig-4ee1@gregkh' --subject-prefix 'PATCH 6.18.y' 'HEAD^..'

Possible dependencies:

thanks,

greg k-h

------------------ original commit in Linus's tree ------------------

From 77bfebf110773f5a0d6b5ff8110896adb2c9c335 Mon Sep 17 00:00:00 2001
From: Alice Ryhl <[email protected]>
Date: Fri, 5 Jun 2026 11:13:50 +0000
Subject: [PATCH] rust_binder: fix BINDER_GET_EXTENDED_ERROR

This code currently copies the ExtendedError struct to the stack, modifies the copy, and then doesn't modify the original. Thus, fix it.

Furthermore, errors when replying must be delivered directly to the remote thread, so update deliver_reply() to take an extended error argument.

drivers/android/binder/error.rs +5 -8
index 45d85d4c2815..1296072c35d9 100644
@@ -73,20 +73,17 @@ impl fmt::Debug for BinderError {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         match self.reply {
             BR_FAILED_REPLY => match self.source.as_ref() {
-                Some(source) => f
-                    .debug_struct("BR_FAILED_REPLY")
-                    .field("source", source)
-                    .finish(),
+                Some(source) => source.fmt(f),
                 None => f.pad("BR_FAILED_REPLY"),
             },
             BR_DEAD_REPLY => f.pad("BR_DEAD_REPLY"),
             BR_FROZEN_REPLY => f.pad("BR_FROZEN_REPLY"),
             BR_TRANSACTION_PENDING_FROZEN => f.pad("BR_TRANSACTION_PENDING_FROZEN"),
             BR_TRANSACTION_COMPLETE => f.pad("BR_TRANSACTION_COMPLETE"),
-            _ => f
-                .debug_struct("BinderError")
-                .field("reply", &self.reply)
-                .finish(),
+            _ => match self.source.as_ref() {
+                Some(source) => source.fmt(f),
+                None => self.reply.fmt(f),
+            },
         }
     }
 }
drivers/android/binder/thread.rs +46 -19

135 lines not on this page · raw message

drivers/android/binder/transaction.rs +7 -8
index 1d9b66920a21..0e5d07b7e6f0 100644
@@ -42,6 +42,7 @@ pub(crate) struct TransactionInfo {
     pub(crate) reply: u32,
     pub(crate) oneway_spam_suspect: bool,
     pub(crate) is_reply: bool,
+    pub(crate) debug_id: usize,
 }
 
 impl TransactionInfo {
@@ -93,7 +94,6 @@ pub(crate) fn new(
         from: &Arc<Thread>,
         info: &mut TransactionInfo,
     ) -> BinderResult<DLArc<Self>> {
-        let debug_id = super::next_debug_id();
         let allow_fds = node_ref.node.flags & FLAT_BINDER_FLAG_ACCEPTS_FDS != 0;
         let txn_security_ctx = node_ref.node.flags & FLAT_BINDER_FLAG_TXN_SECURITY_CTX != 0;
         let mut txn_security_ctx_off = if txn_security_ctx { Some(0) } else { None };
@@ -101,7 +101,7 @@ pub(crate) fn new(
         let mut alloc = match from.copy_transaction_data(
             to.clone(),
             info,
-            debug_id,
+            info.debug_id,
             allow_fds,
             txn_security_ctx_off.as_mut(),
         ) {
@@ -128,7 +128,7 @@ pub(crate) fn new(
         let data_address = alloc.ptr;
 
         Ok(DTRWrap::arc_pin_init(pin_init!(Transaction {
-            debug_id,
+            debug_id: info.debug_id,
             target_node: Some(target_node),
             from_parent,
             sender_euid: Kuid::current_euid(),
@@ -152,9 +152,8 @@ pub(crate) fn new_reply(
         info: &mut TransactionInfo,
         allow_fds: bool,
     ) -> BinderResult<DLArc<Self>> {
-        let debug_id = super::next_debug_id();
         let mut alloc =
-            match from.copy_transaction_data(to.clone(), info, debug_id, allow_fds, None) {
+            match from.copy_transaction_data(to.clone(), info, info.debug_id, allow_fds, None) {
                 Ok(alloc) => alloc,
                 Err(err) => {
                     pr_warn!("Failure in copy_transaction_data: {:?}", err);
@@ -165,7 +164,7 @@ pub(crate) fn new_reply(
             alloc.set_info_clear_on_drop();
         }
         Ok(DTRWrap::arc_pin_init(pin_init!(Transaction {
-            debug_id,
+            debug_id: info.debug_id,
             target_node: None,
             from_parent: None,
             sender_euid: Kuid::current_euid(),
@@ -394,7 +393,7 @@ fn do_work(
         let send_failed_reply = ScopeGuard::new(|| {
             if self.target_node.is_some() && self.flags & TF_ONE_WAY == 0 {
                 let reply = Err(BR_FAILED_REPLY);
-                self.from.deliver_reply(reply, &self);
+                self.from.deliver_reply(reply, &self, None);
             }
             self.drop_outstanding_txn();
         });
@@ -478,7 +477,7 @@ fn cancel(self: DArc<Self>) {
         // If this is not a reply or oneway transaction, then send a dead reply.
         if self.target_node.is_some() && self.flags & TF_ONE_WAY == 0 {
             let reply = Err(BR_DEAD_REPLY);
-            self.from.deliver_reply(reply, &self);
+            self.from.deliver_reply(reply, &self, None);
         }
 
         self.drop_outstanding_txn();
maintainer
#1 lore raw

PATCH 1/2 rust_binder: introduce TransactionInfo

Rust Binder exposes information about transactions that are sent in various ways: printing to the kernel log, tracepoints, files in binderfs, and the upcoming netlink support. Currently all these mechanisms use disparate ways of obtaining the same information, so let's introduce a single Info struct that collects all the required information in a single place, so that all of these different mechanisms can operate in a more uniform way.

For now, the new info struct is only used to replace a few things:
* The BinderTransactionDataSg struct that is passed as an argument to several methods is removed as the information is moved into the new info struct and passed down that way.
* The oneway spam detection fields on Transaction and Allocation can be removed, as the information can be returned to the caller via the mutable info struct instead.
But several other uses of the info struct are planned in follow-up patches.

(cherry picked from commit 5326a18e3e640061ca4b65c1b732feaeace61c39)
[aliceryhl: explicitly impl Zeroable for UserPtr instead of using derive]
---
 drivers/android/binder/allocation.rs  |   3 -
 drivers/android/binder/error.rs       |  10 +-
 drivers/android/binder/process.rs     |  15 +-
 drivers/android/binder/thread.rs      | 190 +++++++++++++++-----------
 drivers/android/binder/transaction.rs |  83 ++++++-----
 rust/kernel/uaccess.rs                |   3 +
 6 files changed, 170 insertions(+), 134 deletions(-)
drivers/android/binder/allocation.rs +0 -3
index d9113e9b98b2..4b08119576fb 100644
@@ -56,7 +56,6 @@ pub(crate) struct Allocation {
     pub(crate) process: Arc<Process>,
     allocation_info: Option<AllocationInfo>,
     free_on_drop: bool,
-    pub(crate) oneway_spam_detected: bool,
     #[allow(dead_code)]
     pub(crate) debug_id: usize,
 }
@@ -68,7 +67,6 @@ pub(crate) fn new(
         offset: usize,
         size: usize,
         ptr: usize,
-        oneway_spam_detected: bool,
     ) -> Self {
         Self {
             process,
@@ -76,7 +74,6 @@ pub(crate) fn new(
             size,
             ptr,
             debug_id,
-            oneway_spam_detected,
             allocation_info: None,
             free_on_drop: true,
         }
drivers/android/binder/error.rs +1 -9
index 9921827267d0..c6a834071f8c 100644
@@ -12,7 +12,7 @@
 /// errno.
 pub(crate) struct BinderError {
     pub(crate) reply: u32,
-    source: Option<Error>,
+    pub(crate) source: Option<Error>,
 }
 
 impl BinderError {
@@ -40,14 +40,6 @@ pub(crate) fn new_frozen_oneway() -> Self {
     pub(crate) fn is_dead(&self) -> bool {
         self.reply == BR_DEAD_REPLY
     }
-
-    pub(crate) fn as_errno(&self) -> kernel::ffi::c_int {
-        self.source.unwrap_or(EINVAL).to_errno()
-    }
-
-    pub(crate) fn should_pr_warn(&self) -> bool {
-        self.source.is_some()
-    }
 }
 
 /// Convert an errno into a `BinderError` and store the errno used to construct it. The errno
drivers/android/binder/process.rs +7 -8
index 5e95aee95347..01ca05d083cf 100644
@@ -47,6 +47,7 @@
     range_alloc::{RangeAllocator, ReserveNew, ReserveNewArgs},
     stats::BinderStats,
     thread::{PushWorkRes, Thread},
+    transaction::TransactionInfo,
     BinderfsProcFile, DArc, DLArc, DTRWrap, DeliverToRead,
 };
 
@@ -967,16 +968,15 @@ pub(crate) fn buffer_alloc(
         self: &Arc<Self>,
         debug_id: usize,
         size: usize,
-        is_oneway: bool,
-        from_pid: i32,
+        info: &mut TransactionInfo,
     ) -> BinderResult<NewAllocation> {
         use kernel::page::PAGE_SIZE;
 
         let mut reserve_new_args = ReserveNewArgs {
             debug_id,
             size,
-            is_oneway,
-            pid: from_pid,
+            is_oneway: info.is_oneway(),
+            pid: info.from_pid,
             ..ReserveNewArgs::default()
         };
 
@@ -992,13 +992,13 @@ pub(crate) fn buffer_alloc(
             reserve_new_args = alloc_request.make_alloc()?;
         };
 
+        info.oneway_spam_suspect = new_alloc.oneway_spam_detected;
         let res = Allocation::new(
             self.clone(),
             debug_id,
             new_alloc.offset,
             size,
             addr + new_alloc.offset,
-            new_alloc.oneway_spam_detected,
         );
 
         // This allocation will be marked as in use until the `Allocation` is used to free it.
@@ -1030,7 +1030,7 @@ pub(crate) fn buffer_get(self: &Arc<Self>, ptr: usize) -> Option<Allocation> {
         let mapping = inner.mapping.as_mut()?;
         let offset = ptr.checked_sub(mapping.address)?;
         let (size, debug_id, odata) = mapping.alloc.reserve_existing(offset).ok()?;
-        let mut alloc = Allocation::new(self.clone(), debug_id, offset, size, ptr, false);
+        let mut alloc = Allocation::new(self.clone(), debug_id, offset, size, ptr);
         if let Some(data) = odata {
             alloc.set_info(data);
         }
@@ -1383,8 +1383,7 @@ fn deferred_release(self: Arc<Self>) {
                 .alloc
                 .take_for_each(|offset, size, debug_id, odata| {
                     let ptr = offset + address;
-                    let mut alloc =
-                        Allocation::new(self.clone(), debug_id, offset, size, ptr, false);
+                    let mut alloc = Allocation::new(self.clone(), debug_id, offset, size, ptr);
                     if let Some(data) = odata {
                         alloc.set_info(data);
                     }
drivers/android/binder/thread.rs +107 -83

290 lines not on this page · raw message

drivers/android/binder/transaction.rs +52 -31

168 lines not on this page · raw message

rust/kernel/uaccess.rs +3 -0
index a8fb4764185a..2035c2877a2b 100644
@@ -21,6 +21,9 @@
 #[derive(Copy, Clone)]
 pub struct UserPtr(*mut c_void);
 
+// SAFETY: Null pointer is a valid value.
+unsafe impl Zeroable for UserPtr {}
+
 impl UserPtr {
     /// Create a `UserPtr` from an integer representing the userspace address.
     #[inline]
Signature · 1 line
2.55.0.795.g602f6c329a-goog
maintainer
#2 lore raw

PATCH 2/2 rust_binder: fix BINDER_GET_EXTENDED_ERROR

This code currently copies the ExtendedError struct to the stack, modifies the copy, and then doesn't modify the original. Thus, fix it.

Furthermore, errors when replying must be delivered directly to the remote thread, so update deliver_reply() to take an extended error argument.

Cc stable <[email protected]>
Fixes eafedbc7c050 ("rust_binder: add Rust Binder driver")
(cherry picked from commit 77bfebf110773f5a0d6b5ff8110896adb2c9c335)
---
 drivers/android/binder/error.rs       | 13 +++---
 drivers/android/binder/thread.rs      | 65 +++++++++++++++++++--------
 drivers/android/binder/transaction.rs | 15 +++----
 3 files changed, 58 insertions(+), 35 deletions(-)
drivers/android/binder/error.rs +5 -8
index c6a834071f8c..fd9e9d9e5658 100644
@@ -72,20 +72,17 @@ impl core::fmt::Debug for BinderError {
     fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
         match self.reply {
             BR_FAILED_REPLY => match self.source.as_ref() {
-                Some(source) => f
-                    .debug_struct("BR_FAILED_REPLY")
-                    .field("source", source)
-                    .finish(),
+                Some(source) => source.fmt(f),
                 None => f.pad("BR_FAILED_REPLY"),
             },
             BR_DEAD_REPLY => f.pad("BR_DEAD_REPLY"),
             BR_FROZEN_REPLY => f.pad("BR_FROZEN_REPLY"),
             BR_TRANSACTION_PENDING_FROZEN => f.pad("BR_TRANSACTION_PENDING_FROZEN"),
             BR_TRANSACTION_COMPLETE => f.pad("BR_TRANSACTION_COMPLETE"),
-            _ => f
-                .debug_struct("BinderError")
-                .field("reply", &self.reply)
-                .finish(),
+            _ => match self.source.as_ref() {
+                Some(source) => source.fmt(f),
+                None => self.reply.fmt(f),
+            },
         }
     }
 }
drivers/android/binder/thread.rs +46 -19

135 lines not on this page · raw message

drivers/android/binder/transaction.rs +7 -8
index 733f452d8f49..b5434a2ae819 100644
@@ -42,6 +42,7 @@ pub(crate) struct TransactionInfo {
     pub(crate) reply: u32,
     pub(crate) oneway_spam_suspect: bool,
     pub(crate) is_reply: bool,
+    pub(crate) debug_id: usize,
 }
 
 impl TransactionInfo {
@@ -82,7 +83,6 @@ pub(crate) fn new(
         from: &Arc<Thread>,
         info: &mut TransactionInfo,
     ) -> BinderResult<DLArc<Self>> {
-        let debug_id = super::next_debug_id();
         let allow_fds = node_ref.node.flags & FLAT_BINDER_FLAG_ACCEPTS_FDS != 0;
         let txn_security_ctx = node_ref.node.flags & FLAT_BINDER_FLAG_TXN_SECURITY_CTX != 0;
         let mut txn_security_ctx_off = if txn_security_ctx { Some(0) } else { None };
@@ -90,7 +90,7 @@ pub(crate) fn new(
         let mut alloc = match from.copy_transaction_data(
             to.clone(),
             info,
-            debug_id,
+            info.debug_id,
             allow_fds,
             txn_security_ctx_off.as_mut(),
         ) {
@@ -117,7 +117,7 @@ pub(crate) fn new(
         let data_address = alloc.ptr;
 
         Ok(DTRWrap::arc_pin_init(pin_init!(Transaction {
-            debug_id,
+            debug_id: info.debug_id,
             target_node: Some(target_node),
             from_parent,
             sender_euid: from.process.task.euid(),
@@ -141,9 +141,8 @@ pub(crate) fn new_reply(
         info: &mut TransactionInfo,
         allow_fds: bool,
     ) -> BinderResult<DLArc<Self>> {
-        let debug_id = super::next_debug_id();
         let mut alloc =
-            match from.copy_transaction_data(to.clone(), info, debug_id, allow_fds, None) {
+            match from.copy_transaction_data(to.clone(), info, info.debug_id, allow_fds, None) {
                 Ok(alloc) => alloc,
                 Err(err) => {
                     pr_warn!("Failure in copy_transaction_data: {:?}", err);
@@ -154,7 +153,7 @@ pub(crate) fn new_reply(
             alloc.set_info_clear_on_drop();
         }
         Ok(DTRWrap::arc_pin_init(pin_init!(Transaction {
-            debug_id,
+            debug_id: info.debug_id,
             target_node: None,
             from_parent: None,
             sender_euid: from.process.task.euid(),
@@ -380,7 +379,7 @@ fn do_work(
         let send_failed_reply = ScopeGuard::new(|| {
             if self.target_node.is_some() && self.flags & TF_ONE_WAY == 0 {
                 let reply = Err(BR_FAILED_REPLY);
-                self.from.deliver_reply(reply, &self);
+                self.from.deliver_reply(reply, &self, None);
             }
             self.drop_outstanding_txn();
         });
@@ -462,7 +461,7 @@ fn cancel(self: DArc<Self>) {
         // If this is not a reply or oneway transaction, then send a dead reply.
         if self.target_node.is_some() && self.flags & TF_ONE_WAY == 0 {
             let reply = Err(BR_DEAD_REPLY);
-            self.from.deliver_reply(reply, &self);
+            self.from.deliver_reply(reply, &self, None);
         }
 
         self.drop_outstanding_txn();
Signature · 1 line
2.55.0.795.g602f6c329a-goog
maintainer Applied
#3 lore raw

Re: [PATCH 6.18.y 1/2] rust_binder: introduce TransactionInfo

In reply to Alice Ryhl
Quoted 3 lines

Rust Binder exposes information about transactions that are sent in various ways: printing to the kernel log, tracepoints, files in binderfs, and the upcoming netlink support.

Queued the series for 6.18, thanks.

Signature · 2 lines
Thanks,
Sasha