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 stats::GLOBAL_STATS.inc_br(code);
122 self.thread.process.stats.inc_br(code);
123 self.writer.write(&code)
124 }
125
126 /// Write something *other than* a return code to user space.
write_payload<T: AsBytes>(&mut self, payload: &T) -> Result127 fn write_payload<T: AsBytes>(&mut self, payload: &T) -> Result {
128 self.writer.write(payload)
129 }
130
len(&self) -> usize131 fn len(&self) -> usize {
132 self.writer.len()
133 }
134 }
135
136 /// Specifies how a type should be delivered to the read part of a BINDER_WRITE_READ ioctl.
137 ///
138 /// When a value is pushed to the todo list for a process or thread, it is stored as a trait object
139 /// with the type `Arc<dyn DeliverToRead>`. Trait objects are a Rust feature that lets you
140 /// implement dynamic dispatch over many different types. This lets us store many different types
141 /// in the todo list.
142 trait DeliverToRead: ListArcSafe + Send + Sync {
143 /// Performs work. Returns true if remaining work items in the queue should be processed
144 /// immediately, or false if it should return to caller before processing additional work
145 /// items.
do_work( self: DArc<Self>, thread: &Thread, writer: &mut BinderReturnWriter<'_>, ) -> Result<bool>146 fn do_work(
147 self: DArc<Self>,
148 thread: &Thread,
149 writer: &mut BinderReturnWriter<'_>,
150 ) -> Result<bool>;
151
152 /// Cancels the given work item. This is called instead of [`DeliverToRead::do_work`] when work
153 /// won't be delivered.
cancel(self: DArc<Self>)154 fn cancel(self: DArc<Self>);
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_list_arc_safe! {
174 impl{T: ListArcSafe + ?Sized} ListArcSafe<0> for DTRWrap<T> {
175 tracked_by wrapped: T;
176 }
177 }
178 kernel::list::impl_list_item! {
179 impl ListItem<0> for DTRWrap<dyn DeliverToRead> {
180 using ListLinksSelfPtr { self.links };
181 }
182 }
183
184 impl<T: ?Sized> core::ops::Deref for DTRWrap<T> {
185 type Target = T;
deref(&self) -> &T186 fn deref(&self) -> &T {
187 &self.wrapped
188 }
189 }
190
191 type DArc<T> = kernel::sync::Arc<DTRWrap<T>>;
192 type DLArc<T> = kernel::list::ListArc<DTRWrap<T>>;
193
194 impl<T: ListArcSafe> DTRWrap<T> {
new(val: impl PinInit<T>) -> impl PinInit<Self>195 fn new(val: impl PinInit<T>) -> impl PinInit<Self> {
196 pin_init!(Self {
197 links <- ListLinksSelfPtr::new(),
198 wrapped <- val,
199 })
200 }
201
arc_try_new(val: T) -> Result<DLArc<T>, kernel::alloc::AllocError>202 fn arc_try_new(val: T) -> Result<DLArc<T>, kernel::alloc::AllocError> {
203 ListArc::pin_init(
204 try_pin_init!(Self {
205 links <- ListLinksSelfPtr::new(),
206 wrapped: val,
207 }),
208 GFP_KERNEL,
209 )
210 .map_err(|_| kernel::alloc::AllocError)
211 }
212
arc_pin_init(init: impl PinInit<T>) -> Result<DLArc<T>, kernel::error::Error>213 fn arc_pin_init(init: impl PinInit<T>) -> Result<DLArc<T>, kernel::error::Error> {
214 ListArc::pin_init(
215 try_pin_init!(Self {
216 links <- ListLinksSelfPtr::new(),
217 wrapped <- init,
218 }),
219 GFP_KERNEL,
220 )
221 }
222 }
223
224 struct DeliverCode {
225 code: u32,
226 skip: Atomic<bool>,
227 }
228
229 kernel::list::impl_list_arc_safe! {
230 impl ListArcSafe<0> for DeliverCode { untracked; }
231 }
232
233 impl DeliverCode {
new(code: u32) -> Self234 fn new(code: u32) -> Self {
235 Self {
236 code,
237 skip: Atomic::new(false),
238 }
239 }
240
241 /// Disable this DeliverCode and make it do nothing.
242 ///
243 /// This is used instead of removing it from the work list, since `LinkedList::remove` is
244 /// unsafe, whereas this method is not.
skip(&self)245 fn skip(&self) {
246 self.skip.store(true, Relaxed);
247 }
248 }
249
250 impl DeliverToRead for DeliverCode {
do_work( self: DArc<Self>, _thread: &Thread, writer: &mut BinderReturnWriter<'_>, ) -> Result<bool>251 fn do_work(
252 self: DArc<Self>,
253 _thread: &Thread,
254 writer: &mut BinderReturnWriter<'_>,
255 ) -> Result<bool> {
256 if !self.skip.load(Relaxed) {
257 writer.write_code(self.code)?;
258 }
259 Ok(true)
260 }
261
cancel(self: DArc<Self>)262 fn cancel(self: DArc<Self>) {}
263
should_sync_wakeup(&self) -> bool264 fn should_sync_wakeup(&self) -> bool {
265 false
266 }
267
debug_print(&self, m: &SeqFile, prefix: &str, _tprefix: &str) -> Result<()>268 fn debug_print(&self, m: &SeqFile, prefix: &str, _tprefix: &str) -> Result<()> {
269 seq_print!(m, "{}", prefix);
270 if self.skip.load(Relaxed) {
271 seq_print!(m, "(skipped) ");
272 }
273 if self.code == defs::BR_TRANSACTION_COMPLETE {
274 seq_print!(m, "transaction complete\n");
275 } else {
276 seq_print!(m, "transaction error: {}\n", self.code);
277 }
278 Ok(())
279 }
280 }
281
ptr_align(value: usize) -> Option<usize>282 fn ptr_align(value: usize) -> Option<usize> {
283 let size = core::mem::size_of::<usize>() - 1;
284 Some(value.checked_add(size)? & !size)
285 }
286
287 // SAFETY: We call register in `init`.
288 static BINDER_SHRINKER: Shrinker = unsafe { Shrinker::new() };
289
290 struct BinderModule {}
291
292 impl kernel::Module for BinderModule {
init(_module: &'static kernel::ThisModule) -> Result<Self>293 fn init(_module: &'static kernel::ThisModule) -> Result<Self> {
294 // SAFETY: The module initializer never runs twice, so we only call this once.
295 unsafe { crate::context::CONTEXTS.init() };
296
297 pr_warn!("Loaded Rust Binder.");
298
299 BINDER_SHRINKER.register(c"android-binder")?;
300
301 // SAFETY: The module is being loaded, so we can initialize binderfs.
302 unsafe { kernel::error::to_result(binderfs::init_rust_binderfs())? };
303
304 Ok(Self {})
305 }
306 }
307
308 /// Makes the inner type Sync.
309 #[repr(transparent)]
310 pub struct AssertSync<T>(T);
311 // SAFETY: Used only to insert C bindings types into globals, which is safe.
312 unsafe impl<T> Sync for AssertSync<T> {}
313
314 /// File operations that rust_binderfs.c can use.
315 #[no_mangle]
316 #[used]
317 pub static rust_binder_fops: AssertSync<kernel::bindings::file_operations> = {
318 // SAFETY: All zeroes is safe for the `file_operations` type.
319 let zeroed_ops = unsafe { core::mem::MaybeUninit::zeroed().assume_init() };
320
321 let ops = kernel::bindings::file_operations {
322 owner: THIS_MODULE.as_ptr(),
323 poll: Some(rust_binder_poll),
324 unlocked_ioctl: Some(rust_binder_ioctl),
325 compat_ioctl: bindings::compat_ptr_ioctl,
326 mmap: Some(rust_binder_mmap),
327 open: Some(rust_binder_open),
328 release: Some(rust_binder_release),
329 flush: Some(rust_binder_flush),
330 ..zeroed_ops
331 };
332 AssertSync(ops)
333 };
334
335 /// # Safety
336 /// Only called by binderfs.
337 #[no_mangle]
rust_binder_new_context( name: *const kernel::ffi::c_char, ) -> *mut kernel::ffi::c_void338 unsafe extern "C" fn rust_binder_new_context(
339 name: *const kernel::ffi::c_char,
340 ) -> *mut kernel::ffi::c_void {
341 // SAFETY: The caller will always provide a valid c string here.
342 let name = unsafe { kernel::str::CStr::from_char_ptr(name) };
343 match Context::new(name) {
344 Ok(ctx) => Arc::into_foreign(ctx),
345 Err(_err) => core::ptr::null_mut(),
346 }
347 }
348
349 /// # Safety
350 /// Only called by binderfs.
351 #[no_mangle]
rust_binder_remove_context(device: *mut kernel::ffi::c_void)352 unsafe extern "C" fn rust_binder_remove_context(device: *mut kernel::ffi::c_void) {
353 if !device.is_null() {
354 // SAFETY: The caller ensures that the `device` pointer came from a previous call to
355 // `rust_binder_new_device`.
356 let ctx = unsafe { Arc::<Context>::from_foreign(device) };
357 ctx.deregister();
358 drop(ctx);
359 }
360 }
361
362 /// # Safety
363 /// Only called by binderfs.
rust_binder_open( inode: *mut bindings::inode, file_ptr: *mut bindings::file, ) -> kernel::ffi::c_int364 unsafe extern "C" fn rust_binder_open(
365 inode: *mut bindings::inode,
366 file_ptr: *mut bindings::file,
367 ) -> kernel::ffi::c_int {
368 // SAFETY: The `rust_binderfs.c` file ensures that `i_private` is set to a
369 // `struct binder_device`.
370 let device = unsafe { (*inode).i_private } as *const binderfs::binder_device;
371
372 assert!(!device.is_null());
373
374 // SAFETY: The `rust_binderfs.c` file ensures that `device->ctx` holds a binder context when
375 // using the rust binder fops.
376 let ctx = unsafe { Arc::<Context>::borrow((*device).ctx) };
377
378 // SAFETY: The caller provides a valid file pointer to a new `struct file`.
379 let file = unsafe { File::from_raw_file(file_ptr) };
380 let process = match Process::open(ctx, file) {
381 Ok(process) => process,
382 Err(err) => return err.to_errno(),
383 };
384
385 // SAFETY: This is an `inode` for a newly created binder file.
386 match unsafe { BinderfsProcFile::new(inode, process.task.pid()) } {
387 Ok(Some(file)) => process.inner.lock().binderfs_file = Some(file),
388 Ok(None) => { /* pid already exists */ }
389 Err(err) => return err.to_errno(),
390 }
391
392 // SAFETY: This file is associated with Rust binder, so we own the `private_data` field.
393 unsafe { (*file_ptr).private_data = process.into_foreign() };
394 0
395 }
396
397 /// # Safety
398 /// Only called by binderfs.
rust_binder_release( _inode: *mut bindings::inode, file: *mut bindings::file, ) -> kernel::ffi::c_int399 unsafe extern "C" fn rust_binder_release(
400 _inode: *mut bindings::inode,
401 file: *mut bindings::file,
402 ) -> kernel::ffi::c_int {
403 // SAFETY: We previously set `private_data` in `rust_binder_open`.
404 let process = unsafe { Arc::<Process>::from_foreign((*file).private_data) };
405 // SAFETY: The caller ensures that the file is valid.
406 let file = unsafe { File::from_raw_file(file) };
407 Process::release(process, file);
408 0
409 }
410
411 /// # Safety
412 /// Only called by binderfs.
rust_binder_ioctl( file: *mut bindings::file, cmd: kernel::ffi::c_uint, arg: kernel::ffi::c_ulong, ) -> kernel::ffi::c_long413 unsafe extern "C" fn rust_binder_ioctl(
414 file: *mut bindings::file,
415 cmd: kernel::ffi::c_uint,
416 arg: kernel::ffi::c_ulong,
417 ) -> kernel::ffi::c_long {
418 // SAFETY: We previously set `private_data` in `rust_binder_open`.
419 let f = unsafe { Arc::<Process>::borrow((*file).private_data) };
420 // SAFETY: The caller ensures that the file is valid.
421 match Process::ioctl(f, unsafe { File::from_raw_file(file) }, cmd as _, arg as _) {
422 Ok(()) => 0,
423 Err(err) => err.to_errno() as isize,
424 }
425 }
426
427 /// # Safety
428 /// Only called by binderfs.
rust_binder_mmap( file: *mut bindings::file, vma: *mut bindings::vm_area_struct, ) -> kernel::ffi::c_int429 unsafe extern "C" fn rust_binder_mmap(
430 file: *mut bindings::file,
431 vma: *mut bindings::vm_area_struct,
432 ) -> kernel::ffi::c_int {
433 // SAFETY: We previously set `private_data` in `rust_binder_open`.
434 let f = unsafe { Arc::<Process>::borrow((*file).private_data) };
435 // SAFETY: The caller ensures that the vma is valid.
436 let area = unsafe { kernel::mm::virt::VmaNew::from_raw(vma) };
437 // SAFETY: The caller ensures that the file is valid.
438 match Process::mmap(f, unsafe { File::from_raw_file(file) }, area) {
439 Ok(()) => 0,
440 Err(err) => err.to_errno(),
441 }
442 }
443
444 /// # Safety
445 /// Only called by binderfs.
rust_binder_poll( file: *mut bindings::file, wait: *mut bindings::poll_table_struct, ) -> bindings::__poll_t446 unsafe extern "C" fn rust_binder_poll(
447 file: *mut bindings::file,
448 wait: *mut bindings::poll_table_struct,
449 ) -> bindings::__poll_t {
450 // SAFETY: We previously set `private_data` in `rust_binder_open`.
451 let f = unsafe { Arc::<Process>::borrow((*file).private_data) };
452 // SAFETY: The caller ensures that the file is valid.
453 let fileref = unsafe { File::from_raw_file(file) };
454 // SAFETY: The caller ensures that the `PollTable` is valid.
455 match Process::poll(f, fileref, unsafe { PollTable::from_raw(wait) }) {
456 Ok(v) => v,
457 Err(_) => bindings::POLLERR,
458 }
459 }
460
461 /// # Safety
462 /// Only called by binderfs.
rust_binder_flush( file: *mut bindings::file, _id: bindings::fl_owner_t, ) -> kernel::ffi::c_int463 unsafe extern "C" fn rust_binder_flush(
464 file: *mut bindings::file,
465 _id: bindings::fl_owner_t,
466 ) -> kernel::ffi::c_int {
467 // SAFETY: We previously set `private_data` in `rust_binder_open`.
468 let f = unsafe { Arc::<Process>::borrow((*file).private_data) };
469 match Process::flush(f) {
470 Ok(()) => 0,
471 Err(err) => err.to_errno(),
472 }
473 }
474
475 /// # Safety
476 /// Only called by binderfs.
477 #[no_mangle]
rust_binder_stats_show( ptr: *mut seq_file, _: *mut kernel::ffi::c_void, ) -> kernel::ffi::c_int478 unsafe extern "C" fn rust_binder_stats_show(
479 ptr: *mut seq_file,
480 _: *mut kernel::ffi::c_void,
481 ) -> kernel::ffi::c_int {
482 // SAFETY: The caller ensures that the pointer is valid and exclusive for the duration in which
483 // this method is called.
484 let m = unsafe { SeqFile::from_raw(ptr) };
485 if let Err(err) = rust_binder_stats_show_impl(m) {
486 seq_print!(m, "failed to generate state: {:?}\n", err);
487 }
488 0
489 }
490
491 /// # Safety
492 /// Only called by binderfs.
493 #[no_mangle]
rust_binder_state_show( ptr: *mut seq_file, _: *mut kernel::ffi::c_void, ) -> kernel::ffi::c_int494 unsafe extern "C" fn rust_binder_state_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_state_show_impl(m) {
502 seq_print!(m, "failed to generate state: {:?}\n", err);
503 }
504 0
505 }
506
507 /// # Safety
508 /// Only called by binderfs.
509 #[no_mangle]
rust_binder_proc_show( ptr: *mut seq_file, _: *mut kernel::ffi::c_void, ) -> kernel::ffi::c_int510 unsafe extern "C" fn rust_binder_proc_show(
511 ptr: *mut seq_file,
512 _: *mut kernel::ffi::c_void,
513 ) -> kernel::ffi::c_int {
514 // SAFETY: Accessing the private field of `seq_file` is okay.
515 let pid = (unsafe { (*ptr).private }) as usize as Pid;
516 // SAFETY: The caller ensures that the pointer is valid and exclusive for the duration in which
517 // this method is called.
518 let m = unsafe { SeqFile::from_raw(ptr) };
519 if let Err(err) = rust_binder_proc_show_impl(m, pid) {
520 seq_print!(m, "failed to generate state: {:?}\n", err);
521 }
522 0
523 }
524
525 /// # Safety
526 /// Only called by binderfs.
527 #[no_mangle]
rust_binder_transactions_show( ptr: *mut seq_file, _: *mut kernel::ffi::c_void, ) -> kernel::ffi::c_int528 unsafe extern "C" fn rust_binder_transactions_show(
529 ptr: *mut seq_file,
530 _: *mut kernel::ffi::c_void,
531 ) -> kernel::ffi::c_int {
532 // SAFETY: The caller ensures that the pointer is valid and exclusive for the duration in which
533 // this method is called.
534 let m = unsafe { SeqFile::from_raw(ptr) };
535 if let Err(err) = rust_binder_transactions_show_impl(m) {
536 seq_print!(m, "failed to generate state: {:?}\n", err);
537 }
538 0
539 }
540
rust_binder_transactions_show_impl(m: &SeqFile) -> Result<()>541 fn rust_binder_transactions_show_impl(m: &SeqFile) -> Result<()> {
542 seq_print!(m, "binder transactions:\n");
543 let contexts = context::get_all_contexts()?;
544 for ctx in contexts {
545 let procs = ctx.get_all_procs()?;
546 for proc in procs {
547 proc.debug_print(m, &ctx, false)?;
548 seq_print!(m, "\n");
549 }
550 }
551 Ok(())
552 }
553
rust_binder_stats_show_impl(m: &SeqFile) -> Result<()>554 fn rust_binder_stats_show_impl(m: &SeqFile) -> Result<()> {
555 seq_print!(m, "binder stats:\n");
556 stats::GLOBAL_STATS.debug_print("", m);
557 let contexts = context::get_all_contexts()?;
558 for ctx in contexts {
559 let procs = ctx.get_all_procs()?;
560 for proc in procs {
561 proc.debug_print_stats(m, &ctx)?;
562 seq_print!(m, "\n");
563 }
564 }
565 Ok(())
566 }
567
rust_binder_state_show_impl(m: &SeqFile) -> Result<()>568 fn rust_binder_state_show_impl(m: &SeqFile) -> Result<()> {
569 seq_print!(m, "binder state:\n");
570 let contexts = context::get_all_contexts()?;
571 for ctx in contexts {
572 let procs = ctx.get_all_procs()?;
573 for proc in procs {
574 proc.debug_print(m, &ctx, true)?;
575 seq_print!(m, "\n");
576 }
577 }
578 Ok(())
579 }
580
rust_binder_proc_show_impl(m: &SeqFile, pid: Pid) -> Result<()>581 fn rust_binder_proc_show_impl(m: &SeqFile, pid: Pid) -> Result<()> {
582 seq_print!(m, "binder proc state:\n");
583 let contexts = context::get_all_contexts()?;
584 for ctx in contexts {
585 let procs = ctx.get_procs_with_pid(pid)?;
586 for proc in procs {
587 proc.debug_print(m, &ctx, true)?;
588 seq_print!(m, "\n");
589 }
590 }
591 Ok(())
592 }
593
594 struct BinderfsProcFile(NonNull<bindings::dentry>);
595
596 // SAFETY: Safe to drop any thread.
597 unsafe impl Send for BinderfsProcFile {}
598
599 impl BinderfsProcFile {
600 /// # Safety
601 ///
602 /// Takes an inode from a newly created binder file.
new(nodp: *mut bindings::inode, pid: i32) -> Result<Option<Self>>603 unsafe fn new(nodp: *mut bindings::inode, pid: i32) -> Result<Option<Self>> {
604 // SAFETY: The caller passes an `inode` for a newly created binder file.
605 let dentry = unsafe { binderfs::rust_binderfs_create_proc_file(nodp, pid) };
606 match kernel::error::from_err_ptr(dentry) {
607 Ok(dentry) => Ok(NonNull::new(dentry).map(Self)),
608 Err(err) if err == EEXIST => Ok(None),
609 Err(err) => Err(err),
610 }
611 }
612 }
613
614 impl Drop for BinderfsProcFile {
drop(&mut self)615 fn drop(&mut self) {
616 // SAFETY: This is a dentry from `rust_binderfs_remove_file` that has not been deleted yet.
617 unsafe { binderfs::rust_binderfs_remove_file(self.0.as_ptr()) };
618 }
619 }
620