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