From nobody Mon Jun 8 09:48:29 2026 Received: from mail-wr1-f73.google.com (mail-wr1-f73.google.com [209.85.221.73]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 137D040DFD1 for ; Thu, 4 Jun 2026 11:37:23 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.221.73 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780573045; cv=none; b=QxffM24169C4PdOeN3vuxL3Q3o+fPyLKIDQr/I4YFFP8192wPUxXorlMnGQYa5yK1FVvjJsvc1cg0QbWJ4MjntTWDSzjdj2Us8g/meopKTyyKpBoBDC+ApAemFirGpoNxTTsiotdgrM75z3QVVDPP//W6hP874HQEmzUNi4+aU4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780573045; c=relaxed/simple; bh=irE7P0EvhrLM851/VIzMflx+0DT1rrsQqwBqQK69O38=; h=Date:Mime-Version:Message-ID:Subject:From:To:Cc:Content-Type; b=cdFX8nSJvQVbfkF2JSgSoj3PEz6WtRcdEULfUZhFPppYbMoMsHl6mnFoNZY09lEoMlCCwGsraCqOt3srpftGncZL2WKEMlIdtZ6I4LBQkLVPzysSc1hYxEevr0b0LOkH+BBPdTeDPMo8Og5Xo2uiHLdGd97qobb6cCUIjOgcW4U= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--aliceryhl.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=H19jR1hV; arc=none smtp.client-ip=209.85.221.73 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--aliceryhl.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="H19jR1hV" Received: by mail-wr1-f73.google.com with SMTP id ffacd0b85a97d-45ef616db45so491209f8f.2 for ; Thu, 04 Jun 2026 04:37:23 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20251104; t=1780573042; x=1781177842; darn=vger.kernel.org; h=cc:to:from:subject:message-id:mime-version:date:from:to:cc:subject :date:message-id:reply-to; bh=Z4SYEfldQ6Lx1qsEjeHpP7N2ec+VzKxXBxUTO3EAbW4=; b=H19jR1hVBgnfS8U7ENcu2kEoqWLhGHYVUALWw1BVnjUHqP21r3alPXmLT7s4aLrgfO kYFDjRT7CBrZD8v9tu4yxDcwa2OSDWlLVxg2hLOhweqc3l0CP4pyYYot/OOMPqsvZDCc XAtsTOJNCGL4ah6WEwXihq/uO3cV5CXF9BOAeFWp7ol3daMxba2Z5S1YxayQcOQ/UFML 57CR81AFznwgxFwM1Cvfh+/mZoyTDaJ6sDcsLjKagbrIuhvrP9nwp3LAFBrKF1hBmfLP m+ZxgchlADkZjvY4MRC8J0I85MnZHhShzPgNYgAxPP3yXyWqm4AKMhsiJj0QmrkcHp15 v1mg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1780573042; x=1781177842; h=cc:to:from:subject:message-id:mime-version:date:x-gm-message-state :from:to:cc:subject:date:message-id:reply-to; bh=Z4SYEfldQ6Lx1qsEjeHpP7N2ec+VzKxXBxUTO3EAbW4=; b=hrlelnr3unijbEA0INjcPt9h9UffkCQXEMBeIvMDJgGKmL8gVEYR9o3eLQKNWzrgjw a9eitlNc1+mXn56Kx6qJASM6EIiamCF3DaSeTApCIo3GnibNtpLdDb/ml9QK8tvBfQKR vKxLVT/gYEAfkiSxNNEYX86PlYCgB2tbzlEpqh7Yff60bwjW0F6zQ9tzO4VkUHixlw8M 63iQNMSJbl5DIUd2s3pSeKh0t4BrZw8oJoZ2IYHI3RcE8JjvhAp8OgIH6ykC234mIPsz 310RxSjl25Gsp8d91oudPwEHOcpMBVDtapHGAFqE9FqhH1SlGHmXZN0VTIBTOzFvIyC1 uYSQ== X-Forwarded-Encrypted: i=1; AFNElJ/pqt5BURp4uFQfx8HupfF6Xnefsct5P7WgVj+etKz//txrRCJ5zlY4frb7WP/FV3v9/Yim59QiWbFF8zA=@vger.kernel.org X-Gm-Message-State: AOJu0YyjNoq7tITwMyhuTYbRiH1CYPnBZ+lSHHvXG7p9th8YY05RiXWu OGNsW6/aPi2JvFVaqAnm5iWKjh2mhkGW80CvMvf0vdMFkZGO9YF0MsoXSyFyCdMWt6qbHmOL+LS lYMLseYHU+IW2uaLteg== X-Received: from wmbjp4.prod.google.com ([2002:a05:600c:5584:b0:490:1aca:caa3]) (user=aliceryhl job=prod-delivery.src-stubby-dispatcher) by 2002:a05:600c:a09:b0:490:4e3e:b483 with SMTP id 5b1f17b1804b1-490b5fe66ebmr124526735e9.22.1780573042354; Thu, 04 Jun 2026 04:37:22 -0700 (PDT) Date: Thu, 04 Jun 2026 11:37:07 +0000 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 X-B4-Tracking: v=1; b=H4sIAGNjIWoC/32NQQ6CMBBFr0Jm7ZhSoI2uvIdhAfRbmig1U0Iwh LtbOYDL95L//kYJEpDoWmwkWEIKccqgTwUNYzd5cHCZSSttVKMtJ8yMdcbk4BgiURh66CoLZS7 GUR6+BY+wHtF7m3kMaY7yOT6W8mf/5paSS66V7eu+NkZVzc3H6J84D/FF7b7vXx2JN4W1AAAA X-Change-Id: 20260527-set-extended-error-e2ca37e0696d X-Developer-Key: i=aliceryhl@google.com; a=openpgp; fpr=49F6C1FAA74960F43A5B86A1EE7A392FDE96209F X-Developer-Signature: v=1; a=openpgp-sha256; l=11686; i=aliceryhl@google.com; h=from:subject:message-id; bh=irE7P0EvhrLM851/VIzMflx+0DT1rrsQqwBqQK69O38=; b=owEBbQKS/ZANAwAKAQRYvu5YxjlGAcsmYgBqIWNsve9gZtqM5uUt+N2Q4G+IS0EkDsd0v69LJ exoO2F4XEuJAjMEAAEKAB0WIQSDkqKUTWQHCvFIvbIEWL7uWMY5RgUCaiFjbAAKCRAEWL7uWMY5 RrwJEACbeiugrl1gmmmcNTUBljKpzv3lyXSJmZ1maRBav1Jz+c24KkqZ7QqJA1pm0bR0ALf2QjQ BV00PXXtAcn3sStLE6jcUX5CVPntHGn6dgC5w8FuSoAGS1jEI/jGyvAXS0zl1/PIXEZHbYEsmkd iUkQIznp342qWzsNuDeTwlT5cVadnbuNZDeZd1KAZe9nPsOZLhqs0wltWd/CxNvJIXNIMR5ZSpv 088JvsKUV06wnTYQfgYshZ/nrOjVrZeUrgFEWzcdJm7AF1/wxtW7GwtFBT0ekDpei1Qz9WBZAv9 RbCo82gV14r6hbh+dH7t+VcSSpboV0lXePcm8rTOZfVyeM2owMmBUHeARlew6oQtY5tJBuGnRns NNACEqkKC+bkGce4doRtXT9ppaoldcfjKXXvJXNjLoyCY9XjoOhp+LiRuAuxX6bMGyj1URDIbBE p0Ex1UMoSmxbIW8ikOVv/YOAgGwDL1METWuCOeq3bDPA/jX4/rdmKLw4XdHfANQYN5yM2goVezO ffNgWCXmcb3CZWhpyHJdQ8Aa1o1XhVe9WWeMy3Ly0lySpivvr/4AnwihdaRXYHaTSsBxgjAl4GV 4yHJSRZTb8N/M2+l5JIMmVCIwLXtPUxhMDmon45xb9g0FgQtsXwz2Av+Ud1sWEGf3RXtO92V5Wv gxXL5PeBndwXJyw== X-Mailer: b4 0.14.3 Message-ID: <20260604-set-extended-error-v2-1-fb0753e7ab53@google.com> Subject: [PATCH v2] rust_binder: fix BINDER_GET_EXTENDED_ERROR From: Alice Ryhl To: Greg Kroah-Hartman , Carlos Llamas Cc: Miguel Ojeda , Boqun Feng , Gary Guo , "=?utf-8?q?Bj=C3=B6rn_Roy_Baron?=" , Benno Lossin , Andreas Hindborg , Alice Ryhl , Trevor Gross , Danilo Krummrich , rust-for-linux@vger.kernel.org, linux-kernel@vger.kernel.org, stable@vger.kernel.org Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable 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@vger.kernel.org Fixes: eafedbc7c050 ("rust_binder: add Rust Binder driver") Signed-off-by: Alice Ryhl --- Changes in v2: - Also handle extended error for replies. - Link to v1: https://lore.kernel.org/r/20260527-set-extended-error-v1-1-40= 7b4b466035@google.com --- 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(-) diff --git a/drivers/android/binder/error.rs b/drivers/android/binder/error= .rs index 45d85d4c2815..63c8d90c409a 100644 --- 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 =3D> match self.source.as_ref() { - Some(source) =3D> f - .debug_struct("BR_FAILED_REPLY") - .field("source", source) - .finish(), + Some(source) =3D> source.fmt(f), None =3D> f.pad("BR_FAILED_REPLY"), }, BR_DEAD_REPLY =3D> f.pad("BR_DEAD_REPLY"), BR_FROZEN_REPLY =3D> f.pad("BR_FROZEN_REPLY"), BR_TRANSACTION_PENDING_FROZEN =3D> f.pad("BR_TRANSACTION_PENDI= NG_FROZEN"), BR_TRANSACTION_COMPLETE =3D> f.pad("BR_TRANSACTION_COMPLETE"), - _ =3D> f - .debug_struct("BinderError") - .field("reply", &self.reply) - .finish(), + _ =3D> match self.source.as_ref() { + Some(source) =3D> source.fmt(f), + None =3D> f.pad("OTHER_ERROR"), + }, } } } diff --git a/drivers/android/binder/thread.rs b/drivers/android/binder/thre= ad.rs index 97d5f31e8fe3..334f4b49511d 100644 --- a/drivers/android/binder/thread.rs +++ b/drivers/android/binder/thread.rs @@ -495,9 +495,16 @@ pub(crate) fn debug_print(self: &Arc, m: &SeqFil= e, print_all: bool) -> Res Ok(()) } =20 + pub(crate) fn clear_extended_error(&self, debug_id: usize) { + self.inner.lock().extended_error =3D ExtendedError::new(debug_id a= s u32, BR_OK, 0); + } + pub(crate) fn get_extended_error(&self, data: UserSlice) -> Result { let mut writer =3D data.writer(); - let ee =3D self.inner.lock().extended_error; + let mut inner =3D self.inner.lock(); + let ee =3D inner.extended_error; + inner.extended_error =3D ExtendedError::new(0, BR_OK, 0); + drop(inner); writer.write(&ee)?; Ok(()) } @@ -1109,7 +1116,10 @@ fn unwind_transaction_stack(self: &Arc) { inner.pop_transaction_to_reply(thread.as_ref()) } { let reply =3D Err(BR_DEAD_REPLY); - if !transaction.from.deliver_single_reply(reply, &transaction)= { + if !transaction + .from + .deliver_single_reply(reply, &transaction, None) + { break; } =20 @@ -1121,8 +1131,9 @@ pub(crate) fn deliver_reply( &self, reply: Result, u32>, transaction: &DArc, + extended_error: Option, ) { - 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 @@ fn deliver_single_reply( &self, reply: Result, u32>, transaction: &DArc, + extended_error: Option, ) -> bool { if let Ok(transaction) =3D &reply { crate::trace::trace_transaction(true, transaction, Some(&self.= task)); @@ -1152,6 +1164,12 @@ fn deliver_single_reply( return true; } =20 + if let Some(ee) =3D extended_error { + if inner.extended_error.command =3D=3D BR_OK { + inner.extended_error =3D ee; + } + } + match reply { Ok(work) =3D> { inner.push_work(work); @@ -1222,6 +1240,9 @@ fn read_transaction_info( info.buffers_size =3D td.buffers_size as usize; // SAFETY: Above `read` call initializes all bytes, so this union = read is ok. info.target_handle =3D unsafe { td.transaction_data.target.handle = }; + + info.debug_id =3D super::next_debug_id(); + Ok(()) } =20 @@ -1230,6 +1251,8 @@ fn transaction(self: &Arc, cmd: u32, reader: &m= ut UserSliceReader) -> Resu let mut info =3D TransactionInfo::zeroed(); self.read_transaction_info(cmd, reader, &mut info)?; =20 + self.clear_extended_error(info.debug_id); + let ret =3D if info.is_reply { self.reply_inner(&mut info) } else if info.is_oneway() { @@ -1239,23 +1262,21 @@ fn transaction(self: &Arc, cmd: u32, reader: = &mut UserSliceReader) -> Resu }; =20 if let Err(err) =3D ret { - if err.reply !=3D BR_TRANSACTION_COMPLETE { - info.reply =3D err.reply; - } - self.push_return_work(err.reply); - if let Some(source) =3D &err.source { - info.errno =3D source.to_errno(); + if err.reply !=3D BR_TRANSACTION_COMPLETE { info.reply =3D err.reply; + if let Some(source) =3D &err.source { + info.errno =3D source.to_errno(); =20 - { - let mut ee =3D self.inner.lock().extended_error; - ee.command =3D err.reply; - ee.param =3D source.to_errno(); + { + let mut inner =3D self.inner.lock(); + inner.extended_error =3D + ExtendedError::new(info.debug_id as u32, err.r= eply, source.to_errno()); + } } =20 pr_warn!( - "{}:{} transaction to {} failed: {source:?}", + "{}:{} transaction to {} failed: {err:?}", info.from_pid, info.from_tid, info.to_pid @@ -1320,18 +1341,24 @@ fn reply_inner(self: &Arc, info: &mut Transac= tionInfo) -> BinderResult { let allow_fds =3D orig.flags & TF_ACCEPT_FDS !=3D 0; let reply =3D Transaction::new_reply(self, process, info, allo= w_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 t= he 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 =3D Err(BR_FAILED_REPLY); - orig.from.deliver_reply(reply, &orig); + + let param =3D err.source.as_ref().map_or(0, |e| e.to_errno()); + let ee =3D ExtendedError::new(orig.debug_id as u32, err.reply,= param); + orig.from + .deliver_reply(Err(BR_FAILED_REPLY), &orig, Some(ee)); err.reply =3D BR_TRANSACTION_COMPLETE; err }); diff --git a/drivers/android/binder/transaction.rs b/drivers/android/binder= /transaction.rs index 1d9b66920a21..0e5d07b7e6f0 100644 --- 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, } =20 impl TransactionInfo { @@ -93,7 +94,6 @@ pub(crate) fn new( from: &Arc, info: &mut TransactionInfo, ) -> BinderResult> { - let debug_id =3D super::next_debug_id(); let allow_fds =3D node_ref.node.flags & FLAT_BINDER_FLAG_ACCEPTS_F= DS !=3D 0; let txn_security_ctx =3D node_ref.node.flags & FLAT_BINDER_FLAG_TX= N_SECURITY_CTX !=3D 0; let mut txn_security_ctx_off =3D if txn_security_ctx { Some(0) } e= lse { None }; @@ -101,7 +101,7 @@ pub(crate) fn new( let mut alloc =3D 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 =3D alloc.ptr; =20 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> { - let debug_id =3D super::next_debug_id(); let mut alloc =3D - match from.copy_transaction_data(to.clone(), info, debug_id, a= llow_fds, None) { + match from.copy_transaction_data(to.clone(), info, info.debug_= id, allow_fds, None) { Ok(alloc) =3D> alloc, Err(err) =3D> { 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 =3D ScopeGuard::new(|| { if self.target_node.is_some() && self.flags & TF_ONE_WAY =3D= =3D 0 { let reply =3D 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) { // 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 =3D=3D 0 { let reply =3D Err(BR_DEAD_REPLY); - self.from.deliver_reply(reply, &self); + self.from.deliver_reply(reply, &self, None); } =20 self.drop_outstanding_txn(); --- base-commit: da61573f783897ae5a96c8f1c71aad6242344feb change-id: 20260527-set-extended-error-e2ca37e0696d Best regards, --=20 Alice Ryhl