1use crate::{
2 parcel::Parcel
3};
4
5use nix::{
6 fcntl::{
7 OFlag,
8 open,
9 },
10 ioctl_readwrite,
11 ioctl_write_int,
12 ioctl_write_ptr,
13 sys::{
14 mman::{
15 MapFlags,
16 mmap,
17 ProtFlags,
18 },
19 stat::Mode,
20 },
21 unistd::close,
22};
23
24use std::{convert::TryFrom, ffi::c_void, mem::size_of, ops::BitOr, os::unix::io::RawFd, ptr, slice};
25
26use num_traits::FromPrimitive;
27
28
29const DEVICE: &str = "/dev/binder";
31
32const DEFAULT_MAX_BINDER_THREADS: u32 = 15;
34
35const PAGE_SIZE: usize = 0x1000;
36const BINDER_VM_SIZE: usize = (1 * 1024 * 1024) - PAGE_SIZE * 2;
37
38
39macro_rules! pack_chars {
40 ($c1:expr, $c2:expr, $c3:expr, $c4:expr) => {
41 (((($c1 as u32) << 24)) | ((($c2 as u32) << 16)) | ((($c3 as u32) << 8)) | ($c4 as u32))
42 };
43}
44
45const BINDER_TYPE_LARGE: u8 = 0x85;
46
47const TF_BINDER: u32 = pack_chars!(b's', b'b', b'*', BINDER_TYPE_LARGE);
48const TF_WEAKBINDER: u32 = pack_chars!(b'w', b'b', b'*', BINDER_TYPE_LARGE);
49const TF_HANDLE: u32 = pack_chars!(b's', b'h', b'*', BINDER_TYPE_LARGE);
50const TF_WEAKHANDLE: u32 = pack_chars!(b'w', b'h', b'*', BINDER_TYPE_LARGE);
51const TF_FD: u32 = pack_chars!(b'f', b'd', b'*', BINDER_TYPE_LARGE);
52const TF_FDA: u32 = pack_chars!(b'f', b'd', b'a', BINDER_TYPE_LARGE);
53const TF_PTR: u32 = pack_chars!(b'p', b't', b'*', BINDER_TYPE_LARGE);
54
55#[repr(u32)]
56#[derive(Debug, Hash, Clone, Copy, PartialEq, FromPrimitive)]
57pub enum BinderType {
58 Binder = TF_BINDER,
59 WeakBinder = TF_WEAKBINDER,
60 Handle = TF_HANDLE,
61 WeakHandle = TF_WEAKHANDLE,
62 Fd = TF_FD,
63 Fda = TF_FDA,
64 Ptr = TF_PTR,
65}
66
67
68#[repr(C)]
69#[derive(Debug)]
70pub struct BinderFlatObject {
71 pub(crate) binder_type: BinderType,
72 flags: u32,
73 pub(crate) handle: *const c_void,
74 cookie: *const c_void,
75}
76
77impl BinderFlatObject {
78 pub fn new(binder_type: BinderType, handle: usize, cookie: usize, flags: u32) -> Self {
79 Self {
80 binder_type,
81 flags,
82 handle: handle as *const c_void,
83 cookie: cookie as *const c_void,
84 }
85
86 }
87
88 pub fn handle(&self) -> *const c_void {
89 self.handle
90 }
91
92 pub fn cookie(&self) -> *const c_void {
93 self.cookie
94 }
95}
96
97const PING_TRANSCATION: u32 = pack_chars!(b'_', b'P',b'N',b'G');
98const DUMP_TRANSACTION: u32 = pack_chars!(b'_', b'D', b'M', b'P');
99const SHELL_COMMAND_TRANSACTION: u32 = pack_chars!(b'_', b'C', b'M', b'D');
100const INTERFACE_TRANSACTION: u32 = pack_chars!(b'_', b'N', b'T', b'F');
101const SYSPROPS_TRANSACTION: u32 = pack_chars!(b'_', b'S', b'P', b'R');
102const EXTENSION_TRANSACTION: u32 = pack_chars!(b'_', b'E', b'X', b'T');
103const DEBUG_PID_TRANSACTION: u32 = pack_chars!(b'_', b'P', b'I', b'D');
104const TWEET_TRANSACTION: u32 = pack_chars!(b'_', b'T', b'W', b'T');
105const LIKE_TRANSACTION: u32 = pack_chars!(b'_', b'L', b'I', b'K');
106
107#[repr(u32)]
108#[derive(Debug, FromPrimitive)]
109pub enum Transaction {
110 FirstCall = 1,
111 LastCall = 0xffffff,
112 Ping = PING_TRANSCATION,
113 Dump = DUMP_TRANSACTION,
114 ShellCommand = SHELL_COMMAND_TRANSACTION,
115 Interface = INTERFACE_TRANSACTION,
116 Sysprops = SYSPROPS_TRANSACTION,
117 Extension = EXTENSION_TRANSACTION,
118 DebugPid = DEBUG_PID_TRANSACTION,
119 Tweet = TWEET_TRANSACTION,
120 Like = LIKE_TRANSACTION,
121}
122
123#[repr(C)]
125pub struct BinderVersion {
126 protocol_version: i32,
127}
128
129
130#[repr(C)]
131pub struct BinderWriteRead {
132 write_size: usize,
133 write_consumed: usize,
134 write_buffer: *const c_void,
135 read_size: usize,
136 read_consumed: usize,
137 read_buffer: *mut c_void,
138}
139
140impl BinderWriteRead {
141 pub fn write_size (&self) -> usize {
142 self.write_size
143 }
144 pub fn write_consumed (&self) -> usize {
145 self.write_consumed
146 }
147 pub fn read_size (&self) -> usize {
148 self.read_size
149 }
150 pub fn read_consumed (&self) -> usize {
151 self.read_consumed
152 }
153 pub fn write_buffer (&self) -> *const c_void {
154
155 self.write_buffer
156 }
157 pub fn read_buffer (&self) -> *mut c_void {
158 self.read_buffer
159 }
160}
161#[repr(C)]
162pub(crate) struct BinderTransactionDataData {
163}
164#[repr(C)]
165#[derive(Debug)]
166pub struct BinderTransactionData {
167 target: u32,
168 cookie: u64,
169 code: u32,
170 flags: u32,
171 sender_pid: u32,
172 sender_euid: u32,
173 data_size: u64,
174 offset_size: u64,
175 data: *mut u8,
176 offsets: *mut usize,
177}
178
179impl BinderTransactionData {
180 pub fn code(&self) -> u32 {
181 self.code
182 }
183 pub fn cookie(&self) -> u64 {
184 self.cookie
185 }
186
187 pub fn target(&self) -> u32 {
188 self.target
189 }
190
191 pub fn flags(&self) -> TransactionFlags {
192 TransactionFlags::from_bits(self.flags).unwrap()
193 }
194
195 pub unsafe fn raw_data(&self) -> &[u8] {
196 std::slice::from_raw_parts(self.data, self.data_size as usize)
197 }
198
199 pub fn parcel(&self) -> Parcel {
200 unsafe { Parcel::from_slice(self.raw_data()) }
201 }
202}
203
204enum Result {
205 InvalidOperation,
206 NoError,
207}
208
209ioctl_readwrite!(binder_write_read, b'b', 1, BinderWriteRead);
210ioctl_write_ptr!(binder_set_max_threads, b'b', 5, u32);
211ioctl_readwrite!(binder_read_version, b'b', 9, BinderVersion);
212
213bitflags! {
214 pub struct TransactionFlags: u32 {
215 const OneWay = 1;
216 const CollectNotedAppOps = 2;
217 const RootObject = 4;
218 const StatusCode = 8;
219 const AcceptFds = 0x10;
220 const ClearBuf = 0x20;
221 }
222}
223
224macro_rules! _iow {
225 ($c1:expr, $c2:expr, $c3:expr) => {
226 (((0x40 << 24)) | ((($c3 as u32) << 16)) | ((($c1 as u32) << 8)) | ($c2 as u32))
227 };
228}
229
230macro_rules! _ior {
231 ($c1:expr, $c2:expr, $c3:expr) => {
232 (((0x80 << 24)) | ((($c3 as u32) << 16)) | ((($c1 as u32) << 8)) | ($c2 as u32))
233 };
234}
235
236macro_rules! _io {
237 ($c1:expr, $c2:expr) => {
238 (((($c1 as u32) << 8)) | ($c2 as u32))
239 };
240}
241
242const BC_TRANSACTION: u32 = _iow!(b'c', 0, 0x40);
243const BC_REPLY: u32 = _iow!(b'c', 1, 0x40);
244const BC_ACQUIRE_RESULT: u32 = _iow!(b'c', 2, 0x4);
245const BC_FREE_BUFFER: u32 = _iow!(b'c', 3, 0x8);
246const BC_INCREFS: u32 = _iow!(b'c', 4, 0x4);
247const BC_ACQUIRE: u32 = _iow!(b'c', 5, 0x4);
248const BC_RELEASE: u32 = _iow!(b'c', 6, 0x4);
249const BC_DECREFS: u32 = _iow!(b'c', 7, 0x4);
250const BC_INCREFS_DONE: u32 = _iow!(b'c', 8, 0x10);
251const BC_ACQUIRE_DONE: u32 = _iow!(b'c', 9, 0x10);
252const BC_ATTEMPT_ACQUIRE: u32 = _iow!(b'c', 10, 0x10);
253const BC_REGISTER_LOOPER: u32 = 25355;
254const BC_ENTER_LOOPER: u32 = 25356;
255const BC_EXIT_LOOPER: u32 = 25357;
256const BC_REQUEST_DEATH_NOTIFICATION: u32 = _iow!(b'c', 14, 0x10);
257const BC_CLEAR_DEATH_NOTIFICATION: u32 = _iow!(b'c', 15, 0x10);
258const BC_DEAD_BINDER_DONE: u32 = _iow!(b'c', 16, 0x8);
259
260#[repr(u32)]
261#[derive(Debug, FromPrimitive)]
262pub enum BinderDriverCommandProtocol {
263 Transaction = BC_TRANSACTION,
264 Reply = BC_REPLY,
265 AcquireResult = BC_ACQUIRE_RESULT,
266 FreeBuffer = BC_FREE_BUFFER,
267 IncRefs = BC_INCREFS,
268 Acquire = BC_ACQUIRE,
269 Release = BC_RELEASE,
270 DecRefs = BC_DECREFS,
271 IncRefsDone = BC_INCREFS_DONE,
272 AcquireDone = BC_ACQUIRE_DONE,
273 AttemptAcquire = BC_ATTEMPT_ACQUIRE,
274 RegisterLooper = BC_REGISTER_LOOPER,
275 EnterLooper = BC_ENTER_LOOPER,
276 ExitLooper = BC_EXIT_LOOPER,
277 RequestDeathNotification = BC_REQUEST_DEATH_NOTIFICATION,
278 ClearDeathNotification = BC_CLEAR_DEATH_NOTIFICATION,
279 DeadBinderDone = BC_DEAD_BINDER_DONE,
280}
281
282impl From<u32> for BinderDriverCommandProtocol {
283 fn from(int: u32) -> Self {
284 BinderDriverCommandProtocol::from_u32(int).unwrap()
285 }
286}
287
288const BR_ERROR: u32 = _ior!(b'r', 0, 4);
289const BR_OK: u32 = _ior!(b'r', 1, 0);
290const BR_TRANSACTION: u32 = _ior!(b'r', 2, 0x40);
291const BR_REPLY: u32 = _ior!(b'r', 3, 0x40);
292const BR_ACQUIRE_RESULT: u32 = _ior!(b'r', 4, 0x4);
293const BR_DEAD_REPLY: u32 = _io!(b'r', 5);
294const BR_TRANSACTION_COMPLETE: u32 = _io!(b'r', 6);
295const BR_INCREFS: u32 = _ior!(b'r', 7, 0x10);
296const BR_ACQUIRE: u32 = _ior!(b'r', 8, 0x10);
297const BR_RELEASE: u32 = _ior!(b'r', 9, 0x10);
298const BR_DECREFS: u32 = _ior!(b'r', 10, 0x10);
299const BR_ATTEMPT_ACQUIRE: u32 = _ior!(b'r', 11, 0x10);
300const BR_NOOP: u32 = _io!(b'r', 12);
301const BR_SPAWN_LOOPER: u32 = _io!(b'r', 13);
302const BR_FINISHED: u32 = _io!(b'r', 14);
303const BR_DEAD_BINDER: u32 = _ior!(b'r', 15, 0x8);
304const BR_CLEAR_DEATH_NOTIFICATION_DONE: u32 = _ior!(b'r', 16, 0x10);
305const BR_FAILED_REPLY: u32 = _io!(b'r', 17);
306
307#[repr(u32)]
308#[derive(Debug, FromPrimitive, ToPrimitive)]
309pub enum BinderDriverReturnProtocol {
310 Error = BR_ERROR,
311 Ok = BR_OK,
312 Transaction = BR_TRANSACTION,
313 Reply = BR_REPLY,
314 AcquireResult = BR_ACQUIRE_RESULT,
315 DeadReply = BR_DEAD_REPLY,
316 TransactionComplete = BR_TRANSACTION_COMPLETE,
317 IncRefs = BR_INCREFS,
318 Acquire = BR_ACQUIRE,
319 Release = BR_RELEASE,
320 DecRefs = BR_DECREFS,
321 AttemptAcquire = BR_ATTEMPT_ACQUIRE,
322 Noop = BR_NOOP,
323 SpawnLooper = BR_SPAWN_LOOPER,
324 Finished = BR_FINISHED,
325 DeadBinder = BR_DEAD_BINDER,
326 ClearDeathNotification = BR_CLEAR_DEATH_NOTIFICATION_DONE,
327 FailedReply = BR_FAILED_REPLY,
328}
329
330impl From<u32> for BinderDriverReturnProtocol {
331 fn from(int: u32) -> Self {
332 BinderDriverReturnProtocol::from_u32(int).unwrap()
333 }
334}
335
336pub struct Binder {
338 fd: RawFd,
339 mem: *const c_void,
340 pending_out_data: Parcel,
341}
342
343impl Binder {
344 pub fn new() -> Self {
345 let mut flags = OFlag::empty();
346 flags.set(OFlag::O_RDWR, true);
347 flags.set(OFlag::O_CLOEXEC, true);
348
349 let fd = open(DEVICE, flags, Mode::empty()).expect("Failed to open binder device");
350
351 let mut binder_version = BinderVersion { protocol_version: 0 };
352 unsafe {
353 binder_read_version(fd, &mut binder_version).expect("Failed to read binder version");
354 }
355
356 let mut flags = MapFlags::empty();
357 flags.set(MapFlags::MAP_PRIVATE, true);
358 flags.set(MapFlags::MAP_NORESERVE, true);
359 let mapping_address = unsafe { mmap(ptr::null_mut(), BINDER_VM_SIZE, ProtFlags::PROT_READ, flags, fd, 0) }.expect("Failed to map the binder file");
360
361 let binder = Self {
362 fd,
363 mem: mapping_address as *const _,
364 pending_out_data: Parcel::empty(),
365 };
366
367 unsafe {
368 binder_set_max_threads(fd, &DEFAULT_MAX_BINDER_THREADS).expect("Failed to set max threads");
369 }
370
371
372 binder
373 }
374
375 pub fn enter_looper(&self) {
377 let mut parcel_out = Parcel::empty();
378
379 parcel_out.write_i32(BinderDriverCommandProtocol::EnterLooper as i32);
380
381 self.write_read(&parcel_out, false);
382 }
383
384 fn exit_looper(&self) {
386 let mut parcel_out = Parcel::empty();
387
388 parcel_out.write_i32(BinderDriverCommandProtocol::ExitLooper as i32);
389
390 self.write_read(&parcel_out, false);
391 }
392
393 pub fn add_ref(&mut self, handle: i32) {
396 self.pending_out_data.write_u32(BinderDriverCommandProtocol::IncRefs as u32);
397 self.pending_out_data.write_i32(handle);
398 }
399
400 pub fn dec_ref(&mut self, handle: i32) {
403 self.pending_out_data.write_u32(BinderDriverCommandProtocol::DecRefs as u32);
404 self.pending_out_data.write_i32(handle);
405 }
406
407 pub fn acquire(&mut self, handle: i32) {
410 self.pending_out_data.write_u32(BinderDriverCommandProtocol::Acquire as u32);
411 self.pending_out_data.write_i32(handle);
412 }
413
414 pub fn release(&mut self, handle: i32) {
417 self.pending_out_data.write_u32(BinderDriverCommandProtocol::Release as u32);
418 self.pending_out_data.write_i32(handle);
419 }
420
421 pub fn transact(&mut self, handle: i32, code: u32, flags: TransactionFlags, data: &mut Parcel) -> (Option<BinderTransactionData>, Parcel) {
422
423 self.pending_out_data.write_i32(BinderDriverCommandProtocol::Transaction as i32);
424
425 let transaction_data_out = BinderTransactionData {
426 target: handle as u32,
427 code,
428 flags: (TransactionFlags::AcceptFds | flags).bits,
429 cookie: 0,
430 sender_pid: 0,
431 sender_euid: 0,
432 data_size: data.len() as u64,
433 offset_size: (data.offsets_len() * size_of::<usize>()) as u64,
434 data: if data.len() != 0 { data.as_mut_ptr() } else { 0 as *mut u8 },
435 offsets: if data.offsets_len() != 0 { data.offsets().as_mut_ptr() } else { 0 as *mut usize },
436 };
437 self.pending_out_data.write_transaction_data(&transaction_data_out);
438
439 self.do_write_read(&mut Parcel::empty())
440 }
441
442 pub fn reply(&mut self, data: &mut Parcel, flags: TransactionFlags) -> (Option<BinderTransactionData>, Parcel) {
443
444 self.pending_out_data.write_i32(BinderDriverCommandProtocol::Reply as i32);
445
446 let transaction_data_out = BinderTransactionData {
447 target: 0xffffffff,
448 code: 0,
449 flags: flags.bits,
450 cookie: 0,
451 sender_pid: 0,
452 sender_euid: 0,
453 data_size: data.len() as u64,
454 offset_size: (data.offsets_len() * size_of::<usize>()) as u64,
455 data: if data.len() != 0 { data.as_mut_ptr() } else { 0 as *mut u8 },
456 offsets: if data.offsets_len() != 0 { data.offsets().as_mut_ptr() } else { 0 as *mut usize },
457 };
458 self.pending_out_data.write_transaction_data(&transaction_data_out);
459
460 self.do_write_read(&mut Parcel::empty())
461 }
462
463 pub fn do_write_read(&mut self, parcel_out: &mut Parcel) -> (Option<BinderTransactionData>, Parcel) {
464 self.pending_out_data.append_parcel(parcel_out);
465 let mut parcel_in = self.write_read(&self.pending_out_data, true);
466 self.pending_out_data.reset();
467
468 self.proccess_incoming(&mut parcel_in)
469 }
470
471 fn proccess_incoming(&mut self, parcel_in: &mut Parcel) -> (Option<BinderTransactionData>, Parcel) {
472 let mut acquire_result = Result::NoError;
473
474 while parcel_in.has_unread_data() {
475 let cmd_u32 = parcel_in.read_u32();
476 let cmd_option = BinderDriverReturnProtocol::from_u32(cmd_u32);
477 match cmd_option {
478 Some(cmd) => match cmd {
479 BinderDriverReturnProtocol::TransactionComplete => {},
480 BinderDriverReturnProtocol::DeadReply => {
481 panic!("Got a DEAD_REPLY");
482 },
483 BinderDriverReturnProtocol::FailedReply => {
484 panic!("Transaction failed");
485 },
486 BinderDriverReturnProtocol::IncRefs => {
487 },
488 BinderDriverReturnProtocol::Acquire => {
489 },
490 BinderDriverReturnProtocol::AcquireResult => {
491 let result = parcel_in.read_i32();
492 acquire_result = if result == 0 {
493 Result::InvalidOperation
494 } else {
495 Result::NoError
496 };
497 },
498 BinderDriverReturnProtocol::Reply | BinderDriverReturnProtocol::Transaction => {
499 let transaction_data_in = parcel_in.read_transaction_data();
500 let parcel = Parcel::from_data_and_offsets(
501 transaction_data_in.data,
502 transaction_data_in.data_size as usize,
503 transaction_data_in.offsets,
504 transaction_data_in.offset_size as usize / size_of::<usize>()
505 );
506 return (
507 Some(transaction_data_in),
508 parcel,
509 );
510 },
511 BinderDriverReturnProtocol::Error => {
512 println!("Got an error {}", parcel_in.read_i32());
513 },
514 BinderDriverReturnProtocol::Noop => {
515 },
516 BinderDriverReturnProtocol::SpawnLooper => {
517 },
518 _ => {}
519
520 },
521 None => {},
522 }
523 }
524
525 (None, Parcel::empty())
526 }
527 fn write_read(&self, data_out: &Parcel, with_read: bool) -> Parcel {
529 let mut data_in = [0u8; 32 * 8];
530
531 let mut write_read_struct = BinderWriteRead {
532 write_size: data_out.len(),
533 write_buffer: data_out.as_ptr() as *const c_void,
534 write_consumed: 0,
535 read_size: if with_read { data_in.len() } else { 0 },
536 read_buffer: data_in.as_mut_ptr() as *mut c_void,
537 read_consumed: 0,
538 };
539
540 unsafe {
541 binder_write_read(self.fd, &mut write_read_struct).expect("Failed to perform write_read");
542 }
543 Parcel::from_slice(&data_in[..write_read_struct.read_consumed])
544
545 }
546
547}
548
549impl Drop for Binder {
551 fn drop(&mut self) {
552 self.exit_looper();
555
556 close(self.fd);
557 }
558}