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