Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/drivers/android/binder/thread.rs
49892 views
1
// SPDX-License-Identifier: GPL-2.0
2
3
// Copyright (C) 2025 Google LLC.
4
5
//! This module defines the `Thread` type, which represents a userspace thread that is using
6
//! binder.
7
//!
8
//! The `Process` object stores all of the threads in an rb tree.
9
10
use kernel::{
11
bindings,
12
fs::{File, LocalFile},
13
list::{AtomicTracker, List, ListArc, ListLinks, TryNewListArc},
14
prelude::*,
15
security,
16
seq_file::SeqFile,
17
seq_print,
18
sync::poll::{PollCondVar, PollTable},
19
sync::{Arc, SpinLock},
20
task::Task,
21
types::ARef,
22
uaccess::UserSlice,
23
uapi,
24
};
25
26
use crate::{
27
allocation::{Allocation, AllocationView, BinderObject, BinderObjectRef, NewAllocation},
28
defs::*,
29
error::BinderResult,
30
process::{GetWorkOrRegister, Process},
31
ptr_align,
32
stats::GLOBAL_STATS,
33
transaction::Transaction,
34
BinderReturnWriter, DArc, DLArc, DTRWrap, DeliverCode, DeliverToRead,
35
};
36
37
use core::{
38
mem::size_of,
39
sync::atomic::{AtomicU32, Ordering},
40
};
41
42
fn is_aligned(value: usize, to: usize) -> bool {
43
value % to == 0
44
}
45
46
/// Stores the layout of the scatter-gather entries. This is used during the `translate_objects`
47
/// call and is discarded when it returns.
48
struct ScatterGatherState {
49
/// A struct that tracks the amount of unused buffer space.
50
unused_buffer_space: UnusedBufferSpace,
51
/// Scatter-gather entries to copy.
52
sg_entries: KVec<ScatterGatherEntry>,
53
/// Indexes into `sg_entries` corresponding to the last binder_buffer_object that
54
/// was processed and all of its ancestors. The array is in sorted order.
55
ancestors: KVec<usize>,
56
}
57
58
/// This entry specifies an additional buffer that should be copied using the scatter-gather
59
/// mechanism.
60
struct ScatterGatherEntry {
61
/// The index in the offset array of the BINDER_TYPE_PTR that this entry originates from.
62
obj_index: usize,
63
/// Offset in target buffer.
64
offset: usize,
65
/// User address in source buffer.
66
sender_uaddr: usize,
67
/// Number of bytes to copy.
68
length: usize,
69
/// The minimum offset of the next fixup in this buffer.
70
fixup_min_offset: usize,
71
/// The offsets within this buffer that contain pointers which should be translated.
72
pointer_fixups: KVec<PointerFixupEntry>,
73
}
74
75
/// This entry specifies that a fixup should happen at `target_offset` of the
76
/// buffer.
77
enum PointerFixupEntry {
78
/// A fixup for a `binder_buffer_object`.
79
Fixup {
80
/// The translated pointer to write.
81
pointer_value: u64,
82
/// The offset at which the value should be written. The offset is relative
83
/// to the original buffer.
84
target_offset: usize,
85
},
86
/// A skip for a `binder_fd_array_object`.
87
Skip {
88
/// The number of bytes to skip.
89
skip: usize,
90
/// The offset at which the skip should happen. The offset is relative
91
/// to the original buffer.
92
target_offset: usize,
93
},
94
}
95
96
/// Return type of `apply_and_validate_fixup_in_parent`.
97
struct ParentFixupInfo {
98
/// The index of the parent buffer in `sg_entries`.
99
parent_sg_index: usize,
100
/// The number of ancestors of the buffer.
101
///
102
/// The buffer is considered an ancestor of itself, so this is always at
103
/// least one.
104
num_ancestors: usize,
105
/// New value of `fixup_min_offset` if this fixup is applied.
106
new_min_offset: usize,
107
/// The offset of the fixup in the target buffer.
108
target_offset: usize,
109
}
110
111
impl ScatterGatherState {
112
/// Called when a `binder_buffer_object` or `binder_fd_array_object` tries
113
/// to access a region in its parent buffer. These accesses have various
114
/// restrictions, which this method verifies.
115
///
116
/// The `parent_offset` and `length` arguments describe the offset and
117
/// length of the access in the parent buffer.
118
///
119
/// # Detailed restrictions
120
///
121
/// Obviously the fixup must be in-bounds for the parent buffer.
122
///
123
/// For safety reasons, we only allow fixups inside a buffer to happen
124
/// at increasing offsets; additionally, we only allow fixup on the last
125
/// buffer object that was verified, or one of its parents.
126
///
127
/// Example of what is allowed:
128
///
129
/// A
130
/// B (parent = A, offset = 0)
131
/// C (parent = A, offset = 16)
132
/// D (parent = C, offset = 0)
133
/// E (parent = A, offset = 32) // min_offset is 16 (C.parent_offset)
134
///
135
/// Examples of what is not allowed:
136
///
137
/// Decreasing offsets within the same parent:
138
/// A
139
/// C (parent = A, offset = 16)
140
/// B (parent = A, offset = 0) // decreasing offset within A
141
///
142
/// Arcerring to a parent that wasn't the last object or any of its parents:
143
/// A
144
/// B (parent = A, offset = 0)
145
/// C (parent = A, offset = 0)
146
/// C (parent = A, offset = 16)
147
/// D (parent = B, offset = 0) // B is not A or any of A's parents
148
fn validate_parent_fixup(
149
&self,
150
parent: usize,
151
parent_offset: usize,
152
length: usize,
153
) -> Result<ParentFixupInfo> {
154
// Using `position` would also be correct, but `rposition` avoids
155
// quadratic running times.
156
let ancestors_i = self
157
.ancestors
158
.iter()
159
.copied()
160
.rposition(|sg_idx| self.sg_entries[sg_idx].obj_index == parent)
161
.ok_or(EINVAL)?;
162
let sg_idx = self.ancestors[ancestors_i];
163
let sg_entry = match self.sg_entries.get(sg_idx) {
164
Some(sg_entry) => sg_entry,
165
None => {
166
pr_err!(
167
"self.ancestors[{}] is {}, but self.sg_entries.len() is {}",
168
ancestors_i,
169
sg_idx,
170
self.sg_entries.len()
171
);
172
return Err(EINVAL);
173
}
174
};
175
if sg_entry.fixup_min_offset > parent_offset {
176
pr_warn!(
177
"validate_parent_fixup: fixup_min_offset={}, parent_offset={}",
178
sg_entry.fixup_min_offset,
179
parent_offset
180
);
181
return Err(EINVAL);
182
}
183
let new_min_offset = parent_offset.checked_add(length).ok_or(EINVAL)?;
184
if new_min_offset > sg_entry.length {
185
pr_warn!(
186
"validate_parent_fixup: new_min_offset={}, sg_entry.length={}",
187
new_min_offset,
188
sg_entry.length
189
);
190
return Err(EINVAL);
191
}
192
let target_offset = sg_entry.offset.checked_add(parent_offset).ok_or(EINVAL)?;
193
// The `ancestors_i + 1` operation can't overflow since the output of the addition is at
194
// most `self.ancestors.len()`, which also fits in a usize.
195
Ok(ParentFixupInfo {
196
parent_sg_index: sg_idx,
197
num_ancestors: ancestors_i + 1,
198
new_min_offset,
199
target_offset,
200
})
201
}
202
}
203
204
/// Keeps track of how much unused buffer space is left. The initial amount is the number of bytes
205
/// requested by the user using the `buffers_size` field of `binder_transaction_data_sg`. Each time
206
/// we translate an object of type `BINDER_TYPE_PTR`, some of the unused buffer space is consumed.
207
struct UnusedBufferSpace {
208
/// The start of the remaining space.
209
offset: usize,
210
/// The end of the remaining space.
211
limit: usize,
212
}
213
impl UnusedBufferSpace {
214
/// Claim the next `size` bytes from the unused buffer space. The offset for the claimed chunk
215
/// into the buffer is returned.
216
fn claim_next(&mut self, size: usize) -> Result<usize> {
217
// We require every chunk to be aligned.
218
let size = ptr_align(size).ok_or(EINVAL)?;
219
let new_offset = self.offset.checked_add(size).ok_or(EINVAL)?;
220
221
if new_offset <= self.limit {
222
let offset = self.offset;
223
self.offset = new_offset;
224
Ok(offset)
225
} else {
226
Err(EINVAL)
227
}
228
}
229
}
230
231
pub(crate) enum PushWorkRes {
232
Ok,
233
FailedDead(DLArc<dyn DeliverToRead>),
234
}
235
236
impl PushWorkRes {
237
fn is_ok(&self) -> bool {
238
match self {
239
PushWorkRes::Ok => true,
240
PushWorkRes::FailedDead(_) => false,
241
}
242
}
243
}
244
245
/// The fields of `Thread` protected by the spinlock.
246
struct InnerThread {
247
/// Determines the looper state of the thread. It is a bit-wise combination of the constants
248
/// prefixed with `LOOPER_`.
249
looper_flags: u32,
250
251
/// Determines whether the looper should return.
252
looper_need_return: bool,
253
254
/// Determines if thread is dead.
255
is_dead: bool,
256
257
/// Work item used to deliver error codes to the thread that started a transaction. Stored here
258
/// so that it can be reused.
259
reply_work: DArc<ThreadError>,
260
261
/// Work item used to deliver error codes to the current thread. Stored here so that it can be
262
/// reused.
263
return_work: DArc<ThreadError>,
264
265
/// Determines whether the work list below should be processed. When set to false, `work_list`
266
/// is treated as if it were empty.
267
process_work_list: bool,
268
/// List of work items to deliver to userspace.
269
work_list: List<DTRWrap<dyn DeliverToRead>>,
270
current_transaction: Option<DArc<Transaction>>,
271
272
/// Extended error information for this thread.
273
extended_error: ExtendedError,
274
}
275
276
const LOOPER_REGISTERED: u32 = 0x01;
277
const LOOPER_ENTERED: u32 = 0x02;
278
const LOOPER_EXITED: u32 = 0x04;
279
const LOOPER_INVALID: u32 = 0x08;
280
const LOOPER_WAITING: u32 = 0x10;
281
const LOOPER_WAITING_PROC: u32 = 0x20;
282
const LOOPER_POLL: u32 = 0x40;
283
284
impl InnerThread {
285
fn new() -> Result<Self> {
286
fn next_err_id() -> u32 {
287
static EE_ID: AtomicU32 = AtomicU32::new(0);
288
EE_ID.fetch_add(1, Ordering::Relaxed)
289
}
290
291
Ok(Self {
292
looper_flags: 0,
293
looper_need_return: false,
294
is_dead: false,
295
process_work_list: false,
296
reply_work: ThreadError::try_new()?,
297
return_work: ThreadError::try_new()?,
298
work_list: List::new(),
299
current_transaction: None,
300
extended_error: ExtendedError::new(next_err_id(), BR_OK, 0),
301
})
302
}
303
304
fn pop_work(&mut self) -> Option<DLArc<dyn DeliverToRead>> {
305
if !self.process_work_list {
306
return None;
307
}
308
309
let ret = self.work_list.pop_front();
310
self.process_work_list = !self.work_list.is_empty();
311
ret
312
}
313
314
fn push_work(&mut self, work: DLArc<dyn DeliverToRead>) -> PushWorkRes {
315
if self.is_dead {
316
PushWorkRes::FailedDead(work)
317
} else {
318
self.work_list.push_back(work);
319
self.process_work_list = true;
320
PushWorkRes::Ok
321
}
322
}
323
324
fn push_reply_work(&mut self, code: u32) {
325
if let Ok(work) = ListArc::try_from_arc(self.reply_work.clone()) {
326
work.set_error_code(code);
327
self.push_work(work);
328
} else {
329
pr_warn!("Thread reply work is already in use.");
330
}
331
}
332
333
fn push_return_work(&mut self, reply: u32) {
334
if let Ok(work) = ListArc::try_from_arc(self.return_work.clone()) {
335
work.set_error_code(reply);
336
self.push_work(work);
337
} else {
338
pr_warn!("Thread return work is already in use.");
339
}
340
}
341
342
/// Used to push work items that do not need to be processed immediately and can wait until the
343
/// thread gets another work item.
344
fn push_work_deferred(&mut self, work: DLArc<dyn DeliverToRead>) {
345
self.work_list.push_back(work);
346
}
347
348
/// Fetches the transaction this thread can reply to. If the thread has a pending transaction
349
/// (that it could respond to) but it has also issued a transaction, it must first wait for the
350
/// previously-issued transaction to complete.
351
///
352
/// The `thread` parameter should be the thread containing this `ThreadInner`.
353
fn pop_transaction_to_reply(&mut self, thread: &Thread) -> Result<DArc<Transaction>> {
354
let transaction = self.current_transaction.take().ok_or(EINVAL)?;
355
if core::ptr::eq(thread, transaction.from.as_ref()) {
356
self.current_transaction = Some(transaction);
357
return Err(EINVAL);
358
}
359
// Find a new current transaction for this thread.
360
self.current_transaction = transaction.find_from(thread).cloned();
361
Ok(transaction)
362
}
363
364
fn pop_transaction_replied(&mut self, transaction: &DArc<Transaction>) -> bool {
365
match self.current_transaction.take() {
366
None => false,
367
Some(old) => {
368
if !Arc::ptr_eq(transaction, &old) {
369
self.current_transaction = Some(old);
370
return false;
371
}
372
self.current_transaction = old.clone_next();
373
true
374
}
375
}
376
}
377
378
fn looper_enter(&mut self) {
379
self.looper_flags |= LOOPER_ENTERED;
380
if self.looper_flags & LOOPER_REGISTERED != 0 {
381
self.looper_flags |= LOOPER_INVALID;
382
}
383
}
384
385
fn looper_register(&mut self, valid: bool) {
386
self.looper_flags |= LOOPER_REGISTERED;
387
if !valid || self.looper_flags & LOOPER_ENTERED != 0 {
388
self.looper_flags |= LOOPER_INVALID;
389
}
390
}
391
392
fn looper_exit(&mut self) {
393
self.looper_flags |= LOOPER_EXITED;
394
}
395
396
/// Determines whether the thread is part of a pool, i.e., if it is a looper.
397
fn is_looper(&self) -> bool {
398
self.looper_flags & (LOOPER_ENTERED | LOOPER_REGISTERED) != 0
399
}
400
401
/// Determines whether the thread should attempt to fetch work items from the process queue.
402
/// This is generally case when the thread is registered as a looper and not part of a
403
/// transaction stack. But if there is local work, we want to return to userspace before we
404
/// deliver any remote work.
405
fn should_use_process_work_queue(&self) -> bool {
406
self.current_transaction.is_none() && !self.process_work_list && self.is_looper()
407
}
408
409
fn poll(&mut self) -> u32 {
410
self.looper_flags |= LOOPER_POLL;
411
if self.process_work_list || self.looper_need_return {
412
bindings::POLLIN
413
} else {
414
0
415
}
416
}
417
}
418
419
/// This represents a thread that's used with binder.
420
#[pin_data]
421
pub(crate) struct Thread {
422
pub(crate) id: i32,
423
pub(crate) process: Arc<Process>,
424
pub(crate) task: ARef<Task>,
425
#[pin]
426
inner: SpinLock<InnerThread>,
427
#[pin]
428
work_condvar: PollCondVar,
429
/// Used to insert this thread into the process' `ready_threads` list.
430
///
431
/// INVARIANT: May never be used for any other list than the `self.process.ready_threads`.
432
#[pin]
433
links: ListLinks,
434
#[pin]
435
links_track: AtomicTracker,
436
}
437
438
kernel::list::impl_list_arc_safe! {
439
impl ListArcSafe<0> for Thread {
440
tracked_by links_track: AtomicTracker;
441
}
442
}
443
kernel::list::impl_list_item! {
444
impl ListItem<0> for Thread {
445
using ListLinks { self.links };
446
}
447
}
448
449
impl Thread {
450
pub(crate) fn new(id: i32, process: Arc<Process>) -> Result<Arc<Self>> {
451
let inner = InnerThread::new()?;
452
453
Arc::pin_init(
454
try_pin_init!(Thread {
455
id,
456
process,
457
task: ARef::from(&**kernel::current!()),
458
inner <- kernel::new_spinlock!(inner, "Thread::inner"),
459
work_condvar <- kernel::new_poll_condvar!("Thread::work_condvar"),
460
links <- ListLinks::new(),
461
links_track <- AtomicTracker::new(),
462
}),
463
GFP_KERNEL,
464
)
465
}
466
467
#[inline(never)]
468
pub(crate) fn debug_print(self: &Arc<Self>, m: &SeqFile, print_all: bool) -> Result<()> {
469
let inner = self.inner.lock();
470
471
if print_all || inner.current_transaction.is_some() || !inner.work_list.is_empty() {
472
seq_print!(
473
m,
474
" thread {}: l {:02x} need_return {}\n",
475
self.id,
476
inner.looper_flags,
477
inner.looper_need_return,
478
);
479
}
480
481
let mut t_opt = inner.current_transaction.as_ref();
482
while let Some(t) = t_opt {
483
if Arc::ptr_eq(&t.from, self) {
484
t.debug_print_inner(m, " outgoing transaction ");
485
t_opt = t.from_parent.as_ref();
486
} else if Arc::ptr_eq(&t.to, &self.process) {
487
t.debug_print_inner(m, " incoming transaction ");
488
t_opt = t.find_from(self);
489
} else {
490
t.debug_print_inner(m, " bad transaction ");
491
t_opt = None;
492
}
493
}
494
495
for work in &inner.work_list {
496
work.debug_print(m, " ", " pending transaction ")?;
497
}
498
Ok(())
499
}
500
501
pub(crate) fn get_extended_error(&self, data: UserSlice) -> Result {
502
let mut writer = data.writer();
503
let ee = self.inner.lock().extended_error;
504
writer.write(&ee)?;
505
Ok(())
506
}
507
508
pub(crate) fn set_current_transaction(&self, transaction: DArc<Transaction>) {
509
self.inner.lock().current_transaction = Some(transaction);
510
}
511
512
pub(crate) fn has_current_transaction(&self) -> bool {
513
self.inner.lock().current_transaction.is_some()
514
}
515
516
/// Attempts to fetch a work item from the thread-local queue. The behaviour if the queue is
517
/// empty depends on `wait`: if it is true, the function waits for some work to be queued (or a
518
/// signal); otherwise it returns indicating that none is available.
519
fn get_work_local(self: &Arc<Self>, wait: bool) -> Result<Option<DLArc<dyn DeliverToRead>>> {
520
{
521
let mut inner = self.inner.lock();
522
if inner.looper_need_return {
523
return Ok(inner.pop_work());
524
}
525
}
526
527
// Try once if the caller does not want to wait.
528
if !wait {
529
return self.inner.lock().pop_work().ok_or(EAGAIN).map(Some);
530
}
531
532
// Loop waiting only on the local queue (i.e., not registering with the process queue).
533
let mut inner = self.inner.lock();
534
loop {
535
if let Some(work) = inner.pop_work() {
536
return Ok(Some(work));
537
}
538
539
inner.looper_flags |= LOOPER_WAITING;
540
let signal_pending = self.work_condvar.wait_interruptible_freezable(&mut inner);
541
inner.looper_flags &= !LOOPER_WAITING;
542
543
if signal_pending {
544
return Err(EINTR);
545
}
546
if inner.looper_need_return {
547
return Ok(None);
548
}
549
}
550
}
551
552
/// Attempts to fetch a work item from the thread-local queue, falling back to the process-wide
553
/// queue if none is available locally.
554
///
555
/// This must only be called when the thread is not participating in a transaction chain. If it
556
/// is, the local version (`get_work_local`) should be used instead.
557
fn get_work(self: &Arc<Self>, wait: bool) -> Result<Option<DLArc<dyn DeliverToRead>>> {
558
// Try to get work from the thread's work queue, using only a local lock.
559
{
560
let mut inner = self.inner.lock();
561
if let Some(work) = inner.pop_work() {
562
return Ok(Some(work));
563
}
564
if inner.looper_need_return {
565
drop(inner);
566
return Ok(self.process.get_work());
567
}
568
}
569
570
// If the caller doesn't want to wait, try to grab work from the process queue.
571
//
572
// We know nothing will have been queued directly to the thread queue because it is not in
573
// a transaction and it is not in the process' ready list.
574
if !wait {
575
return self.process.get_work().ok_or(EAGAIN).map(Some);
576
}
577
578
// Get work from the process queue. If none is available, atomically register as ready.
579
let reg = match self.process.get_work_or_register(self) {
580
GetWorkOrRegister::Work(work) => return Ok(Some(work)),
581
GetWorkOrRegister::Register(reg) => reg,
582
};
583
584
let mut inner = self.inner.lock();
585
loop {
586
if let Some(work) = inner.pop_work() {
587
return Ok(Some(work));
588
}
589
590
inner.looper_flags |= LOOPER_WAITING | LOOPER_WAITING_PROC;
591
let signal_pending = self.work_condvar.wait_interruptible_freezable(&mut inner);
592
inner.looper_flags &= !(LOOPER_WAITING | LOOPER_WAITING_PROC);
593
594
if signal_pending || inner.looper_need_return {
595
// We need to return now. We need to pull the thread off the list of ready threads
596
// (by dropping `reg`), then check the state again after it's off the list to
597
// ensure that something was not queued in the meantime. If something has been
598
// queued, we just return it (instead of the error).
599
drop(inner);
600
drop(reg);
601
602
let res = match self.inner.lock().pop_work() {
603
Some(work) => Ok(Some(work)),
604
None if signal_pending => Err(EINTR),
605
None => Ok(None),
606
};
607
return res;
608
}
609
}
610
}
611
612
/// Push the provided work item to be delivered to user space via this thread.
613
///
614
/// Returns whether the item was successfully pushed. This can only fail if the thread is dead.
615
pub(crate) fn push_work(&self, work: DLArc<dyn DeliverToRead>) -> PushWorkRes {
616
let sync = work.should_sync_wakeup();
617
618
let res = self.inner.lock().push_work(work);
619
620
if res.is_ok() {
621
if sync {
622
self.work_condvar.notify_sync();
623
} else {
624
self.work_condvar.notify_one();
625
}
626
}
627
628
res
629
}
630
631
/// Attempts to push to given work item to the thread if it's a looper thread (i.e., if it's
632
/// part of a thread pool) and is alive. Otherwise, push the work item to the process instead.
633
pub(crate) fn push_work_if_looper(&self, work: DLArc<dyn DeliverToRead>) -> BinderResult {
634
let mut inner = self.inner.lock();
635
if inner.is_looper() && !inner.is_dead {
636
inner.push_work(work);
637
Ok(())
638
} else {
639
drop(inner);
640
self.process.push_work(work)
641
}
642
}
643
644
pub(crate) fn push_work_deferred(&self, work: DLArc<dyn DeliverToRead>) {
645
self.inner.lock().push_work_deferred(work);
646
}
647
648
pub(crate) fn push_return_work(&self, reply: u32) {
649
self.inner.lock().push_return_work(reply);
650
}
651
652
fn translate_object(
653
&self,
654
obj_index: usize,
655
offset: usize,
656
object: BinderObjectRef<'_>,
657
view: &mut AllocationView<'_>,
658
allow_fds: bool,
659
sg_state: &mut ScatterGatherState,
660
) -> BinderResult {
661
match object {
662
BinderObjectRef::Binder(obj) => {
663
let strong = obj.hdr.type_ == BINDER_TYPE_BINDER;
664
// SAFETY: `binder` is a `binder_uintptr_t`; any bit pattern is a valid
665
// representation.
666
let ptr = unsafe { obj.__bindgen_anon_1.binder } as _;
667
let cookie = obj.cookie as _;
668
let flags = obj.flags as _;
669
let node = self
670
.process
671
.as_arc_borrow()
672
.get_node(ptr, cookie, flags, strong, self)?;
673
security::binder_transfer_binder(&self.process.cred, &view.alloc.process.cred)?;
674
view.transfer_binder_object(offset, obj, strong, node)?;
675
}
676
BinderObjectRef::Handle(obj) => {
677
let strong = obj.hdr.type_ == BINDER_TYPE_HANDLE;
678
// SAFETY: `handle` is a `u32`; any bit pattern is a valid representation.
679
let handle = unsafe { obj.__bindgen_anon_1.handle } as _;
680
let node = self.process.get_node_from_handle(handle, strong)?;
681
security::binder_transfer_binder(&self.process.cred, &view.alloc.process.cred)?;
682
view.transfer_binder_object(offset, obj, strong, node)?;
683
}
684
BinderObjectRef::Fd(obj) => {
685
if !allow_fds {
686
return Err(EPERM.into());
687
}
688
689
// SAFETY: `fd` is a `u32`; any bit pattern is a valid representation.
690
let fd = unsafe { obj.__bindgen_anon_1.fd };
691
let file = LocalFile::fget(fd)?;
692
// SAFETY: The binder driver never calls `fdget_pos` and this code runs from an
693
// ioctl, so there are no active calls to `fdget_pos` on this thread.
694
let file = unsafe { LocalFile::assume_no_fdget_pos(file) };
695
security::binder_transfer_file(
696
&self.process.cred,
697
&view.alloc.process.cred,
698
&file,
699
)?;
700
701
let mut obj_write = BinderFdObject::default();
702
obj_write.hdr.type_ = BINDER_TYPE_FD;
703
// This will be overwritten with the actual fd when the transaction is received.
704
obj_write.__bindgen_anon_1.fd = u32::MAX;
705
obj_write.cookie = obj.cookie;
706
view.write::<BinderFdObject>(offset, &obj_write)?;
707
708
const FD_FIELD_OFFSET: usize =
709
core::mem::offset_of!(uapi::binder_fd_object, __bindgen_anon_1.fd);
710
711
let field_offset = offset + FD_FIELD_OFFSET;
712
713
view.alloc.info_add_fd(file, field_offset, false)?;
714
}
715
BinderObjectRef::Ptr(obj) => {
716
let obj_length = obj.length.try_into().map_err(|_| EINVAL)?;
717
let alloc_offset = match sg_state.unused_buffer_space.claim_next(obj_length) {
718
Ok(alloc_offset) => alloc_offset,
719
Err(err) => {
720
pr_warn!(
721
"Failed to claim space for a BINDER_TYPE_PTR. (offset: {}, limit: {}, size: {})",
722
sg_state.unused_buffer_space.offset,
723
sg_state.unused_buffer_space.limit,
724
obj_length,
725
);
726
return Err(err.into());
727
}
728
};
729
730
let sg_state_idx = sg_state.sg_entries.len();
731
sg_state.sg_entries.push(
732
ScatterGatherEntry {
733
obj_index,
734
offset: alloc_offset,
735
sender_uaddr: obj.buffer as _,
736
length: obj_length,
737
pointer_fixups: KVec::new(),
738
fixup_min_offset: 0,
739
},
740
GFP_KERNEL,
741
)?;
742
743
let buffer_ptr_in_user_space = (view.alloc.ptr + alloc_offset) as u64;
744
745
if obj.flags & uapi::BINDER_BUFFER_FLAG_HAS_PARENT == 0 {
746
sg_state.ancestors.clear();
747
sg_state.ancestors.push(sg_state_idx, GFP_KERNEL)?;
748
} else {
749
// Another buffer also has a pointer to this buffer, and we need to fixup that
750
// pointer too.
751
752
let parent_index = usize::try_from(obj.parent).map_err(|_| EINVAL)?;
753
let parent_offset = usize::try_from(obj.parent_offset).map_err(|_| EINVAL)?;
754
755
let info = sg_state.validate_parent_fixup(
756
parent_index,
757
parent_offset,
758
size_of::<u64>(),
759
)?;
760
761
sg_state.ancestors.truncate(info.num_ancestors);
762
sg_state.ancestors.push(sg_state_idx, GFP_KERNEL)?;
763
764
let parent_entry = match sg_state.sg_entries.get_mut(info.parent_sg_index) {
765
Some(parent_entry) => parent_entry,
766
None => {
767
pr_err!(
768
"validate_parent_fixup returned index out of bounds for sg.entries"
769
);
770
return Err(EINVAL.into());
771
}
772
};
773
774
parent_entry.fixup_min_offset = info.new_min_offset;
775
parent_entry.pointer_fixups.push(
776
PointerFixupEntry::Fixup {
777
pointer_value: buffer_ptr_in_user_space,
778
target_offset: info.target_offset,
779
},
780
GFP_KERNEL,
781
)?;
782
}
783
784
let mut obj_write = BinderBufferObject::default();
785
obj_write.hdr.type_ = BINDER_TYPE_PTR;
786
obj_write.flags = obj.flags;
787
obj_write.buffer = buffer_ptr_in_user_space;
788
obj_write.length = obj.length;
789
obj_write.parent = obj.parent;
790
obj_write.parent_offset = obj.parent_offset;
791
view.write::<BinderBufferObject>(offset, &obj_write)?;
792
}
793
BinderObjectRef::Fda(obj) => {
794
if !allow_fds {
795
return Err(EPERM.into());
796
}
797
let parent_index = usize::try_from(obj.parent).map_err(|_| EINVAL)?;
798
let parent_offset = usize::try_from(obj.parent_offset).map_err(|_| EINVAL)?;
799
let num_fds = usize::try_from(obj.num_fds).map_err(|_| EINVAL)?;
800
let fds_len = num_fds.checked_mul(size_of::<u32>()).ok_or(EINVAL)?;
801
802
if !is_aligned(parent_offset, size_of::<u32>()) {
803
return Err(EINVAL.into());
804
}
805
806
let info = sg_state.validate_parent_fixup(parent_index, parent_offset, fds_len)?;
807
view.alloc.info_add_fd_reserve(num_fds)?;
808
809
sg_state.ancestors.truncate(info.num_ancestors);
810
let parent_entry = match sg_state.sg_entries.get_mut(info.parent_sg_index) {
811
Some(parent_entry) => parent_entry,
812
None => {
813
pr_err!(
814
"validate_parent_fixup returned index out of bounds for sg.entries"
815
);
816
return Err(EINVAL.into());
817
}
818
};
819
820
if !is_aligned(parent_entry.sender_uaddr, size_of::<u32>()) {
821
return Err(EINVAL.into());
822
}
823
824
parent_entry.fixup_min_offset = info.new_min_offset;
825
parent_entry
826
.pointer_fixups
827
.push(
828
PointerFixupEntry::Skip {
829
skip: fds_len,
830
target_offset: info.target_offset,
831
},
832
GFP_KERNEL,
833
)
834
.map_err(|_| ENOMEM)?;
835
836
let fda_uaddr = parent_entry
837
.sender_uaddr
838
.checked_add(parent_offset)
839
.ok_or(EINVAL)?;
840
841
let mut fda_bytes = KVec::new();
842
UserSlice::new(UserPtr::from_addr(fda_uaddr as _), fds_len)
843
.read_all(&mut fda_bytes, GFP_KERNEL)?;
844
845
if fds_len != fda_bytes.len() {
846
pr_err!("UserSlice::read_all returned wrong length in BINDER_TYPE_FDA");
847
return Err(EINVAL.into());
848
}
849
850
for i in (0..fds_len).step_by(size_of::<u32>()) {
851
let fd = {
852
let mut fd_bytes = [0u8; size_of::<u32>()];
853
fd_bytes.copy_from_slice(&fda_bytes[i..i + size_of::<u32>()]);
854
u32::from_ne_bytes(fd_bytes)
855
};
856
857
let file = LocalFile::fget(fd)?;
858
// SAFETY: The binder driver never calls `fdget_pos` and this code runs from an
859
// ioctl, so there are no active calls to `fdget_pos` on this thread.
860
let file = unsafe { LocalFile::assume_no_fdget_pos(file) };
861
security::binder_transfer_file(
862
&self.process.cred,
863
&view.alloc.process.cred,
864
&file,
865
)?;
866
867
// The `validate_parent_fixup` call ensuers that this addition will not
868
// overflow.
869
view.alloc.info_add_fd(file, info.target_offset + i, true)?;
870
}
871
drop(fda_bytes);
872
873
let mut obj_write = BinderFdArrayObject::default();
874
obj_write.hdr.type_ = BINDER_TYPE_FDA;
875
obj_write.num_fds = obj.num_fds;
876
obj_write.parent = obj.parent;
877
obj_write.parent_offset = obj.parent_offset;
878
view.write::<BinderFdArrayObject>(offset, &obj_write)?;
879
}
880
}
881
Ok(())
882
}
883
884
fn apply_sg(&self, alloc: &mut Allocation, sg_state: &mut ScatterGatherState) -> BinderResult {
885
for sg_entry in &mut sg_state.sg_entries {
886
let mut end_of_previous_fixup = sg_entry.offset;
887
let offset_end = sg_entry.offset.checked_add(sg_entry.length).ok_or(EINVAL)?;
888
889
let mut reader =
890
UserSlice::new(UserPtr::from_addr(sg_entry.sender_uaddr), sg_entry.length).reader();
891
for fixup in &mut sg_entry.pointer_fixups {
892
let (fixup_len, fixup_offset) = match fixup {
893
PointerFixupEntry::Fixup { target_offset, .. } => {
894
(size_of::<u64>(), *target_offset)
895
}
896
PointerFixupEntry::Skip {
897
skip,
898
target_offset,
899
} => (*skip, *target_offset),
900
};
901
902
let target_offset_end = fixup_offset.checked_add(fixup_len).ok_or(EINVAL)?;
903
if fixup_offset < end_of_previous_fixup || offset_end < target_offset_end {
904
pr_warn!(
905
"Fixups oob {} {} {} {}",
906
fixup_offset,
907
end_of_previous_fixup,
908
offset_end,
909
target_offset_end
910
);
911
return Err(EINVAL.into());
912
}
913
914
let copy_off = end_of_previous_fixup;
915
let copy_len = fixup_offset - end_of_previous_fixup;
916
if let Err(err) = alloc.copy_into(&mut reader, copy_off, copy_len) {
917
pr_warn!("Failed copying into alloc: {:?}", err);
918
return Err(err.into());
919
}
920
if let PointerFixupEntry::Fixup { pointer_value, .. } = fixup {
921
let res = alloc.write::<u64>(fixup_offset, pointer_value);
922
if let Err(err) = res {
923
pr_warn!("Failed copying ptr into alloc: {:?}", err);
924
return Err(err.into());
925
}
926
}
927
if let Err(err) = reader.skip(fixup_len) {
928
pr_warn!("Failed skipping {} from reader: {:?}", fixup_len, err);
929
return Err(err.into());
930
}
931
end_of_previous_fixup = target_offset_end;
932
}
933
let copy_off = end_of_previous_fixup;
934
let copy_len = offset_end - end_of_previous_fixup;
935
if let Err(err) = alloc.copy_into(&mut reader, copy_off, copy_len) {
936
pr_warn!("Failed copying remainder into alloc: {:?}", err);
937
return Err(err.into());
938
}
939
}
940
Ok(())
941
}
942
943
/// This method copies the payload of a transaction into the target process.
944
///
945
/// The resulting payload will have several different components, which will be stored next to
946
/// each other in the allocation. Furthermore, various objects can be embedded in the payload,
947
/// and those objects have to be translated so that they make sense to the target transaction.
948
pub(crate) fn copy_transaction_data(
949
&self,
950
to_process: Arc<Process>,
951
tr: &BinderTransactionDataSg,
952
debug_id: usize,
953
allow_fds: bool,
954
txn_security_ctx_offset: Option<&mut usize>,
955
) -> BinderResult<NewAllocation> {
956
let trd = &tr.transaction_data;
957
let is_oneway = trd.flags & TF_ONE_WAY != 0;
958
let mut secctx = if let Some(offset) = txn_security_ctx_offset {
959
let secid = self.process.cred.get_secid();
960
let ctx = match security::SecurityCtx::from_secid(secid) {
961
Ok(ctx) => ctx,
962
Err(err) => {
963
pr_warn!("Failed to get security ctx for id {}: {:?}", secid, err);
964
return Err(err.into());
965
}
966
};
967
Some((offset, ctx))
968
} else {
969
None
970
};
971
972
let data_size = trd.data_size.try_into().map_err(|_| EINVAL)?;
973
let aligned_data_size = ptr_align(data_size).ok_or(EINVAL)?;
974
let offsets_size: usize = trd.offsets_size.try_into().map_err(|_| EINVAL)?;
975
let buffers_size: usize = tr.buffers_size.try_into().map_err(|_| EINVAL)?;
976
let aligned_secctx_size = match secctx.as_ref() {
977
Some((_offset, ctx)) => ptr_align(ctx.len()).ok_or(EINVAL)?,
978
None => 0,
979
};
980
981
if !is_aligned(offsets_size, size_of::<u64>()) {
982
return Err(EINVAL.into());
983
}
984
if !is_aligned(buffers_size, size_of::<u64>()) {
985
return Err(EINVAL.into());
986
}
987
988
// This guarantees that at least `sizeof(usize)` bytes will be allocated.
989
let len = usize::max(
990
aligned_data_size
991
.checked_add(offsets_size)
992
.and_then(|sum| sum.checked_add(buffers_size))
993
.and_then(|sum| sum.checked_add(aligned_secctx_size))
994
.ok_or(ENOMEM)?,
995
size_of::<u64>(),
996
);
997
let secctx_off = aligned_data_size + offsets_size + buffers_size;
998
let mut alloc =
999
match to_process.buffer_alloc(debug_id, len, is_oneway, self.process.task.pid()) {
1000
Ok(alloc) => alloc,
1001
Err(err) => {
1002
pr_warn!(
1003
"Failed to allocate buffer. len:{}, is_oneway:{}",
1004
len,
1005
is_oneway
1006
);
1007
return Err(err);
1008
}
1009
};
1010
1011
// SAFETY: This accesses a union field, but it's okay because the field's type is valid for
1012
// all bit-patterns.
1013
let trd_data_ptr = unsafe { &trd.data.ptr };
1014
let mut buffer_reader =
1015
UserSlice::new(UserPtr::from_addr(trd_data_ptr.buffer as _), data_size).reader();
1016
let mut end_of_previous_object = 0;
1017
let mut sg_state = None;
1018
1019
// Copy offsets if there are any.
1020
if offsets_size > 0 {
1021
{
1022
let mut reader =
1023
UserSlice::new(UserPtr::from_addr(trd_data_ptr.offsets as _), offsets_size)
1024
.reader();
1025
alloc.copy_into(&mut reader, aligned_data_size, offsets_size)?;
1026
}
1027
1028
let offsets_start = aligned_data_size;
1029
let offsets_end = aligned_data_size + offsets_size;
1030
1031
// This state is used for BINDER_TYPE_PTR objects.
1032
let sg_state = sg_state.insert(ScatterGatherState {
1033
unused_buffer_space: UnusedBufferSpace {
1034
offset: offsets_end,
1035
limit: offsets_end + buffers_size,
1036
},
1037
sg_entries: KVec::new(),
1038
ancestors: KVec::new(),
1039
});
1040
1041
// Traverse the objects specified.
1042
let mut view = AllocationView::new(&mut alloc, data_size);
1043
for (index, index_offset) in (offsets_start..offsets_end)
1044
.step_by(size_of::<u64>())
1045
.enumerate()
1046
{
1047
let offset: usize = view
1048
.alloc
1049
.read::<u64>(index_offset)?
1050
.try_into()
1051
.map_err(|_| EINVAL)?;
1052
1053
if offset < end_of_previous_object || !is_aligned(offset, size_of::<u32>()) {
1054
pr_warn!("Got transaction with invalid offset.");
1055
return Err(EINVAL.into());
1056
}
1057
1058
// Copy data between two objects.
1059
if end_of_previous_object < offset {
1060
view.copy_into(
1061
&mut buffer_reader,
1062
end_of_previous_object,
1063
offset - end_of_previous_object,
1064
)?;
1065
}
1066
1067
let mut object = BinderObject::read_from(&mut buffer_reader)?;
1068
1069
match self.translate_object(
1070
index,
1071
offset,
1072
object.as_ref(),
1073
&mut view,
1074
allow_fds,
1075
sg_state,
1076
) {
1077
Ok(()) => end_of_previous_object = offset + object.size(),
1078
Err(err) => {
1079
pr_warn!("Error while translating object.");
1080
return Err(err);
1081
}
1082
}
1083
1084
// Update the indexes containing objects to clean up.
1085
let offset_after_object = index_offset + size_of::<u64>();
1086
view.alloc
1087
.set_info_offsets(offsets_start..offset_after_object);
1088
}
1089
}
1090
1091
// Copy remaining raw data.
1092
alloc.copy_into(
1093
&mut buffer_reader,
1094
end_of_previous_object,
1095
data_size - end_of_previous_object,
1096
)?;
1097
1098
if let Some(sg_state) = sg_state.as_mut() {
1099
if let Err(err) = self.apply_sg(&mut alloc, sg_state) {
1100
pr_warn!("Failure in apply_sg: {:?}", err);
1101
return Err(err);
1102
}
1103
}
1104
1105
if let Some((off_out, secctx)) = secctx.as_mut() {
1106
if let Err(err) = alloc.write(secctx_off, secctx.as_bytes()) {
1107
pr_warn!("Failed to write security context: {:?}", err);
1108
return Err(err.into());
1109
}
1110
**off_out = secctx_off;
1111
}
1112
Ok(alloc)
1113
}
1114
1115
fn unwind_transaction_stack(self: &Arc<Self>) {
1116
let mut thread = self.clone();
1117
while let Ok(transaction) = {
1118
let mut inner = thread.inner.lock();
1119
inner.pop_transaction_to_reply(thread.as_ref())
1120
} {
1121
let reply = Err(BR_DEAD_REPLY);
1122
if !transaction.from.deliver_single_reply(reply, &transaction) {
1123
break;
1124
}
1125
1126
thread = transaction.from.clone();
1127
}
1128
}
1129
1130
pub(crate) fn deliver_reply(
1131
&self,
1132
reply: Result<DLArc<Transaction>, u32>,
1133
transaction: &DArc<Transaction>,
1134
) {
1135
if self.deliver_single_reply(reply, transaction) {
1136
transaction.from.unwind_transaction_stack();
1137
}
1138
}
1139
1140
/// Delivers a reply to the thread that started a transaction. The reply can either be a
1141
/// reply-transaction or an error code to be delivered instead.
1142
///
1143
/// Returns whether the thread is dead. If it is, the caller is expected to unwind the
1144
/// transaction stack by completing transactions for threads that are dead.
1145
fn deliver_single_reply(
1146
&self,
1147
reply: Result<DLArc<Transaction>, u32>,
1148
transaction: &DArc<Transaction>,
1149
) -> bool {
1150
if let Ok(transaction) = &reply {
1151
transaction.set_outstanding(&mut self.process.inner.lock());
1152
}
1153
1154
{
1155
let mut inner = self.inner.lock();
1156
if !inner.pop_transaction_replied(transaction) {
1157
return false;
1158
}
1159
1160
if inner.is_dead {
1161
return true;
1162
}
1163
1164
match reply {
1165
Ok(work) => {
1166
inner.push_work(work);
1167
}
1168
Err(code) => inner.push_reply_work(code),
1169
}
1170
}
1171
1172
// Notify the thread now that we've released the inner lock.
1173
self.work_condvar.notify_sync();
1174
false
1175
}
1176
1177
/// Determines if the given transaction is the current transaction for this thread.
1178
fn is_current_transaction(&self, transaction: &DArc<Transaction>) -> bool {
1179
let inner = self.inner.lock();
1180
match &inner.current_transaction {
1181
None => false,
1182
Some(current) => Arc::ptr_eq(current, transaction),
1183
}
1184
}
1185
1186
/// Determines the current top of the transaction stack. It fails if the top is in another
1187
/// thread (i.e., this thread belongs to a stack but it has called another thread). The top is
1188
/// [`None`] if the thread is not currently participating in a transaction stack.
1189
fn top_of_transaction_stack(&self) -> Result<Option<DArc<Transaction>>> {
1190
let inner = self.inner.lock();
1191
if let Some(cur) = &inner.current_transaction {
1192
if core::ptr::eq(self, cur.from.as_ref()) {
1193
pr_warn!("got new transaction with bad transaction stack");
1194
return Err(EINVAL);
1195
}
1196
Ok(Some(cur.clone()))
1197
} else {
1198
Ok(None)
1199
}
1200
}
1201
1202
fn transaction<T>(self: &Arc<Self>, tr: &BinderTransactionDataSg, inner: T)
1203
where
1204
T: FnOnce(&Arc<Self>, &BinderTransactionDataSg) -> BinderResult,
1205
{
1206
if let Err(err) = inner(self, tr) {
1207
if err.should_pr_warn() {
1208
let mut ee = self.inner.lock().extended_error;
1209
ee.command = err.reply;
1210
ee.param = err.as_errno();
1211
pr_warn!(
1212
"Transaction failed: {:?} my_pid:{}",
1213
err,
1214
self.process.pid_in_current_ns()
1215
);
1216
}
1217
1218
self.push_return_work(err.reply);
1219
}
1220
}
1221
1222
fn transaction_inner(self: &Arc<Self>, tr: &BinderTransactionDataSg) -> BinderResult {
1223
// SAFETY: Handle's type has no invalid bit patterns.
1224
let handle = unsafe { tr.transaction_data.target.handle };
1225
let node_ref = self.process.get_transaction_node(handle)?;
1226
security::binder_transaction(&self.process.cred, &node_ref.node.owner.cred)?;
1227
// TODO: We need to ensure that there isn't a pending transaction in the work queue. How
1228
// could this happen?
1229
let top = self.top_of_transaction_stack()?;
1230
let list_completion = DTRWrap::arc_try_new(DeliverCode::new(BR_TRANSACTION_COMPLETE))?;
1231
let completion = list_completion.clone_arc();
1232
let transaction = Transaction::new(node_ref, top, self, tr)?;
1233
1234
// Check that the transaction stack hasn't changed while the lock was released, then update
1235
// it with the new transaction.
1236
{
1237
let mut inner = self.inner.lock();
1238
if !transaction.is_stacked_on(&inner.current_transaction) {
1239
pr_warn!("Transaction stack changed during transaction!");
1240
return Err(EINVAL.into());
1241
}
1242
inner.current_transaction = Some(transaction.clone_arc());
1243
// We push the completion as a deferred work so that we wait for the reply before
1244
// returning to userland.
1245
inner.push_work_deferred(list_completion);
1246
}
1247
1248
if let Err(e) = transaction.submit() {
1249
completion.skip();
1250
// Define `transaction` first to drop it after `inner`.
1251
let transaction;
1252
let mut inner = self.inner.lock();
1253
transaction = inner.current_transaction.take().unwrap();
1254
inner.current_transaction = transaction.clone_next();
1255
Err(e)
1256
} else {
1257
Ok(())
1258
}
1259
}
1260
1261
fn reply_inner(self: &Arc<Self>, tr: &BinderTransactionDataSg) -> BinderResult {
1262
let orig = self.inner.lock().pop_transaction_to_reply(self)?;
1263
if !orig.from.is_current_transaction(&orig) {
1264
return Err(EINVAL.into());
1265
}
1266
1267
// We need to complete the transaction even if we cannot complete building the reply.
1268
let out = (|| -> BinderResult<_> {
1269
let completion = DTRWrap::arc_try_new(DeliverCode::new(BR_TRANSACTION_COMPLETE))?;
1270
let process = orig.from.process.clone();
1271
let allow_fds = orig.flags & TF_ACCEPT_FDS != 0;
1272
let reply = Transaction::new_reply(self, process, tr, allow_fds)?;
1273
self.inner.lock().push_work(completion);
1274
orig.from.deliver_reply(Ok(reply), &orig);
1275
Ok(())
1276
})()
1277
.map_err(|mut err| {
1278
// At this point we only return `BR_TRANSACTION_COMPLETE` to the caller, and we must let
1279
// the sender know that the transaction has completed (with an error in this case).
1280
pr_warn!(
1281
"Failure {:?} during reply - delivering BR_FAILED_REPLY to sender.",
1282
err
1283
);
1284
let reply = Err(BR_FAILED_REPLY);
1285
orig.from.deliver_reply(reply, &orig);
1286
err.reply = BR_TRANSACTION_COMPLETE;
1287
err
1288
});
1289
1290
out
1291
}
1292
1293
fn oneway_transaction_inner(self: &Arc<Self>, tr: &BinderTransactionDataSg) -> BinderResult {
1294
// SAFETY: The `handle` field is valid for all possible byte values, so reading from the
1295
// union is okay.
1296
let handle = unsafe { tr.transaction_data.target.handle };
1297
let node_ref = self.process.get_transaction_node(handle)?;
1298
security::binder_transaction(&self.process.cred, &node_ref.node.owner.cred)?;
1299
let transaction = Transaction::new(node_ref, None, self, tr)?;
1300
let code = if self.process.is_oneway_spam_detection_enabled()
1301
&& transaction.oneway_spam_detected
1302
{
1303
BR_ONEWAY_SPAM_SUSPECT
1304
} else {
1305
BR_TRANSACTION_COMPLETE
1306
};
1307
let list_completion = DTRWrap::arc_try_new(DeliverCode::new(code))?;
1308
let completion = list_completion.clone_arc();
1309
self.inner.lock().push_work(list_completion);
1310
match transaction.submit() {
1311
Ok(()) => Ok(()),
1312
Err(err) => {
1313
completion.skip();
1314
Err(err)
1315
}
1316
}
1317
}
1318
1319
fn write(self: &Arc<Self>, req: &mut BinderWriteRead) -> Result {
1320
let write_start = req.write_buffer.wrapping_add(req.write_consumed);
1321
let write_len = req.write_size.saturating_sub(req.write_consumed);
1322
let mut reader =
1323
UserSlice::new(UserPtr::from_addr(write_start as _), write_len as _).reader();
1324
1325
while reader.len() >= size_of::<u32>() && self.inner.lock().return_work.is_unused() {
1326
let before = reader.len();
1327
let cmd = reader.read::<u32>()?;
1328
GLOBAL_STATS.inc_bc(cmd);
1329
self.process.stats.inc_bc(cmd);
1330
match cmd {
1331
BC_TRANSACTION => {
1332
let tr = reader.read::<BinderTransactionData>()?.with_buffers_size(0);
1333
if tr.transaction_data.flags & TF_ONE_WAY != 0 {
1334
self.transaction(&tr, Self::oneway_transaction_inner);
1335
} else {
1336
self.transaction(&tr, Self::transaction_inner);
1337
}
1338
}
1339
BC_TRANSACTION_SG => {
1340
let tr = reader.read::<BinderTransactionDataSg>()?;
1341
if tr.transaction_data.flags & TF_ONE_WAY != 0 {
1342
self.transaction(&tr, Self::oneway_transaction_inner);
1343
} else {
1344
self.transaction(&tr, Self::transaction_inner);
1345
}
1346
}
1347
BC_REPLY => {
1348
let tr = reader.read::<BinderTransactionData>()?.with_buffers_size(0);
1349
self.transaction(&tr, Self::reply_inner)
1350
}
1351
BC_REPLY_SG => {
1352
let tr = reader.read::<BinderTransactionDataSg>()?;
1353
self.transaction(&tr, Self::reply_inner)
1354
}
1355
BC_FREE_BUFFER => {
1356
let buffer = self.process.buffer_get(reader.read()?);
1357
if let Some(buffer) = buffer {
1358
if buffer.looper_need_return_on_free() {
1359
self.inner.lock().looper_need_return = true;
1360
}
1361
drop(buffer);
1362
}
1363
}
1364
BC_INCREFS => {
1365
self.process
1366
.as_arc_borrow()
1367
.update_ref(reader.read()?, true, false)?
1368
}
1369
BC_ACQUIRE => {
1370
self.process
1371
.as_arc_borrow()
1372
.update_ref(reader.read()?, true, true)?
1373
}
1374
BC_RELEASE => {
1375
self.process
1376
.as_arc_borrow()
1377
.update_ref(reader.read()?, false, true)?
1378
}
1379
BC_DECREFS => {
1380
self.process
1381
.as_arc_borrow()
1382
.update_ref(reader.read()?, false, false)?
1383
}
1384
BC_INCREFS_DONE => self.process.inc_ref_done(&mut reader, false)?,
1385
BC_ACQUIRE_DONE => self.process.inc_ref_done(&mut reader, true)?,
1386
BC_REQUEST_DEATH_NOTIFICATION => self.process.request_death(&mut reader, self)?,
1387
BC_CLEAR_DEATH_NOTIFICATION => self.process.clear_death(&mut reader, self)?,
1388
BC_DEAD_BINDER_DONE => self.process.dead_binder_done(reader.read()?, self),
1389
BC_REGISTER_LOOPER => {
1390
let valid = self.process.register_thread();
1391
self.inner.lock().looper_register(valid);
1392
}
1393
BC_ENTER_LOOPER => self.inner.lock().looper_enter(),
1394
BC_EXIT_LOOPER => self.inner.lock().looper_exit(),
1395
BC_REQUEST_FREEZE_NOTIFICATION => self.process.request_freeze_notif(&mut reader)?,
1396
BC_CLEAR_FREEZE_NOTIFICATION => self.process.clear_freeze_notif(&mut reader)?,
1397
BC_FREEZE_NOTIFICATION_DONE => self.process.freeze_notif_done(&mut reader)?,
1398
1399
// Fail if given an unknown error code.
1400
// BC_ATTEMPT_ACQUIRE and BC_ACQUIRE_RESULT are no longer supported.
1401
_ => return Err(EINVAL),
1402
}
1403
// Update the number of write bytes consumed.
1404
req.write_consumed += (before - reader.len()) as u64;
1405
}
1406
1407
Ok(())
1408
}
1409
1410
fn read(self: &Arc<Self>, req: &mut BinderWriteRead, wait: bool) -> Result {
1411
let read_start = req.read_buffer.wrapping_add(req.read_consumed);
1412
let read_len = req.read_size.saturating_sub(req.read_consumed);
1413
let mut writer = BinderReturnWriter::new(
1414
UserSlice::new(UserPtr::from_addr(read_start as _), read_len as _).writer(),
1415
self,
1416
);
1417
let (in_pool, use_proc_queue) = {
1418
let inner = self.inner.lock();
1419
(inner.is_looper(), inner.should_use_process_work_queue())
1420
};
1421
1422
let getter = if use_proc_queue {
1423
Self::get_work
1424
} else {
1425
Self::get_work_local
1426
};
1427
1428
// Reserve some room at the beginning of the read buffer so that we can send a
1429
// BR_SPAWN_LOOPER if we need to.
1430
let mut has_noop_placeholder = false;
1431
if req.read_consumed == 0 {
1432
if let Err(err) = writer.write_code(BR_NOOP) {
1433
pr_warn!("Failure when writing BR_NOOP at beginning of buffer.");
1434
return Err(err);
1435
}
1436
has_noop_placeholder = true;
1437
}
1438
1439
// Loop doing work while there is room in the buffer.
1440
let initial_len = writer.len();
1441
while writer.len() >= size_of::<uapi::binder_transaction_data_secctx>() + 4 {
1442
match getter(self, wait && initial_len == writer.len()) {
1443
Ok(Some(work)) => match work.into_arc().do_work(self, &mut writer) {
1444
Ok(true) => {}
1445
Ok(false) => break,
1446
Err(err) => {
1447
return Err(err);
1448
}
1449
},
1450
Ok(None) => {
1451
break;
1452
}
1453
Err(err) => {
1454
// Propagate the error if we haven't written anything else.
1455
if err != EINTR && err != EAGAIN {
1456
pr_warn!("Failure in work getter: {:?}", err);
1457
}
1458
if initial_len == writer.len() {
1459
return Err(err);
1460
} else {
1461
break;
1462
}
1463
}
1464
}
1465
}
1466
1467
req.read_consumed += read_len - writer.len() as u64;
1468
1469
// Write BR_SPAWN_LOOPER if the process needs more threads for its pool.
1470
if has_noop_placeholder && in_pool && self.process.needs_thread() {
1471
let mut writer =
1472
UserSlice::new(UserPtr::from_addr(req.read_buffer as _), req.read_size as _)
1473
.writer();
1474
writer.write(&BR_SPAWN_LOOPER)?;
1475
}
1476
Ok(())
1477
}
1478
1479
pub(crate) fn write_read(self: &Arc<Self>, data: UserSlice, wait: bool) -> Result {
1480
let (mut reader, mut writer) = data.reader_writer();
1481
let mut req = reader.read::<BinderWriteRead>()?;
1482
1483
// Go through the write buffer.
1484
let mut ret = Ok(());
1485
if req.write_size > 0 {
1486
ret = self.write(&mut req);
1487
if let Err(err) = ret {
1488
pr_warn!(
1489
"Write failure {:?} in pid:{}",
1490
err,
1491
self.process.pid_in_current_ns()
1492
);
1493
req.read_consumed = 0;
1494
writer.write(&req)?;
1495
self.inner.lock().looper_need_return = false;
1496
return ret;
1497
}
1498
}
1499
1500
// Go through the work queue.
1501
if req.read_size > 0 {
1502
ret = self.read(&mut req, wait);
1503
if ret.is_err() && ret != Err(EINTR) {
1504
pr_warn!(
1505
"Read failure {:?} in pid:{}",
1506
ret,
1507
self.process.pid_in_current_ns()
1508
);
1509
}
1510
}
1511
1512
// Write the request back so that the consumed fields are visible to the caller.
1513
writer.write(&req)?;
1514
1515
self.inner.lock().looper_need_return = false;
1516
1517
ret
1518
}
1519
1520
pub(crate) fn poll(&self, file: &File, table: PollTable<'_>) -> (bool, u32) {
1521
table.register_wait(file, &self.work_condvar);
1522
let mut inner = self.inner.lock();
1523
(inner.should_use_process_work_queue(), inner.poll())
1524
}
1525
1526
/// Make the call to `get_work` or `get_work_local` return immediately, if any.
1527
pub(crate) fn exit_looper(&self) {
1528
let mut inner = self.inner.lock();
1529
let should_notify = inner.looper_flags & LOOPER_WAITING != 0;
1530
if should_notify {
1531
inner.looper_need_return = true;
1532
}
1533
drop(inner);
1534
1535
if should_notify {
1536
self.work_condvar.notify_one();
1537
}
1538
}
1539
1540
pub(crate) fn notify_if_poll_ready(&self, sync: bool) {
1541
// Determine if we need to notify. This requires the lock.
1542
let inner = self.inner.lock();
1543
let notify = inner.looper_flags & LOOPER_POLL != 0 && inner.should_use_process_work_queue();
1544
drop(inner);
1545
1546
// Now that the lock is no longer held, notify the waiters if we have to.
1547
if notify {
1548
if sync {
1549
self.work_condvar.notify_sync();
1550
} else {
1551
self.work_condvar.notify_one();
1552
}
1553
}
1554
}
1555
1556
pub(crate) fn release(self: &Arc<Self>) {
1557
self.inner.lock().is_dead = true;
1558
1559
//self.work_condvar.clear();
1560
self.unwind_transaction_stack();
1561
1562
// Cancel all pending work items.
1563
while let Ok(Some(work)) = self.get_work_local(false) {
1564
work.into_arc().cancel();
1565
}
1566
}
1567
}
1568
1569
#[pin_data]
1570
struct ThreadError {
1571
error_code: AtomicU32,
1572
#[pin]
1573
links_track: AtomicTracker,
1574
}
1575
1576
impl ThreadError {
1577
fn try_new() -> Result<DArc<Self>> {
1578
DTRWrap::arc_pin_init(pin_init!(Self {
1579
error_code: AtomicU32::new(BR_OK),
1580
links_track <- AtomicTracker::new(),
1581
}))
1582
.map(ListArc::into_arc)
1583
}
1584
1585
fn set_error_code(&self, code: u32) {
1586
self.error_code.store(code, Ordering::Relaxed);
1587
}
1588
1589
fn is_unused(&self) -> bool {
1590
self.error_code.load(Ordering::Relaxed) == BR_OK
1591
}
1592
}
1593
1594
impl DeliverToRead for ThreadError {
1595
fn do_work(
1596
self: DArc<Self>,
1597
_thread: &Thread,
1598
writer: &mut BinderReturnWriter<'_>,
1599
) -> Result<bool> {
1600
let code = self.error_code.load(Ordering::Relaxed);
1601
self.error_code.store(BR_OK, Ordering::Relaxed);
1602
writer.write_code(code)?;
1603
Ok(true)
1604
}
1605
1606
fn cancel(self: DArc<Self>) {}
1607
1608
fn should_sync_wakeup(&self) -> bool {
1609
false
1610
}
1611
1612
fn debug_print(&self, m: &SeqFile, prefix: &str, _tprefix: &str) -> Result<()> {
1613
seq_print!(
1614
m,
1615
"{}transaction error: {}\n",
1616
prefix,
1617
self.error_code.load(Ordering::Relaxed)
1618
);
1619
Ok(())
1620
}
1621
}
1622
1623
kernel::list::impl_list_arc_safe! {
1624
impl ListArcSafe<0> for ThreadError {
1625
tracked_by links_track: AtomicTracker;
1626
}
1627
}
1628
1629