ANDROID: ashmem_rust: Add is_ashmem_file()
The minidump module iterates over open files and VMAs for each process and reports information that is useful for debugging. A useful piece of information is what ashmem files are currently referenced either via a userspace memory mapping or a file descriptor. Therefore, add is_ashmem_file() to aid in identifying those references. Unfortunately, the logic that exports Rust symbols to other kernel modules only considers the crates under the rust/ directory at the root of the kernel repository. Since there's no support to include symbols from crates defined outside of that repository, add ashmem_rust_exports.c to export is_ashmem_file(). Changes from older versions of this patch: - Reworded commit message for clarity. - Implemented is_ashmem_file() in Rust, since android16-6.12+ will use Rust for ashmem. Bug: 193397560 Change-Id: I5b7816ad4775e5cf2c4f41c28b1c8dacc2c85b7e Signed-off-by: Isaac J. Manjarres <isaacmanjarres@google.com>
This commit is contained in:
committed by
Isaac Manjarres
parent
0d890f867e
commit
6bdbae6ea9
@@ -3,3 +3,4 @@ ccflags-y += -I$(src) # needed for trace events
|
|||||||
|
|
||||||
obj-$(CONFIG_ASHMEM_C) += ashmem.o
|
obj-$(CONFIG_ASHMEM_C) += ashmem.o
|
||||||
obj-$(CONFIG_ASHMEM_RUST) += ashmem_rust.o
|
obj-$(CONFIG_ASHMEM_RUST) += ashmem_rust.o
|
||||||
|
ashmem_rust-objs += ashmem_rust.o ashmem_rust_exports.o
|
||||||
|
|||||||
@@ -31,4 +31,6 @@ enum {
|
|||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
bool is_ashmem_file(struct file *file);
|
||||||
|
|
||||||
#endif /* _LINUX_ASHMEM_H */
|
#endif /* _LINUX_ASHMEM_H */
|
||||||
|
|||||||
@@ -12,7 +12,8 @@
|
|||||||
|
|
||||||
use core::{
|
use core::{
|
||||||
pin::Pin,
|
pin::Pin,
|
||||||
sync::atomic::{AtomicBool, AtomicUsize, Ordering},
|
ptr::null_mut,
|
||||||
|
sync::atomic::{AtomicBool, AtomicPtr, AtomicUsize, Ordering},
|
||||||
};
|
};
|
||||||
use kernel::{
|
use kernel::{
|
||||||
bindings::{self, ASHMEM_GET_PIN_STATUS, ASHMEM_PIN, ASHMEM_UNPIN},
|
bindings::{self, ASHMEM_GET_PIN_STATUS, ASHMEM_PIN, ASHMEM_UNPIN},
|
||||||
@@ -71,6 +72,7 @@ fn has_cap_sys_admin() -> bool {
|
|||||||
static NUM_PIN_IOCTLS_WAITING: AtomicUsize = AtomicUsize::new(0);
|
static NUM_PIN_IOCTLS_WAITING: AtomicUsize = AtomicUsize::new(0);
|
||||||
static IGNORE_UNSET_PROT_READ: AtomicBool = AtomicBool::new(false);
|
static IGNORE_UNSET_PROT_READ: AtomicBool = AtomicBool::new(false);
|
||||||
static IGNORE_UNSET_PROT_EXEC: AtomicBool = AtomicBool::new(false);
|
static IGNORE_UNSET_PROT_EXEC: AtomicBool = AtomicBool::new(false);
|
||||||
|
static ASHMEM_FOPS_PTR: AtomicPtr<bindings::file_operations> = AtomicPtr::new(null_mut());
|
||||||
|
|
||||||
fn shrinker_should_stop() -> bool {
|
fn shrinker_should_stop() -> bool {
|
||||||
NUM_PIN_IOCTLS_WAITING.load(Ordering::Relaxed) > 0
|
NUM_PIN_IOCTLS_WAITING.load(Ordering::Relaxed) > 0
|
||||||
@@ -104,13 +106,20 @@ impl kernel::Module for AshmemModule {
|
|||||||
|
|
||||||
ashmem_range::set_shrinker_enabled(true)?;
|
ashmem_range::set_shrinker_enabled(true)?;
|
||||||
|
|
||||||
|
let ashmem_miscdevice_registration = KBox::pin_init(
|
||||||
|
MiscDeviceRegistration::register(MiscDeviceOptions {
|
||||||
|
name: c_str!("ashmem"),
|
||||||
|
}),
|
||||||
|
GFP_KERNEL,
|
||||||
|
)?;
|
||||||
|
let ashmem_miscdevice_ptr = ashmem_miscdevice_registration.as_raw();
|
||||||
|
// SAFETY: ashmem_miscdevice_registration is pinned and is never destroyed, so reading
|
||||||
|
// and storing the fops pointer this way should be fine.
|
||||||
|
let fops_ptr = unsafe { (*ashmem_miscdevice_ptr).fops };
|
||||||
|
ASHMEM_FOPS_PTR.store(fops_ptr.cast_mut(), Ordering::Relaxed);
|
||||||
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
_misc: KBox::pin_init(
|
_misc: ashmem_miscdevice_registration,
|
||||||
MiscDeviceRegistration::register(MiscDeviceOptions {
|
|
||||||
name: c_str!("ashmem"),
|
|
||||||
}),
|
|
||||||
GFP_KERNEL,
|
|
||||||
)?,
|
|
||||||
_toggle_unpin: AshmemToggleMisc::<AshmemToggleShrinker>::new()?,
|
_toggle_unpin: AshmemToggleMisc::<AshmemToggleShrinker>::new()?,
|
||||||
_toggle_read: AshmemToggleMisc::<AshmemToggleRead>::new()?,
|
_toggle_read: AshmemToggleMisc::<AshmemToggleRead>::new()?,
|
||||||
_toggle_exec: AshmemToggleMisc::<AshmemToggleExec>::new()?,
|
_toggle_exec: AshmemToggleMisc::<AshmemToggleExec>::new()?,
|
||||||
@@ -638,3 +647,18 @@ fn ashmem_memfd_ioctl_inner(file: &File, cmd: u32, arg: usize) -> Result<isize>
|
|||||||
_ => Err(EINVAL),
|
_ => Err(EINVAL),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// # Safety
|
||||||
|
///
|
||||||
|
/// The caller must ensure that `file` is valid for the duration of this function.
|
||||||
|
#[no_mangle]
|
||||||
|
unsafe extern "C" fn is_ashmem_file(file: *mut bindings::file) -> bool {
|
||||||
|
let ashmem_fops_ptr = ASHMEM_FOPS_PTR.load(Ordering::Relaxed);
|
||||||
|
if file.is_null() || ashmem_fops_ptr.is_null() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// SAFETY: Accessing the f_op field of a non-NULL file structure is always okay.
|
||||||
|
let fops_ptr = unsafe { (*file).f_op };
|
||||||
|
fops_ptr == ashmem_fops_ptr
|
||||||
|
}
|
||||||
|
|||||||
@@ -0,0 +1,19 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-2.0
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Symbols exported from the Ashmem Rust driver for loadable kernel modules to use.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2025, Google LLC.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <linux/export.h>
|
||||||
|
|
||||||
|
#include "ashmem.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* List symbols that need to be exported to loadable kernel modules below. This is needed because
|
||||||
|
* the logic that exports symbols from Rust crates only considers the crates under the rust/
|
||||||
|
* directory at the root of the kernel repo. It currently does not support exporting symbols from
|
||||||
|
* other crates.
|
||||||
|
*/
|
||||||
|
EXPORT_SYMBOL_GPL(is_ashmem_file);
|
||||||
Reference in New Issue
Block a user