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