Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/drivers/android/binder/rust_binder_main.rs
29520 views
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" {
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
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
92
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> {
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.
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.
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]
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;
178
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> {
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
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 {
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
242
impl 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
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 {
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_unlocked_ioctl),
317
compat_ioctl: Some(rust_binder_compat_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]
330
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]
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.
356
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.
391
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.
405
unsafe extern "C" fn rust_binder_compat_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::compat_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.
421
unsafe extern "C" fn rust_binder_unlocked_ioctl(
422
file: *mut bindings::file,
423
cmd: kernel::ffi::c_uint,
424
arg: kernel::ffi::c_ulong,
425
) -> kernel::ffi::c_long {
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 file is valid.
429
match Process::ioctl(f, unsafe { File::from_raw_file(file) }, cmd as _, arg as _) {
430
Ok(()) => 0,
431
Err(err) => err.to_errno() as isize,
432
}
433
}
434
435
/// # Safety
436
/// Only called by binderfs.
437
unsafe extern "C" fn rust_binder_mmap(
438
file: *mut bindings::file,
439
vma: *mut bindings::vm_area_struct,
440
) -> kernel::ffi::c_int {
441
// SAFETY: We previously set `private_data` in `rust_binder_open`.
442
let f = unsafe { Arc::<Process>::borrow((*file).private_data) };
443
// SAFETY: The caller ensures that the vma is valid.
444
let area = unsafe { kernel::mm::virt::VmaNew::from_raw(vma) };
445
// SAFETY: The caller ensures that the file is valid.
446
match Process::mmap(f, unsafe { File::from_raw_file(file) }, area) {
447
Ok(()) => 0,
448
Err(err) => err.to_errno(),
449
}
450
}
451
452
/// # Safety
453
/// Only called by binderfs.
454
unsafe extern "C" fn rust_binder_poll(
455
file: *mut bindings::file,
456
wait: *mut bindings::poll_table_struct,
457
) -> bindings::__poll_t {
458
// SAFETY: We previously set `private_data` in `rust_binder_open`.
459
let f = unsafe { Arc::<Process>::borrow((*file).private_data) };
460
// SAFETY: The caller ensures that the file is valid.
461
let fileref = unsafe { File::from_raw_file(file) };
462
// SAFETY: The caller ensures that the `PollTable` is valid.
463
match Process::poll(f, fileref, unsafe { PollTable::from_raw(wait) }) {
464
Ok(v) => v,
465
Err(_) => bindings::POLLERR,
466
}
467
}
468
469
/// # Safety
470
/// Only called by binderfs.
471
unsafe extern "C" fn rust_binder_flush(
472
file: *mut bindings::file,
473
_id: bindings::fl_owner_t,
474
) -> kernel::ffi::c_int {
475
// SAFETY: We previously set `private_data` in `rust_binder_open`.
476
let f = unsafe { Arc::<Process>::borrow((*file).private_data) };
477
match Process::flush(f) {
478
Ok(()) => 0,
479
Err(err) => err.to_errno(),
480
}
481
}
482
483
/// # Safety
484
/// Only called by binderfs.
485
#[no_mangle]
486
unsafe extern "C" fn rust_binder_stats_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_stats_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]
502
unsafe extern "C" fn rust_binder_state_show(
503
ptr: *mut seq_file,
504
_: *mut kernel::ffi::c_void,
505
) -> kernel::ffi::c_int {
506
// SAFETY: The caller ensures that the pointer is valid and exclusive for the duration in which
507
// this method is called.
508
let m = unsafe { SeqFile::from_raw(ptr) };
509
if let Err(err) = rust_binder_state_show_impl(m) {
510
seq_print!(m, "failed to generate state: {:?}\n", err);
511
}
512
0
513
}
514
515
/// # Safety
516
/// Only called by binderfs.
517
#[no_mangle]
518
unsafe extern "C" fn rust_binder_proc_show(
519
ptr: *mut seq_file,
520
_: *mut kernel::ffi::c_void,
521
) -> kernel::ffi::c_int {
522
// SAFETY: Accessing the private field of `seq_file` is okay.
523
let pid = (unsafe { (*ptr).private }) as usize as Pid;
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_proc_show_impl(m, pid) {
528
seq_print!(m, "failed to generate state: {:?}\n", err);
529
}
530
0
531
}
532
533
/// # Safety
534
/// Only called by binderfs.
535
#[no_mangle]
536
unsafe extern "C" fn rust_binder_transactions_show(
537
ptr: *mut seq_file,
538
_: *mut kernel::ffi::c_void,
539
) -> kernel::ffi::c_int {
540
// SAFETY: The caller ensures that the pointer is valid and exclusive for the duration in which
541
// this method is called.
542
let m = unsafe { SeqFile::from_raw(ptr) };
543
if let Err(err) = rust_binder_transactions_show_impl(m) {
544
seq_print!(m, "failed to generate state: {:?}\n", err);
545
}
546
0
547
}
548
549
fn rust_binder_transactions_show_impl(m: &SeqFile) -> Result<()> {
550
seq_print!(m, "binder transactions:\n");
551
let contexts = context::get_all_contexts()?;
552
for ctx in contexts {
553
let procs = ctx.get_all_procs()?;
554
for proc in procs {
555
proc.debug_print(m, &ctx, false)?;
556
seq_print!(m, "\n");
557
}
558
}
559
Ok(())
560
}
561
562
fn rust_binder_stats_show_impl(m: &SeqFile) -> Result<()> {
563
seq_print!(m, "binder stats:\n");
564
stats::GLOBAL_STATS.debug_print("", m);
565
let contexts = context::get_all_contexts()?;
566
for ctx in contexts {
567
let procs = ctx.get_all_procs()?;
568
for proc in procs {
569
proc.debug_print_stats(m, &ctx)?;
570
seq_print!(m, "\n");
571
}
572
}
573
Ok(())
574
}
575
576
fn rust_binder_state_show_impl(m: &SeqFile) -> Result<()> {
577
seq_print!(m, "binder state:\n");
578
let contexts = context::get_all_contexts()?;
579
for ctx in contexts {
580
let procs = ctx.get_all_procs()?;
581
for proc in procs {
582
proc.debug_print(m, &ctx, true)?;
583
seq_print!(m, "\n");
584
}
585
}
586
Ok(())
587
}
588
589
fn rust_binder_proc_show_impl(m: &SeqFile, pid: Pid) -> Result<()> {
590
seq_print!(m, "binder proc state:\n");
591
let contexts = context::get_all_contexts()?;
592
for ctx in contexts {
593
let procs = ctx.get_procs_with_pid(pid)?;
594
for proc in procs {
595
proc.debug_print(m, &ctx, true)?;
596
seq_print!(m, "\n");
597
}
598
}
599
Ok(())
600
}
601
602
struct BinderfsProcFile(NonNull<bindings::dentry>);
603
604
// SAFETY: Safe to drop any thread.
605
unsafe impl Send for BinderfsProcFile {}
606
607
impl BinderfsProcFile {
608
/// # Safety
609
///
610
/// Takes an inode from a newly created binder file.
611
unsafe fn new(nodp: *mut bindings::inode, pid: i32) -> Result<Option<Self>> {
612
// SAFETY: The caller passes an `inode` for a newly created binder file.
613
let dentry = unsafe { binderfs::rust_binderfs_create_proc_file(nodp, pid) };
614
match kernel::error::from_err_ptr(dentry) {
615
Ok(dentry) => Ok(NonNull::new(dentry).map(Self)),
616
Err(err) if err == EEXIST => Ok(None),
617
Err(err) => Err(err),
618
}
619
}
620
}
621
622
impl Drop for BinderfsProcFile {
623
fn drop(&mut self) {
624
// SAFETY: This is a dentry from `rust_binderfs_remove_file` that has not been deleted yet.
625
unsafe { binderfs::rust_binderfs_remove_file(self.0.as_ptr()) };
626
}
627
}
628
629