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