projects/linux·blob master · refs

626 lines · 18.5 KiB

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