]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
7.1-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 13 Jul 2026 13:15:12 +0000 (15:15 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 13 Jul 2026 13:15:12 +0000 (15:15 +0200)
added patches:
rust_binder-clear-freeze-listener-on-node-removal.patch
rust_binder-fix-binder_get_extended_error.patch
rust_binder-reject-context-manager-self-transaction.patch
rust_binder-synchronize-rust-binder-stats-with-freeze-commands.patch
rust_binder-use-a-u64-stride-when-cleaning-up-the-offsets-array.patch
usb-typec-tcpci_rt1711h-unregister-tcpci-port-with-devres.patch
usb-xhci-fix-sleep-in-atomic-context-in-xhci_free_streams.patch
xhci-sideband-fix-ring-sg-table-pages-leak.patch

queue-7.1/rust_binder-clear-freeze-listener-on-node-removal.patch [new file with mode: 0644]
queue-7.1/rust_binder-fix-binder_get_extended_error.patch [new file with mode: 0644]
queue-7.1/rust_binder-reject-context-manager-self-transaction.patch [new file with mode: 0644]
queue-7.1/rust_binder-synchronize-rust-binder-stats-with-freeze-commands.patch [new file with mode: 0644]
queue-7.1/rust_binder-use-a-u64-stride-when-cleaning-up-the-offsets-array.patch [new file with mode: 0644]
queue-7.1/series
queue-7.1/usb-typec-tcpci_rt1711h-unregister-tcpci-port-with-devres.patch [new file with mode: 0644]
queue-7.1/usb-xhci-fix-sleep-in-atomic-context-in-xhci_free_streams.patch [new file with mode: 0644]
queue-7.1/xhci-sideband-fix-ring-sg-table-pages-leak.patch [new file with mode: 0644]

diff --git a/queue-7.1/rust_binder-clear-freeze-listener-on-node-removal.patch b/queue-7.1/rust_binder-clear-freeze-listener-on-node-removal.patch
new file mode 100644 (file)
index 0000000..c5a71fd
--- /dev/null
@@ -0,0 +1,115 @@
+From bc4a9828897871ff3e5a1f8a1d346decbf4ee95e Mon Sep 17 00:00:00 2001
+From: Alice Ryhl <aliceryhl@google.com>
+Date: Fri, 3 Jul 2026 11:25:12 +0000
+Subject: rust_binder: clear freeze listener on node removal
+
+From: Alice Ryhl <aliceryhl@google.com>
+
+commit bc4a9828897871ff3e5a1f8a1d346decbf4ee95e upstream.
+
+Generally userspace is supposed to explicitly clear freeze listeners
+before they drop the refcount on the node ref to zero, but there's
+nothing forcing that. Currently, in this scenario the freeze listener
+remains in the freeze_listeners rbtree and in the remote node's freeze
+listener list, even though the ref for which the listener is registered
+is gone. This could potentially lead to a memory leak due to a refcount
+cycle. Thus, remove the freeze listener in this scenario.
+
+Cc: stable <stable@kernel.org>
+Fixes: eafedbc7c050 ("rust_binder: add Rust Binder driver")
+Signed-off-by: Alice Ryhl <aliceryhl@google.com>
+Link: https://patch.msgid.link/20260703-remove-freeze-on-remove-node-v3-1-6e0c4547af46@google.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/android/binder/freeze.rs  |   11 +++++++++--
+ drivers/android/binder/node.rs    |   10 ++++++----
+ drivers/android/binder/process.rs |   12 +++++++++++-
+ 3 files changed, 26 insertions(+), 7 deletions(-)
+
+--- a/drivers/android/binder/freeze.rs
++++ b/drivers/android/binder/freeze.rs
+@@ -154,10 +154,17 @@ impl DeliverToRead for FreezeMessage {
+ }
+ impl FreezeListener {
+-    pub(crate) fn on_process_exit(&self, proc: &Arc<Process>) {
++    /// Called when this freeze listener is cleared abnormally.
++    ///
++    /// This occurs either because the process exited or because the process dropped its last
++    /// refcount on the node ref without explicitly removing the freeze listener first.
++    ///
++    /// The returned `KVVec` is just a value that should be dropped outside of the lock.
++    pub(crate) fn on_process_cleanup(&self, proc: &Process) -> KVVec<Arc<Process>> {
+         if !self.is_clearing {
+-            self.node.remove_freeze_listener(proc);
++            return self.node.remove_freeze_listener(proc);
+         }
++        KVVec::new()
+     }
+ }
+--- a/drivers/android/binder/node.rs
++++ b/drivers/android/binder/node.rs
+@@ -682,12 +682,13 @@ impl Node {
+         }
+     }
+-    pub(crate) fn remove_freeze_listener(&self, p: &Arc<Process>) {
+-        let _unused_capacity;
++    pub(crate) fn remove_freeze_listener(&self, p: &Process) -> KVVec<Arc<Process>> {
+         let mut guard = self.owner.inner.lock();
+         let inner = self.inner.access_mut(&mut guard);
+         let len = inner.freeze_list.len();
+-        inner.freeze_list.retain(|proc| !Arc::ptr_eq(proc, p));
++        inner
++            .freeze_list
++            .retain(|proc| !core::ptr::eq::<Process>(&**proc, p));
+         if len == inner.freeze_list.len() {
+             pr_warn!(
+                 "Could not remove freeze listener for {}\n",
+@@ -695,8 +696,9 @@ impl Node {
+             );
+         }
+         if inner.freeze_list.is_empty() {
+-            _unused_capacity = mem::take(&mut inner.freeze_list);
++            return mem::take(&mut inner.freeze_list);
+         }
++        KVVec::new()
+     }
+     pub(crate) fn freeze_list<'a>(&'a self, guard: &'a ProcessInner) -> &'a [Arc<Process>] {
+--- a/drivers/android/binder/process.rs
++++ b/drivers/android/binder/process.rs
+@@ -946,6 +946,8 @@ impl Process {
+         // To preserve original binder behaviour, we only fail requests where the manager tries to
+         // increment references on itself.
++        let _to_free_freeze_listener;
++        let _to_free_freeze_listener_cleanup;
+         let mut refs = self.node_refs.lock();
+         if let Some(info) = refs.by_handle.get_mut(&handle) {
+             if info.node_ref().update(inc, strong) {
+@@ -961,6 +963,14 @@ impl Process {
+                 unsafe { info.node_ref2().node.remove_node_info(info) };
+                 let id = info.node_ref().node.global_id();
++
++                if let Some(freeze) = *info.freeze() {
++                    if let Some(fl) = refs.freeze_listeners.remove(&freeze) {
++                        _to_free_freeze_listener_cleanup = fl.on_process_cleanup(&self);
++                        _to_free_freeze_listener = fl;
++                    }
++                }
++
+                 refs.by_handle.remove(&handle);
+                 refs.by_node.remove(&id);
+                 refs.handle_is_present.release_id(handle as usize);
+@@ -1384,7 +1394,7 @@ impl Process {
+         // Clean up freeze listeners.
+         let freeze_listeners = take(&mut self.node_refs.lock().freeze_listeners);
+         for listener in freeze_listeners.values() {
+-            listener.on_process_exit(&self);
++            listener.on_process_cleanup(&self);
+         }
+         drop(freeze_listeners);
diff --git a/queue-7.1/rust_binder-fix-binder_get_extended_error.patch b/queue-7.1/rust_binder-fix-binder_get_extended_error.patch
new file mode 100644 (file)
index 0000000..585475a
--- /dev/null
@@ -0,0 +1,277 @@
+From 77bfebf110773f5a0d6b5ff8110896adb2c9c335 Mon Sep 17 00:00:00 2001
+From: Alice Ryhl <aliceryhl@google.com>
+Date: Fri, 5 Jun 2026 11:13:50 +0000
+Subject: rust_binder: fix BINDER_GET_EXTENDED_ERROR
+
+From: Alice Ryhl <aliceryhl@google.com>
+
+commit 77bfebf110773f5a0d6b5ff8110896adb2c9c335 upstream.
+
+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 <stable@kernel.org>
+Fixes: eafedbc7c050 ("rust_binder: add Rust Binder driver")
+Signed-off-by: Alice Ryhl <aliceryhl@google.com>
+Acked-by: Carlos Llamas <cmllamas@google.com>
+Link: https://patch.msgid.link/20260605-set-extended-error-v3-1-d60b69a75f97@google.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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(-)
+
+--- a/drivers/android/binder/error.rs
++++ b/drivers/android/binder/error.rs
+@@ -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),
++            },
+         }
+     }
+ }
+--- a/drivers/android/binder/thread.rs
++++ b/drivers/android/binder/thread.rs
+@@ -495,9 +495,16 @@ impl Thread {
+         Ok(())
+     }
++    pub(crate) fn clear_extended_error(&self, debug_id: usize) {
++        self.inner.lock().extended_error = ExtendedError::new(debug_id as u32, BR_OK, 0);
++    }
++
+     pub(crate) fn get_extended_error(&self, data: UserSlice) -> Result {
+         let mut writer = data.writer();
+-        let ee = self.inner.lock().extended_error;
++        let mut inner = self.inner.lock();
++        let ee = inner.extended_error;
++        inner.extended_error = ExtendedError::new(0, BR_OK, 0);
++        drop(inner);
+         writer.write(&ee)?;
+         Ok(())
+     }
+@@ -1109,7 +1116,10 @@ impl Thread {
+             inner.pop_transaction_to_reply(thread.as_ref())
+         } {
+             let reply = Err(BR_DEAD_REPLY);
+-            if !transaction.from.deliver_single_reply(reply, &transaction) {
++            if !transaction
++                .from
++                .deliver_single_reply(reply, &transaction, None)
++            {
+                 break;
+             }
+@@ -1121,8 +1131,9 @@ impl Thread {
+         &self,
+         reply: Result<DLArc<Transaction>, u32>,
+         transaction: &DArc<Transaction>,
++        extended_error: Option<ExtendedError>,
+     ) {
+-        if self.deliver_single_reply(reply, transaction) {
++        if self.deliver_single_reply(reply, transaction, extended_error) {
+             transaction.from.unwind_transaction_stack();
+         }
+     }
+@@ -1136,6 +1147,7 @@ impl Thread {
+         &self,
+         reply: Result<DLArc<Transaction>, u32>,
+         transaction: &DArc<Transaction>,
++        extended_error: Option<ExtendedError>,
+     ) -> bool {
+         if let Ok(transaction) = &reply {
+             crate::trace::trace_transaction(true, transaction, Some(&self.task));
+@@ -1152,6 +1164,12 @@ impl Thread {
+                 return true;
+             }
++            if let Some(ee) = extended_error {
++                if inner.extended_error.command == BR_OK {
++                    inner.extended_error = ee;
++                }
++            }
++
+             match reply {
+                 Ok(work) => {
+                     inner.push_work(work);
+@@ -1222,6 +1240,9 @@ impl Thread {
+         info.buffers_size = td.buffers_size as usize;
+         // SAFETY: Above `read` call initializes all bytes, so this union read is ok.
+         info.target_handle = unsafe { td.transaction_data.target.handle };
++
++        info.debug_id = super::next_debug_id();
++
+         Ok(())
+     }
+@@ -1230,6 +1251,8 @@ impl Thread {
+         let mut info = TransactionInfo::zeroed();
+         self.read_transaction_info(cmd, reader, &mut info)?;
++        self.clear_extended_error(info.debug_id);
++
+         let ret = if info.is_reply {
+             self.reply_inner(&mut info)
+         } else if info.is_oneway() {
+@@ -1239,23 +1262,21 @@ impl Thread {
+         };
+         if let Err(err) = ret {
+-            if err.reply != BR_TRANSACTION_COMPLETE {
+-                info.reply = err.reply;
+-            }
+-
+             self.push_return_work(err.reply);
+-            if let Some(source) = &err.source {
+-                info.errno = source.to_errno();
++            if err.reply != BR_TRANSACTION_COMPLETE {
+                 info.reply = err.reply;
++                if let Some(source) = &err.source {
++                    info.errno = source.to_errno();
+-                {
+-                    let mut ee = self.inner.lock().extended_error;
+-                    ee.command = err.reply;
+-                    ee.param = source.to_errno();
++                    {
++                        let mut inner = self.inner.lock();
++                        inner.extended_error =
++                            ExtendedError::new(info.debug_id as u32, err.reply, source.to_errno());
++                    }
+                 }
+                 pr_warn!(
+-                    "{}:{} transaction to {} failed: {source:?}",
++                    "{}:{} transaction to {} failed: {err:?}",
+                     info.from_pid,
+                     info.from_tid,
+                     info.to_pid
+@@ -1320,18 +1341,24 @@ impl Thread {
+             let allow_fds = orig.flags & TF_ACCEPT_FDS != 0;
+             let reply = Transaction::new_reply(self, process, info, allow_fds)?;
+             self.inner.lock().push_work(completion);
+-            orig.from.deliver_reply(Ok(reply), &orig);
++            orig.from.deliver_reply(Ok(reply), &orig, None);
+             Ok(())
+         })()
+         .map_err(|mut err| {
+             // At this point we only return `BR_TRANSACTION_COMPLETE` to the caller, and we must let
+             // the sender know that the transaction has completed (with an error in this case).
++
+             pr_warn!(
+-                "Failure {:?} during reply - delivering BR_FAILED_REPLY to sender.",
+-                err
++                "{}:{} reply to {} failed: {err:?}",
++                info.from_pid,
++                info.from_tid,
++                info.to_pid
+             );
+-            let reply = Err(BR_FAILED_REPLY);
+-            orig.from.deliver_reply(reply, &orig);
++
++            let param = err.source.as_ref().map_or(0, |e| e.to_errno());
++            let ee = ExtendedError::new(info.debug_id as u32, err.reply, param);
++            orig.from
++                .deliver_reply(Err(BR_FAILED_REPLY), &orig, Some(ee));
+             err.reply = BR_TRANSACTION_COMPLETE;
+             err
+         });
+--- a/drivers/android/binder/transaction.rs
++++ b/drivers/android/binder/transaction.rs
+@@ -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 @@ impl Transaction {
+         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 @@ impl Transaction {
+         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 @@ impl Transaction {
+         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 @@ impl Transaction {
+         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 @@ impl Transaction {
+             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 @@ impl DeliverToRead for Transaction {
+         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 @@ impl DeliverToRead for Transaction {
+         // 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();
diff --git a/queue-7.1/rust_binder-reject-context-manager-self-transaction.patch b/queue-7.1/rust_binder-reject-context-manager-self-transaction.patch
new file mode 100644 (file)
index 0000000..1b8c622
--- /dev/null
@@ -0,0 +1,46 @@
+From 6849cabfd30fb5727cfd31e8241e15801e17ebf9 Mon Sep 17 00:00:00 2001
+From: Keshav Verma <iganschel@gmail.com>
+Date: Thu, 25 Jun 2026 16:09:57 +0530
+Subject: rust_binder: reject context manager self-transaction
+
+From: Keshav Verma <iganschel@gmail.com>
+
+commit 6849cabfd30fb5727cfd31e8241e15801e17ebf9 upstream.
+
+Rust binder resolved handle 0 to the context manager node, but it does not
+reject the case where the caller owns the same node.
+
+The C binder driver rejects transactions from the context-manager process
+to handle 0 after resolving the target node. Match that behavior in Rust
+Binder by rejecting handle 0 transactions when the resolved context-manager
+node is owned by the calling process.
+
+This applies to both synchronous and oneway transactions because both paths
+resolve the target through Process::get_transaction_node().
+
+Cc: stable <stable@kernel.org>
+Fixes: eafedbc7c050 ("rust_binder: add Rust Binder driver")
+Signed-off-by: Keshav Verma <iganschel@gmail.com>
+Reviewed-by: Alice Ryhl <aliceryhl@google.com>
+Link: https://patch.msgid.link/20260625103957.730-1-iganschel@gmail.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/android/binder/process.rs |    6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+--- a/drivers/android/binder/process.rs
++++ b/drivers/android/binder/process.rs
+@@ -900,7 +900,11 @@ impl Process {
+     pub(crate) fn get_transaction_node(&self, handle: u32) -> BinderResult<NodeRef> {
+         // When handle is zero, try to get the context manager.
+         if handle == 0 {
+-            Ok(self.ctx.get_manager_node(true)?)
++            let node_ref = self.ctx.get_manager_node(true)?;
++            if core::ptr::eq(self, &*node_ref.node.owner) {
++                return Err(EINVAL.into());
++            }
++            Ok(node_ref)
+         } else {
+             Ok(self.get_node_from_handle(handle, true)?)
+         }
diff --git a/queue-7.1/rust_binder-synchronize-rust-binder-stats-with-freeze-commands.patch b/queue-7.1/rust_binder-synchronize-rust-binder-stats-with-freeze-commands.patch
new file mode 100644 (file)
index 0000000..fa4f0d1
--- /dev/null
@@ -0,0 +1,70 @@
+From eb1645bf10190e71f6f0316e37ff70755d719b53 Mon Sep 17 00:00:00 2001
+From: Keshav Verma <iganschel@gmail.com>
+Date: Tue, 16 Jun 2026 02:47:43 +0530
+Subject: rust_binder: synchronize Rust Binder stats with freeze commands
+
+From: Keshav Verma <iganschel@gmail.com>
+
+commit eb1645bf10190e71f6f0316e37ff70755d719b53 upstream.
+
+Rust Binder stats use BC_COUNT and BR_COUNT to size the command and
+return counters, and use event string tables when printing debug
+statistics.
+
+The Binder protocol includes freeze-related commands and return codes,
+but the Rust Binder statistics code was not updated to cover them. As a
+result, those commands and return codes are not accounted for or printed
+by the stats debug output.
+
+Update the counts and event string tables so these commands and return
+codes are included in the debug statistics output.
+
+Fixes: eafedbc7c050 ("rust_binder: add Rust Binder driver")
+Cc: stable <stable@kernel.org>
+Acked-by: Carlos Llamas <cmllamas@google.com>
+Reviewed-by: Alice Ryhl <aliceryhl@google.com>
+Signed-off-by: Keshav Verma <iganschel@gmail.com>
+Link: https://patch.msgid.link/20260615211743.734-1-iganschel@gmail.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/android/binder/rust_binder_events.c |    7 ++++++-
+ drivers/android/binder/stats.rs             |    4 ++--
+ 2 files changed, 8 insertions(+), 3 deletions(-)
+
+--- a/drivers/android/binder/rust_binder_events.c
++++ b/drivers/android/binder/rust_binder_events.c
+@@ -28,6 +28,9 @@ const char * const binder_command_string
+       "BC_DEAD_BINDER_DONE",
+       "BC_TRANSACTION_SG",
+       "BC_REPLY_SG",
++      "BC_REQUEST_FREEZE_NOTIFICATION",
++      "BC_CLEAR_FREEZE_NOTIFICATION",
++      "BC_FREEZE_NOTIFICATION_DONE",
+ };
+ const char * const binder_return_strings[] = {
+@@ -51,7 +54,9 @@ const char * const binder_return_strings
+       "BR_FAILED_REPLY",
+       "BR_FROZEN_REPLY",
+       "BR_ONEWAY_SPAM_SUSPECT",
+-      "BR_TRANSACTION_PENDING_FROZEN"
++      "BR_TRANSACTION_PENDING_FROZEN",
++      "BR_FROZEN_BINDER",
++      "BR_CLEAR_FREEZE_NOTIFICATION_DONE",
+ };
+ #define CREATE_TRACE_POINTS
+--- a/drivers/android/binder/stats.rs
++++ b/drivers/android/binder/stats.rs
+@@ -8,8 +8,8 @@ use crate::defs::*;
+ use kernel::sync::atomic::{ordering::Relaxed, Atomic};
+ use kernel::{ioctl::_IOC_NR, seq_file::SeqFile, seq_print};
+-const BC_COUNT: usize = _IOC_NR(BC_REPLY_SG) as usize + 1;
+-const BR_COUNT: usize = _IOC_NR(BR_TRANSACTION_PENDING_FROZEN) as usize + 1;
++const BC_COUNT: usize = _IOC_NR(BC_FREEZE_NOTIFICATION_DONE) as usize + 1;
++const BR_COUNT: usize = _IOC_NR(BR_CLEAR_FREEZE_NOTIFICATION_DONE) as usize + 1;
+ pub(crate) static GLOBAL_STATS: BinderStats = BinderStats::new();
diff --git a/queue-7.1/rust_binder-use-a-u64-stride-when-cleaning-up-the-offsets-array.patch b/queue-7.1/rust_binder-use-a-u64-stride-when-cleaning-up-the-offsets-array.patch
new file mode 100644 (file)
index 0000000..5070119
--- /dev/null
@@ -0,0 +1,62 @@
+From 803c8a9502e9b97cd6ae937618ef4a8fd6274343 Mon Sep 17 00:00:00 2001
+From: Hyunwoo Kim <imv4bel@gmail.com>
+Date: Sun, 31 May 2026 22:29:24 +0900
+Subject: rust_binder: use a u64 stride when cleaning up the offsets array
+
+From: Hyunwoo Kim <imv4bel@gmail.com>
+
+commit 803c8a9502e9b97cd6ae937618ef4a8fd6274343 upstream.
+
+Allocation's Drop walks the offsets array (binder_size_t = u64 entries),
+cleaning up the objects, but it used usize instead of u64 for both the
+stride and the per-entry read.
+
+On 64-bit kernels (usize == u64) this is harmless, but on 32-bit kernels
+it walks the 8-byte entries in 4-byte steps, iterating an N-entry array
+2N times, and reads the always-zero high word as offset 0, cleaning up
+the object at offset 0 N extra times. As a result the referenced node or
+handle ends up with a lower reference count than it actually has (a
+refcount over-decrement), and binder's reference accounting is corrupted;
+for example, the owner can be notified of a strong reference release
+(BR_RELEASE) even though references still remain.
+
+Change the stride to u64, and read each entry as a u64, narrowing it to
+usize with try_into().
+
+On 32-bit ARM, when this over-decrement would drive a count below zero,
+the driver's existing refcount guard refuses it and fires:
+
+  rust_binder: Failure: refcount underflow!
+
+Cc: stable <stable@kernel.org>
+Fixes: eafedbc7c050 ("rust_binder: add Rust Binder driver")
+Signed-off-by: Hyunwoo Kim <imv4bel@gmail.com>
+Acked-by: Carlos Llamas <cmllamas@google.com>
+Reviewed-by: Alice Ryhl <aliceryhl@google.com>
+Link: https://patch.msgid.link/ahw3tFhLz9bMMJAO@v4bel
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/android/binder/allocation.rs |    5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+--- a/drivers/android/binder/allocation.rs
++++ b/drivers/android/binder/allocation.rs
+@@ -259,7 +259,7 @@ impl Drop for Allocation {
+             if let Some(offsets) = info.offsets.clone() {
+                 let view = AllocationView::new(self, offsets.start);
+-                for i in offsets.step_by(size_of::<usize>()) {
++                for i in offsets.step_by(size_of::<u64>()) {
+                     if view.cleanup_object(i).is_err() {
+                         pr_warn!("Error cleaning up object at offset {}\n", i)
+                     }
+@@ -420,7 +420,8 @@ impl<'a> AllocationView<'a> {
+     }
+     fn cleanup_object(&self, index_offset: usize) -> Result {
+-        let offset = self.alloc.read(index_offset)?;
++        let offset = self.alloc.read::<u64>(index_offset)?;
++        let offset: usize = offset.try_into().map_err(|_| EINVAL)?;
+         let header = self.read::<BinderObjectHeader>(offset)?;
+         match header.type_ {
+             BINDER_TYPE_WEAK_BINDER | BINDER_TYPE_BINDER => {
index 2ec43d2bcfe943ab0af5f7dcffac57bf3fb37dfd..de58a9f5a3d0a5c0a778a2e1ee44072736c72c54 100644 (file)
@@ -116,3 +116,11 @@ bluetooth-btusb-fix-use-after-free-on-marvell-probe-failure.patch
 bluetooth-btusb-fix-wakeup-source-leak-on-probe-failure.patch
 binder-fix-uaf-in-binder_thread_release.patch
 binder-fix-uaf-in-binder_free_transaction.patch
+rust_binder-use-a-u64-stride-when-cleaning-up-the-offsets-array.patch
+rust_binder-fix-binder_get_extended_error.patch
+rust_binder-reject-context-manager-self-transaction.patch
+rust_binder-synchronize-rust-binder-stats-with-freeze-commands.patch
+rust_binder-clear-freeze-listener-on-node-removal.patch
+usb-xhci-fix-sleep-in-atomic-context-in-xhci_free_streams.patch
+xhci-sideband-fix-ring-sg-table-pages-leak.patch
+usb-typec-tcpci_rt1711h-unregister-tcpci-port-with-devres.patch
diff --git a/queue-7.1/usb-typec-tcpci_rt1711h-unregister-tcpci-port-with-devres.patch b/queue-7.1/usb-typec-tcpci_rt1711h-unregister-tcpci-port-with-devres.patch
new file mode 100644 (file)
index 0000000..dceb783
--- /dev/null
@@ -0,0 +1,77 @@
+From e8da46d99d3710106e7c44db14566bf9b57386b5 Mon Sep 17 00:00:00 2001
+From: Myeonghun Pak <mhun512@gmail.com>
+Date: Mon, 6 Jul 2026 23:53:12 +0900
+Subject: usb: typec: tcpci_rt1711h: unregister TCPCI port with devres
+
+From: Myeonghun Pak <mhun512@gmail.com>
+
+commit e8da46d99d3710106e7c44db14566bf9b57386b5 upstream.
+
+rt1711h_probe() registers the TCPCI port before requesting the interrupt
+and enabling alert interrupts. If either of those later steps fails, the
+probe function returns without unregistering the TCPCI port. The explicit
+unregister currently only happens from the remove callback.
+
+Register a devres action immediately after tcpci_register_port() succeeds,
+so tcpci_unregister_port() runs on later probe failures and on driver
+detach. Drop the remove callback to avoid unregistering the same port
+twice.
+
+This issue was identified during our ongoing static-analysis research while
+reviewing kernel code.
+
+Fixes: 302c570bf36e ("usb: typec: tcpci_rt1711h: avoid screaming irq causing boot hangs")
+Cc: stable <stable@kernel.org>
+Co-developed-by: Ijae Kim <ae878000@gmail.com>
+Signed-off-by: Ijae Kim <ae878000@gmail.com>
+Signed-off-by: Myeonghun Pak <mhun512@gmail.com>
+Link: https://patch.msgid.link/20260706145312.37260-1-mhun512@gmail.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/typec/tcpm/tcpci_rt1711h.c |   13 ++++++++-----
+ 1 file changed, 8 insertions(+), 5 deletions(-)
+
+--- a/drivers/usb/typec/tcpm/tcpci_rt1711h.c
++++ b/drivers/usb/typec/tcpm/tcpci_rt1711h.c
+@@ -295,6 +295,8 @@ static int rt1711h_sw_reset(struct rt171
+       return 0;
+ }
++static void rt1711h_unregister_tcpci_port(void *tcpci);
++
+ static int rt1711h_probe(struct i2c_client *client)
+ {
+       int ret;
+@@ -340,6 +342,10 @@ static int rt1711h_probe(struct i2c_clie
+       if (IS_ERR_OR_NULL(chip->tcpci))
+               return PTR_ERR(chip->tcpci);
++      ret = devm_add_action_or_reset(chip->dev, rt1711h_unregister_tcpci_port, chip->tcpci);
++      if (ret)
++              return ret;
++
+       ret = devm_request_threaded_irq(chip->dev, client->irq, NULL,
+                                       rt1711h_irq,
+                                       IRQF_ONESHOT | IRQF_TRIGGER_LOW,
+@@ -357,11 +363,9 @@ static int rt1711h_probe(struct i2c_clie
+       return 0;
+ }
+-static void rt1711h_remove(struct i2c_client *client)
++static void rt1711h_unregister_tcpci_port(void *tcpci)
+ {
+-      struct rt1711h_chip *chip = i2c_get_clientdata(client);
+-
+-      tcpci_unregister_port(chip->tcpci);
++      tcpci_unregister_port(tcpci);
+ }
+ static const struct rt1711h_chip_info rt1711h = {
+@@ -394,7 +398,6 @@ static struct i2c_driver rt1711h_i2c_dri
+               .of_match_table = rt1711h_of_match,
+       },
+       .probe = rt1711h_probe,
+-      .remove = rt1711h_remove,
+       .id_table = rt1711h_id,
+ };
+ module_i2c_driver(rt1711h_i2c_driver);
diff --git a/queue-7.1/usb-xhci-fix-sleep-in-atomic-context-in-xhci_free_streams.patch b/queue-7.1/usb-xhci-fix-sleep-in-atomic-context-in-xhci_free_streams.patch
new file mode 100644 (file)
index 0000000..1571b22
--- /dev/null
@@ -0,0 +1,86 @@
+From 42c37c4b75d38b51d84f31a8e29427f5e06a7c2a Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?=E8=83=A1=E8=BF=9E=E5=8B=A4?= <hulianqin@vivo.com>
+Date: Fri, 3 Jul 2026 17:40:33 +0300
+Subject: usb: xhci: Fix sleep in atomic context in xhci_free_streams()
+
+From: 胡连勤 <hulianqin@vivo.com>
+
+commit 42c37c4b75d38b51d84f31a8e29427f5e06a7c2a upstream.
+
+When a USB device with active stream endpoints is disconnected,
+xhci_free_streams() is called from the hub_event workqueue to
+free the stream resources.  It calls xhci_free_stream_info()
+while holding xhci->lock with irqs disabled.
+
+xhci_free_stream_info() invokes xhci_free_stream_ctx(), which
+calls dma_free_coherent() for large stream context arrays.
+
+dma_free_coherent() can sleep (e.g. via vunmap), triggering
+a BUG when called from atomic context.
+
+Call trace:
+ dma_free_attrs+0x174/0x220
+ xhci_free_stream_info+0xd0/0x11c
+ xhci_free_streams+0x278/0x37c
+ usb_free_streams+0x98/0xc0
+ usb_unbind_interface+0x1b8/0x2f8
+ device_release_driver_internal+0x1d4/0x2cc
+ device_release_driver+0x18/0x28
+ bus_remove_device+0x160/0x1a4
+ device_del+0x1ec/0x350
+ usb_disable_device+0x98/0x214
+ usb_disconnect+0xf0/0x35c
+ hub_event+0xab4/0x19ec
+ process_one_work+0x278/0x63c
+
+Fix this by saving the stream_info pointers and clearing the
+ep references under the lock, then calling xhci_free_stream_info()
+outside the lock where sleeping is allowed.
+
+Fixes: 8df75f42f8e6 ("USB: xhci: Add memory allocation for USB3 bulk streams.")
+Cc: stable <stable@kernel.org>
+Signed-off-by: Lianqin Hu <hulianqin@vivo.com>
+Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com>
+Link: https://patch.msgid.link/20260703144033.483286-3-mathias.nyman@linux.intel.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/host/xhci.c |   11 ++++++++++-
+ 1 file changed, 10 insertions(+), 1 deletion(-)
+
+--- a/drivers/usb/host/xhci.c
++++ b/drivers/usb/host/xhci.c
+@@ -3788,6 +3788,7 @@ static int xhci_free_streams(struct usb_
+       struct xhci_virt_device *vdev;
+       struct xhci_command *command;
+       struct xhci_input_control_ctx *ctrl_ctx;
++      struct xhci_stream_info *stream_info[EP_CTX_PER_DEV];
+       unsigned int ep_index;
+       unsigned long flags;
+       u32 changed_ep_bitmask;
+@@ -3848,10 +3849,15 @@ static int xhci_free_streams(struct usb_
+       if (ret < 0)
+               return ret;
++      /*
++       * dma_free_coherent() called by xhci_free_stream_info() may sleep,
++       * so save stream_info pointers and clear references under lock,
++       * then free the memory outside lock.
++       */
+       spin_lock_irqsave(&xhci->lock, flags);
+       for (i = 0; i < num_eps; i++) {
+               ep_index = xhci_get_endpoint_index(&eps[i]->desc);
+-              xhci_free_stream_info(xhci, vdev->eps[ep_index].stream_info);
++              stream_info[i] = vdev->eps[ep_index].stream_info;
+               vdev->eps[ep_index].stream_info = NULL;
+               /* FIXME Unset maxPstreams in endpoint context and
+                * update deq ptr to point to normal string ring.
+@@ -3861,6 +3867,9 @@ static int xhci_free_streams(struct usb_
+       }
+       spin_unlock_irqrestore(&xhci->lock, flags);
++      for (i = 0; i < num_eps; i++)
++              xhci_free_stream_info(xhci, stream_info[i]);
++
+       return 0;
+ }
diff --git a/queue-7.1/xhci-sideband-fix-ring-sg-table-pages-leak.patch b/queue-7.1/xhci-sideband-fix-ring-sg-table-pages-leak.patch
new file mode 100644 (file)
index 0000000..5cc56d3
--- /dev/null
@@ -0,0 +1,43 @@
+From 49f6e3c3ef19f04f6657ed8dce550e36c763abb8 Mon Sep 17 00:00:00 2001
+From: Xu Rao <raoxu@uniontech.com>
+Date: Fri, 3 Jul 2026 17:40:32 +0300
+Subject: xhci: sideband: fix ring sg table pages leak
+
+From: Xu Rao <raoxu@uniontech.com>
+
+commit 49f6e3c3ef19f04f6657ed8dce550e36c763abb8 upstream.
+
+xhci_ring_to_sgtable() allocates a temporary pages array and
+uses it to build the returned sg_table with
+sg_alloc_table_from_pages().
+
+The error paths free the pages array, but the success path
+returns the sg_table without freeing it. This leaks the temporary
+array every time a sideband client gets an endpoint or event ring
+buffer.
+
+Free the pages array after sg_alloc_table_from_pages() succeeds.
+The returned sg_table has its own scatterlist entries and does not
+depend on the temporary array after construction.
+
+Fixes: de66754e9f80 ("xhci: sideband: add initial api to register a secondary interrupter entity")
+Cc: stable <stable@kernel.org>
+Signed-off-by: Xu Rao <raoxu@uniontech.com>
+Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com>
+Link: https://patch.msgid.link/20260703144033.483286-2-mathias.nyman@linux.intel.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/host/xhci-sideband.c |    2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/drivers/usb/host/xhci-sideband.c
++++ b/drivers/usb/host/xhci-sideband.c
+@@ -58,6 +58,8 @@ xhci_ring_to_sgtable(struct xhci_sideban
+       if (sg_alloc_table_from_pages(sgt, pages, n_pages, 0, sz, GFP_KERNEL))
+               goto err;
++      kvfree(pages);
++
+       /*
+        * Save first segment dma address to sg dma_address field for the sideband
+        * client to have access to the IOVA of the ring.