projects/linux·blob master · refs

1762 lines · 65.5 KiB

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