• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // SPDX-License-Identifier: GPL-2.0
2 
3 // Copyright (C) 2024 Google LLC.
4 
5 //! Binder -- the Android IPC mechanism.
6 #![recursion_limit = "256"]
7 
8 use kernel::{
9     bindings::{self, seq_file},
10     fs::File,
11     list::{HasListLinks, ListArc, ListArcSafe, ListLinksSelfPtr, TryNewListArc},
12     prelude::*,
13     seq_file::SeqFile,
14     seq_print,
15     sync::poll::PollTable,
16     sync::Arc,
17     task::Pid,
18     types::{AsBytes, ForeignOwnable},
19     uaccess::UserSliceWriter,
20 };
21 
22 use crate::{context::Context, page_range::Shrinker, process::Process, thread::Thread};
23 
24 use core::{
25     ptr::NonNull,
26     sync::atomic::{AtomicBool, AtomicUsize, Ordering},
27 };
28 
29 mod allocation;
30 mod context;
31 mod deferred_close;
32 mod defs;
33 mod error;
34 mod node;
35 mod page_range;
36 mod prio;
37 mod process;
38 mod range_alloc;
39 mod stats;
40 mod thread;
41 mod trace;
42 mod transaction;
43 
44 #[allow(warnings)] // generated bindgen code
45 mod binderfs {
46     use kernel::bindings::{dentry, inode};
47 
48     extern "C" {
init_rust_binderfs() -> kernel::ffi::c_int49         pub fn init_rust_binderfs() -> kernel::ffi::c_int;
50     }
51     extern "C" {
rust_binderfs_create_proc_file( nodp: *mut inode, pid: kernel::ffi::c_int, ) -> *mut dentry52         pub fn rust_binderfs_create_proc_file(
53             nodp: *mut inode,
54             pid: kernel::ffi::c_int,
55         ) -> *mut dentry;
56     }
57     extern "C" {
rust_binderfs_remove_file(dentry: *mut dentry)58         pub fn rust_binderfs_remove_file(dentry: *mut dentry);
59     }
60     pub type rust_binder_context = *mut kernel::ffi::c_void;
61     #[repr(C)]
62     #[derive(Copy, Clone)]
63     pub struct binder_device {
64         pub minor: kernel::ffi::c_int,
65         pub ctx: rust_binder_context,
66     }
67     impl Default for binder_device {
default() -> Self68         fn default() -> Self {
69             let mut s = ::core::mem::MaybeUninit::<Self>::uninit();
70             unsafe {
71                 ::core::ptr::write_bytes(s.as_mut_ptr(), 0, 1);
72                 s.assume_init()
73             }
74         }
75     }
76 }
77 
78 module! {
79     type: BinderModule,
80     name: "rust_binder",
81     author: "Wedson Almeida Filho, Alice Ryhl",
82     description: "Android Binder",
83     license: "GPL",
84 }
85 
86 use kernel::bindings::rust_binder_layout;
87 #[no_mangle]
88 static RUST_BINDER_LAYOUT: rust_binder_layout = rust_binder_layout {
89     t: transaction::TRANSACTION_LAYOUT,
90     th: thread::THREAD_LAYOUT,
91     p: process::PROCESS_LAYOUT,
92     n: node::NODE_LAYOUT,
93 };
94 
next_debug_id() -> usize95 fn next_debug_id() -> usize {
96     static NEXT_DEBUG_ID: AtomicUsize = AtomicUsize::new(0);
97 
98     NEXT_DEBUG_ID.fetch_add(1, Ordering::Relaxed)
99 }
100 
101 /// Provides a single place to write Binder return values via the
102 /// supplied `UserSliceWriter`.
103 pub(crate) struct BinderReturnWriter<'a> {
104     writer: UserSliceWriter,
105     thread: &'a Thread,
106 }
107 
108 impl<'a> BinderReturnWriter<'a> {
new(writer: UserSliceWriter, thread: &'a Thread) -> Self109     fn new(writer: UserSliceWriter, thread: &'a Thread) -> Self {
110         BinderReturnWriter { writer, thread }
111     }
112 
113     /// Write a return code back to user space.
114     /// Should be a `BR_` constant from [`defs`] e.g. [`defs::BR_TRANSACTION_COMPLETE`].
write_code(&mut self, code: u32) -> Result115     fn write_code(&mut self, code: u32) -> Result {
116         crate::trace::trace_return(code);
117         stats::GLOBAL_STATS.inc_br(code);
118         self.thread.process.stats.inc_br(code);
119         self.writer.write(&code)
120     }
121 
122     /// Write something *other than* a return code to user space.
write_payload<T: AsBytes>(&mut self, payload: &T) -> Result123     fn write_payload<T: AsBytes>(&mut self, payload: &T) -> Result {
124         self.writer.write(payload)
125     }
126 
len(&self) -> usize127     fn len(&self) -> usize {
128         self.writer.len()
129     }
130 }
131 
132 /// Specifies how a type should be delivered to the read part of a BINDER_WRITE_READ ioctl.
133 ///
134 /// When a value is pushed to the todo list for a process or thread, it is stored as a trait object
135 /// with the type `Arc<dyn DeliverToRead>`. Trait objects are a Rust feature that lets you
136 /// implement dynamic dispatch over many different types. This lets us store many different types
137 /// in the todo list.
138 trait DeliverToRead: ListArcSafe + Send + Sync {
139     /// Performs work. Returns true if remaining work items in the queue should be processed
140     /// immediately, or false if it should return to caller before processing additional work
141     /// items.
do_work( self: DArc<Self>, thread: &Thread, writer: &mut BinderReturnWriter<'_>, ) -> Result<bool>142     fn do_work(
143         self: DArc<Self>,
144         thread: &Thread,
145         writer: &mut BinderReturnWriter<'_>,
146     ) -> Result<bool>;
147 
148     /// Cancels the given work item. This is called instead of [`DeliverToRead::do_work`] when work
149     /// won't be delivered.
cancel(self: DArc<Self>)150     fn cancel(self: DArc<Self>);
151 
152     /// Called when a work item is delivered directly to a specific thread, rather than to the
153     /// process work list.
on_thread_selected(&self, _thread: &thread::Thread)154     fn on_thread_selected(&self, _thread: &thread::Thread);
155 
156     /// Should we use `wake_up_interruptible_sync` or `wake_up_interruptible` when scheduling this
157     /// work item?
158     ///
159     /// Generally only set to true for non-oneway transactions.
should_sync_wakeup(&self) -> bool160     fn should_sync_wakeup(&self) -> bool;
161 
debug_print(&self, m: &SeqFile, prefix: &str, transaction_prefix: &str) -> Result<()>162     fn debug_print(&self, m: &SeqFile, prefix: &str, transaction_prefix: &str) -> Result<()>;
163 }
164 
165 // Wrapper around a `DeliverToRead` with linked list links.
166 #[pin_data]
167 struct DTRWrap<T: ?Sized> {
168     #[pin]
169     links: ListLinksSelfPtr<DTRWrap<dyn DeliverToRead>>,
170     #[pin]
171     wrapped: T,
172 }
173 kernel::list::impl_has_list_links_self_ptr! {
174     impl HasSelfPtr<DTRWrap<dyn DeliverToRead>> for DTRWrap<dyn DeliverToRead> { self.links }
175 }
176 kernel::list::impl_list_arc_safe! {
177     impl{T: ListArcSafe + ?Sized} ListArcSafe<0> for DTRWrap<T> {
178         tracked_by wrapped: T;
179     }
180 }
181 kernel::list::impl_list_item! {
182     impl ListItem<0> for DTRWrap<dyn DeliverToRead> {
183         using ListLinksSelfPtr;
184     }
185 }
186 
187 impl<T: ?Sized> core::ops::Deref for DTRWrap<T> {
188     type Target = T;
deref(&self) -> &T189     fn deref(&self) -> &T {
190         &self.wrapped
191     }
192 }
193 
194 type DArc<T> = kernel::sync::Arc<DTRWrap<T>>;
195 type DLArc<T> = kernel::list::ListArc<DTRWrap<T>>;
196 
197 impl<T: ListArcSafe> DTRWrap<T> {
new(val: impl PinInit<T>) -> impl PinInit<Self>198     fn new(val: impl PinInit<T>) -> impl PinInit<Self> {
199         pin_init!(Self {
200             links <- ListLinksSelfPtr::new(),
201             wrapped <- val,
202         })
203     }
204 
arc_try_new(val: T) -> Result<DLArc<T>, kernel::alloc::AllocError>205     fn arc_try_new(val: T) -> Result<DLArc<T>, kernel::alloc::AllocError> {
206         ListArc::pin_init(
207             try_pin_init!(Self {
208                 links <- ListLinksSelfPtr::new(),
209                 wrapped: val,
210             }),
211             GFP_KERNEL,
212         )
213         .map_err(|_| kernel::alloc::AllocError)
214     }
215 
arc_pin_init(init: impl PinInit<T>) -> Result<DLArc<T>, kernel::error::Error>216     fn arc_pin_init(init: impl PinInit<T>) -> Result<DLArc<T>, kernel::error::Error> {
217         ListArc::pin_init(
218             try_pin_init!(Self {
219                 links <- ListLinksSelfPtr::new(),
220                 wrapped <- init,
221             }),
222             GFP_KERNEL,
223         )
224     }
225 }
226 
227 struct DeliverCode {
228     code: u32,
229     skip: AtomicBool,
230 }
231 
232 kernel::list::impl_list_arc_safe! {
233     impl ListArcSafe<0> for DeliverCode { untracked; }
234 }
235 
236 impl DeliverCode {
new(code: u32) -> Self237     fn new(code: u32) -> Self {
238         Self {
239             code,
240             skip: AtomicBool::new(false),
241         }
242     }
243 
244     /// Disable this DeliverCode and make it do nothing.
245     ///
246     /// This is used instead of removing it from the work list, since `LinkedList::remove` is
247     /// unsafe, whereas this method is not.
skip(&self)248     fn skip(&self) {
249         self.skip.store(true, Ordering::Relaxed);
250     }
251 }
252 
253 impl DeliverToRead for DeliverCode {
do_work( self: DArc<Self>, _thread: &Thread, writer: &mut BinderReturnWriter<'_>, ) -> Result<bool>254     fn do_work(
255         self: DArc<Self>,
256         _thread: &Thread,
257         writer: &mut BinderReturnWriter<'_>,
258     ) -> Result<bool> {
259         if !self.skip.load(Ordering::Relaxed) {
260             writer.write_code(self.code)?;
261         }
262         Ok(true)
263     }
264 
cancel(self: DArc<Self>)265     fn cancel(self: DArc<Self>) {}
on_thread_selected(&self, _thread: &Thread)266     fn on_thread_selected(&self, _thread: &Thread) {}
267 
should_sync_wakeup(&self) -> bool268     fn should_sync_wakeup(&self) -> bool {
269         false
270     }
271 
debug_print(&self, m: &SeqFile, prefix: &str, _tprefix: &str) -> Result<()>272     fn debug_print(&self, m: &SeqFile, prefix: &str, _tprefix: &str) -> Result<()> {
273         seq_print!(m, "{}", prefix);
274         if self.skip.load(Ordering::Relaxed) {
275             seq_print!(m, "(skipped) ");
276         }
277         if self.code == defs::BR_TRANSACTION_COMPLETE {
278             seq_print!(m, "transaction complete\n");
279         } else {
280             seq_print!(m, "transaction error: {}\n", self.code);
281         }
282         Ok(())
283     }
284 }
285 
ptr_align(value: usize) -> Option<usize>286 fn ptr_align(value: usize) -> Option<usize> {
287     let size = core::mem::size_of::<usize>() - 1;
288     Some(value.checked_add(size)? & !size)
289 }
290 
291 // SAFETY: We call register in `init`.
292 static BINDER_SHRINKER: Shrinker = unsafe { Shrinker::new() };
293 
294 struct BinderModule {}
295 
296 impl kernel::Module for BinderModule {
init(_module: &'static kernel::ThisModule) -> Result<Self>297     fn init(_module: &'static kernel::ThisModule) -> Result<Self> {
298         // SAFETY: The module initializer never runs twice, so we only call this once.
299         unsafe { crate::context::CONTEXTS.init() };
300 
301         // SAFETY: This just accesses global booleans.
302         unsafe {
303             extern "C" {
304                 static mut binder_use_rust: i32;
305                 fn unload_binder() -> i32;
306             }
307 
308             if binder_use_rust == 0 {
309                 return Ok(Self {});
310             }
311             if unload_binder() != 0 {
312                 pr_err!("Failed to unload C Binder.");
313                 return Ok(Self {});
314             }
315         }
316 
317         pr_warn!("Loaded Rust Binder.");
318 
319         BINDER_SHRINKER.register(kernel::c_str!("android-binder"))?;
320 
321         // SAFETY: The module is being loaded, so we can initialize binderfs.
322         unsafe { kernel::error::to_result(binderfs::init_rust_binderfs())? };
323 
324         Ok(Self {})
325     }
326 }
327 
328 /// Makes the inner type Sync.
329 #[repr(transparent)]
330 pub struct AssertSync<T>(T);
331 // SAFETY: Used only to insert `file_operations` into a global, which is safe.
332 unsafe impl<T> Sync for AssertSync<T> {}
333 
334 /// File operations that rust_binderfs.c can use.
335 #[no_mangle]
336 #[used]
337 pub static rust_binder_fops: AssertSync<kernel::bindings::file_operations> = {
338     // SAFETY: All zeroes is safe for the `file_operations` type.
339     let zeroed_ops = unsafe { core::mem::MaybeUninit::zeroed().assume_init() };
340 
341     let ops = kernel::bindings::file_operations {
342         owner: THIS_MODULE.as_ptr(),
343         poll: Some(rust_binder_poll),
344         unlocked_ioctl: Some(rust_binder_unlocked_ioctl),
345         compat_ioctl: Some(rust_binder_compat_ioctl),
346         mmap: Some(rust_binder_mmap),
347         open: Some(rust_binder_open),
348         release: Some(rust_binder_release),
349         flush: Some(rust_binder_flush),
350         ..zeroed_ops
351     };
352     AssertSync(ops)
353 };
354 
355 #[no_mangle]
rust_binder_new_context( name: *const kernel::ffi::c_char, ) -> *mut kernel::ffi::c_void356 unsafe extern "C" fn rust_binder_new_context(
357     name: *const kernel::ffi::c_char,
358 ) -> *mut kernel::ffi::c_void {
359     // SAFETY: The caller will always provide a valid c string here.
360     let name = unsafe { kernel::str::CStr::from_char_ptr(name) };
361     match Context::new(name) {
362         Ok(ctx) => Arc::into_foreign(ctx).cast_mut(),
363         Err(_err) => core::ptr::null_mut(),
364     }
365 }
366 
367 #[no_mangle]
rust_binder_remove_context(device: *mut kernel::ffi::c_void)368 unsafe extern "C" fn rust_binder_remove_context(device: *mut kernel::ffi::c_void) {
369     if !device.is_null() {
370         // SAFETY: The caller ensures that the `device` pointer came from a previous call to
371         // `rust_binder_new_device`.
372         let ctx = unsafe { Arc::<Context>::from_foreign(device) };
373         ctx.deregister();
374         drop(ctx);
375     }
376 }
377 
rust_binder_open( inode: *mut bindings::inode, file_ptr: *mut bindings::file, ) -> kernel::ffi::c_int378 unsafe extern "C" fn rust_binder_open(
379     inode: *mut bindings::inode,
380     file_ptr: *mut bindings::file,
381 ) -> kernel::ffi::c_int {
382     // SAFETY: The `rust_binderfs.c` file ensures that `i_private` is set to a
383     // `struct binder_device`.
384     let device = unsafe { (*inode).i_private } as *const binderfs::binder_device;
385 
386     assert!(!device.is_null());
387 
388     // SAFETY: The `rust_binderfs.c` file ensures that `device->ctx` holds a binder context when
389     // using the rust binder fops.
390     let ctx = unsafe { Arc::<Context>::borrow((*device).ctx) };
391 
392     // SAFETY: The caller provides a valid file pointer to a new `struct file`.
393     let file = unsafe { File::from_raw_file(file_ptr) };
394     let process = match Process::open(ctx, file) {
395         Ok(process) => process,
396         Err(err) => return err.to_errno(),
397     };
398 
399     // SAFETY: This is an `inode` for a newly created binder file.
400     match unsafe { BinderfsProcFile::new(inode, process.task.pid()) } {
401         Ok(Some(file)) => process.inner.lock().binderfs_file = Some(file),
402         Ok(None) => { /* pid already exists */ }
403         Err(err) => return err.to_errno(),
404     }
405 
406     // SAFETY: This file is associated with Rust binder, so we own the `private_data` field.
407     unsafe { (*file_ptr).private_data = process.into_foreign().cast_mut() };
408     0
409 }
410 
rust_binder_release( _inode: *mut bindings::inode, file: *mut bindings::file, ) -> kernel::ffi::c_int411 unsafe extern "C" fn rust_binder_release(
412     _inode: *mut bindings::inode,
413     file: *mut bindings::file,
414 ) -> kernel::ffi::c_int {
415     // SAFETY: We previously set `private_data` in `rust_binder_open`.
416     let process = unsafe { Arc::<Process>::from_foreign((*file).private_data) };
417     // SAFETY: The caller ensures that the file is valid.
418     let file = unsafe { File::from_raw_file(file) };
419     Process::release(process, file);
420     0
421 }
422 
rust_binder_compat_ioctl( file: *mut bindings::file, cmd: kernel::ffi::c_uint, arg: kernel::ffi::c_ulong, ) -> kernel::ffi::c_long423 unsafe extern "C" fn rust_binder_compat_ioctl(
424     file: *mut bindings::file,
425     cmd: kernel::ffi::c_uint,
426     arg: kernel::ffi::c_ulong,
427 ) -> kernel::ffi::c_long {
428     // SAFETY: We previously set `private_data` in `rust_binder_open`.
429     let f = unsafe { Arc::<Process>::borrow((*file).private_data) };
430     // SAFETY: The caller ensures that the file is valid.
431     match Process::compat_ioctl(f, unsafe { File::from_raw_file(file) }, cmd as _, arg as _) {
432         Ok(()) => 0,
433         Err(err) => err.to_errno() as isize,
434     }
435 }
436 
rust_binder_unlocked_ioctl( file: *mut bindings::file, cmd: kernel::ffi::c_uint, arg: kernel::ffi::c_ulong, ) -> kernel::ffi::c_long437 unsafe extern "C" fn rust_binder_unlocked_ioctl(
438     file: *mut bindings::file,
439     cmd: kernel::ffi::c_uint,
440     arg: kernel::ffi::c_ulong,
441 ) -> kernel::ffi::c_long {
442     // SAFETY: We previously set `private_data` in `rust_binder_open`.
443     let f = unsafe { Arc::<Process>::borrow((*file).private_data) };
444     // SAFETY: The caller ensures that the file is valid.
445     match Process::ioctl(f, unsafe { File::from_raw_file(file) }, cmd as _, arg as _) {
446         Ok(()) => 0,
447         Err(err) => err.to_errno() as isize,
448     }
449 }
450 
rust_binder_mmap( file: *mut bindings::file, vma: *mut bindings::vm_area_struct, ) -> kernel::ffi::c_int451 unsafe extern "C" fn rust_binder_mmap(
452     file: *mut bindings::file,
453     vma: *mut bindings::vm_area_struct,
454 ) -> kernel::ffi::c_int {
455     // SAFETY: We previously set `private_data` in `rust_binder_open`.
456     let f = unsafe { Arc::<Process>::borrow((*file).private_data) };
457     // SAFETY: The caller ensures that the vma is valid.
458     let area = unsafe { kernel::mm::virt::VmaNew::from_raw(vma) };
459     // SAFETY: The caller ensures that the file is valid.
460     match Process::mmap(f, unsafe { File::from_raw_file(file) }, area) {
461         Ok(()) => 0,
462         Err(err) => err.to_errno(),
463     }
464 }
465 
rust_binder_poll( file: *mut bindings::file, wait: *mut bindings::poll_table_struct, ) -> bindings::__poll_t466 unsafe extern "C" fn rust_binder_poll(
467     file: *mut bindings::file,
468     wait: *mut bindings::poll_table_struct,
469 ) -> bindings::__poll_t {
470     // SAFETY: We previously set `private_data` in `rust_binder_open`.
471     let f = unsafe { Arc::<Process>::borrow((*file).private_data) };
472     // SAFETY: The caller ensures that the file is valid.
473     let fileref = unsafe { File::from_raw_file(file) };
474     // SAFETY: The caller ensures that the `PollTable` is valid.
475     match Process::poll(f, fileref, unsafe { PollTable::from_raw(wait) }) {
476         Ok(v) => v,
477         Err(_) => bindings::POLLERR,
478     }
479 }
480 
rust_binder_flush( file: *mut bindings::file, _id: bindings::fl_owner_t, ) -> kernel::ffi::c_int481 unsafe extern "C" fn rust_binder_flush(
482     file: *mut bindings::file,
483     _id: bindings::fl_owner_t,
484 ) -> kernel::ffi::c_int {
485     // SAFETY: We previously set `private_data` in `rust_binder_open`.
486     let f = unsafe { Arc::<Process>::borrow((*file).private_data) };
487     match Process::flush(f) {
488         Ok(()) => 0,
489         Err(err) => err.to_errno(),
490     }
491 }
492 
493 #[no_mangle]
rust_binder_stats_show( ptr: *mut seq_file, _: *mut kernel::ffi::c_void, ) -> kernel::ffi::c_int494 unsafe extern "C" fn rust_binder_stats_show(
495     ptr: *mut seq_file,
496     _: *mut kernel::ffi::c_void,
497 ) -> kernel::ffi::c_int {
498     // SAFETY: The caller ensures that the pointer is valid and exclusive for the duration in which
499     // this method is called.
500     let m = unsafe { SeqFile::from_raw(ptr) };
501     if let Err(err) = rust_binder_stats_show_impl(m) {
502         seq_print!(m, "failed to generate state: {:?}\n", err);
503     }
504     0
505 }
506 
507 #[no_mangle]
rust_binder_state_show( ptr: *mut seq_file, _: *mut kernel::ffi::c_void, ) -> kernel::ffi::c_int508 unsafe extern "C" fn rust_binder_state_show(
509     ptr: *mut seq_file,
510     _: *mut kernel::ffi::c_void,
511 ) -> kernel::ffi::c_int {
512     // SAFETY: The caller ensures that the pointer is valid and exclusive for the duration in which
513     // this method is called.
514     let m = unsafe { SeqFile::from_raw(ptr) };
515     if let Err(err) = rust_binder_state_show_impl(m) {
516         seq_print!(m, "failed to generate state: {:?}\n", err);
517     }
518     0
519 }
520 
521 #[no_mangle]
rust_binder_proc_show( ptr: *mut seq_file, _: *mut kernel::ffi::c_void, ) -> kernel::ffi::c_int522 unsafe extern "C" fn rust_binder_proc_show(
523     ptr: *mut seq_file,
524     _: *mut kernel::ffi::c_void,
525 ) -> kernel::ffi::c_int {
526     // SAFETY: Accessing the private field of `seq_file` is okay.
527     let pid = (unsafe { (*ptr).private }) as usize as Pid;
528     // SAFETY: The caller ensures that the pointer is valid and exclusive for the duration in which
529     // this method is called.
530     let m = unsafe { SeqFile::from_raw(ptr) };
531     if let Err(err) = rust_binder_proc_show_impl(m, pid) {
532         seq_print!(m, "failed to generate state: {:?}\n", err);
533     }
534     0
535 }
536 
537 #[no_mangle]
rust_binder_transactions_show( ptr: *mut seq_file, _: *mut kernel::ffi::c_void, ) -> kernel::ffi::c_int538 unsafe extern "C" fn rust_binder_transactions_show(
539     ptr: *mut seq_file,
540     _: *mut kernel::ffi::c_void,
541 ) -> kernel::ffi::c_int {
542     // SAFETY: The caller ensures that the pointer is valid and exclusive for the duration in which
543     // this method is called.
544     let m = unsafe { SeqFile::from_raw(ptr) };
545     if let Err(err) = rust_binder_transactions_show_impl(m) {
546         seq_print!(m, "failed to generate state: {:?}\n", err);
547     }
548     0
549 }
550 
rust_binder_transactions_show_impl(m: &SeqFile) -> Result<()>551 fn rust_binder_transactions_show_impl(m: &SeqFile) -> Result<()> {
552     seq_print!(m, "binder transactions:\n");
553     let contexts = context::get_all_contexts()?;
554     for ctx in contexts {
555         let procs = ctx.get_all_procs()?;
556         for proc in procs {
557             proc.debug_print(m, &ctx, false)?;
558             seq_print!(m, "\n");
559         }
560     }
561     Ok(())
562 }
563 
rust_binder_stats_show_impl(m: &SeqFile) -> Result<()>564 fn rust_binder_stats_show_impl(m: &SeqFile) -> Result<()> {
565     seq_print!(m, "binder stats:\n");
566     stats::GLOBAL_STATS.debug_print("", m);
567     let contexts = context::get_all_contexts()?;
568     for ctx in contexts {
569         let procs = ctx.get_all_procs()?;
570         for proc in procs {
571             proc.debug_print_stats(m, &ctx)?;
572             seq_print!(m, "\n");
573         }
574     }
575     Ok(())
576 }
577 
rust_binder_state_show_impl(m: &SeqFile) -> Result<()>578 fn rust_binder_state_show_impl(m: &SeqFile) -> Result<()> {
579     seq_print!(m, "binder state:\n");
580     let contexts = context::get_all_contexts()?;
581     for ctx in contexts {
582         let procs = ctx.get_all_procs()?;
583         for proc in procs {
584             proc.debug_print(m, &ctx, true)?;
585             seq_print!(m, "\n");
586         }
587     }
588     Ok(())
589 }
590 
rust_binder_proc_show_impl(m: &SeqFile, pid: Pid) -> Result<()>591 fn rust_binder_proc_show_impl(m: &SeqFile, pid: Pid) -> Result<()> {
592     seq_print!(m, "binder proc state:\n");
593     let contexts = context::get_all_contexts()?;
594     for ctx in contexts {
595         let procs = ctx.get_procs_with_pid(pid)?;
596         for proc in procs {
597             proc.debug_print(m, &ctx, true)?;
598             seq_print!(m, "\n");
599         }
600     }
601     Ok(())
602 }
603 
604 struct BinderfsProcFile(NonNull<bindings::dentry>);
605 
606 // SAFETY: Safe to drop any thread.
607 unsafe impl Send for BinderfsProcFile {}
608 
609 impl BinderfsProcFile {
610     /// # Safety
611     ///
612     /// Takes an inode from a newly created binder file.
new(nodp: *mut bindings::inode, pid: i32) -> Result<Option<Self>>613     unsafe fn new(nodp: *mut bindings::inode, pid: i32) -> Result<Option<Self>> {
614         // SAFETY: The caller passes an `inode` for a newly created binder file.
615         let dentry = unsafe { binderfs::rust_binderfs_create_proc_file(nodp, pid) };
616         match kernel::error::from_err_ptr(dentry) {
617             Ok(dentry) => Ok(NonNull::new(dentry).map(Self)),
618             Err(err) if err == EEXIST => Ok(None),
619             Err(err) => Err(err),
620         }
621     }
622 }
623 
624 impl Drop for BinderfsProcFile {
drop(&mut self)625     fn drop(&mut self) {
626         // SAFETY: This is a dentry from `rust_binderfs_remove_file` that has not been deleted yet.
627         unsafe { binderfs::rust_binderfs_remove_file(self.0.as_ptr()) };
628     }
629 }
630