• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // SPDX-License-Identifier: GPL-2.0
2 
3 // Copyright (C) 2024 Google LLC.
4 
5 use crate::{defs::BinderTransactionDataSg, node::Node, thread::Thread, transaction::Transaction};
6 
7 use kernel::bindings::{
8     binder_transaction_data_sg, flat_binder_object, rust_binder_node, rust_binder_thread,
9     rust_binder_transaction, task_struct,
10 };
11 use kernel::error::Result;
12 use kernel::ffi::{c_int, c_uint, c_ulong};
13 use kernel::task::{Pid, Task};
14 use kernel::tracepoint::declare_trace;
15 use kernel::uapi;
16 
17 declare_trace! {
18     unsafe fn rust_binder_ioctl(cmd: c_uint, arg: c_ulong);
19     unsafe fn rust_binder_ioctl_done(ret: c_int);
20     unsafe fn rust_binder_read_done(ret: c_int);
21     unsafe fn rust_binder_write_done(ret: c_int);
22     unsafe fn rust_binder_set_priority(thread: *mut task_struct, desired_prio: c_int, new_prio: c_int);
23     unsafe fn android_vh_rust_binder_set_priority(t: rust_binder_transaction, task: *mut task_struct);
24     unsafe fn android_vh_rust_binder_restore_priority(task: *mut task_struct);
25     unsafe fn rust_binder_wait_for_work(proc_work: bool, transaction_stack: bool, thread_todo: bool);
26     unsafe fn rust_binder_transaction(reply: bool, t: rust_binder_transaction);
27     unsafe fn rust_binder_transaction_received(t: rust_binder_transaction);
28     unsafe fn rust_binder_transaction_thread_selected(t: rust_binder_transaction, thread: rust_binder_thread);
29     unsafe fn rust_binder_transaction_node_send(t_debug_id: c_int, n: rust_binder_node,
30                                                 orig: *const flat_binder_object,
31                                                 trans: *const flat_binder_object);
32     unsafe fn rust_binder_transaction_fd_send(t_debug_id: c_int, fd: c_int, offset: usize);
33     unsafe fn rust_binder_transaction_fd_recv(t_debug_id: c_int, fd: c_int, offset: usize);
34     unsafe fn rust_binder_transaction_alloc_buf(debug_id: c_int, data: *const binder_transaction_data_sg);
35     unsafe fn rust_binder_transaction_buffer_release(debug_id: c_int);
36     unsafe fn rust_binder_transaction_failed_buffer_release(debug_id: c_int);
37     unsafe fn rust_binder_transaction_update_buffer_release(debug_id: c_int);
38     unsafe fn rust_binder_update_page_range(pid: c_int, allocate: bool, start: usize, end: usize);
39     unsafe fn rust_binder_alloc_lru_start(pid: c_int, page_index: usize);
40     unsafe fn rust_binder_alloc_lru_end(pid: c_int, page_index: usize);
41     unsafe fn rust_binder_free_lru_start(pid: c_int, page_index: usize);
42     unsafe fn rust_binder_free_lru_end(pid: c_int, page_index: usize);
43     unsafe fn rust_binder_alloc_page_start(pid: c_int, page_index: usize);
44     unsafe fn rust_binder_alloc_page_end(pid: c_int, page_index: usize);
45     unsafe fn rust_binder_unmap_user_start(pid: c_int, page_index: usize);
46     unsafe fn rust_binder_unmap_user_end(pid: c_int, page_index: usize);
47     unsafe fn rust_binder_unmap_kernel_start(pid: c_int, page_index: usize);
48     unsafe fn rust_binder_unmap_kernel_end(pid: c_int, page_index: usize);
49     unsafe fn rust_binder_command(cmd: u32);
50     unsafe fn rust_binder_return(ret: u32);
51 }
52 
53 #[inline]
raw_transaction(t: &Transaction) -> rust_binder_transaction54 fn raw_transaction(t: &Transaction) -> rust_binder_transaction {
55     t as *const Transaction as rust_binder_transaction
56 }
57 
58 #[inline]
raw_thread(t: &Thread) -> rust_binder_thread59 fn raw_thread(t: &Thread) -> rust_binder_thread {
60     t as *const Thread as rust_binder_thread
61 }
62 
63 #[inline]
raw_node(n: &Node) -> rust_binder_node64 fn raw_node(n: &Node) -> rust_binder_node {
65     n as *const Node as rust_binder_node
66 }
67 
68 #[inline]
to_errno(ret: Result) -> i3269 fn to_errno(ret: Result) -> i32 {
70     match ret {
71         Ok(()) => 0,
72         Err(err) => err.to_errno(),
73     }
74 }
75 
76 #[inline]
trace_ioctl(cmd: u32, arg: usize)77 pub(crate) fn trace_ioctl(cmd: u32, arg: usize) {
78     // SAFETY: Always safe to call.
79     unsafe { rust_binder_ioctl(cmd, arg as c_ulong) }
80 }
81 
82 #[inline]
trace_ioctl_done(ret: Result)83 pub(crate) fn trace_ioctl_done(ret: Result) {
84     // SAFETY: Always safe to call.
85     unsafe { rust_binder_ioctl_done(to_errno(ret)) }
86 }
87 
88 #[inline]
trace_read_done(ret: Result)89 pub(crate) fn trace_read_done(ret: Result) {
90     // SAFETY: Always safe to call.
91     unsafe { rust_binder_read_done(to_errno(ret)) }
92 }
93 
94 #[inline]
trace_write_done(ret: Result)95 pub(crate) fn trace_write_done(ret: Result) {
96     // SAFETY: Always safe to call.
97     unsafe { rust_binder_write_done(to_errno(ret)) }
98 }
99 
100 #[inline]
trace_set_priority(thread: &Task, desired_prio: c_int, new_prio: c_int)101 pub(crate) fn trace_set_priority(thread: &Task, desired_prio: c_int, new_prio: c_int) {
102     // SAFETY: The pointer to the task is valid for the duration of this call.
103     unsafe { rust_binder_set_priority(thread.as_ptr(), desired_prio, new_prio) }
104 }
105 
106 #[inline]
vh_set_priority(t: &Transaction, task: &Task)107 pub(crate) fn vh_set_priority(t: &Transaction, task: &Task) {
108     // SAFETY: The pointers to `t` and `task` are valid.
109     unsafe { android_vh_rust_binder_set_priority(raw_transaction(t), task.as_ptr()) }
110 }
111 
112 #[inline]
vh_restore_priority(task: &Task)113 pub(crate) fn vh_restore_priority(task: &Task) {
114     // SAFETY: The pointer to `task` is valid.
115     unsafe { android_vh_rust_binder_restore_priority(task.as_ptr()) }
116 }
117 
118 #[inline]
trace_wait_for_work(proc_work: bool, transaction_stack: bool, thread_todo: bool)119 pub(crate) fn trace_wait_for_work(proc_work: bool, transaction_stack: bool, thread_todo: bool) {
120     // SAFETY: Always safe to call.
121     unsafe { rust_binder_wait_for_work(proc_work, transaction_stack, thread_todo) }
122 }
123 
124 #[inline]
trace_transaction(reply: bool, t: &Transaction)125 pub(crate) fn trace_transaction(reply: bool, t: &Transaction) {
126     // SAFETY: The raw transaction is valid for the duration of this call.
127     unsafe { rust_binder_transaction(reply, raw_transaction(t)) }
128 }
129 
130 #[inline]
trace_transaction_received(t: &Transaction)131 pub(crate) fn trace_transaction_received(t: &Transaction) {
132     // SAFETY: The raw transaction is valid for the duration of this call.
133     unsafe { rust_binder_transaction_received(raw_transaction(t)) }
134 }
135 
136 #[inline]
trace_transaction_thread_selected(t: &Transaction, th: &Thread)137 pub(crate) fn trace_transaction_thread_selected(t: &Transaction, th: &Thread) {
138     // SAFETY: The raw transaction is valid for the duration of this call.
139     unsafe { rust_binder_transaction_thread_selected(raw_transaction(t), raw_thread(th)) }
140 }
141 
142 #[inline]
trace_transaction_node_send( t_debug_id: usize, n: &Node, orig: &uapi::flat_binder_object, trans: &uapi::flat_binder_object, )143 pub(crate) fn trace_transaction_node_send(
144     t_debug_id: usize,
145     n: &Node,
146     orig: &uapi::flat_binder_object,
147     trans: &uapi::flat_binder_object,
148 ) {
149     // CAST: Types are identical.
150     let orig = orig as *const uapi::flat_binder_object as *const flat_binder_object;
151     // CAST: Types are identical.
152     let trans = trans as *const uapi::flat_binder_object as *const flat_binder_object;
153 
154     // SAFETY: The pointers are valid for the duration of this call.
155     unsafe { rust_binder_transaction_node_send(t_debug_id as c_int, raw_node(n), orig, trans) }
156 }
157 
158 #[inline]
trace_transaction_fd_send(t_debug_id: usize, fd: u32, offset: usize)159 pub(crate) fn trace_transaction_fd_send(t_debug_id: usize, fd: u32, offset: usize) {
160     // SAFETY: This function is always safe to call.
161     unsafe { rust_binder_transaction_fd_send(t_debug_id as c_int, fd as c_int, offset) }
162 }
163 
164 #[inline]
trace_transaction_fd_recv(t_debug_id: usize, fd: u32, offset: usize)165 pub(crate) fn trace_transaction_fd_recv(t_debug_id: usize, fd: u32, offset: usize) {
166     // SAFETY: This function is always safe to call.
167     unsafe { rust_binder_transaction_fd_recv(t_debug_id as c_int, fd as c_int, offset) }
168 }
169 
170 #[inline]
trace_transaction_alloc_buf(debug_id: usize, data: &BinderTransactionDataSg)171 pub(crate) fn trace_transaction_alloc_buf(debug_id: usize, data: &BinderTransactionDataSg) {
172     let data = data as *const BinderTransactionDataSg;
173     // SAFETY: The `data` pointer is valid.
174     unsafe { rust_binder_transaction_alloc_buf(debug_id as c_int, data.cast()) }
175 }
176 
177 #[inline]
trace_transaction_buffer_release(debug_id: usize)178 pub(crate) fn trace_transaction_buffer_release(debug_id: usize) {
179     // SAFETY: Always safe to call.
180     unsafe { rust_binder_transaction_buffer_release(debug_id as c_int) }
181 }
182 
183 #[inline]
trace_transaction_failed_buffer_release(debug_id: usize)184 pub(crate) fn trace_transaction_failed_buffer_release(debug_id: usize) {
185     // SAFETY: Always safe to call.
186     unsafe { rust_binder_transaction_failed_buffer_release(debug_id as c_int) }
187 }
188 
189 #[inline]
trace_transaction_update_buffer_release(debug_id: usize)190 pub(crate) fn trace_transaction_update_buffer_release(debug_id: usize) {
191     // SAFETY: Always safe to call.
192     unsafe { rust_binder_transaction_update_buffer_release(debug_id as c_int) }
193 }
194 
195 #[inline]
trace_update_page_range(pid: Pid, allocate: bool, start: usize, end: usize)196 pub(crate) fn trace_update_page_range(pid: Pid, allocate: bool, start: usize, end: usize) {
197     // SAFETY: Always safe to call.
198     unsafe { rust_binder_update_page_range(pid as c_int, allocate, start, end) }
199 }
200 
201 macro_rules! define_wrapper_lru_page_class {
202     ($(fn $name:ident;)*) => {$(
203         kernel::macros::paste! {
204             #[inline]
205             pub(crate) fn [< trace_ $name >](pid: Pid, page_index: usize) {
206                 // SAFETY: Always safe to call.
207                 unsafe { [< rust_binder_ $name >](pid as c_int, page_index) }
208             }
209         }
210     )*}
211 }
212 
213 define_wrapper_lru_page_class! {
214     fn alloc_lru_start;
215     fn alloc_lru_end;
216     fn free_lru_start;
217     fn free_lru_end;
218     fn alloc_page_start;
219     fn alloc_page_end;
220     fn unmap_user_start;
221     fn unmap_user_end;
222     fn unmap_kernel_start;
223     fn unmap_kernel_end;
224 }
225 
226 #[inline]
trace_command(cmd: u32)227 pub(crate) fn trace_command(cmd: u32) {
228     // SAFETY: Trivially safe to call with primitive u32.
229     unsafe { rust_binder_command(cmd) }
230 }
231 
232 #[inline]
trace_return(ret: u32)233 pub(crate) fn trace_return(ret: u32) {
234     // SAFETY: Trivially safe to call with primitive u32.
235     unsafe { rust_binder_return(ret) }
236 }
237