diff --git a/drivers/staging/android/ashmem.h b/drivers/staging/android/ashmem.h index f649afa0d963..ad64cf791f2e 100644 --- a/drivers/staging/android/ashmem.h +++ b/drivers/staging/android/ashmem.h @@ -32,5 +32,6 @@ enum { #endif bool is_ashmem_file(struct file *file); +int ashmem_area_name(struct file *file, char *name); #endif /* _LINUX_ASHMEM_H */ diff --git a/drivers/staging/android/ashmem_rust.rs b/drivers/staging/android/ashmem_rust.rs index e3f1165f1ed4..b147e524f88f 100644 --- a/drivers/staging/android/ashmem_rust.rs +++ b/drivers/staging/android/ashmem_rust.rs @@ -30,6 +30,7 @@ use kernel::{ seq_file::{seq_print, SeqFile}, sync::{new_mutex, Mutex, UniqueArc}, task::Task, + types::ForeignOwnable, uaccess::{UserSlice, UserSliceReader, UserSliceWriter}, }; @@ -662,3 +663,47 @@ unsafe extern "C" fn is_ashmem_file(file: *mut bindings::file) -> bool { let fops_ptr = unsafe { (*file).f_op }; fops_ptr == ashmem_fops_ptr } + +/// # Safety +/// +/// The caller must ensure that `file` references a valid file for the duration of 'a. +unsafe fn get_ashmem_area<'a>(file: *mut bindings::file) -> Result<&'a Ashmem, Error> { + // SAFETY: Caller ensures that file is valid, so this should be safe. + if unsafe { is_ashmem_file(file) } { + return Err(EINVAL); + } + + // SAFETY: Given that this is an ashmem file, it should be safe to access the private_data + // field containing the Ashmem struct. + let private = unsafe { (*file).private_data }; + // SAFETY: Since this is an ashmem file, we know the type of the struct and can reference it + // safely. + let ashmem = unsafe { <::Ptr as ForeignOwnable>::borrow(private) }; + Ok(ashmem.get_ref()) +} + +/// # Safety +/// +/// The caller must ensure the following prior to invoking this function: +/// 1. `name` is valid for writing and at least of size ASHMEM_FULL_NAME_LEN. +/// 2. `file` is valid for the duration of this function. +#[no_mangle] +unsafe extern "C" fn ashmem_area_name( + file: *mut bindings::file, + name: *mut kernel::ffi::c_char, +) -> c_int { + if name.is_null() { + return EINVAL.to_errno() as c_int; + } + + // SAFETY: file is valid for the duration of this function. + match unsafe { get_ashmem_area(file) } { + Ok(ashmem) => { + let name_buffer = name.cast::<[u8; ASHMEM_FULL_NAME_LEN]>(); + // SAFETY: Caller guarantees that the pointer is valid for writing. + ashmem.inner.lock().full_name(unsafe { &mut *name_buffer }); + 0 + } + Err(err) => err.to_errno() as c_int, + } +} diff --git a/drivers/staging/android/ashmem_rust_exports.c b/drivers/staging/android/ashmem_rust_exports.c index 1de744975ca8..95546739bd6f 100644 --- a/drivers/staging/android/ashmem_rust_exports.c +++ b/drivers/staging/android/ashmem_rust_exports.c @@ -17,3 +17,4 @@ * other crates. */ EXPORT_SYMBOL_GPL(is_ashmem_file); +EXPORT_SYMBOL_GPL(ashmem_area_name);