rust_binder: report freeze notification only when fully frozen

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>
Acked-by: Carlos Llamas <cmllamas@google.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by Alice Ryhl and committed by Greg Kroah-Hartman b5ce7a5c 99559e5b

+42 -14
+2 -2
drivers/android/binder/freeze.rs
··· 121 121 writer.write_payload(&self.cookie.0)?; 122 122 Ok(true) 123 123 } else { 124 - let is_frozen = freeze.node.owner.inner.lock().is_frozen; 124 + let is_frozen = freeze.node.owner.inner.lock().is_frozen.is_fully_frozen(); 125 125 if freeze.last_is_frozen == Some(is_frozen) { 126 126 return Ok(true); 127 127 } ··· 254 254 ); 255 255 return Err(EINVAL); 256 256 } 257 - let is_frozen = freeze.node.owner.inner.lock().is_frozen; 257 + let is_frozen = freeze.node.owner.inner.lock().is_frozen.is_fully_frozen(); 258 258 if freeze.is_clearing || freeze.last_is_frozen != Some(is_frozen) { 259 259 // Immediately send another FreezeMessage. 260 260 clear_msg = Some(FreezeMessage::init(alloc, cookie));
+37 -9
drivers/android/binder/process.rs
··· 72 72 const PROC_DEFER_FLUSH: u8 = 1; 73 73 const PROC_DEFER_RELEASE: u8 = 2; 74 74 75 + #[derive(Copy, Clone)] 76 + pub(crate) enum IsFrozen { 77 + Yes, 78 + No, 79 + InProgress, 80 + } 81 + 82 + impl IsFrozen { 83 + /// Whether incoming transactions should be rejected due to freeze. 84 + pub(crate) fn is_frozen(self) -> bool { 85 + match self { 86 + IsFrozen::Yes => true, 87 + IsFrozen::No => false, 88 + IsFrozen::InProgress => true, 89 + } 90 + } 91 + 92 + /// Whether freeze notifications consider this process frozen. 93 + pub(crate) fn is_fully_frozen(self) -> bool { 94 + match self { 95 + IsFrozen::Yes => true, 96 + IsFrozen::No => false, 97 + IsFrozen::InProgress => false, 98 + } 99 + } 100 + } 101 + 75 102 /// The fields of `Process` protected by the spinlock. 76 103 pub(crate) struct ProcessInner { 77 104 is_manager: bool, ··· 125 98 /// are woken up. 126 99 outstanding_txns: u32, 127 100 /// Process is frozen and unable to service binder transactions. 128 - pub(crate) is_frozen: bool, 101 + pub(crate) is_frozen: IsFrozen, 129 102 /// Process received sync transactions since last frozen. 130 103 pub(crate) sync_recv: bool, 131 104 /// Process received async transactions since last frozen. ··· 151 124 started_thread_count: 0, 152 125 defer_work: 0, 153 126 outstanding_txns: 0, 154 - is_frozen: false, 127 + is_frozen: IsFrozen::No, 155 128 sync_recv: false, 156 129 async_recv: false, 157 130 binderfs_file: None, ··· 1287 1260 let is_manager = { 1288 1261 let mut inner = self.inner.lock(); 1289 1262 inner.is_dead = true; 1290 - inner.is_frozen = false; 1263 + inner.is_frozen = IsFrozen::No; 1291 1264 inner.sync_recv = false; 1292 1265 inner.async_recv = false; 1293 1266 inner.is_manager ··· 1394 1367 return; 1395 1368 } 1396 1369 inner.outstanding_txns -= 1; 1397 - inner.is_frozen && inner.outstanding_txns == 0 1370 + inner.is_frozen.is_frozen() && inner.outstanding_txns == 0 1398 1371 }; 1399 1372 1400 1373 if wake { ··· 1408 1381 let mut inner = self.inner.lock(); 1409 1382 inner.sync_recv = false; 1410 1383 inner.async_recv = false; 1411 - inner.is_frozen = false; 1384 + inner.is_frozen = IsFrozen::No; 1412 1385 drop(inner); 1413 1386 msgs.send_messages(); 1414 1387 return Ok(()); ··· 1417 1390 let mut inner = self.inner.lock(); 1418 1391 inner.sync_recv = false; 1419 1392 inner.async_recv = false; 1420 - inner.is_frozen = true; 1393 + inner.is_frozen = IsFrozen::InProgress; 1421 1394 1422 1395 if info.timeout_ms > 0 { 1423 1396 let mut jiffies = kernel::time::msecs_to_jiffies(info.timeout_ms); ··· 1431 1404 .wait_interruptible_timeout(&mut inner, jiffies) 1432 1405 { 1433 1406 CondVarTimeoutResult::Signal { .. } => { 1434 - inner.is_frozen = false; 1407 + inner.is_frozen = IsFrozen::No; 1435 1408 return Err(ERESTARTSYS); 1436 1409 } 1437 1410 CondVarTimeoutResult::Woken { jiffies: remaining } => { ··· 1445 1418 } 1446 1419 1447 1420 if inner.txns_pending_locked() { 1448 - inner.is_frozen = false; 1421 + inner.is_frozen = IsFrozen::No; 1449 1422 Err(EAGAIN) 1450 1423 } else { 1451 1424 drop(inner); 1452 1425 match self.prepare_freeze_messages() { 1453 1426 Ok(batch) => { 1427 + self.inner.lock().is_frozen = IsFrozen::Yes; 1454 1428 batch.send_messages(); 1455 1429 Ok(()) 1456 1430 } 1457 1431 Err(kernel::alloc::AllocError) => { 1458 - self.inner.lock().is_frozen = false; 1432 + self.inner.lock().is_frozen = IsFrozen::No; 1459 1433 Err(ENOMEM) 1460 1434 } 1461 1435 }
+3 -3
drivers/android/binder/transaction.rs
··· 249 249 250 250 if oneway { 251 251 if let Some(target_node) = self.target_node.clone() { 252 - if process_inner.is_frozen { 252 + if process_inner.is_frozen.is_frozen() { 253 253 process_inner.async_recv = true; 254 254 if self.flags & TF_UPDATE_TXN != 0 { 255 255 if let Some(t_outdated) = ··· 270 270 } 271 271 } 272 272 273 - if process_inner.is_frozen { 273 + if process_inner.is_frozen.is_frozen() { 274 274 return Err(BinderError::new_frozen_oneway()); 275 275 } else { 276 276 return Ok(()); ··· 280 280 } 281 281 } 282 282 283 - if process_inner.is_frozen { 283 + if process_inner.is_frozen.is_frozen() { 284 284 process_inner.sync_recv = true; 285 285 return Err(BinderError::new_frozen()); 286 286 }