| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617 |
- // SPDX-License-Identifier: GPL-2.0
- // Copyright (C) 2025 Google LLC.
- //! Binder -- the Android IPC mechanism.
- #![recursion_limit = "256"]
- #![allow(
- clippy::as_underscore,
- clippy::ref_as_ptr,
- clippy::ptr_as_ptr,
- clippy::cast_lossless
- )]
- use kernel::{
- bindings::{self, seq_file},
- fs::File,
- list::{ListArc, ListArcSafe, ListLinksSelfPtr, TryNewListArc},
- prelude::*,
- seq_file::SeqFile,
- seq_print,
- sync::atomic::{ordering::Relaxed, Atomic},
- sync::poll::PollTable,
- sync::Arc,
- task::Pid,
- transmute::AsBytes,
- types::ForeignOwnable,
- uaccess::UserSliceWriter,
- };
- use crate::{context::Context, page_range::Shrinker, process::Process, thread::Thread};
- use core::ptr::NonNull;
- mod allocation;
- mod context;
- mod deferred_close;
- mod defs;
- mod error;
- mod node;
- mod page_range;
- mod process;
- mod range_alloc;
- mod stats;
- mod thread;
- mod trace;
- mod transaction;
- #[allow(warnings)] // generated bindgen code
- mod binderfs {
- use kernel::bindings::{dentry, inode};
- extern "C" {
- pub fn init_rust_binderfs() -> kernel::ffi::c_int;
- }
- extern "C" {
- pub fn rust_binderfs_create_proc_file(
- nodp: *mut inode,
- pid: kernel::ffi::c_int,
- ) -> *mut dentry;
- }
- extern "C" {
- pub fn rust_binderfs_remove_file(dentry: *mut dentry);
- }
- pub type rust_binder_context = *mut kernel::ffi::c_void;
- #[repr(C)]
- #[derive(Copy, Clone)]
- pub struct binder_device {
- pub minor: kernel::ffi::c_int,
- pub ctx: rust_binder_context,
- }
- impl Default for binder_device {
- fn default() -> Self {
- let mut s = ::core::mem::MaybeUninit::<Self>::uninit();
- unsafe {
- ::core::ptr::write_bytes(s.as_mut_ptr(), 0, 1);
- s.assume_init()
- }
- }
- }
- }
- module! {
- type: BinderModule,
- name: "rust_binder",
- authors: ["Wedson Almeida Filho", "Alice Ryhl"],
- description: "Android Binder",
- license: "GPL",
- }
- use kernel::bindings::rust_binder_layout;
- #[no_mangle]
- static RUST_BINDER_LAYOUT: rust_binder_layout = rust_binder_layout {
- t: transaction::TRANSACTION_LAYOUT,
- p: process::PROCESS_LAYOUT,
- n: node::NODE_LAYOUT,
- };
- fn next_debug_id() -> usize {
- static NEXT_DEBUG_ID: Atomic<usize> = Atomic::new(0);
- NEXT_DEBUG_ID.fetch_add(1, Relaxed)
- }
- /// Provides a single place to write Binder return values via the
- /// supplied `UserSliceWriter`.
- pub(crate) struct BinderReturnWriter<'a> {
- writer: UserSliceWriter,
- thread: &'a Thread,
- }
- impl<'a> BinderReturnWriter<'a> {
- fn new(writer: UserSliceWriter, thread: &'a Thread) -> Self {
- BinderReturnWriter { writer, thread }
- }
- /// Write a return code back to user space.
- /// Should be a `BR_` constant from [`defs`] e.g. [`defs::BR_TRANSACTION_COMPLETE`].
- fn write_code(&mut self, code: u32) -> Result {
- stats::GLOBAL_STATS.inc_br(code);
- self.thread.process.stats.inc_br(code);
- self.writer.write(&code)
- }
- /// Write something *other than* a return code to user space.
- fn write_payload<T: AsBytes>(&mut self, payload: &T) -> Result {
- self.writer.write(payload)
- }
- fn len(&self) -> usize {
- self.writer.len()
- }
- }
- /// Specifies how a type should be delivered to the read part of a BINDER_WRITE_READ ioctl.
- ///
- /// When a value is pushed to the todo list for a process or thread, it is stored as a trait object
- /// with the type `Arc<dyn DeliverToRead>`. Trait objects are a Rust feature that lets you
- /// implement dynamic dispatch over many different types. This lets us store many different types
- /// in the todo list.
- trait DeliverToRead: ListArcSafe + Send + Sync {
- /// Performs work. Returns true if remaining work items in the queue should be processed
- /// immediately, or false if it should return to caller before processing additional work
- /// items.
- fn do_work(
- self: DArc<Self>,
- thread: &Thread,
- writer: &mut BinderReturnWriter<'_>,
- ) -> Result<bool>;
- /// Cancels the given work item. This is called instead of [`DeliverToRead::do_work`] when work
- /// won't be delivered.
- fn cancel(self: DArc<Self>);
- /// Should we use `wake_up_interruptible_sync` or `wake_up_interruptible` when scheduling this
- /// work item?
- ///
- /// Generally only set to true for non-oneway transactions.
- fn should_sync_wakeup(&self) -> bool;
- fn debug_print(&self, m: &SeqFile, prefix: &str, transaction_prefix: &str) -> Result<()>;
- }
- // Wrapper around a `DeliverToRead` with linked list links.
- #[pin_data]
- struct DTRWrap<T: ?Sized> {
- #[pin]
- links: ListLinksSelfPtr<DTRWrap<dyn DeliverToRead>>,
- #[pin]
- wrapped: T,
- }
- kernel::list::impl_list_arc_safe! {
- impl{T: ListArcSafe + ?Sized} ListArcSafe<0> for DTRWrap<T> {
- tracked_by wrapped: T;
- }
- }
- kernel::list::impl_list_item! {
- impl ListItem<0> for DTRWrap<dyn DeliverToRead> {
- using ListLinksSelfPtr { self.links };
- }
- }
- impl<T: ?Sized> core::ops::Deref for DTRWrap<T> {
- type Target = T;
- fn deref(&self) -> &T {
- &self.wrapped
- }
- }
- type DArc<T> = kernel::sync::Arc<DTRWrap<T>>;
- type DLArc<T> = kernel::list::ListArc<DTRWrap<T>>;
- impl<T: ListArcSafe> DTRWrap<T> {
- fn new(val: impl PinInit<T>) -> impl PinInit<Self> {
- pin_init!(Self {
- links <- ListLinksSelfPtr::new(),
- wrapped <- val,
- })
- }
- fn arc_try_new(val: T) -> Result<DLArc<T>, kernel::alloc::AllocError> {
- ListArc::pin_init(
- try_pin_init!(Self {
- links <- ListLinksSelfPtr::new(),
- wrapped: val,
- }),
- GFP_KERNEL,
- )
- .map_err(|_| kernel::alloc::AllocError)
- }
- fn arc_pin_init(init: impl PinInit<T>) -> Result<DLArc<T>, kernel::error::Error> {
- ListArc::pin_init(
- try_pin_init!(Self {
- links <- ListLinksSelfPtr::new(),
- wrapped <- init,
- }),
- GFP_KERNEL,
- )
- }
- }
- struct DeliverCode {
- code: u32,
- skip: Atomic<bool>,
- }
- kernel::list::impl_list_arc_safe! {
- impl ListArcSafe<0> for DeliverCode { untracked; }
- }
- impl DeliverCode {
- fn new(code: u32) -> Self {
- Self {
- code,
- skip: Atomic::new(false),
- }
- }
- /// Disable this DeliverCode and make it do nothing.
- ///
- /// This is used instead of removing it from the work list, since `LinkedList::remove` is
- /// unsafe, whereas this method is not.
- fn skip(&self) {
- self.skip.store(true, Relaxed);
- }
- }
- impl DeliverToRead for DeliverCode {
- fn do_work(
- self: DArc<Self>,
- _thread: &Thread,
- writer: &mut BinderReturnWriter<'_>,
- ) -> Result<bool> {
- if !self.skip.load(Relaxed) {
- writer.write_code(self.code)?;
- }
- Ok(true)
- }
- fn cancel(self: DArc<Self>) {}
- fn should_sync_wakeup(&self) -> bool {
- false
- }
- fn debug_print(&self, m: &SeqFile, prefix: &str, _tprefix: &str) -> Result<()> {
- seq_print!(m, "{}", prefix);
- if self.skip.load(Relaxed) {
- seq_print!(m, "(skipped) ");
- }
- if self.code == defs::BR_TRANSACTION_COMPLETE {
- seq_print!(m, "transaction complete\n");
- } else {
- seq_print!(m, "transaction error: {}\n", self.code);
- }
- Ok(())
- }
- }
- fn ptr_align(value: usize) -> Option<usize> {
- let size = core::mem::size_of::<usize>() - 1;
- Some(value.checked_add(size)? & !size)
- }
- // SAFETY: We call register in `init`.
- static BINDER_SHRINKER: Shrinker = unsafe { Shrinker::new() };
- struct BinderModule {}
- impl kernel::Module for BinderModule {
- fn init(_module: &'static kernel::ThisModule) -> Result<Self> {
- // SAFETY: The module initializer never runs twice, so we only call this once.
- unsafe { crate::context::CONTEXTS.init() };
- pr_warn!("Loaded Rust Binder.");
- BINDER_SHRINKER.register(c"android-binder")?;
- // SAFETY: The module is being loaded, so we can initialize binderfs.
- unsafe { kernel::error::to_result(binderfs::init_rust_binderfs())? };
- Ok(Self {})
- }
- }
- /// Makes the inner type Sync.
- #[repr(transparent)]
- pub struct AssertSync<T>(T);
- // SAFETY: Used only to insert C bindings types into globals, which is safe.
- unsafe impl<T> Sync for AssertSync<T> {}
- /// File operations that rust_binderfs.c can use.
- #[no_mangle]
- #[used]
- pub static rust_binder_fops: AssertSync<kernel::bindings::file_operations> = {
- // SAFETY: All zeroes is safe for the `file_operations` type.
- let zeroed_ops = unsafe { core::mem::MaybeUninit::zeroed().assume_init() };
- let ops = kernel::bindings::file_operations {
- owner: THIS_MODULE.as_ptr(),
- poll: Some(rust_binder_poll),
- unlocked_ioctl: Some(rust_binder_ioctl),
- compat_ioctl: bindings::compat_ptr_ioctl,
- mmap: Some(rust_binder_mmap),
- open: Some(rust_binder_open),
- release: Some(rust_binder_release),
- flush: Some(rust_binder_flush),
- ..zeroed_ops
- };
- AssertSync(ops)
- };
- /// # Safety
- /// Only called by binderfs.
- #[no_mangle]
- unsafe extern "C" fn rust_binder_new_context(
- name: *const kernel::ffi::c_char,
- ) -> *mut kernel::ffi::c_void {
- // SAFETY: The caller will always provide a valid c string here.
- let name = unsafe { kernel::str::CStr::from_char_ptr(name) };
- match Context::new(name) {
- Ok(ctx) => Arc::into_foreign(ctx),
- Err(_err) => core::ptr::null_mut(),
- }
- }
- /// # Safety
- /// Only called by binderfs.
- #[no_mangle]
- unsafe extern "C" fn rust_binder_remove_context(device: *mut kernel::ffi::c_void) {
- if !device.is_null() {
- // SAFETY: The caller ensures that the `device` pointer came from a previous call to
- // `rust_binder_new_device`.
- let ctx = unsafe { Arc::<Context>::from_foreign(device) };
- ctx.deregister();
- drop(ctx);
- }
- }
- /// # Safety
- /// Only called by binderfs.
- unsafe extern "C" fn rust_binder_open(
- inode: *mut bindings::inode,
- file_ptr: *mut bindings::file,
- ) -> kernel::ffi::c_int {
- // SAFETY: The `rust_binderfs.c` file ensures that `i_private` is set to a
- // `struct binder_device`.
- let device = unsafe { (*inode).i_private } as *const binderfs::binder_device;
- assert!(!device.is_null());
- // SAFETY: The `rust_binderfs.c` file ensures that `device->ctx` holds a binder context when
- // using the rust binder fops.
- let ctx = unsafe { Arc::<Context>::borrow((*device).ctx) };
- // SAFETY: The caller provides a valid file pointer to a new `struct file`.
- let file = unsafe { File::from_raw_file(file_ptr) };
- let process = match Process::open(ctx, file) {
- Ok(process) => process,
- Err(err) => return err.to_errno(),
- };
- // SAFETY: This is an `inode` for a newly created binder file.
- match unsafe { BinderfsProcFile::new(inode, process.task.pid()) } {
- Ok(Some(file)) => process.inner.lock().binderfs_file = Some(file),
- Ok(None) => { /* pid already exists */ }
- Err(err) => return err.to_errno(),
- }
- // SAFETY: This file is associated with Rust binder, so we own the `private_data` field.
- unsafe { (*file_ptr).private_data = process.into_foreign() };
- 0
- }
- /// # Safety
- /// Only called by binderfs.
- unsafe extern "C" fn rust_binder_release(
- _inode: *mut bindings::inode,
- file: *mut bindings::file,
- ) -> kernel::ffi::c_int {
- // SAFETY: We previously set `private_data` in `rust_binder_open`.
- let process = unsafe { Arc::<Process>::from_foreign((*file).private_data) };
- // SAFETY: The caller ensures that the file is valid.
- let file = unsafe { File::from_raw_file(file) };
- Process::release(process, file);
- 0
- }
- /// # Safety
- /// Only called by binderfs.
- unsafe extern "C" fn rust_binder_ioctl(
- file: *mut bindings::file,
- cmd: kernel::ffi::c_uint,
- arg: kernel::ffi::c_ulong,
- ) -> kernel::ffi::c_long {
- // SAFETY: We previously set `private_data` in `rust_binder_open`.
- let f = unsafe { Arc::<Process>::borrow((*file).private_data) };
- // SAFETY: The caller ensures that the file is valid.
- match Process::ioctl(f, unsafe { File::from_raw_file(file) }, cmd as _, arg as _) {
- Ok(()) => 0,
- Err(err) => err.to_errno() as isize,
- }
- }
- /// # Safety
- /// Only called by binderfs.
- unsafe extern "C" fn rust_binder_mmap(
- file: *mut bindings::file,
- vma: *mut bindings::vm_area_struct,
- ) -> kernel::ffi::c_int {
- // SAFETY: We previously set `private_data` in `rust_binder_open`.
- let f = unsafe { Arc::<Process>::borrow((*file).private_data) };
- // SAFETY: The caller ensures that the vma is valid.
- let area = unsafe { kernel::mm::virt::VmaNew::from_raw(vma) };
- // SAFETY: The caller ensures that the file is valid.
- match Process::mmap(f, unsafe { File::from_raw_file(file) }, area) {
- Ok(()) => 0,
- Err(err) => err.to_errno(),
- }
- }
- /// # Safety
- /// Only called by binderfs.
- unsafe extern "C" fn rust_binder_poll(
- file: *mut bindings::file,
- wait: *mut bindings::poll_table_struct,
- ) -> bindings::__poll_t {
- // SAFETY: We previously set `private_data` in `rust_binder_open`.
- let f = unsafe { Arc::<Process>::borrow((*file).private_data) };
- // SAFETY: The caller ensures that the file is valid.
- let fileref = unsafe { File::from_raw_file(file) };
- // SAFETY: The caller ensures that the `PollTable` is valid.
- match Process::poll(f, fileref, unsafe { PollTable::from_raw(wait) }) {
- Ok(v) => v,
- Err(_) => bindings::POLLERR,
- }
- }
- /// # Safety
- /// Only called by binderfs.
- unsafe extern "C" fn rust_binder_flush(
- file: *mut bindings::file,
- _id: bindings::fl_owner_t,
- ) -> kernel::ffi::c_int {
- // SAFETY: We previously set `private_data` in `rust_binder_open`.
- let f = unsafe { Arc::<Process>::borrow((*file).private_data) };
- match Process::flush(f) {
- Ok(()) => 0,
- Err(err) => err.to_errno(),
- }
- }
- /// # Safety
- /// Only called by binderfs.
- #[no_mangle]
- unsafe extern "C" fn rust_binder_stats_show(
- ptr: *mut seq_file,
- _: *mut kernel::ffi::c_void,
- ) -> kernel::ffi::c_int {
- // SAFETY: The caller ensures that the pointer is valid and exclusive for the duration in which
- // this method is called.
- let m = unsafe { SeqFile::from_raw(ptr) };
- if let Err(err) = rust_binder_stats_show_impl(m) {
- seq_print!(m, "failed to generate state: {:?}\n", err);
- }
- 0
- }
- /// # Safety
- /// Only called by binderfs.
- #[no_mangle]
- unsafe extern "C" fn rust_binder_state_show(
- ptr: *mut seq_file,
- _: *mut kernel::ffi::c_void,
- ) -> kernel::ffi::c_int {
- // SAFETY: The caller ensures that the pointer is valid and exclusive for the duration in which
- // this method is called.
- let m = unsafe { SeqFile::from_raw(ptr) };
- if let Err(err) = rust_binder_state_show_impl(m) {
- seq_print!(m, "failed to generate state: {:?}\n", err);
- }
- 0
- }
- /// # Safety
- /// Only called by binderfs.
- #[no_mangle]
- unsafe extern "C" fn rust_binder_proc_show(
- ptr: *mut seq_file,
- _: *mut kernel::ffi::c_void,
- ) -> kernel::ffi::c_int {
- // SAFETY: Accessing the private field of `seq_file` is okay.
- let pid = (unsafe { (*ptr).private }) as usize as Pid;
- // SAFETY: The caller ensures that the pointer is valid and exclusive for the duration in which
- // this method is called.
- let m = unsafe { SeqFile::from_raw(ptr) };
- if let Err(err) = rust_binder_proc_show_impl(m, pid) {
- seq_print!(m, "failed to generate state: {:?}\n", err);
- }
- 0
- }
- /// # Safety
- /// Only called by binderfs.
- #[no_mangle]
- unsafe extern "C" fn rust_binder_transactions_show(
- ptr: *mut seq_file,
- _: *mut kernel::ffi::c_void,
- ) -> kernel::ffi::c_int {
- // SAFETY: The caller ensures that the pointer is valid and exclusive for the duration in which
- // this method is called.
- let m = unsafe { SeqFile::from_raw(ptr) };
- if let Err(err) = rust_binder_transactions_show_impl(m) {
- seq_print!(m, "failed to generate state: {:?}\n", err);
- }
- 0
- }
- fn rust_binder_transactions_show_impl(m: &SeqFile) -> Result<()> {
- seq_print!(m, "binder transactions:\n");
- let contexts = context::get_all_contexts()?;
- for ctx in contexts {
- let procs = ctx.get_all_procs()?;
- for proc in procs {
- proc.debug_print(m, &ctx, false)?;
- seq_print!(m, "\n");
- }
- }
- Ok(())
- }
- fn rust_binder_stats_show_impl(m: &SeqFile) -> Result<()> {
- seq_print!(m, "binder stats:\n");
- stats::GLOBAL_STATS.debug_print("", m);
- let contexts = context::get_all_contexts()?;
- for ctx in contexts {
- let procs = ctx.get_all_procs()?;
- for proc in procs {
- proc.debug_print_stats(m, &ctx)?;
- seq_print!(m, "\n");
- }
- }
- Ok(())
- }
- fn rust_binder_state_show_impl(m: &SeqFile) -> Result<()> {
- seq_print!(m, "binder state:\n");
- let contexts = context::get_all_contexts()?;
- for ctx in contexts {
- let procs = ctx.get_all_procs()?;
- for proc in procs {
- proc.debug_print(m, &ctx, true)?;
- seq_print!(m, "\n");
- }
- }
- Ok(())
- }
- fn rust_binder_proc_show_impl(m: &SeqFile, pid: Pid) -> Result<()> {
- seq_print!(m, "binder proc state:\n");
- let contexts = context::get_all_contexts()?;
- for ctx in contexts {
- let procs = ctx.get_procs_with_pid(pid)?;
- for proc in procs {
- proc.debug_print(m, &ctx, true)?;
- seq_print!(m, "\n");
- }
- }
- Ok(())
- }
- struct BinderfsProcFile(NonNull<bindings::dentry>);
- // SAFETY: Safe to drop any thread.
- unsafe impl Send for BinderfsProcFile {}
- impl BinderfsProcFile {
- /// # Safety
- ///
- /// Takes an inode from a newly created binder file.
- unsafe fn new(nodp: *mut bindings::inode, pid: i32) -> Result<Option<Self>> {
- // SAFETY: The caller passes an `inode` for a newly created binder file.
- let dentry = unsafe { binderfs::rust_binderfs_create_proc_file(nodp, pid) };
- match kernel::error::from_err_ptr(dentry) {
- Ok(dentry) => Ok(NonNull::new(dentry).map(Self)),
- Err(err) if err == EEXIST => Ok(None),
- Err(err) => Err(err),
- }
- }
- }
- impl Drop for BinderfsProcFile {
- fn drop(&mut self) {
- // SAFETY: This is a dentry from `rust_binderfs_remove_file` that has not been deleted yet.
- unsafe { binderfs::rust_binderfs_remove_file(self.0.as_ptr()) };
- }
- }
|