From: Carlos Llamas <cmllamas@google.com>
To: Alice Ryhl <aliceryhl@google.com>
Cc: "Greg Kroah-Hartman" <gregkh@linuxfoundation.org>,
"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>,
"Suren Baghdasaryan" <surenb@google.com>,
linux-kernel@vger.kernel.org, rust-for-linux@vger.kernel.org
Subject: Re: [PATCH v2 3/3] rust_binder: report freeze notification only when fully frozen
Date: Wed, 8 Oct 2025 16:54:10 +0000 [thread overview]
Message-ID: <aOaXMrGD1xIGIHkP@google.com> (raw)
In-Reply-To: <20251007-binder-freeze-v2-3-5376bd64fb59@google.com>
On Tue, Oct 07, 2025 at 09:39:53AM +0000, Alice Ryhl wrote:
> 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
>
Acked-by: Carlos Llamas <cmllamas@google.com>
prev parent reply other threads:[~2025-10-08 16:54 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 ` [PATCH v2 3/3] rust_binder: report freeze notification only when fully frozen Alice Ryhl
2025-10-08 16:54 ` Carlos Llamas [this message]
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=aOaXMrGD1xIGIHkP@google.com \
--to=cmllamas@google.com \
--cc=aliceryhl@google.com \
--cc=arve@android.com \
--cc=brauner@kernel.org \
--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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.