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