Skip to content

Commit b5ce7a5

Browse files
Darksonngregkh
authored andcommitted
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 <[email protected]> Acked-by: Carlos Llamas <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent 99559e5 commit b5ce7a5

File tree

3 files changed

+42
-14
lines changed

3 files changed

+42
-14
lines changed

drivers/android/binder/freeze.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ impl DeliverToRead for FreezeMessage {
121121
writer.write_payload(&self.cookie.0)?;
122122
Ok(true)
123123
} 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();
125125
if freeze.last_is_frozen == Some(is_frozen) {
126126
return Ok(true);
127127
}
@@ -254,7 +254,7 @@ impl Process {
254254
);
255255
return Err(EINVAL);
256256
}
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();
258258
if freeze.is_clearing || freeze.last_is_frozen != Some(is_frozen) {
259259
// Immediately send another FreezeMessage.
260260
clear_msg = Some(FreezeMessage::init(alloc, cookie));

drivers/android/binder/process.rs

Lines changed: 37 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,33 @@ impl Mapping {
7272
const PROC_DEFER_FLUSH: u8 = 1;
7373
const PROC_DEFER_RELEASE: u8 = 2;
7474

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+
75102
/// The fields of `Process` protected by the spinlock.
76103
pub(crate) struct ProcessInner {
77104
is_manager: bool,
@@ -98,7 +125,7 @@ pub(crate) struct ProcessInner {
98125
/// are woken up.
99126
outstanding_txns: u32,
100127
/// Process is frozen and unable to service binder transactions.
101-
pub(crate) is_frozen: bool,
128+
pub(crate) is_frozen: IsFrozen,
102129
/// Process received sync transactions since last frozen.
103130
pub(crate) sync_recv: bool,
104131
/// Process received async transactions since last frozen.
@@ -124,7 +151,7 @@ impl ProcessInner {
124151
started_thread_count: 0,
125152
defer_work: 0,
126153
outstanding_txns: 0,
127-
is_frozen: false,
154+
is_frozen: IsFrozen::No,
128155
sync_recv: false,
129156
async_recv: false,
130157
binderfs_file: None,
@@ -1260,7 +1287,7 @@ impl Process {
12601287
let is_manager = {
12611288
let mut inner = self.inner.lock();
12621289
inner.is_dead = true;
1263-
inner.is_frozen = false;
1290+
inner.is_frozen = IsFrozen::No;
12641291
inner.sync_recv = false;
12651292
inner.async_recv = false;
12661293
inner.is_manager
@@ -1367,7 +1394,7 @@ impl Process {
13671394
return;
13681395
}
13691396
inner.outstanding_txns -= 1;
1370-
inner.is_frozen && inner.outstanding_txns == 0
1397+
inner.is_frozen.is_frozen() && inner.outstanding_txns == 0
13711398
};
13721399

13731400
if wake {
@@ -1381,7 +1408,7 @@ impl Process {
13811408
let mut inner = self.inner.lock();
13821409
inner.sync_recv = false;
13831410
inner.async_recv = false;
1384-
inner.is_frozen = false;
1411+
inner.is_frozen = IsFrozen::No;
13851412
drop(inner);
13861413
msgs.send_messages();
13871414
return Ok(());
@@ -1390,7 +1417,7 @@ impl Process {
13901417
let mut inner = self.inner.lock();
13911418
inner.sync_recv = false;
13921419
inner.async_recv = false;
1393-
inner.is_frozen = true;
1420+
inner.is_frozen = IsFrozen::InProgress;
13941421

13951422
if info.timeout_ms > 0 {
13961423
let mut jiffies = kernel::time::msecs_to_jiffies(info.timeout_ms);
@@ -1404,7 +1431,7 @@ impl Process {
14041431
.wait_interruptible_timeout(&mut inner, jiffies)
14051432
{
14061433
CondVarTimeoutResult::Signal { .. } => {
1407-
inner.is_frozen = false;
1434+
inner.is_frozen = IsFrozen::No;
14081435
return Err(ERESTARTSYS);
14091436
}
14101437
CondVarTimeoutResult::Woken { jiffies: remaining } => {
@@ -1418,17 +1445,18 @@ impl Process {
14181445
}
14191446

14201447
if inner.txns_pending_locked() {
1421-
inner.is_frozen = false;
1448+
inner.is_frozen = IsFrozen::No;
14221449
Err(EAGAIN)
14231450
} else {
14241451
drop(inner);
14251452
match self.prepare_freeze_messages() {
14261453
Ok(batch) => {
1454+
self.inner.lock().is_frozen = IsFrozen::Yes;
14271455
batch.send_messages();
14281456
Ok(())
14291457
}
14301458
Err(kernel::alloc::AllocError) => {
1431-
self.inner.lock().is_frozen = false;
1459+
self.inner.lock().is_frozen = IsFrozen::No;
14321460
Err(ENOMEM)
14331461
}
14341462
}

drivers/android/binder/transaction.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -249,7 +249,7 @@ impl Transaction {
249249

250250
if oneway {
251251
if let Some(target_node) = self.target_node.clone() {
252-
if process_inner.is_frozen {
252+
if process_inner.is_frozen.is_frozen() {
253253
process_inner.async_recv = true;
254254
if self.flags & TF_UPDATE_TXN != 0 {
255255
if let Some(t_outdated) =
@@ -270,7 +270,7 @@ impl Transaction {
270270
}
271271
}
272272

273-
if process_inner.is_frozen {
273+
if process_inner.is_frozen.is_frozen() {
274274
return Err(BinderError::new_frozen_oneway());
275275
} else {
276276
return Ok(());
@@ -280,7 +280,7 @@ impl Transaction {
280280
}
281281
}
282282

283-
if process_inner.is_frozen {
283+
if process_inner.is_frozen.is_frozen() {
284284
process_inner.sync_recv = true;
285285
return Err(BinderError::new_frozen());
286286
}

0 commit comments

Comments
 (0)