rust_binder_main.rs 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617
  1. // SPDX-License-Identifier: GPL-2.0
  2. // Copyright (C) 2025 Google LLC.
  3. //! Binder -- the Android IPC mechanism.
  4. #![recursion_limit = "256"]
  5. #![allow(
  6. clippy::as_underscore,
  7. clippy::ref_as_ptr,
  8. clippy::ptr_as_ptr,
  9. clippy::cast_lossless
  10. )]
  11. use kernel::{
  12. bindings::{self, seq_file},
  13. fs::File,
  14. list::{ListArc, ListArcSafe, ListLinksSelfPtr, TryNewListArc},
  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. use crate::{context::Context, page_range::Shrinker, process::Process, thread::Thread};
  27. use core::ptr::NonNull;
  28. mod allocation;
  29. mod context;
  30. mod deferred_close;
  31. mod defs;
  32. mod error;
  33. mod node;
  34. mod page_range;
  35. mod process;
  36. mod range_alloc;
  37. mod stats;
  38. mod thread;
  39. mod trace;
  40. mod transaction;
  41. #[allow(warnings)] // generated bindgen code
  42. mod binderfs {
  43. use kernel::bindings::{dentry, inode};
  44. extern "C" {
  45. pub fn init_rust_binderfs() -> kernel::ffi::c_int;
  46. }
  47. extern "C" {
  48. pub fn rust_binderfs_create_proc_file(
  49. nodp: *mut inode,
  50. pid: kernel::ffi::c_int,
  51. ) -> *mut dentry;
  52. }
  53. extern "C" {
  54. pub fn rust_binderfs_remove_file(dentry: *mut dentry);
  55. }
  56. pub type rust_binder_context = *mut kernel::ffi::c_void;
  57. #[repr(C)]
  58. #[derive(Copy, Clone)]
  59. pub struct binder_device {
  60. pub minor: kernel::ffi::c_int,
  61. pub ctx: rust_binder_context,
  62. }
  63. impl Default for binder_device {
  64. fn default() -> Self {
  65. let mut s = ::core::mem::MaybeUninit::<Self>::uninit();
  66. unsafe {
  67. ::core::ptr::write_bytes(s.as_mut_ptr(), 0, 1);
  68. s.assume_init()
  69. }
  70. }
  71. }
  72. }
  73. module! {
  74. type: BinderModule,
  75. name: "rust_binder",
  76. authors: ["Wedson Almeida Filho", "Alice Ryhl"],
  77. description: "Android Binder",
  78. license: "GPL",
  79. }
  80. use kernel::bindings::rust_binder_layout;
  81. #[no_mangle]
  82. static RUST_BINDER_LAYOUT: rust_binder_layout = rust_binder_layout {
  83. t: transaction::TRANSACTION_LAYOUT,
  84. p: process::PROCESS_LAYOUT,
  85. n: node::NODE_LAYOUT,
  86. };
  87. fn next_debug_id() -> usize {
  88. static NEXT_DEBUG_ID: Atomic<usize> = Atomic::new(0);
  89. NEXT_DEBUG_ID.fetch_add(1, Relaxed)
  90. }
  91. /// Provides a single place to write Binder return values via the
  92. /// supplied `UserSliceWriter`.
  93. pub(crate) struct BinderReturnWriter<'a> {
  94. writer: UserSliceWriter,
  95. thread: &'a Thread,
  96. }
  97. impl<'a> BinderReturnWriter<'a> {
  98. fn new(writer: UserSliceWriter, thread: &'a Thread) -> Self {
  99. BinderReturnWriter { writer, thread }
  100. }
  101. /// Write a return code back to user space.
  102. /// Should be a `BR_` constant from [`defs`] e.g. [`defs::BR_TRANSACTION_COMPLETE`].
  103. fn write_code(&mut self, code: u32) -> Result {
  104. stats::GLOBAL_STATS.inc_br(code);
  105. self.thread.process.stats.inc_br(code);
  106. self.writer.write(&code)
  107. }
  108. /// Write something *other than* a return code to user space.
  109. fn write_payload<T: AsBytes>(&mut self, payload: &T) -> Result {
  110. self.writer.write(payload)
  111. }
  112. fn len(&self) -> usize {
  113. self.writer.len()
  114. }
  115. }
  116. /// Specifies how a type should be delivered to the read part of a BINDER_WRITE_READ ioctl.
  117. ///
  118. /// When a value is pushed to the todo list for a process or thread, it is stored as a trait object
  119. /// with the type `Arc<dyn DeliverToRead>`. Trait objects are a Rust feature that lets you
  120. /// implement dynamic dispatch over many different types. This lets us store many different types
  121. /// in the todo list.
  122. trait DeliverToRead: ListArcSafe + Send + Sync {
  123. /// Performs work. Returns true if remaining work items in the queue should be processed
  124. /// immediately, or false if it should return to caller before processing additional work
  125. /// items.
  126. fn do_work(
  127. self: DArc<Self>,
  128. thread: &Thread,
  129. writer: &mut BinderReturnWriter<'_>,
  130. ) -> Result<bool>;
  131. /// Cancels the given work item. This is called instead of [`DeliverToRead::do_work`] when work
  132. /// won't be delivered.
  133. fn cancel(self: DArc<Self>);
  134. /// Should we use `wake_up_interruptible_sync` or `wake_up_interruptible` when scheduling this
  135. /// work item?
  136. ///
  137. /// Generally only set to true for non-oneway transactions.
  138. fn should_sync_wakeup(&self) -> bool;
  139. fn debug_print(&self, m: &SeqFile, prefix: &str, transaction_prefix: &str) -> Result<()>;
  140. }
  141. // Wrapper around a `DeliverToRead` with linked list links.
  142. #[pin_data]
  143. struct DTRWrap<T: ?Sized> {
  144. #[pin]
  145. links: ListLinksSelfPtr<DTRWrap<dyn DeliverToRead>>,
  146. #[pin]
  147. wrapped: T,
  148. }
  149. kernel::list::impl_list_arc_safe! {
  150. impl{T: ListArcSafe + ?Sized} ListArcSafe<0> for DTRWrap<T> {
  151. tracked_by wrapped: T;
  152. }
  153. }
  154. kernel::list::impl_list_item! {
  155. impl ListItem<0> for DTRWrap<dyn DeliverToRead> {
  156. using ListLinksSelfPtr { self.links };
  157. }
  158. }
  159. impl<T: ?Sized> core::ops::Deref for DTRWrap<T> {
  160. type Target = T;
  161. fn deref(&self) -> &T {
  162. &self.wrapped
  163. }
  164. }
  165. type DArc<T> = kernel::sync::Arc<DTRWrap<T>>;
  166. type DLArc<T> = kernel::list::ListArc<DTRWrap<T>>;
  167. impl<T: ListArcSafe> DTRWrap<T> {
  168. fn new(val: impl PinInit<T>) -> impl PinInit<Self> {
  169. pin_init!(Self {
  170. links <- ListLinksSelfPtr::new(),
  171. wrapped <- val,
  172. })
  173. }
  174. fn arc_try_new(val: T) -> Result<DLArc<T>, kernel::alloc::AllocError> {
  175. ListArc::pin_init(
  176. try_pin_init!(Self {
  177. links <- ListLinksSelfPtr::new(),
  178. wrapped: val,
  179. }),
  180. GFP_KERNEL,
  181. )
  182. .map_err(|_| kernel::alloc::AllocError)
  183. }
  184. fn arc_pin_init(init: impl PinInit<T>) -> Result<DLArc<T>, kernel::error::Error> {
  185. ListArc::pin_init(
  186. try_pin_init!(Self {
  187. links <- ListLinksSelfPtr::new(),
  188. wrapped <- init,
  189. }),
  190. GFP_KERNEL,
  191. )
  192. }
  193. }
  194. struct DeliverCode {
  195. code: u32,
  196. skip: Atomic<bool>,
  197. }
  198. kernel::list::impl_list_arc_safe! {
  199. impl ListArcSafe<0> for DeliverCode { untracked; }
  200. }
  201. impl DeliverCode {
  202. fn new(code: u32) -> Self {
  203. Self {
  204. code,
  205. skip: Atomic::new(false),
  206. }
  207. }
  208. /// Disable this DeliverCode and make it do nothing.
  209. ///
  210. /// This is used instead of removing it from the work list, since `LinkedList::remove` is
  211. /// unsafe, whereas this method is not.
  212. fn skip(&self) {
  213. self.skip.store(true, Relaxed);
  214. }
  215. }
  216. impl DeliverToRead for DeliverCode {
  217. fn do_work(
  218. self: DArc<Self>,
  219. _thread: &Thread,
  220. writer: &mut BinderReturnWriter<'_>,
  221. ) -> Result<bool> {
  222. if !self.skip.load(Relaxed) {
  223. writer.write_code(self.code)?;
  224. }
  225. Ok(true)
  226. }
  227. fn cancel(self: DArc<Self>) {}
  228. fn should_sync_wakeup(&self) -> bool {
  229. false
  230. }
  231. fn debug_print(&self, m: &SeqFile, prefix: &str, _tprefix: &str) -> Result<()> {
  232. seq_print!(m, "{}", prefix);
  233. if self.skip.load(Relaxed) {
  234. seq_print!(m, "(skipped) ");
  235. }
  236. if self.code == defs::BR_TRANSACTION_COMPLETE {
  237. seq_print!(m, "transaction complete\n");
  238. } else {
  239. seq_print!(m, "transaction error: {}\n", self.code);
  240. }
  241. Ok(())
  242. }
  243. }
  244. fn ptr_align(value: usize) -> Option<usize> {
  245. let size = core::mem::size_of::<usize>() - 1;
  246. Some(value.checked_add(size)? & !size)
  247. }
  248. // SAFETY: We call register in `init`.
  249. static BINDER_SHRINKER: Shrinker = unsafe { Shrinker::new() };
  250. struct BinderModule {}
  251. impl kernel::Module for BinderModule {
  252. fn init(_module: &'static kernel::ThisModule) -> Result<Self> {
  253. // SAFETY: The module initializer never runs twice, so we only call this once.
  254. unsafe { crate::context::CONTEXTS.init() };
  255. pr_warn!("Loaded Rust Binder.");
  256. BINDER_SHRINKER.register(c"android-binder")?;
  257. // SAFETY: The module is being loaded, so we can initialize binderfs.
  258. unsafe { kernel::error::to_result(binderfs::init_rust_binderfs())? };
  259. Ok(Self {})
  260. }
  261. }
  262. /// Makes the inner type Sync.
  263. #[repr(transparent)]
  264. pub struct AssertSync<T>(T);
  265. // SAFETY: Used only to insert C bindings types into globals, which is safe.
  266. unsafe impl<T> Sync for AssertSync<T> {}
  267. /// File operations that rust_binderfs.c can use.
  268. #[no_mangle]
  269. #[used]
  270. pub static rust_binder_fops: AssertSync<kernel::bindings::file_operations> = {
  271. // SAFETY: All zeroes is safe for the `file_operations` type.
  272. let zeroed_ops = unsafe { core::mem::MaybeUninit::zeroed().assume_init() };
  273. let ops = kernel::bindings::file_operations {
  274. owner: THIS_MODULE.as_ptr(),
  275. poll: Some(rust_binder_poll),
  276. unlocked_ioctl: Some(rust_binder_ioctl),
  277. compat_ioctl: bindings::compat_ptr_ioctl,
  278. mmap: Some(rust_binder_mmap),
  279. open: Some(rust_binder_open),
  280. release: Some(rust_binder_release),
  281. flush: Some(rust_binder_flush),
  282. ..zeroed_ops
  283. };
  284. AssertSync(ops)
  285. };
  286. /// # Safety
  287. /// Only called by binderfs.
  288. #[no_mangle]
  289. unsafe extern "C" fn rust_binder_new_context(
  290. name: *const kernel::ffi::c_char,
  291. ) -> *mut kernel::ffi::c_void {
  292. // SAFETY: The caller will always provide a valid c string here.
  293. let name = unsafe { kernel::str::CStr::from_char_ptr(name) };
  294. match Context::new(name) {
  295. Ok(ctx) => Arc::into_foreign(ctx),
  296. Err(_err) => core::ptr::null_mut(),
  297. }
  298. }
  299. /// # Safety
  300. /// Only called by binderfs.
  301. #[no_mangle]
  302. unsafe extern "C" fn rust_binder_remove_context(device: *mut kernel::ffi::c_void) {
  303. if !device.is_null() {
  304. // SAFETY: The caller ensures that the `device` pointer came from a previous call to
  305. // `rust_binder_new_device`.
  306. let ctx = unsafe { Arc::<Context>::from_foreign(device) };
  307. ctx.deregister();
  308. drop(ctx);
  309. }
  310. }
  311. /// # Safety
  312. /// Only called by binderfs.
  313. unsafe extern "C" fn rust_binder_open(
  314. inode: *mut bindings::inode,
  315. file_ptr: *mut bindings::file,
  316. ) -> kernel::ffi::c_int {
  317. // SAFETY: The `rust_binderfs.c` file ensures that `i_private` is set to a
  318. // `struct binder_device`.
  319. let device = unsafe { (*inode).i_private } as *const binderfs::binder_device;
  320. assert!(!device.is_null());
  321. // SAFETY: The `rust_binderfs.c` file ensures that `device->ctx` holds a binder context when
  322. // using the rust binder fops.
  323. let ctx = unsafe { Arc::<Context>::borrow((*device).ctx) };
  324. // SAFETY: The caller provides a valid file pointer to a new `struct file`.
  325. let file = unsafe { File::from_raw_file(file_ptr) };
  326. let process = match Process::open(ctx, file) {
  327. Ok(process) => process,
  328. Err(err) => return err.to_errno(),
  329. };
  330. // SAFETY: This is an `inode` for a newly created binder file.
  331. match unsafe { BinderfsProcFile::new(inode, process.task.pid()) } {
  332. Ok(Some(file)) => process.inner.lock().binderfs_file = Some(file),
  333. Ok(None) => { /* pid already exists */ }
  334. Err(err) => return err.to_errno(),
  335. }
  336. // SAFETY: This file is associated with Rust binder, so we own the `private_data` field.
  337. unsafe { (*file_ptr).private_data = process.into_foreign() };
  338. 0
  339. }
  340. /// # Safety
  341. /// Only called by binderfs.
  342. unsafe extern "C" fn rust_binder_release(
  343. _inode: *mut bindings::inode,
  344. file: *mut bindings::file,
  345. ) -> kernel::ffi::c_int {
  346. // SAFETY: We previously set `private_data` in `rust_binder_open`.
  347. let process = unsafe { Arc::<Process>::from_foreign((*file).private_data) };
  348. // SAFETY: The caller ensures that the file is valid.
  349. let file = unsafe { File::from_raw_file(file) };
  350. Process::release(process, file);
  351. 0
  352. }
  353. /// # Safety
  354. /// Only called by binderfs.
  355. unsafe extern "C" fn rust_binder_ioctl(
  356. file: *mut bindings::file,
  357. cmd: kernel::ffi::c_uint,
  358. arg: kernel::ffi::c_ulong,
  359. ) -> kernel::ffi::c_long {
  360. // SAFETY: We previously set `private_data` in `rust_binder_open`.
  361. let f = unsafe { Arc::<Process>::borrow((*file).private_data) };
  362. // SAFETY: The caller ensures that the file is valid.
  363. match Process::ioctl(f, unsafe { File::from_raw_file(file) }, cmd as _, arg as _) {
  364. Ok(()) => 0,
  365. Err(err) => err.to_errno() as isize,
  366. }
  367. }
  368. /// # Safety
  369. /// Only called by binderfs.
  370. unsafe extern "C" fn rust_binder_mmap(
  371. file: *mut bindings::file,
  372. vma: *mut bindings::vm_area_struct,
  373. ) -> kernel::ffi::c_int {
  374. // SAFETY: We previously set `private_data` in `rust_binder_open`.
  375. let f = unsafe { Arc::<Process>::borrow((*file).private_data) };
  376. // SAFETY: The caller ensures that the vma is valid.
  377. let area = unsafe { kernel::mm::virt::VmaNew::from_raw(vma) };
  378. // SAFETY: The caller ensures that the file is valid.
  379. match Process::mmap(f, unsafe { File::from_raw_file(file) }, area) {
  380. Ok(()) => 0,
  381. Err(err) => err.to_errno(),
  382. }
  383. }
  384. /// # Safety
  385. /// Only called by binderfs.
  386. unsafe extern "C" fn rust_binder_poll(
  387. file: *mut bindings::file,
  388. wait: *mut bindings::poll_table_struct,
  389. ) -> bindings::__poll_t {
  390. // SAFETY: We previously set `private_data` in `rust_binder_open`.
  391. let f = unsafe { Arc::<Process>::borrow((*file).private_data) };
  392. // SAFETY: The caller ensures that the file is valid.
  393. let fileref = unsafe { File::from_raw_file(file) };
  394. // SAFETY: The caller ensures that the `PollTable` is valid.
  395. match Process::poll(f, fileref, unsafe { PollTable::from_raw(wait) }) {
  396. Ok(v) => v,
  397. Err(_) => bindings::POLLERR,
  398. }
  399. }
  400. /// # Safety
  401. /// Only called by binderfs.
  402. unsafe extern "C" fn rust_binder_flush(
  403. file: *mut bindings::file,
  404. _id: bindings::fl_owner_t,
  405. ) -> kernel::ffi::c_int {
  406. // SAFETY: We previously set `private_data` in `rust_binder_open`.
  407. let f = unsafe { Arc::<Process>::borrow((*file).private_data) };
  408. match Process::flush(f) {
  409. Ok(()) => 0,
  410. Err(err) => err.to_errno(),
  411. }
  412. }
  413. /// # Safety
  414. /// Only called by binderfs.
  415. #[no_mangle]
  416. unsafe extern "C" fn rust_binder_stats_show(
  417. ptr: *mut seq_file,
  418. _: *mut kernel::ffi::c_void,
  419. ) -> kernel::ffi::c_int {
  420. // SAFETY: The caller ensures that the pointer is valid and exclusive for the duration in which
  421. // this method is called.
  422. let m = unsafe { SeqFile::from_raw(ptr) };
  423. if let Err(err) = rust_binder_stats_show_impl(m) {
  424. seq_print!(m, "failed to generate state: {:?}\n", err);
  425. }
  426. 0
  427. }
  428. /// # Safety
  429. /// Only called by binderfs.
  430. #[no_mangle]
  431. unsafe extern "C" fn rust_binder_state_show(
  432. ptr: *mut seq_file,
  433. _: *mut kernel::ffi::c_void,
  434. ) -> kernel::ffi::c_int {
  435. // SAFETY: The caller ensures that the pointer is valid and exclusive for the duration in which
  436. // this method is called.
  437. let m = unsafe { SeqFile::from_raw(ptr) };
  438. if let Err(err) = rust_binder_state_show_impl(m) {
  439. seq_print!(m, "failed to generate state: {:?}\n", err);
  440. }
  441. 0
  442. }
  443. /// # Safety
  444. /// Only called by binderfs.
  445. #[no_mangle]
  446. unsafe extern "C" fn rust_binder_proc_show(
  447. ptr: *mut seq_file,
  448. _: *mut kernel::ffi::c_void,
  449. ) -> kernel::ffi::c_int {
  450. // SAFETY: Accessing the private field of `seq_file` is okay.
  451. let pid = (unsafe { (*ptr).private }) as usize as Pid;
  452. // SAFETY: The caller ensures that the pointer is valid and exclusive for the duration in which
  453. // this method is called.
  454. let m = unsafe { SeqFile::from_raw(ptr) };
  455. if let Err(err) = rust_binder_proc_show_impl(m, pid) {
  456. seq_print!(m, "failed to generate state: {:?}\n", err);
  457. }
  458. 0
  459. }
  460. /// # Safety
  461. /// Only called by binderfs.
  462. #[no_mangle]
  463. unsafe extern "C" fn rust_binder_transactions_show(
  464. ptr: *mut seq_file,
  465. _: *mut kernel::ffi::c_void,
  466. ) -> kernel::ffi::c_int {
  467. // SAFETY: The caller ensures that the pointer is valid and exclusive for the duration in which
  468. // this method is called.
  469. let m = unsafe { SeqFile::from_raw(ptr) };
  470. if let Err(err) = rust_binder_transactions_show_impl(m) {
  471. seq_print!(m, "failed to generate state: {:?}\n", err);
  472. }
  473. 0
  474. }
  475. fn rust_binder_transactions_show_impl(m: &SeqFile) -> Result<()> {
  476. seq_print!(m, "binder transactions:\n");
  477. let contexts = context::get_all_contexts()?;
  478. for ctx in contexts {
  479. let procs = ctx.get_all_procs()?;
  480. for proc in procs {
  481. proc.debug_print(m, &ctx, false)?;
  482. seq_print!(m, "\n");
  483. }
  484. }
  485. Ok(())
  486. }
  487. fn rust_binder_stats_show_impl(m: &SeqFile) -> Result<()> {
  488. seq_print!(m, "binder stats:\n");
  489. stats::GLOBAL_STATS.debug_print("", m);
  490. let contexts = context::get_all_contexts()?;
  491. for ctx in contexts {
  492. let procs = ctx.get_all_procs()?;
  493. for proc in procs {
  494. proc.debug_print_stats(m, &ctx)?;
  495. seq_print!(m, "\n");
  496. }
  497. }
  498. Ok(())
  499. }
  500. fn rust_binder_state_show_impl(m: &SeqFile) -> Result<()> {
  501. seq_print!(m, "binder state:\n");
  502. let contexts = context::get_all_contexts()?;
  503. for ctx in contexts {
  504. let procs = ctx.get_all_procs()?;
  505. for proc in procs {
  506. proc.debug_print(m, &ctx, true)?;
  507. seq_print!(m, "\n");
  508. }
  509. }
  510. Ok(())
  511. }
  512. fn rust_binder_proc_show_impl(m: &SeqFile, pid: Pid) -> Result<()> {
  513. seq_print!(m, "binder proc state:\n");
  514. let contexts = context::get_all_contexts()?;
  515. for ctx in contexts {
  516. let procs = ctx.get_procs_with_pid(pid)?;
  517. for proc in procs {
  518. proc.debug_print(m, &ctx, true)?;
  519. seq_print!(m, "\n");
  520. }
  521. }
  522. Ok(())
  523. }
  524. struct BinderfsProcFile(NonNull<bindings::dentry>);
  525. // SAFETY: Safe to drop any thread.
  526. unsafe impl Send for BinderfsProcFile {}
  527. impl BinderfsProcFile {
  528. /// # Safety
  529. ///
  530. /// Takes an inode from a newly created binder file.
  531. unsafe fn new(nodp: *mut bindings::inode, pid: i32) -> Result<Option<Self>> {
  532. // SAFETY: The caller passes an `inode` for a newly created binder file.
  533. let dentry = unsafe { binderfs::rust_binderfs_create_proc_file(nodp, pid) };
  534. match kernel::error::from_err_ptr(dentry) {
  535. Ok(dentry) => Ok(NonNull::new(dentry).map(Self)),
  536. Err(err) if err == EEXIST => Ok(None),
  537. Err(err) => Err(err),
  538. }
  539. }
  540. }
  541. impl Drop for BinderfsProcFile {
  542. fn drop(&mut self) {
  543. // SAFETY: This is a dentry from `rust_binderfs_remove_file` that has not been deleted yet.
  544. unsafe { binderfs::rust_binderfs_remove_file(self.0.as_ptr()) };
  545. }
  546. }