From 99559e5bb4c6795824b6531ad61519c1d9500079 Mon Sep 17 00:00:00 2001 From: Alice Ryhl Date: Tue, 7 Oct 2025 09:39:52 +0000 Subject: [PATCH] rust_binder: don't delete FreezeListener if there are pending duplicates When userspace issues commands to a freeze listener, it identifies it using a cookie. Normally this cookie uniquely identifies a freeze listener, but when userspace clears a listener with the intent of deleting it, it's allowed to "regret" clearing it and create a new freeze listener for the same node using the same cookie. (IMO this was an API mistake, but userspace relies on it.) Currently if the active freeze listener gets fully deleted while there are still pending duplicates, then the code incorrectly deletes the pending duplicates too. To fix this, do not delete the entry if there are still pending duplicates. Since the current data structure requires a main freeze listener, we convert one pending duplicate into the primary listener in this scenario. Signed-off-by: Alice Ryhl Acked-by: Carlos Llamas Signed-off-by: Greg Kroah-Hartman --- drivers/android/binder/freeze.rs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/drivers/android/binder/freeze.rs b/drivers/android/binder/freeze.rs index 74bebb8d4d9b2..e304aceca7f31 100644 --- a/drivers/android/binder/freeze.rs +++ b/drivers/android/binder/freeze.rs @@ -106,7 +106,16 @@ impl DeliverToRead for FreezeMessage { return Ok(true); } if freeze.is_clearing { - _removed_listener = freeze_entry.remove_node(); + kernel::warn_on!(freeze.num_cleared_duplicates != 0); + if freeze.num_pending_duplicates > 0 { + // The primary freeze listener was deleted, so convert a pending duplicate back + // into the primary one. + freeze.num_pending_duplicates -= 1; + freeze.is_pending = true; + freeze.is_clearing = true; + } else { + _removed_listener = freeze_entry.remove_node(); + } drop(node_refs); writer.write_code(BR_CLEAR_FREEZE_NOTIFICATION_DONE)?; writer.write_payload(&self.cookie.0)?; -- 2.47.3