File Index
Files and directories
Sign in
FILE

rust_binder_main.rs

File preview with syntax highlighting.

linux-6.19.14/drivers/android/binder/rust_binder_main.rs RUST
  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
 14use 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
 29use crate::{context::Context, page_range::Shrinker, process::Process, thread::Thread};
 30
 31use core::{
 32    ptr::NonNull,
 33    sync::atomic::{AtomicBool, AtomicUsize, Ordering},
 34};
 35
 36mod allocation;
 37mod context;
 38mod deferred_close;
 39mod defs;
 40mod error;
 41mod node;
 42mod page_range;
 43mod process;
 44mod range_alloc;
 45mod stats;
 46mod thread;
 47mod trace;
 48mod transaction;
 49
 50#[allow(warnings)] // generated bindgen code
 51mod binderfs {
 52    use kernel::bindings::{dentry, inode};
 53
 54    extern "C" {
 55        pub fn init_rust_binderfs() -> kernel::ffi::c_int;
 56    }
 57    extern "C" {
 58        pub fn rust_binderfs_create_proc_file(
 59            nodp: *mut inode,
 60            pid: kernel::ffi::c_int,
 61        ) -> *mut dentry;
 62    }
 63    extern "C" {
 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 {
 74        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
 84module! {
 85    type: BinderModule,
 86    name: "rust_binder",
 87    authors: ["Wedson Almeida Filho", "Alice Ryhl"],
 88    description: "Android Binder",
 89    license: "GPL",
 90}
 91
 92fn 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`.
100pub(crate) struct BinderReturnWriter<'a> {
101    writer: UserSliceWriter,
102    thread: &'a Thread,
103}
104
105impl<'a> BinderReturnWriter<'a> {
106    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`].
112    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.
119    fn write_payload<T: AsBytes>(&mut self, payload: &T) -> Result {
120        self.writer.write(payload)
121    }
122
123    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.
134trait 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.
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.
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.
152    fn should_sync_wakeup(&self) -> bool;
153
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]
159struct DTRWrap<T: ?Sized> {
160    #[pin]
161    links: ListLinksSelfPtr<DTRWrap<dyn DeliverToRead>>,
162    #[pin]
163    wrapped: T,
164}
165kernel::list::impl_list_arc_safe! {
166    impl{T: ListArcSafe + ?Sized} ListArcSafe<0> for DTRWrap<T> {
167        tracked_by wrapped: T;
168    }
169}
170kernel::list::impl_list_item! {
171    impl ListItem<0> for DTRWrap<dyn DeliverToRead> {
172        using ListLinksSelfPtr { self.links };
173    }
174}
175
176impl<T: ?Sized> core::ops::Deref for DTRWrap<T> {
177    type Target = T;
178    fn deref(&self) -> &T {
179        &self.wrapped
180    }
181}
182
183type DArc<T> = kernel::sync::Arc<DTRWrap<T>>;
184type DLArc<T> = kernel::list::ListArc<DTRWrap<T>>;
185
186impl<T: ListArcSafe> DTRWrap<T> {
187    fn new(val: impl PinInit<T>) -> impl PinInit<Self> {
188        pin_init!(Self {
189            links <- ListLinksSelfPtr::new(),
190            wrapped <- val,
191        })
192    }
193
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
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
216struct DeliverCode {
217    code: u32,
218    skip: AtomicBool,
219}
220
221kernel::list::impl_list_arc_safe! {
222    impl ListArcSafe<0> for DeliverCode { untracked; }
223}
224
225impl DeliverCode {
226    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.
237    fn skip(&self) {
238        self.skip.store(true, Ordering::Relaxed);
239    }
240}
241
242impl DeliverToRead for DeliverCode {
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
254    fn cancel(self: DArc<Self>) {}
255
256    fn should_sync_wakeup(&self) -> bool {
257        false
258    }
259
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
274fn 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`.
280static BINDER_SHRINKER: Shrinker = unsafe { Shrinker::new() };
281
282struct BinderModule {}
283
284impl kernel::Module for BinderModule {
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)]
302pub struct AssertSync<T>(T);
303// SAFETY: Used only to insert C bindings types into globals, which is safe.
304unsafe impl<T> Sync for AssertSync<T> {}
305
306/// File operations that rust_binderfs.c can use.
307#[no_mangle]
308#[used]
309pub 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        #[cfg(CONFIG_COMPAT)]
318        compat_ioctl: Some(bindings::compat_ptr_ioctl),
319        mmap: Some(rust_binder_mmap),
320        open: Some(rust_binder_open),
321        release: Some(rust_binder_release),
322        flush: Some(rust_binder_flush),
323        ..zeroed_ops
324    };
325    AssertSync(ops)
326};
327
328/// # Safety
329/// Only called by binderfs.
330#[no_mangle]
331unsafe extern "C" fn rust_binder_new_context(
332    name: *const kernel::ffi::c_char,
333) -> *mut kernel::ffi::c_void {
334    // SAFETY: The caller will always provide a valid c string here.
335    let name = unsafe { kernel::str::CStr::from_char_ptr(name) };
336    match Context::new(name) {
337        Ok(ctx) => Arc::into_foreign(ctx),
338        Err(_err) => core::ptr::null_mut(),
339    }
340}
341
342/// # Safety
343/// Only called by binderfs.
344#[no_mangle]
345unsafe extern "C" fn rust_binder_remove_context(device: *mut kernel::ffi::c_void) {
346    if !device.is_null() {
347        // SAFETY: The caller ensures that the `device` pointer came from a previous call to
348        // `rust_binder_new_device`.
349        let ctx = unsafe { Arc::<Context>::from_foreign(device) };
350        ctx.deregister();
351        drop(ctx);
352    }
353}
354
355/// # Safety
356/// Only called by binderfs.
357unsafe extern "C" fn rust_binder_open(
358    inode: *mut bindings::inode,
359    file_ptr: *mut bindings::file,
360) -> kernel::ffi::c_int {
361    // SAFETY: The `rust_binderfs.c` file ensures that `i_private` is set to a
362    // `struct binder_device`.
363    let device = unsafe { (*inode).i_private } as *const binderfs::binder_device;
364
365    assert!(!device.is_null());
366
367    // SAFETY: The `rust_binderfs.c` file ensures that `device->ctx` holds a binder context when
368    // using the rust binder fops.
369    let ctx = unsafe { Arc::<Context>::borrow((*device).ctx) };
370
371    // SAFETY: The caller provides a valid file pointer to a new `struct file`.
372    let file = unsafe { File::from_raw_file(file_ptr) };
373    let process = match Process::open(ctx, file) {
374        Ok(process) => process,
375        Err(err) => return err.to_errno(),
376    };
377
378    // SAFETY: This is an `inode` for a newly created binder file.
379    match unsafe { BinderfsProcFile::new(inode, process.task.pid()) } {
380        Ok(Some(file)) => process.inner.lock().binderfs_file = Some(file),
381        Ok(None) => { /* pid already exists */ }
382        Err(err) => return err.to_errno(),
383    }
384
385    // SAFETY: This file is associated with Rust binder, so we own the `private_data` field.
386    unsafe { (*file_ptr).private_data = process.into_foreign() };
387    0
388}
389
390/// # Safety
391/// Only called by binderfs.
392unsafe extern "C" fn rust_binder_release(
393    _inode: *mut bindings::inode,
394    file: *mut bindings::file,
395) -> kernel::ffi::c_int {
396    // SAFETY: We previously set `private_data` in `rust_binder_open`.
397    let process = unsafe { Arc::<Process>::from_foreign((*file).private_data) };
398    // SAFETY: The caller ensures that the file is valid.
399    let file = unsafe { File::from_raw_file(file) };
400    Process::release(process, file);
401    0
402}
403
404/// # Safety
405/// Only called by binderfs.
406unsafe extern "C" fn rust_binder_ioctl(
407    file: *mut bindings::file,
408    cmd: kernel::ffi::c_uint,
409    arg: kernel::ffi::c_ulong,
410) -> kernel::ffi::c_long {
411    // SAFETY: We previously set `private_data` in `rust_binder_open`.
412    let f = unsafe { Arc::<Process>::borrow((*file).private_data) };
413    // SAFETY: The caller ensures that the file is valid.
414    match Process::ioctl(f, unsafe { File::from_raw_file(file) }, cmd as _, arg as _) {
415        Ok(()) => 0,
416        Err(err) => err.to_errno() as isize,
417    }
418}
419
420/// # Safety
421/// Only called by binderfs.
422unsafe extern "C" fn rust_binder_mmap(
423    file: *mut bindings::file,
424    vma: *mut bindings::vm_area_struct,
425) -> kernel::ffi::c_int {
426    // SAFETY: We previously set `private_data` in `rust_binder_open`.
427    let f = unsafe { Arc::<Process>::borrow((*file).private_data) };
428    // SAFETY: The caller ensures that the vma is valid.
429    let area = unsafe { kernel::mm::virt::VmaNew::from_raw(vma) };
430    // SAFETY: The caller ensures that the file is valid.
431    match Process::mmap(f, unsafe { File::from_raw_file(file) }, area) {
432        Ok(()) => 0,
433        Err(err) => err.to_errno(),
434    }
435}
436
437/// # Safety
438/// Only called by binderfs.
439unsafe extern "C" fn rust_binder_poll(
440    file: *mut bindings::file,
441    wait: *mut bindings::poll_table_struct,
442) -> bindings::__poll_t {
443    // SAFETY: We previously set `private_data` in `rust_binder_open`.
444    let f = unsafe { Arc::<Process>::borrow((*file).private_data) };
445    // SAFETY: The caller ensures that the file is valid.
446    let fileref = unsafe { File::from_raw_file(file) };
447    // SAFETY: The caller ensures that the `PollTable` is valid.
448    match Process::poll(f, fileref, unsafe { PollTable::from_raw(wait) }) {
449        Ok(v) => v,
450        Err(_) => bindings::POLLERR,
451    }
452}
453
454/// # Safety
455/// Only called by binderfs.
456unsafe extern "C" fn rust_binder_flush(
457    file: *mut bindings::file,
458    _id: bindings::fl_owner_t,
459) -> kernel::ffi::c_int {
460    // SAFETY: We previously set `private_data` in `rust_binder_open`.
461    let f = unsafe { Arc::<Process>::borrow((*file).private_data) };
462    match Process::flush(f) {
463        Ok(()) => 0,
464        Err(err) => err.to_errno(),
465    }
466}
467
468/// # Safety
469/// Only called by binderfs.
470#[no_mangle]
471unsafe extern "C" fn rust_binder_stats_show(
472    ptr: *mut seq_file,
473    _: *mut kernel::ffi::c_void,
474) -> kernel::ffi::c_int {
475    // SAFETY: The caller ensures that the pointer is valid and exclusive for the duration in which
476    // this method is called.
477    let m = unsafe { SeqFile::from_raw(ptr) };
478    if let Err(err) = rust_binder_stats_show_impl(m) {
479        seq_print!(m, "failed to generate state: {:?}\n", err);
480    }
481    0
482}
483
484/// # Safety
485/// Only called by binderfs.
486#[no_mangle]
487unsafe extern "C" fn rust_binder_state_show(
488    ptr: *mut seq_file,
489    _: *mut kernel::ffi::c_void,
490) -> kernel::ffi::c_int {
491    // SAFETY: The caller ensures that the pointer is valid and exclusive for the duration in which
492    // this method is called.
493    let m = unsafe { SeqFile::from_raw(ptr) };
494    if let Err(err) = rust_binder_state_show_impl(m) {
495        seq_print!(m, "failed to generate state: {:?}\n", err);
496    }
497    0
498}
499
500/// # Safety
501/// Only called by binderfs.
502#[no_mangle]
503unsafe extern "C" fn rust_binder_proc_show(
504    ptr: *mut seq_file,
505    _: *mut kernel::ffi::c_void,
506) -> kernel::ffi::c_int {
507    // SAFETY: Accessing the private field of `seq_file` is okay.
508    let pid = (unsafe { (*ptr).private }) as usize as Pid;
509    // SAFETY: The caller ensures that the pointer is valid and exclusive for the duration in which
510    // this method is called.
511    let m = unsafe { SeqFile::from_raw(ptr) };
512    if let Err(err) = rust_binder_proc_show_impl(m, pid) {
513        seq_print!(m, "failed to generate state: {:?}\n", err);
514    }
515    0
516}
517
518/// # Safety
519/// Only called by binderfs.
520#[no_mangle]
521unsafe extern "C" fn rust_binder_transactions_show(
522    ptr: *mut seq_file,
523    _: *mut kernel::ffi::c_void,
524) -> kernel::ffi::c_int {
525    // SAFETY: The caller ensures that the pointer is valid and exclusive for the duration in which
526    // this method is called.
527    let m = unsafe { SeqFile::from_raw(ptr) };
528    if let Err(err) = rust_binder_transactions_show_impl(m) {
529        seq_print!(m, "failed to generate state: {:?}\n", err);
530    }
531    0
532}
533
534fn rust_binder_transactions_show_impl(m: &SeqFile) -> Result<()> {
535    seq_print!(m, "binder transactions:\n");
536    let contexts = context::get_all_contexts()?;
537    for ctx in contexts {
538        let procs = ctx.get_all_procs()?;
539        for proc in procs {
540            proc.debug_print(m, &ctx, false)?;
541            seq_print!(m, "\n");
542        }
543    }
544    Ok(())
545}
546
547fn rust_binder_stats_show_impl(m: &SeqFile) -> Result<()> {
548    seq_print!(m, "binder stats:\n");
549    stats::GLOBAL_STATS.debug_print("", m);
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_stats(m, &ctx)?;
555            seq_print!(m, "\n");
556        }
557    }
558    Ok(())
559}
560
561fn rust_binder_state_show_impl(m: &SeqFile) -> Result<()> {
562    seq_print!(m, "binder state:\n");
563    let contexts = context::get_all_contexts()?;
564    for ctx in contexts {
565        let procs = ctx.get_all_procs()?;
566        for proc in procs {
567            proc.debug_print(m, &ctx, true)?;
568            seq_print!(m, "\n");
569        }
570    }
571    Ok(())
572}
573
574fn rust_binder_proc_show_impl(m: &SeqFile, pid: Pid) -> Result<()> {
575    seq_print!(m, "binder proc state:\n");
576    let contexts = context::get_all_contexts()?;
577    for ctx in contexts {
578        let procs = ctx.get_procs_with_pid(pid)?;
579        for proc in procs {
580            proc.debug_print(m, &ctx, true)?;
581            seq_print!(m, "\n");
582        }
583    }
584    Ok(())
585}
586
587struct BinderfsProcFile(NonNull<bindings::dentry>);
588
589// SAFETY: Safe to drop any thread.
590unsafe impl Send for BinderfsProcFile {}
591
592impl BinderfsProcFile {
593    /// # Safety
594    ///
595    /// Takes an inode from a newly created binder file.
596    unsafe fn new(nodp: *mut bindings::inode, pid: i32) -> Result<Option<Self>> {
597        // SAFETY: The caller passes an `inode` for a newly created binder file.
598        let dentry = unsafe { binderfs::rust_binderfs_create_proc_file(nodp, pid) };
599        match kernel::error::from_err_ptr(dentry) {
600            Ok(dentry) => Ok(NonNull::new(dentry).map(Self)),
601            Err(err) if err == EEXIST => Ok(None),
602            Err(err) => Err(err),
603        }
604    }
605}
606
607impl Drop for BinderfsProcFile {
608    fn drop(&mut self) {
609        // SAFETY: This is a dentry from `rust_binderfs_remove_file` that has not been deleted yet.
610        unsafe { binderfs::rust_binderfs_remove_file(self.0.as_ptr()) };
611    }
612}
~/ Read-only file preview.