From: Alice Ryhl <aliceryhl@google.com>
To: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: "Arve Hjønnevåg" <arve@android.com>,
"Todd Kjos" <tkjos@android.com>,
"Martijn Coenen" <maco@android.com>,
"Joel Fernandes" <joelagnelf@nvidia.com>,
"Christian Brauner" <brauner@kernel.org>,
"Carlos Llamas" <cmllamas@google.com>,
"Suren Baghdasaryan" <surenb@google.com>,
linux-kernel@vger.kernel.org, rust-for-linux@vger.kernel.org,
"Alice Ryhl" <aliceryhl@google.com>
Subject: [PATCH v2 3/3] rust_binder: report freeze notification only when fully frozen
Date: Tue, 07 Oct 2025 09:39:53 +0000 [thread overview]
Message-ID: <20251007-binder-freeze-v2-3-5376bd64fb59@google.com> (raw)
In-Reply-To: <20251007-binder-freeze-v2-0-5376bd64fb59@google.com>
Binder only sends out freeze notifications when ioctl_freeze() completes
and the process has become fully frozen. However, if a freeze
notification is registered during the freeze operation, then it
registers an initial state of 'frozen'. This is a problem because if
the freeze operation fails, then the listener is not told about that
state change, leading to lost updates.
Signed-off-by: Alice Ryhl <aliceryhl@google.com>
---
This is also an issue in C Binder. A fix for that will be sent
separately.
---
drivers/android/binder/freeze.rs | 4 +--
drivers/android/binder/process.rs | 46 ++++++++++++++++++++++++++++-------
drivers/android/binder/transaction.rs | 6 ++---
3 files changed, 42 insertions(+), 14 deletions(-)
diff --git a/drivers/android/binder/freeze.rs b/drivers/android/binder/freeze.rs
index e304aceca7f31c15444cf67bb13488cd144345e6..220de35ae85ac8de2af717129011e0ace0677b7d 100644
--- a/drivers/android/binder/freeze.rs
+++ b/drivers/android/binder/freeze.rs
@@ -121,7 +121,7 @@ fn do_work(
writer.write_payload(&self.cookie.0)?;
Ok(true)
} else {
- let is_frozen = freeze.node.owner.inner.lock().is_frozen;
+ let is_frozen = freeze.node.owner.inner.lock().is_frozen.is_fully_frozen();
if freeze.last_is_frozen == Some(is_frozen) {
return Ok(true);
}
@@ -254,7 +254,7 @@ pub(crate) fn freeze_notif_done(self: &Arc<Self>, reader: &mut UserSliceReader)
);
return Err(EINVAL);
}
- let is_frozen = freeze.node.owner.inner.lock().is_frozen;
+ let is_frozen = freeze.node.owner.inner.lock().is_frozen.is_fully_frozen();
if freeze.is_clearing || freeze.last_is_frozen != Some(is_frozen) {
// Immediately send another FreezeMessage.
clear_msg = Some(FreezeMessage::init(alloc, cookie));
diff --git a/drivers/android/binder/process.rs b/drivers/android/binder/process.rs
index f13a747e784c84a0fb09cbf47442712106eba07c..2da9344397506a3f6d6b13411c45d5ded92d6db1 100644
--- a/drivers/android/binder/process.rs
+++ b/drivers/android/binder/process.rs
@@ -72,6 +72,33 @@ fn new(address: usize, size: usize) -> Self {
const PROC_DEFER_FLUSH: u8 = 1;
const PROC_DEFER_RELEASE: u8 = 2;
+#[derive(Copy, Clone)]
+pub(crate) enum IsFrozen {
+ Yes,
+ No,
+ InProgress,
+}
+
+impl IsFrozen {
+ /// Whether incoming transactions should be rejected due to freeze.
+ pub(crate) fn is_frozen(self) -> bool {
+ match self {
+ IsFrozen::Yes => true,
+ IsFrozen::No => false,
+ IsFrozen::InProgress => true,
+ }
+ }
+
+ /// Whether freeze notifications consider this process frozen.
+ pub(crate) fn is_fully_frozen(self) -> bool {
+ match self {
+ IsFrozen::Yes => true,
+ IsFrozen::No => false,
+ IsFrozen::InProgress => false,
+ }
+ }
+}
+
/// The fields of `Process` protected by the spinlock.
pub(crate) struct ProcessInner {
is_manager: bool,
@@ -98,7 +125,7 @@ pub(crate) struct ProcessInner {
/// are woken up.
outstanding_txns: u32,
/// Process is frozen and unable to service binder transactions.
- pub(crate) is_frozen: bool,
+ pub(crate) is_frozen: IsFrozen,
/// Process received sync transactions since last frozen.
pub(crate) sync_recv: bool,
/// Process received async transactions since last frozen.
@@ -124,7 +151,7 @@ fn new() -> Self {
started_thread_count: 0,
defer_work: 0,
outstanding_txns: 0,
- is_frozen: false,
+ is_frozen: IsFrozen::No,
sync_recv: false,
async_recv: false,
binderfs_file: None,
@@ -1260,7 +1287,7 @@ fn deferred_release(self: Arc<Self>) {
let is_manager = {
let mut inner = self.inner.lock();
inner.is_dead = true;
- inner.is_frozen = false;
+ inner.is_frozen = IsFrozen::No;
inner.sync_recv = false;
inner.async_recv = false;
inner.is_manager
@@ -1371,7 +1398,7 @@ pub(crate) fn drop_outstanding_txn(&self) {
return;
}
inner.outstanding_txns -= 1;
- inner.is_frozen && inner.outstanding_txns == 0
+ inner.is_frozen.is_frozen() && inner.outstanding_txns == 0
};
if wake {
@@ -1385,7 +1412,7 @@ pub(crate) fn ioctl_freeze(&self, info: &BinderFreezeInfo) -> Result {
let mut inner = self.inner.lock();
inner.sync_recv = false;
inner.async_recv = false;
- inner.is_frozen = false;
+ inner.is_frozen = IsFrozen::No;
drop(inner);
msgs.send_messages();
return Ok(());
@@ -1394,7 +1421,7 @@ pub(crate) fn ioctl_freeze(&self, info: &BinderFreezeInfo) -> Result {
let mut inner = self.inner.lock();
inner.sync_recv = false;
inner.async_recv = false;
- inner.is_frozen = true;
+ inner.is_frozen = IsFrozen::InProgress;
if info.timeout_ms > 0 {
let mut jiffies = kernel::time::msecs_to_jiffies(info.timeout_ms);
@@ -1408,7 +1435,7 @@ pub(crate) fn ioctl_freeze(&self, info: &BinderFreezeInfo) -> Result {
.wait_interruptible_timeout(&mut inner, jiffies)
{
CondVarTimeoutResult::Signal { .. } => {
- inner.is_frozen = false;
+ inner.is_frozen = IsFrozen::No;
return Err(ERESTARTSYS);
}
CondVarTimeoutResult::Woken { jiffies: remaining } => {
@@ -1422,17 +1449,18 @@ pub(crate) fn ioctl_freeze(&self, info: &BinderFreezeInfo) -> Result {
}
if inner.txns_pending_locked() {
- inner.is_frozen = false;
+ inner.is_frozen = IsFrozen::No;
Err(EAGAIN)
} else {
drop(inner);
match self.prepare_freeze_messages() {
Ok(batch) => {
+ self.inner.lock().is_frozen = IsFrozen::Yes;
batch.send_messages();
Ok(())
}
Err(kernel::alloc::AllocError) => {
- self.inner.lock().is_frozen = false;
+ self.inner.lock().is_frozen = IsFrozen::No;
Err(ENOMEM)
}
}
diff --git a/drivers/android/binder/transaction.rs b/drivers/android/binder/transaction.rs
index 02512175d6229535373f2d3e543ba8c91ecd72f0..4bd3c0e417eb93d5d62d9c20daadde1fb0e4990f 100644
--- a/drivers/android/binder/transaction.rs
+++ b/drivers/android/binder/transaction.rs
@@ -249,7 +249,7 @@ pub(crate) fn submit(self: DLArc<Self>) -> BinderResult {
if oneway {
if let Some(target_node) = self.target_node.clone() {
- if process_inner.is_frozen {
+ if process_inner.is_frozen.is_frozen() {
process_inner.async_recv = true;
if self.flags & TF_UPDATE_TXN != 0 {
if let Some(t_outdated) =
@@ -270,7 +270,7 @@ pub(crate) fn submit(self: DLArc<Self>) -> BinderResult {
}
}
- if process_inner.is_frozen {
+ if process_inner.is_frozen.is_frozen() {
return Err(BinderError::new_frozen_oneway());
} else {
return Ok(());
@@ -280,7 +280,7 @@ pub(crate) fn submit(self: DLArc<Self>) -> BinderResult {
}
}
- if process_inner.is_frozen {
+ if process_inner.is_frozen.is_frozen() {
process_inner.sync_recv = true;
return Err(BinderError::new_frozen());
}
--
2.51.0.618.g983fd99d29-goog
next prev parent reply other threads:[~2025-10-07 9:40 UTC|newest]
Thread overview: 12+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-10-07 9:39 [PATCH v2 0/3] Fix three issues with freeze listeners Alice Ryhl
2025-10-07 9:39 ` [PATCH v2 1/3] rust_binder: freeze_notif_done should resend if wrong state Alice Ryhl
2025-10-08 16:32 ` Carlos Llamas
2025-10-08 16:34 ` Alice Ryhl
2025-10-08 16:38 ` Carlos Llamas
2025-10-08 16:41 ` Alice Ryhl
2025-10-08 16:52 ` Carlos Llamas
2025-10-09 11:19 ` Alice Ryhl
2025-10-07 9:39 ` [PATCH v2 2/3] rust_binder: don't delete FreezeListener if there are pending duplicates Alice Ryhl
2025-10-08 16:53 ` Carlos Llamas
2025-10-07 9:39 ` Alice Ryhl [this message]
2025-10-08 16:54 ` [PATCH v2 3/3] rust_binder: report freeze notification only when fully frozen Carlos Llamas
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20251007-binder-freeze-v2-3-5376bd64fb59@google.com \
--to=aliceryhl@google.com \
--cc=arve@android.com \
--cc=brauner@kernel.org \
--cc=cmllamas@google.com \
--cc=gregkh@linuxfoundation.org \
--cc=joelagnelf@nvidia.com \
--cc=linux-kernel@vger.kernel.org \
--cc=maco@android.com \
--cc=rust-for-linux@vger.kernel.org \
--cc=surenb@google.com \
--cc=tkjos@android.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®