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