1 // SPDX-License-Identifier: GPL-2.0 2 3 // Copyright (C) 2025 Google LLC. 4 5 use kernel::{ 6 alloc::AllocError, 7 list::ListArc, 8 prelude::*, 9 rbtree::{self, RBTreeNodeReservation}, 10 seq_file::SeqFile, 11 seq_print, 12 sync::{Arc, UniqueArc}, 13 uaccess::UserSliceReader, 14 }; 15 16 use crate::{ 17 defs::*, node::Node, process::Process, thread::Thread, BinderReturnWriter, DArc, DLArc, 18 DTRWrap, DeliverToRead, 19 }; 20 21 #[derive(Clone, Copy, Eq, PartialEq, Ord, PartialOrd)] 22 pub(crate) struct FreezeCookie(u64); 23 24 /// Represents a listener for changes to the frozen state of a process. 25 pub(crate) struct FreezeListener { 26 /// The node we are listening for. 27 pub(crate) node: DArc<Node>, 28 /// The cookie of this freeze listener. 29 cookie: FreezeCookie, 30 /// What value of `is_frozen` did we most recently tell userspace about? 31 last_is_frozen: Option<bool>, 32 /// We sent a `BR_FROZEN_BINDER` and we are waiting for `BC_FREEZE_NOTIFICATION_DONE` before 33 /// sending any other commands. 34 is_pending: bool, 35 /// Userspace sent `BC_CLEAR_FREEZE_NOTIFICATION` and we need to reply with 36 /// `BR_CLEAR_FREEZE_NOTIFICATION_DONE` as soon as possible. If `is_pending` is set, then we 37 /// must wait for it to be unset before we can reply. 38 is_clearing: bool, 39 /// Number of cleared duplicates that can't be deleted until userspace sends 40 /// `BC_FREEZE_NOTIFICATION_DONE`. 41 num_pending_duplicates: u64, 42 /// Number of cleared duplicates that can be deleted. 43 num_cleared_duplicates: u64, 44 } 45 46 impl FreezeListener { 47 /// Is it okay to create a new listener with the same cookie as this one for the provided node? 48 /// 49 /// Under some scenarios, userspace may delete a freeze listener and immediately recreate it 50 /// with the same cookie. This results in duplicate listeners. To avoid issues with ambiguity, 51 /// we allow this only if the new listener is for the same node, and we also require that the 52 /// old listener has already been cleared. allow_duplicate(&self, node: &DArc<Node>) -> bool53 fn allow_duplicate(&self, node: &DArc<Node>) -> bool { 54 Arc::ptr_eq(&self.node, node) && self.is_clearing 55 } 56 } 57 58 type UninitFM = UniqueArc<core::mem::MaybeUninit<DTRWrap<FreezeMessage>>>; 59 60 /// Represents a notification that the freeze state has changed. 61 pub(crate) struct FreezeMessage { 62 cookie: FreezeCookie, 63 } 64 65 kernel::list::impl_list_arc_safe! { 66 impl ListArcSafe<0> for FreezeMessage { 67 untracked; 68 } 69 } 70 71 impl FreezeMessage { new(flags: kernel::alloc::Flags) -> Result<UninitFM, AllocError>72 fn new(flags: kernel::alloc::Flags) -> Result<UninitFM, AllocError> { 73 UniqueArc::new_uninit(flags) 74 } 75 init(ua: UninitFM, cookie: FreezeCookie) -> DLArc<FreezeMessage>76 fn init(ua: UninitFM, cookie: FreezeCookie) -> DLArc<FreezeMessage> { 77 match ua.pin_init_with(DTRWrap::new(FreezeMessage { cookie })) { 78 Ok(msg) => ListArc::from(msg), 79 Err(err) => match err {}, 80 } 81 } 82 } 83 84 impl DeliverToRead for FreezeMessage { do_work( self: DArc<Self>, thread: &Thread, writer: &mut BinderReturnWriter<'_>, ) -> Result<bool>85 fn do_work( 86 self: DArc<Self>, 87 thread: &Thread, 88 writer: &mut BinderReturnWriter<'_>, 89 ) -> Result<bool> { 90 let _removed_listener; 91 let mut node_refs = thread.process.node_refs.lock(); 92 let Some(mut freeze_entry) = node_refs.freeze_listeners.find_mut(&self.cookie) else { 93 return Ok(true); 94 }; 95 let freeze = freeze_entry.get_mut(); 96 97 if freeze.num_cleared_duplicates > 0 { 98 freeze.num_cleared_duplicates -= 1; 99 drop(node_refs); 100 writer.write_code(BR_CLEAR_FREEZE_NOTIFICATION_DONE)?; 101 writer.write_payload(&self.cookie.0)?; 102 return Ok(true); 103 } 104 105 if freeze.is_pending { 106 return Ok(true); 107 } 108 if freeze.is_clearing { 109 kernel::warn_on!(freeze.num_cleared_duplicates != 0); 110 if freeze.num_pending_duplicates > 0 { 111 // The primary freeze listener was deleted, so convert a pending duplicate back 112 // into the primary one. 113 freeze.num_pending_duplicates -= 1; 114 freeze.is_pending = true; 115 freeze.is_clearing = true; 116 } else { 117 _removed_listener = freeze_entry.remove_node(); 118 } 119 drop(node_refs); 120 writer.write_code(BR_CLEAR_FREEZE_NOTIFICATION_DONE)?; 121 writer.write_payload(&self.cookie.0)?; 122 Ok(true) 123 } else { 124 let is_frozen = freeze.node.owner.inner.lock().is_frozen.is_fully_frozen(); 125 if freeze.last_is_frozen == Some(is_frozen) { 126 return Ok(true); 127 } 128 129 let mut state_info = BinderFrozenStateInfo::default(); 130 state_info.is_frozen = is_frozen as u32; 131 state_info.cookie = freeze.cookie.0; 132 freeze.is_pending = true; 133 freeze.last_is_frozen = Some(is_frozen); 134 drop(node_refs); 135 136 writer.write_code(BR_FROZEN_BINDER)?; 137 writer.write_payload(&state_info)?; 138 // BR_FROZEN_BINDER notifications can cause transactions 139 Ok(false) 140 } 141 } 142 cancel(self: DArc<Self>)143 fn cancel(self: DArc<Self>) {} 144 should_sync_wakeup(&self) -> bool145 fn should_sync_wakeup(&self) -> bool { 146 false 147 } 148 149 #[inline(never)] debug_print(&self, m: &SeqFile, prefix: &str, _tprefix: &str) -> Result<()>150 fn debug_print(&self, m: &SeqFile, prefix: &str, _tprefix: &str) -> Result<()> { 151 seq_print!(m, "{}has frozen binder\n", prefix); 152 Ok(()) 153 } 154 } 155 156 impl FreezeListener { 157 /// Called when this freeze listener is cleared abnormally. 158 /// 159 /// This occurs either because the process exited or because the process dropped its last 160 /// refcount on the node ref without explicitly removing the freeze listener first. 161 /// 162 /// The returned `KVVec` is just a value that should be dropped outside of the lock. on_process_cleanup(&self, proc: &Process) -> KVVec<Arc<Process>>163 pub(crate) fn on_process_cleanup(&self, proc: &Process) -> KVVec<Arc<Process>> { 164 if !self.is_clearing { 165 return self.node.remove_freeze_listener(proc); 166 } 167 KVVec::new() 168 } 169 } 170 171 impl Process { request_freeze_notif( self: &Arc<Self>, reader: &mut UserSliceReader, ) -> Result<()>172 pub(crate) fn request_freeze_notif( 173 self: &Arc<Self>, 174 reader: &mut UserSliceReader, 175 ) -> Result<()> { 176 let hc = reader.read::<BinderHandleCookie>()?; 177 let handle = hc.handle; 178 let cookie = FreezeCookie(hc.cookie); 179 180 let msg = FreezeMessage::new(GFP_KERNEL)?; 181 let alloc = RBTreeNodeReservation::new(GFP_KERNEL)?; 182 183 let mut node_refs_guard = self.node_refs.lock(); 184 let node_refs = &mut *node_refs_guard; 185 let Some(info) = node_refs.by_handle.get_mut(&handle) else { 186 pr_warn!("BC_REQUEST_FREEZE_NOTIFICATION invalid ref {}\n", handle); 187 return Err(EINVAL); 188 }; 189 if info.freeze().is_some() { 190 pr_warn!("BC_REQUEST_FREEZE_NOTIFICATION already set\n"); 191 return Err(EINVAL); 192 } 193 let node_ref = info.node_ref(); 194 let freeze_entry = node_refs.freeze_listeners.entry(cookie); 195 196 if let rbtree::Entry::Occupied(ref dupe) = freeze_entry { 197 if !dupe.get().allow_duplicate(&node_ref.node) { 198 pr_warn!("BC_REQUEST_FREEZE_NOTIFICATION duplicate cookie\n"); 199 return Err(EINVAL); 200 } 201 } 202 203 // All failure paths must come before this call, and all modifications must come after this 204 // call. 205 node_ref.node.add_freeze_listener(self, GFP_KERNEL)?; 206 207 match freeze_entry { 208 rbtree::Entry::Vacant(entry) => { 209 entry.insert( 210 FreezeListener { 211 cookie, 212 node: node_ref.node.clone(), 213 last_is_frozen: None, 214 is_pending: false, 215 is_clearing: false, 216 num_pending_duplicates: 0, 217 num_cleared_duplicates: 0, 218 }, 219 alloc, 220 ); 221 } 222 rbtree::Entry::Occupied(mut dupe) => { 223 let dupe = dupe.get_mut(); 224 if dupe.is_pending { 225 dupe.num_pending_duplicates += 1; 226 } else { 227 dupe.num_cleared_duplicates += 1; 228 } 229 dupe.last_is_frozen = None; 230 dupe.is_pending = false; 231 dupe.is_clearing = false; 232 } 233 } 234 235 *info.freeze() = Some(cookie); 236 let msg = FreezeMessage::init(msg, cookie); 237 drop(node_refs_guard); 238 let _ = self.push_work(msg); 239 Ok(()) 240 } 241 freeze_notif_done(self: &Arc<Self>, reader: &mut UserSliceReader) -> Result<()>242 pub(crate) fn freeze_notif_done(self: &Arc<Self>, reader: &mut UserSliceReader) -> Result<()> { 243 let cookie = FreezeCookie(reader.read()?); 244 let alloc = FreezeMessage::new(GFP_KERNEL)?; 245 let mut node_refs_guard = self.node_refs.lock(); 246 let node_refs = &mut *node_refs_guard; 247 let Some(freeze) = node_refs.freeze_listeners.get_mut(&cookie) else { 248 pr_warn!("BC_FREEZE_NOTIFICATION_DONE {:016x} not found\n", cookie.0); 249 return Err(EINVAL); 250 }; 251 let mut clear_msg = None; 252 if freeze.num_pending_duplicates > 0 { 253 clear_msg = Some(FreezeMessage::init(alloc, cookie)); 254 freeze.num_pending_duplicates -= 1; 255 freeze.num_cleared_duplicates += 1; 256 } else { 257 if !freeze.is_pending { 258 pr_warn!( 259 "BC_FREEZE_NOTIFICATION_DONE {:016x} not pending\n", 260 cookie.0 261 ); 262 return Err(EINVAL); 263 } 264 let is_frozen = freeze.node.owner.inner.lock().is_frozen.is_fully_frozen(); 265 if freeze.is_clearing || freeze.last_is_frozen != Some(is_frozen) { 266 // Immediately send another FreezeMessage. 267 clear_msg = Some(FreezeMessage::init(alloc, cookie)); 268 } 269 freeze.is_pending = false; 270 } 271 drop(node_refs_guard); 272 if let Some(clear_msg) = clear_msg { 273 let _ = self.push_work(clear_msg); 274 } 275 Ok(()) 276 } 277 clear_freeze_notif(self: &Arc<Self>, reader: &mut UserSliceReader) -> Result<()>278 pub(crate) fn clear_freeze_notif(self: &Arc<Self>, reader: &mut UserSliceReader) -> Result<()> { 279 let hc = reader.read::<BinderHandleCookie>()?; 280 let handle = hc.handle; 281 let cookie = FreezeCookie(hc.cookie); 282 283 let alloc = FreezeMessage::new(GFP_KERNEL)?; 284 let mut node_refs_guard = self.node_refs.lock(); 285 let node_refs = &mut *node_refs_guard; 286 let Some(info) = node_refs.by_handle.get_mut(&handle) else { 287 pr_warn!("BC_CLEAR_FREEZE_NOTIFICATION invalid ref {}\n", handle); 288 return Err(EINVAL); 289 }; 290 let Some(info_cookie) = info.freeze() else { 291 pr_warn!("BC_CLEAR_FREEZE_NOTIFICATION freeze notification not active\n"); 292 return Err(EINVAL); 293 }; 294 if *info_cookie != cookie { 295 pr_warn!("BC_CLEAR_FREEZE_NOTIFICATION freeze notification cookie mismatch\n"); 296 return Err(EINVAL); 297 } 298 let Some(listener) = node_refs.freeze_listeners.get_mut(&cookie) else { 299 pr_warn!("BC_CLEAR_FREEZE_NOTIFICATION invalid cookie {}\n", handle); 300 return Err(EINVAL); 301 }; 302 listener.is_clearing = true; 303 listener.node.remove_freeze_listener(self); 304 *info.freeze() = None; 305 let mut msg = None; 306 if !listener.is_pending { 307 msg = Some(FreezeMessage::init(alloc, cookie)); 308 } 309 drop(node_refs_guard); 310 311 if let Some(msg) = msg { 312 let _ = self.push_work(msg); 313 } 314 Ok(()) 315 } 316 get_freeze_cookie(&self, node: &DArc<Node>) -> Option<FreezeCookie>317 fn get_freeze_cookie(&self, node: &DArc<Node>) -> Option<FreezeCookie> { 318 let node_refs = &mut *self.node_refs.lock(); 319 let handle = node_refs.by_node.get(&node.global_id())?; 320 let node_ref = node_refs.by_handle.get_mut(handle)?; 321 *node_ref.freeze() 322 } 323 324 /// Creates a vector of every freeze listener on this process. 325 /// 326 /// Returns pairs of the remote process listening for notifications and the local node it is 327 /// listening on. 328 #[expect(clippy::type_complexity)] find_freeze_recipients(&self) -> Result<KVVec<(DArc<Node>, Arc<Process>)>, AllocError>329 fn find_freeze_recipients(&self) -> Result<KVVec<(DArc<Node>, Arc<Process>)>, AllocError> { 330 // Defined before `inner` to drop after releasing spinlock if `push_within_capacity` fails. 331 let mut node_proc_pair; 332 333 // We pre-allocate space for up to 8 recipients before we take the spinlock. However, if 334 // the allocation fails, use a vector with a capacity of zero instead of failing. After 335 // all, there might not be any freeze listeners, in which case this operation could still 336 // succeed. 337 let mut recipients = 338 KVVec::with_capacity(8, GFP_KERNEL).unwrap_or_else(|_err| KVVec::new()); 339 340 let mut inner = self.lock_with_nodes(); 341 let mut curr = inner.nodes.cursor_front_mut(); 342 while let Some(cursor) = curr { 343 let (key, node) = cursor.current(); 344 let key = *key; 345 let list = node.freeze_list(&inner.inner); 346 let len = list.len(); 347 348 if recipients.spare_capacity_mut().len() < len { 349 drop(inner); 350 recipients.reserve(len, GFP_KERNEL)?; 351 inner = self.lock_with_nodes(); 352 // Find the node we were looking at and try again. If the set of nodes was changed, 353 // then just proceed to the next node. This is ok because we don't guarantee the 354 // inclusion of nodes that are added or removed in parallel with this operation. 355 curr = inner.nodes.cursor_lower_bound_mut(&key); 356 continue; 357 } 358 359 for proc in list { 360 node_proc_pair = (node.clone(), proc.clone()); 361 recipients 362 .push_within_capacity(node_proc_pair) 363 .map_err(|_| { 364 pr_err!( 365 "push_within_capacity failed even though we checked the capacity\n" 366 ); 367 AllocError 368 })?; 369 } 370 371 curr = cursor.move_next(); 372 } 373 Ok(recipients) 374 } 375 376 /// Prepare allocations for sending freeze messages. prepare_freeze_messages(&self) -> Result<FreezeMessages, AllocError>377 pub(crate) fn prepare_freeze_messages(&self) -> Result<FreezeMessages, AllocError> { 378 let recipients = self.find_freeze_recipients()?; 379 let mut batch = KVVec::with_capacity(recipients.len(), GFP_KERNEL)?; 380 for (node, proc) in recipients { 381 let Some(cookie) = proc.get_freeze_cookie(&node) else { 382 // If the freeze listener was removed in the meantime, just discard the 383 // notification. 384 continue; 385 }; 386 let msg_alloc = FreezeMessage::new(GFP_KERNEL)?; 387 let msg = FreezeMessage::init(msg_alloc, cookie); 388 batch.push((proc, msg), GFP_KERNEL)?; 389 } 390 391 Ok(FreezeMessages { batch }) 392 } 393 } 394 395 pub(crate) struct FreezeMessages { 396 batch: KVVec<(Arc<Process>, DLArc<FreezeMessage>)>, 397 } 398 399 impl FreezeMessages { send_messages(self)400 pub(crate) fn send_messages(self) { 401 for (proc, msg) in self.batch { 402 let _ = proc.push_work(msg); 403 } 404 } 405 } 406