From: Alice Ryhl Date: Tue, 7 Oct 2025 09:39:52 +0000 (+0000) Subject: rust_binder: don't delete FreezeListener if there are pending duplicates X-Git-Tag: v6.18-rc3~1^2~12 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=99559e5bb4c6795824b6531ad61519c1d9500079;p=thirdparty%2Flinux.git 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 --- diff --git a/drivers/android/binder/freeze.rs b/drivers/android/binder/freeze.rs index 74bebb8d4d9b..e304aceca7f3 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)?;