rust_binder: add ownership assertion to Node::add_death
Subsystems (2)
PATCH 1/1 rust_binder: add ownership assertion to Node::add_death
The // SAFETY: comment in NodeDeath::set_cleared assumes that a NodeDeath is never inserted into the death list of any Node other than its owner. However, this invariant is not enforced by the safe function Node::add_death, which inserts NodeDeath into the death list without checking that death.node == self, leaving a risk for future code that may miss this implicit invariant and cause undefined behavior.
Add an assertion to make this precondition explicit and catch potential violations early.
--- drivers/android/binder/node.rs | 4 ++++ 1 file changed, 4 insertions(+)
drivers/android/binder/node.rs +4 -0
@@ -333,6 +333,10 @@ pub(crate) fn add_death( death: ListArc<DTRWrap<NodeDeath>, 1>, guard: &mut Guard<'_, ProcessInner, SpinLockBackend>, ) { +assert! ( + core::ptr::eq (self, &**death.node), +"attempt to add NodeDeath to the wrong death list" + ); self.inner.access_mut (guard).death_list.push_back (death); }
base-commit: 287afdc7671a03081f48f3407bc59862c202bd4b
Signature · 1 line
2.47.3
Onur Özkan
reviewerQuoted 22 lines · On Tue, 09 Jun 2026 23:55:44 -0400 Georgios Androutsopoulos…
The
// SAFETY:comment inNodeDeath::set_clearedassumes that a NodeDeath is never inserted into the death list of any Node other than its owner. However, this invariant is not enforced by the safe functionNode::add_death, which inserts NodeDeath into the death list without checking that death.node == self, leaving a risk for future code that may miss this implicit invariant and cause undefined behavior.Add an assertion to make this precondition explicit and catch potential violations early.
Signed-off-by Georgios Androutsopoulos <[email protected]>--- drivers/android/binder/node.rs | 4 ++++ 1 file changed, 4 insertions(+)drivers/android/binder/node.rs +0
-0
drivers/android/binder/node.rs pub(crate) fn add_death( · line 339
Quoted 7 lines
drivers/android/binder/node.rs +4
-0@@ -333,6 +333,10 @@ pub(crate) fn add_death( death: ListArc<DTRWrap<NodeDeath>, 1>, guard: &mut Guard<'_, ProcessInner, SpinLockBackend>, ) { +assert! ( + core::ptr::eq (self, &**death.node), +"attempt to add NodeDeath to the wrong death list" + );
I think having a debug_assert! should be fine. That's also your suggestion in the GH issue link above.
Thanks,
Onur
Quoted 8 lines
drivers/android/binder/node.rs +0
-0self.inner.access_mut (guard).death_list.push_back (death); }base-commit:
287afdc7671a03081f48f3407bc59862c202bd4bSignature · 1 line
2.47.3
Quoted 3 lines · Onur Özkan
I think having a
debug_assert!should be fine. That's also your suggestion in the GH issue link above.
Yeah, there seems to be confusion about the asserts.
If there were a soundness issue, then an assert! may "fix" it, but it would usually the wrong way to do so, and a debug_assert! wouldn't be a fix it at all.
And for other cases, assert! is typically too strong for Linux (outside const context, tests, special cfgs, etc.).
In addition, please consider whether a pr_warn(_once)! or similar may be a good idea to pair with the debug_assert!.
Cheers,
Miguel
Gary Guo
reviewerQuoted 11 lines · Miguel Ojeda
Quoted 3 lines · Onur Özkan
I think having a
debug_assert!should be fine. That's also your suggestion in the GH issue link above.Yeah, there seems to be confusion about the asserts.
If there were a soundness issue, then an
assert!may "fix" it, but it would usually the wrong way to do so, and adebug_assert!wouldn't be a fix it at all.
Quoted 5 lines
And for other cases,
assert!is typically too strong for Linux (outside const context, tests, specialcfgs, etc.).In addition, please consider whether a
pr_warn(_once)!or similar may be a good idea to pair with thedebug_assert!.
pr_warn is probably a bad idea here. Given the code relies it for soundness. You're either sure that it won't happen, then you use debug_assert!, or you are not sure, and use assert!.
There's no "I am fairly certain but the code should keep running despite invariance violation" for this one.
Best,
Gary
Miguel Ojeda
maintainerQuoted 7 lines · On Wed, 10 Jun 2026 14:39:46 +0100 Gary Guo <[email protected]> wrote:
pr_warnis probably a bad idea here. Given the code relies it for soundness. You're either sure that it won't happen, then you usedebug_assert!, or you are not sure, and useassert!.There's no "I am fairly certain but the code should keep running despite invariance violation" for this one.
[ I keep getting your emails way later than they appear in the list...
I spotted this one as well in the mailing list. ]
I agree that continuining in this particular case is quite bad, and you know I would be stricter than the C side for this sort of thing -- it is closer to an indexing gone wrong where we panic as well.
But to clarify, the pr_warn! is not the important bit here -- I was giving the general rule that if debug_assert! is OK in a particular situation, then as usual we should consider a pr_warn! as well, i.e. that is the Erroneous Behavior combo for us.
And if it is not OK to continue in a certain situation, then something else entirely needs to be done.
That is what I pointed out in the GitHub issue, i.e. that the original debug_assert! suggestion cannot fix a soundness issue.
Cheers,
Miguel
Gary Guo
reviewerQuoted 11 lines · Miguel Ojeda
Quoted 7 lines · On Wed, 10 Jun 2026 14:39:46 +0100 Gary Guo <[email protected]> wrote:
pr_warnis probably a bad idea here. Given the code relies it for soundness. You're either sure that it won't happen, then you usedebug_assert!, or you are not sure, and useassert!.There's no "I am fairly certain but the code should keep running despite invariance violation" for this one.
[ I keep getting your emails way later than they appear in the list...
I spotted this one as well in the mailing list. ]
If you're using gmail, you might be hitting the receive limit? You can receive at most 60 emails per minute.
If you have more emails then it'll bounce. My email provider will retry after 15 minutes for up to 6 times, so if you're consistently hitting the receive limit, then it might take up to 1.5 hr for you to receive my email (or for me to receive a delivery failure notification).
Best,
Gary
Quoted 8 lines · Gary Guo
If you're using gmail, you might be hitting the receive limit? You can receive at most 60 emails per minute.
If you have more emails then it'll bounce. My email provider will retry after 15 minutes for up to 6 times, so if you're consistently hitting the receive limit, then it might take up to 1.5 hr for you to receive my email (or for me to receive a delivery failure notification).
Hmm... I don't think that is the issue (I only noticed it with you so far). It is also way more than 1 hour. The other one, for instance, was about a day late, to the point that I got this last one of yours earlier than the other one (!).
I guess I will ask the admins.
Cheers,
Miguel
PATCH v2 1/1 rust_binder: add ownership assertion to Node::add_death
In reply to Georgios AndroutsopoulosThe // SAFETY: comment in NodeDeath::set_cleared assumes that a NodeDeath is never inserted into the death list of any Node other than its owner. However, this invariant is not enforced by the safe function Node::add_death, which inserts NodeDeath into the death list without checking that death.node == self, leaving a risk for future code that may miss this implicit invariant and cause undefined behavior.
Add an assertion to make this precondition explicit and catch potential violations early.
---
Changes in v2:
- Replace assert!() with pr_warn() + debug_assert() following feedback from Onur Özkan and Miguel Ojeda.
Link to v1: https://lore.kernel.org/rust-for-linux/[email protected]/
--- drivers/android/binder/node.rs | 5 +++++ 1 file changed, 5 insertions(+)
drivers/android/binder/node.rs +5 -0
@@ -333,6 +333,11 @@ pub(crate) fn add_death( death: ListArc<DTRWrap<NodeDeath>, 1>, guard: &mut Guard<'_, ProcessInner, SpinLockBackend>, ) { +let is_valid = core::ptr::eq (self, &**death.node); +if !is_valid { +pr_warn! ("attempt to add NodeDeath to the wrong death list\n" ); + } +debug_assert! (is_valid); self.inner.access_mut (guard).death_list.push_back (death); }
base-commit: 287afdc7671a03081f48f3407bc59862c202bd4b
Signature · 1 line
2.47.3
Quoted 2 lines · Georgios Androutsopoulos
debug_assert!(is_valid);
If the Binder maintainers decide they want the pr_warn! (_once?), then this could go inside the if with a false condition.
Cheers,
Miguel
Alice Ryhl
maintainerQuoted 28 lines · Georgios Androutsopoulos
The
// SAFETY:comment inNodeDeath::set_clearedassumes that a NodeDeath is never inserted into the death list of any Node other than its owner. However, this invariant is not enforced by the safe functionNode::add_death, which inserts NodeDeath into the death list without checking that death.node == self, leaving a risk for future code that may miss this implicit invariant and cause undefined behavior.Add an assertion to make this precondition explicit and catch potential violations early.
Signed-off-by Georgios Androutsopoulos <[email protected]>---
Changes in v2:
- Replace assert!() withpr_warn()+debug_assert()following feedback from Onur Özkan and Miguel Ojeda.Link to v1: https://lore.kernel.org/rust-for-linux/[email protected]/
--- drivers/android/binder/node.rs | 5 +++++ 1 file changed, 5 insertions(+)drivers/android/binder/node.rs +0
-0
drivers/android/binder/node.rs pub(crate) fn add_death( · line 340
Quoted 8 lines
drivers/android/binder/node.rs +5
-0@@ -333,6 +333,11 @@ pub(crate) fn add_death( death: ListArc<DTRWrap<NodeDeath>, 1>, guard: &mut Guard<'_, ProcessInner, SpinLockBackend>, ) { +let is_valid = core::ptr::eq (self, &**death.node); +if !is_valid { +pr_warn! ("attempt to add NodeDeath to the wrong death list\n" ); + } +debug_assert! (is_valid);
If this assertion fails we should not continue. Either use a full panic, or do a warn_on! and return without adding it.
Alice
Quoted 2 lines · Alice Ryhl
If this assertion fails we should not continue. Either use a full panic, or do a
warn_on! and return without adding it.
Thank you for the feedback. Would you prefer we go back to the original patch suggestion with the assert!() that contains the message, without pr_warn()?
assert!(
core::ptr::eq(self, &**death.node),
"attempt to add NodeDeath to the wrong death list"
);Best,
Georgios
Alice Ryhl
maintainerQuoted 5 lines · George Androutsopoulos
Quoted 2 lines · Alice Ryhl
If this assertion fails we should not continue. Either use a full panic, or do a
warn_on! and return without adding it.
Quoted 7 lines
Thank you for the feedback. Would you prefer we go back to the original patch suggestion with the assert!() that contains the message, without
pr_warn()?assert!( core::ptr::eq(self, &**death.node), "attempt to add NodeDeath to the wrong death list" );
Doing an assert is fine, thanks.
Alice
PATCH v3 1/1 rust_binder: add ownership assertion to Node::add_death
In reply to Georgios AndroutsopoulosThe // SAFETY: comment in NodeDeath::set_cleared assumes that a NodeDeath is never inserted into the death list of any Node other than its owner. However, this invariant is not enforced by the safe function Node::add_death, which inserts NodeDeath into the death list without checking that death.node == self, leaving a risk for future code that may miss this implicit invariant and cause undefined behavior.
Add an assertion to make this precondition explicit and catch potential violations early.
---
Changes in v3:
- Reverted to assert!() following feedback from Alice Ryhl.
Link to v2: https://lore.kernel.org/rust-for-linux/[email protected]/
--- drivers/android/binder/node.rs | 4 ++++ 1 file changed, 4 insertions(+)
drivers/android/binder/node.rs +4 -0
@@ -333,6 +333,10 @@ pub(crate) fn add_death( death: ListArc<DTRWrap<NodeDeath>, 1>, guard: &mut Guard<'_, ProcessInner, SpinLockBackend>, ) { +assert! ( + core::ptr::eq (self, &**death.node), +"attempt to add NodeDeath to the wrong death list" + ); self.inner.access_mut (guard).death_list.push_back (death); }
Signature · 1 line
2.47.3
Quoted 8 lines · Georgios Androutsopoulos
The
// SAFETY:comment inNodeDeath::set_clearedassumes that a NodeDeath is never inserted into the death list of any Node other than its owner. However, this invariant is not enforced by the safe functionNode::add_death, which inserts NodeDeath into the death list without checking that death.node == self, leaving a risk for future code that may miss this implicit invariant and cause undefined behavior.
Quoted 6 lines
Add an assertion to make this precondition explicit and catch potential violations early.
Signed-off-by Georgios Androutsopoulos <[email protected]>