freeze.rs 14 KB

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