| 1 | |
| 2 |
|
| 3 | |
| 4 |
|
| 5 | |
| 6 |
|
| 7 | #![crate_name = "rust_binder"]
|
| 8 | #![recursion_limit = "256"]
|
| 9 |
|
| 10 | use kernel::{
|
| 11 | bindings::{self, seq_file},
|
| 12 | fs::File,
|
| 13 | list::{ListArc, ListArcSafe, ListLinksSelfPtr, TryNewListArc},
|
| 14 | module::this_module,
|
| 15 | prelude::*,
|
| 16 | seq_file::SeqFile,
|
| 17 | seq_print,
|
| 18 | sync::atomic::{ordering::Relaxed, Atomic},
|
| 19 | sync::poll::PollTable,
|
| 20 | sync::Arc,
|
| 21 | task::Pid,
|
| 22 | transmute::AsBytes,
|
| 23 | types::ForeignOwnable,
|
| 24 | uaccess::UserSliceWriter,
|
| 25 | };
|
| 26 |
|
| 27 | use crate::{context::Context, page_range::Shrinker, process::Process, thread::Thread};
|
| 28 |
|
| 29 | use core::ptr::NonNull;
|
| 30 |
|
| 31 | mod allocation;
|
| 32 | mod context;
|
| 33 | mod deferred_close;
|
| 34 | mod defs;
|
| 35 | #[macro_use]
|
| 36 | mod debug;
|
| 37 | mod error;
|
| 38 | mod netlink;
|
| 39 | mod node;
|
| 40 | mod page_range;
|
| 41 | mod process;
|
| 42 | mod range_alloc;
|
| 43 | mod stats;
|
| 44 | mod thread;
|
| 45 | mod trace;
|
| 46 | mod transaction;
|
| 47 |
|
| 48 | #[allow(warnings)] |
| 49 | mod binderfs {
|
| 50 | use kernel::bindings::{dentry, inode};
|
| 51 |
|
| 52 | extern "C" {
|
| 53 | pub fn init_rust_binderfs() -> kernel::ffi::c_int;
|
| 54 | }
|
| 55 | extern "C" {
|
| 56 | pub fn rust_binderfs_create_proc_file(
|
| 57 | nodp: *mut inode,
|
| 58 | pid: kernel::ffi::c_int,
|
| 59 | ) -> *mut dentry;
|
| 60 | }
|
| 61 | extern "C" {
|
| 62 | pub fn rust_binderfs_remove_file(dentry: *mut dentry);
|
| 63 | }
|
| 64 | pub type rust_binder_context = *mut kernel::ffi::c_void;
|
| 65 | #[repr(C)]
|
| 66 | #[derive(Copy, Clone)]
|
| 67 | pub struct binder_device {
|
| 68 | pub minor: kernel::ffi::c_int,
|
| 69 | pub ctx: rust_binder_context,
|
| 70 | }
|
| 71 | impl Default for binder_device {
|
| 72 | fn default() -> Self {
|
| 73 | let mut s = ::core::mem::MaybeUninit::<Self>::uninit();
|
| 74 | unsafe {
|
| 75 | ::core::ptr::write_bytes(s.as_mut_ptr(), 0, 1);
|
| 76 | s.assume_init()
|
| 77 | }
|
| 78 | }
|
| 79 | }
|
| 80 | }
|
| 81 |
|
| 82 | module! {
|
| 83 | type: BinderModule,
|
| 84 | name: "rust_binder",
|
| 85 | authors: ["Wedson Almeida Filho", "Alice Ryhl"],
|
| 86 | description: "Android Binder",
|
| 87 | license: "GPL",
|
| 88 | }
|
| 89 |
|
| 90 | use kernel::bindings::rust_binder_layout;
|
| 91 | #[no_mangle]
|
| 92 | static RUST_BINDER_LAYOUT: rust_binder_layout = rust_binder_layout {
|
| 93 | t: transaction::TRANSACTION_LAYOUT,
|
| 94 | p: process::PROCESS_LAYOUT,
|
| 95 | n: node::NODE_LAYOUT,
|
| 96 | };
|
| 97 |
|
| 98 | fn next_debug_id() -> usize {
|
| 99 | static NEXT_DEBUG_ID: Atomic<usize> = Atomic::new(0);
|
| 100 |
|
| 101 | NEXT_DEBUG_ID.fetch_add(1, Relaxed)
|
| 102 | }
|
| 103 |
|
| 104 | |
| 105 | |
| 106 | pub(crate) struct BinderReturnWriter<'a> {
|
| 107 | writer: UserSliceWriter,
|
| 108 | thread: &'a Thread,
|
| 109 | }
|
| 110 |
|
| 111 | impl<'a> BinderReturnWriter<'a> {
|
| 112 | fn new(writer: UserSliceWriter, thread: &'a Thread) -> Self {
|
| 113 | BinderReturnWriter { writer, thread }
|
| 114 | }
|
| 115 |
|
| 116 | |
| 117 | |
| 118 | fn write_code(&mut self, code: u32) -> Result {
|
| 119 | crate::trace::trace_return(code);
|
| 120 | stats::GLOBAL_STATS.inc_br(code);
|
| 121 | self.thread.process.stats.inc_br(code);
|
| 122 | self.writer.write(&code)
|
| 123 | }
|
| 124 |
|
| 125 | |
| 126 | fn write_payload<T: AsBytes>(&mut self, payload: &T) -> Result {
|
| 127 | self.writer.write(payload)
|
| 128 | }
|
| 129 |
|
| 130 | fn len(&self) -> usize {
|
| 131 | self.writer.len()
|
| 132 | }
|
| 133 | }
|
| 134 |
|
| 135 | |
| 136 | |
| 137 | |
| 138 | |
| 139 | |
| 140 | |
| 141 | trait DeliverToRead: ListArcSafe + Send + Sync {
|
| 142 | |
| 143 | |
| 144 | |
| 145 | fn do_work(
|
| 146 | self: DArc<Self>,
|
| 147 | thread: &Thread,
|
| 148 | writer: &mut BinderReturnWriter<'_>,
|
| 149 | ) -> Result<bool>;
|
| 150 |
|
| 151 | |
| 152 | |
| 153 | fn cancel(self: DArc<Self>);
|
| 154 |
|
| 155 | |
| 156 | |
| 157 | |
| 158 | |
| 159 | fn should_sync_wakeup(&self) -> bool;
|
| 160 |
|
| 161 | fn debug_print(&self, m: &SeqFile, prefix: &str, transaction_prefix: &str) -> Result<()>;
|
| 162 | }
|
| 163 |
|
| 164 | |
| 165 | #[pin_data]
|
| 166 | struct DTRWrap<T: ?Sized> {
|
| 167 | #[pin]
|
| 168 | links: ListLinksSelfPtr<DTRWrap<dyn DeliverToRead>>,
|
| 169 | #[pin]
|
| 170 | wrapped: T,
|
| 171 | }
|
| 172 | kernel::list::impl_list_arc_safe! {
|
| 173 | impl{T: ListArcSafe + ?Sized} ListArcSafe<0> for DTRWrap<T> {
|
| 174 | tracked_by wrapped: T;
|
| 175 | }
|
| 176 | }
|
| 177 | kernel::list::impl_list_item! {
|
| 178 | impl ListItem<0> for DTRWrap<dyn DeliverToRead> {
|
| 179 | using ListLinksSelfPtr { self.links };
|
| 180 | }
|
| 181 | }
|
| 182 |
|
| 183 | impl<T: ?Sized> core::ops::Deref for DTRWrap<T> {
|
| 184 | type Target = T;
|
| 185 | fn deref(&self) -> &T {
|
| 186 | &self.wrapped
|
| 187 | }
|
| 188 | }
|
| 189 |
|
| 190 | type DArc<T> = kernel::sync::Arc<DTRWrap<T>>;
|
| 191 | type DLArc<T> = kernel::list::ListArc<DTRWrap<T>>;
|
| 192 |
|
| 193 | impl<T: ListArcSafe> DTRWrap<T> {
|
| 194 | fn new(val: impl PinInit<T>) -> impl PinInit<Self> {
|
| 195 | pin_init!(Self {
|
| 196 | links <- ListLinksSelfPtr::new(),
|
| 197 | wrapped <- val,
|
| 198 | })
|
| 199 | }
|
| 200 |
|
| 201 | fn arc_try_new(val: T) -> Result<DLArc<T>, kernel::alloc::AllocError> {
|
| 202 | ListArc::pin_init(
|
| 203 | try_pin_init!(Self {
|
| 204 | links <- ListLinksSelfPtr::new(),
|
| 205 | wrapped: val,
|
| 206 | }),
|
| 207 | GFP_KERNEL,
|
| 208 | )
|
| 209 | .map_err(|_| kernel::alloc::AllocError)
|
| 210 | }
|
| 211 |
|
| 212 | fn arc_pin_init(init: impl PinInit<T>) -> Result<DLArc<T>, kernel::error::Error> {
|
| 213 | ListArc::pin_init(
|
| 214 | try_pin_init!(Self {
|
| 215 | links <- ListLinksSelfPtr::new(),
|
| 216 | wrapped <- init,
|
| 217 | }),
|
| 218 | GFP_KERNEL,
|
| 219 | )
|
| 220 | }
|
| 221 | }
|
| 222 |
|
| 223 | struct DeliverCode {
|
| 224 | code: u32,
|
| 225 | skip: Atomic<bool>,
|
| 226 | pid: i32,
|
| 227 | }
|
| 228 |
|
| 229 | kernel::list::impl_list_arc_safe! {
|
| 230 | impl ListArcSafe<0> for DeliverCode { untracked; }
|
| 231 | }
|
| 232 |
|
| 233 | impl DeliverCode {
|
| 234 | fn new(code: u32, pid: i32) -> Self {
|
| 235 | Self {
|
| 236 | code,
|
| 237 | skip: Atomic::new(false),
|
| 238 | pid,
|
| 239 | }
|
| 240 | }
|
| 241 |
|
| 242 | |
| 243 | |
| 244 | |
| 245 | |
| 246 | fn skip(&self) {
|
| 247 | self.skip.store(true, Relaxed);
|
| 248 | }
|
| 249 | }
|
| 250 |
|
| 251 | impl DeliverToRead for DeliverCode {
|
| 252 | fn do_work(
|
| 253 | self: DArc<Self>,
|
| 254 | _thread: &Thread,
|
| 255 | writer: &mut BinderReturnWriter<'_>,
|
| 256 | ) -> Result<bool> {
|
| 257 | if !self.skip.load(Relaxed) {
|
| 258 | writer.write_code(self.code)?;
|
| 259 | }
|
| 260 | Ok(true)
|
| 261 | }
|
| 262 |
|
| 263 | fn cancel(self: DArc<Self>) {
|
| 264 | if !self.skip.load(Relaxed) {
|
| 265 | binder_debug!(
|
| 266 | pid = self.pid,
|
| 267 | DeadTransaction,
|
| 268 | "undelivered TRANSACTION_COMPLETE"
|
| 269 | );
|
| 270 | }
|
| 271 | }
|
| 272 |
|
| 273 | fn should_sync_wakeup(&self) -> bool {
|
| 274 | false
|
| 275 | }
|
| 276 |
|
| 277 | fn debug_print(&self, m: &SeqFile, prefix: &str, _tprefix: &str) -> Result<()> {
|
| 278 | seq_print!(m, "{}", prefix);
|
| 279 | if self.skip.load(Relaxed) {
|
| 280 | seq_print!(m, "(skipped) ");
|
| 281 | }
|
| 282 | if self.code == defs::BR_TRANSACTION_COMPLETE {
|
| 283 | seq_print!(m, "transaction complete\n");
|
| 284 | } else {
|
| 285 | seq_print!(m, "transaction error: {}\n", self.code);
|
| 286 | }
|
| 287 | Ok(())
|
| 288 | }
|
| 289 | }
|
| 290 |
|
| 291 | fn ptr_align(value: usize) -> Option<usize> {
|
| 292 | let size = core::mem::size_of::<usize>() - 1;
|
| 293 | Some(value.checked_add(size)? & !size)
|
| 294 | }
|
| 295 |
|
| 296 | |
| 297 | static BINDER_SHRINKER: Shrinker = unsafe { Shrinker::new() };
|
| 298 |
|
| 299 | struct BinderModule {
|
| 300 | _netlink: kernel::net::netlink::Registration,
|
| 301 | }
|
| 302 |
|
| 303 | impl kernel::Module for BinderModule {
|
| 304 | fn init(_module: &'static kernel::ThisModule) -> Result<Self> {
|
| 305 | |
| 306 | unsafe { crate::context::CONTEXTS.init() };
|
| 307 |
|
| 308 | let netlink = crate::netlink::BINDER_NL_FAMILY.register()?;
|
| 309 | BINDER_SHRINKER.register(c"android-binder")?;
|
| 310 |
|
| 311 | |
| 312 | unsafe { kernel::error::to_result(binderfs::init_rust_binderfs())? };
|
| 313 |
|
| 314 | Ok(Self { _netlink: netlink })
|
| 315 | }
|
| 316 | }
|
| 317 |
|
| 318 | |
| 319 | #[repr(transparent)]
|
| 320 | pub struct AssertSync<T>(T);
|
| 321 | |
| 322 | unsafe impl<T> Sync for AssertSync<T> {}
|
| 323 |
|
| 324 | |
| 325 | #[no_mangle]
|
| 326 | #[used]
|
| 327 | pub static rust_binder_fops: AssertSync<kernel::bindings::file_operations> = {
|
| 328 | let ops = kernel::bindings::file_operations {
|
| 329 | owner: this_module::<LocalModule>().as_ptr(),
|
| 330 | poll: Some(rust_binder_poll),
|
| 331 | unlocked_ioctl: Some(rust_binder_ioctl),
|
| 332 | compat_ioctl: bindings::compat_ptr_ioctl,
|
| 333 | mmap: Some(rust_binder_mmap),
|
| 334 | open: Some(rust_binder_open),
|
| 335 | release: Some(rust_binder_release),
|
| 336 | flush: Some(rust_binder_flush),
|
| 337 | ..pin_init::zeroed()
|
| 338 | };
|
| 339 | AssertSync(ops)
|
| 340 | };
|
| 341 |
|
| 342 | |
| 343 | |
| 344 | #[no_mangle]
|
| 345 | unsafe extern "C" fn rust_binder_new_context(
|
| 346 | name: *const kernel::ffi::c_char,
|
| 347 | ) -> *mut kernel::ffi::c_void {
|
| 348 | |
| 349 | let name = unsafe { kernel::str::CStr::from_char_ptr(name) };
|
| 350 | match Context::new(name) {
|
| 351 | Ok(ctx) => Arc::into_foreign(ctx),
|
| 352 | Err(_err) => core::ptr::null_mut(),
|
| 353 | }
|
| 354 | }
|
| 355 |
|
| 356 | |
| 357 | |
| 358 | #[no_mangle]
|
| 359 | unsafe extern "C" fn rust_binder_remove_context(device: *mut kernel::ffi::c_void) {
|
| 360 | if !device.is_null() {
|
| 361 | |
| 362 | |
| 363 | let ctx = unsafe { Arc::<Context>::from_foreign(device) };
|
| 364 | ctx.deregister();
|
| 365 | drop(ctx);
|
| 366 | }
|
| 367 | }
|
| 368 |
|
| 369 | |
| 370 | |
| 371 | unsafe extern "C" fn rust_binder_open(
|
| 372 | inode: *mut bindings::inode,
|
| 373 | file_ptr: *mut bindings::file,
|
| 374 | ) -> kernel::ffi::c_int {
|
| 375 | |
| 376 | |
| 377 | let device = unsafe { (*inode).i_private } as *const binderfs::binder_device;
|
| 378 |
|
| 379 | assert!(!device.is_null());
|
| 380 |
|
| 381 | |
| 382 | |
| 383 | let ctx = unsafe { Arc::<Context>::borrow((*device).ctx) };
|
| 384 |
|
| 385 | |
| 386 | let file = unsafe { File::from_raw_file(file_ptr) };
|
| 387 | let process = match Process::open(ctx, file) {
|
| 388 | Ok(process) => process,
|
| 389 | Err(err) => return err.to_errno(),
|
| 390 | };
|
| 391 |
|
| 392 | |
| 393 | match unsafe { BinderfsProcFile::new(inode, process.task.pid()) } {
|
| 394 | Ok(Some(file)) => process.inner.lock().binderfs_file = Some(file),
|
| 395 | Ok(None) => { }
|
| 396 | Err(err) => return err.to_errno(),
|
| 397 | }
|
| 398 |
|
| 399 | |
| 400 | unsafe { (*file_ptr).private_data = process.into_foreign() };
|
| 401 | 0
|
| 402 | }
|
| 403 |
|
| 404 | |
| 405 | |
| 406 | unsafe extern "C" fn rust_binder_release(
|
| 407 | _inode: *mut bindings::inode,
|
| 408 | file: *mut bindings::file,
|
| 409 | ) -> kernel::ffi::c_int {
|
| 410 | |
| 411 | let process = unsafe { Arc::<Process>::from_foreign((*file).private_data) };
|
| 412 | |
| 413 | let file = unsafe { File::from_raw_file(file) };
|
| 414 | Process::release(process, file);
|
| 415 | 0
|
| 416 | }
|
| 417 |
|
| 418 | |
| 419 | |
| 420 | unsafe extern "C" fn rust_binder_ioctl(
|
| 421 | file: *mut bindings::file,
|
| 422 | cmd: kernel::ffi::c_uint,
|
| 423 | arg: kernel::ffi::c_ulong,
|
| 424 | ) -> kernel::ffi::c_long {
|
| 425 | |
| 426 | let f = unsafe { Arc::<Process>::borrow((*file).private_data) };
|
| 427 | |
| 428 | match Process::ioctl(f, unsafe { File::from_raw_file(file) }, cmd, arg) {
|
| 429 | Ok(()) => 0,
|
| 430 | Err(err) => err.to_errno() as isize,
|
| 431 | }
|
| 432 | }
|
| 433 |
|
| 434 | |
| 435 | |
| 436 | unsafe extern "C" fn rust_binder_mmap(
|
| 437 | file: *mut bindings::file,
|
| 438 | vma: *mut bindings::vm_area_struct,
|
| 439 | ) -> kernel::ffi::c_int {
|
| 440 | |
| 441 | let f = unsafe { Arc::<Process>::borrow((*file).private_data) };
|
| 442 | |
| 443 | let area = unsafe { kernel::mm::virt::VmaNew::from_raw(vma) };
|
| 444 | |
| 445 | match Process::mmap(f, unsafe { File::from_raw_file(file) }, area) {
|
| 446 | Ok(()) => 0,
|
| 447 | Err(err) => err.to_errno(),
|
| 448 | }
|
| 449 | }
|
| 450 |
|
| 451 | |
| 452 | |
| 453 | unsafe extern "C" fn rust_binder_poll(
|
| 454 | file: *mut bindings::file,
|
| 455 | wait: *mut bindings::poll_table_struct,
|
| 456 | ) -> bindings::__poll_t {
|
| 457 | |
| 458 | let f = unsafe { Arc::<Process>::borrow((*file).private_data) };
|
| 459 | |
| 460 | let fileref = unsafe { File::from_raw_file(file) };
|
| 461 | |
| 462 | match Process::poll(f, fileref, unsafe { PollTable::from_raw(wait) }) {
|
| 463 | Ok(v) => v,
|
| 464 | Err(_) => bindings::POLLERR,
|
| 465 | }
|
| 466 | }
|
| 467 |
|
| 468 | |
| 469 | |
| 470 | unsafe extern "C" fn rust_binder_flush(
|
| 471 | file: *mut bindings::file,
|
| 472 | _id: bindings::fl_owner_t,
|
| 473 | ) -> kernel::ffi::c_int {
|
| 474 | |
| 475 | let f = unsafe { Arc::<Process>::borrow((*file).private_data) };
|
| 476 | match Process::flush(f) {
|
| 477 | Ok(()) => 0,
|
| 478 | Err(err) => err.to_errno(),
|
| 479 | }
|
| 480 | }
|
| 481 |
|
| 482 | |
| 483 | |
| 484 | #[no_mangle]
|
| 485 | unsafe extern "C" fn rust_binder_stats_show(
|
| 486 | ptr: *mut seq_file,
|
| 487 | _: *mut kernel::ffi::c_void,
|
| 488 | ) -> kernel::ffi::c_int {
|
| 489 | |
| 490 | |
| 491 | let m = unsafe { SeqFile::from_raw(ptr) };
|
| 492 | if let Err(err) = rust_binder_stats_show_impl(m) {
|
| 493 | seq_print!(m, "failed to generate state: {:?}\n", err);
|
| 494 | }
|
| 495 | 0
|
| 496 | }
|
| 497 |
|
| 498 | |
| 499 | |
| 500 | #[no_mangle]
|
| 501 | unsafe extern "C" fn rust_binder_state_show(
|
| 502 | ptr: *mut seq_file,
|
| 503 | _: *mut kernel::ffi::c_void,
|
| 504 | ) -> kernel::ffi::c_int {
|
| 505 | |
| 506 | |
| 507 | let m = unsafe { SeqFile::from_raw(ptr) };
|
| 508 | if let Err(err) = rust_binder_state_show_impl(m) {
|
| 509 | seq_print!(m, "failed to generate state: {:?}\n", err);
|
| 510 | }
|
| 511 | 0
|
| 512 | }
|
| 513 |
|
| 514 | |
| 515 | |
| 516 | #[no_mangle]
|
| 517 | unsafe extern "C" fn rust_binder_proc_show(
|
| 518 | ptr: *mut seq_file,
|
| 519 | _: *mut kernel::ffi::c_void,
|
| 520 | ) -> kernel::ffi::c_int {
|
| 521 | |
| 522 | let pid = unsafe { (*ptr).private }.addr() as Pid;
|
| 523 | |
| 524 | |
| 525 | let m = unsafe { SeqFile::from_raw(ptr) };
|
| 526 | if let Err(err) = rust_binder_proc_show_impl(m, pid) {
|
| 527 | seq_print!(m, "failed to generate state: {:?}\n", err);
|
| 528 | }
|
| 529 | 0
|
| 530 | }
|
| 531 |
|
| 532 | |
| 533 | |
| 534 | #[no_mangle]
|
| 535 | unsafe extern "C" fn rust_binder_transactions_show(
|
| 536 | ptr: *mut seq_file,
|
| 537 | _: *mut kernel::ffi::c_void,
|
| 538 | ) -> kernel::ffi::c_int {
|
| 539 | |
| 540 | |
| 541 | let m = unsafe { SeqFile::from_raw(ptr) };
|
| 542 | if let Err(err) = rust_binder_transactions_show_impl(m) {
|
| 543 | seq_print!(m, "failed to generate state: {:?}\n", err);
|
| 544 | }
|
| 545 | 0
|
| 546 | }
|
| 547 |
|
| 548 | fn rust_binder_transactions_show_impl(m: &SeqFile) -> Result<()> {
|
| 549 | seq_print!(m, "binder transactions:\n");
|
| 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(m, &ctx, false)?;
|
| 555 | seq_print!(m, "\n");
|
| 556 | }
|
| 557 | }
|
| 558 | Ok(())
|
| 559 | }
|
| 560 |
|
| 561 | fn rust_binder_stats_show_impl(m: &SeqFile) -> Result<()> {
|
| 562 | seq_print!(m, "binder stats:\n");
|
| 563 | stats::GLOBAL_STATS.debug_print("", m);
|
| 564 | let contexts = context::get_all_contexts()?;
|
| 565 | for ctx in contexts {
|
| 566 | let procs = ctx.get_all_procs()?;
|
| 567 | for proc in procs {
|
| 568 | proc.debug_print_stats(m, &ctx)?;
|
| 569 | seq_print!(m, "\n");
|
| 570 | }
|
| 571 | }
|
| 572 | Ok(())
|
| 573 | }
|
| 574 |
|
| 575 | fn rust_binder_state_show_impl(m: &SeqFile) -> Result<()> {
|
| 576 | seq_print!(m, "binder state:\n");
|
| 577 | let contexts = context::get_all_contexts()?;
|
| 578 | for ctx in contexts {
|
| 579 | let procs = ctx.get_all_procs()?;
|
| 580 | for proc in procs {
|
| 581 | proc.debug_print(m, &ctx, true)?;
|
| 582 | seq_print!(m, "\n");
|
| 583 | }
|
| 584 | }
|
| 585 | Ok(())
|
| 586 | }
|
| 587 |
|
| 588 | fn rust_binder_proc_show_impl(m: &SeqFile, pid: Pid) -> Result<()> {
|
| 589 | seq_print!(m, "binder proc state:\n");
|
| 590 | let contexts = context::get_all_contexts()?;
|
| 591 | for ctx in contexts {
|
| 592 | let procs = ctx.get_procs_with_pid(pid)?;
|
| 593 | for proc in procs {
|
| 594 | proc.debug_print(m, &ctx, true)?;
|
| 595 | seq_print!(m, "\n");
|
| 596 | }
|
| 597 | }
|
| 598 | Ok(())
|
| 599 | }
|
| 600 |
|
| 601 | struct BinderfsProcFile(NonNull<bindings::dentry>);
|
| 602 |
|
| 603 | |
| 604 | unsafe impl Send for BinderfsProcFile {}
|
| 605 |
|
| 606 | impl BinderfsProcFile {
|
| 607 | |
| 608 | |
| 609 | |
| 610 | unsafe fn new(nodp: *mut bindings::inode, pid: i32) -> Result<Option<Self>> {
|
| 611 | |
| 612 | let dentry = unsafe { binderfs::rust_binderfs_create_proc_file(nodp, pid) };
|
| 613 | match kernel::error::from_err_ptr(dentry) {
|
| 614 | Ok(dentry) => Ok(NonNull::new(dentry).map(Self)),
|
| 615 | Err(err) if err == EEXIST => Ok(None),
|
| 616 | Err(err) => Err(err),
|
| 617 | }
|
| 618 | }
|
| 619 | }
|
| 620 |
|
| 621 | impl Drop for BinderfsProcFile {
|
| 622 | fn drop(&mut self) {
|
| 623 | |
| 624 | unsafe { binderfs::rust_binderfs_remove_file(self.0.as_ptr()) };
|
| 625 | }
|
| 626 | }
|