diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 19:33:14 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 19:33:14 +0000 |
commit | 36d22d82aa202bb199967e9512281e9a53db42c9 (patch) | |
tree | 105e8c98ddea1c1e4784a60a5a6410fa416be2de /third_party/rust/ashmem | |
parent | Initial commit. (diff) | |
download | firefox-esr-upstream.tar.xz firefox-esr-upstream.zip |
Adding upstream version 115.7.0esr.upstream/115.7.0esrupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'third_party/rust/ashmem')
-rw-r--r-- | third_party/rust/ashmem/.cargo-checksum.json | 1 | ||||
-rw-r--r-- | third_party/rust/ashmem/Cargo.toml | 24 | ||||
-rw-r--r-- | third_party/rust/ashmem/README.md | 14 | ||||
-rwxr-xr-x | third_party/rust/ashmem/src/lib.rs | 160 |
4 files changed, 199 insertions, 0 deletions
diff --git a/third_party/rust/ashmem/.cargo-checksum.json b/third_party/rust/ashmem/.cargo-checksum.json new file mode 100644 index 0000000000..4fac4e23d1 --- /dev/null +++ b/third_party/rust/ashmem/.cargo-checksum.json @@ -0,0 +1 @@ +{"files":{"Cargo.toml":"3b0ce20438cc2ce5485f734aaf93b50976757d39eab3d78b788932cf734d7830","README.md":"1513a18130cee5213ff581dd1703897ba9ad3f99fc601e502745833f93b78a25","src/lib.rs":"1306aacebf851c0ba32ef6c142dc35db678cf5463f267a226a4a10fd1c02041b"},"package":"b947f77692187a29daa2768b6644e589cef61e7434bb96300197acfb876105ac"}
\ No newline at end of file diff --git a/third_party/rust/ashmem/Cargo.toml b/third_party/rust/ashmem/Cargo.toml new file mode 100644 index 0000000000..81ccdbddbf --- /dev/null +++ b/third_party/rust/ashmem/Cargo.toml @@ -0,0 +1,24 @@ +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies. +# +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. + +[package] +edition = "2018" +name = "ashmem" +version = "0.1.2" +authors = ["Matthew Gregan <kinetik@flim.org>"] +description = "Rust wrapper around Android's ASharedMemory (ashmem) API" +license = "ISC" +repository = "https://github.com/kinetiknz/ashmem-rs" +[dependencies.ioctl-sys] +version = "0.7" + +[dependencies.libc] +version = "0.2" diff --git a/third_party/rust/ashmem/README.md b/third_party/rust/ashmem/README.md new file mode 100644 index 0000000000..ce19cf4e15 --- /dev/null +++ b/third_party/rust/ashmem/README.md @@ -0,0 +1,14 @@ +# ashmem-rs + +Provides a compatibility interface for Android 8.0's public ASharedMemory API. + +Some variant of ashmem has existed in Android as a private API for some time. Originally available only via [direct ioctl interface](https://elixir.bootlin.com/linux/v5.11.8/source/drivers/staging/android/uapi/ashmem.h), it later became callable (still private) via ashmem_create_region (et al.) in libcutils. + +[ASharedMemory](https://developer.android.com/ndk/reference/group/memory) is the public API to ashmem made available in Android 8.0 (API level 26). +Builds targeting Android 10 (API 29) are no longer permitted to access ashmem via the ioctl interface. This makes life for a portable program difficult - you can't reliably use the old or new interface during this transition period. + +ashmem-rs provides a simple wrapper around the ASharedMemory API, directly calling the public API implementation via dynamically loaded libandroid where available, and falling back to the direct ioctl interface elsewhere. + +References: + - [ASharedMemory documentation](https://developer.android.com/ndk/reference/group/memory) + - [Linux kernel ashmem.h definitions](https://elixir.bootlin.com/linux/v5.11.8/source/drivers/staging/android/uapi/ashmem.h) diff --git a/third_party/rust/ashmem/src/lib.rs b/third_party/rust/ashmem/src/lib.rs new file mode 100755 index 0000000000..93c91c8969 --- /dev/null +++ b/third_party/rust/ashmem/src/lib.rs @@ -0,0 +1,160 @@ +#![cfg(target_os = "android")] +//! Provides a wrapper around Android's ASharedMemory API. +//! +//! ashmem has existed in Android as a non-public API for some time. +//! Originally accessed via ioctl, it was later available via libcutils as ashmem_create_region etc. +//! ASharedMemory is the new public API, but it isn't available until API 26 (Android 8). +//! Builds targeting Android 10 (API 29) are no longer permitted to access ashmem via the ioctl interface. +//! This makes life for a portable program difficult - you can't reliably use the old or new interface during this transition period. +//! We try to dynamically load the new API first, then fall back to the ioctl interface. +//! +//! References: +//! - [ASharedMemory documentation](https://developer.android.com/ndk/reference/group/memory) +//! - [Linux ashmem.h definitions](https://elixir.bootlin.com/linux/v5.11.8/source/drivers/staging/android/uapi/ashmem.h) + +#[macro_use] +extern crate ioctl_sys; + +const __ASHMEMIOC: u32 = 0x77; + +static mut LIBANDROID_ASHAREDMEMORY_CREATE: Option< + extern "C" fn(*const libc::c_char, libc::size_t) -> libc::c_int, +> = None; +static mut LIBANDROID_ASHAREDMEMORY_GETSIZE: Option<extern "C" fn(libc::c_int) -> libc::size_t> = + None; +static mut LIBANDROID_ASHAREDMEMORY_SETPROT: Option< + extern "C" fn(libc::c_int, libc::c_int) -> libc::c_int, +> = None; + +unsafe fn maybe_init() { + const LIBANDROID_NAME: *const libc::c_char = "libandroid.so\0".as_ptr() as *const libc::c_char; + const LIBANDROID_ASHAREDMEMORY_CREATE_NAME: *const libc::c_char = + "ASharedMemory_create\0".as_ptr() as _; + const LIBANDROID_ASHAREDMEMORY_GETSIZE_NAME: *const libc::c_char = + "ASharedMemory_getSize\0".as_ptr() as _; + const LIBANDROID_ASHAREDMEMORY_SETPROT_NAME: *const libc::c_char = + "ASharedMemory_setProt\0".as_ptr() as _; + static ONCE: std::sync::Once = std::sync::Once::new(); + ONCE.call_once(|| { + // Leak the handle, there's no safe time to close it. + let handle = libc::dlopen(LIBANDROID_NAME, libc::RTLD_LAZY | libc::RTLD_LOCAL); + if handle.is_null() { + return; + } + // Transmute guarantee for `fn -> Option<fn>`: https://doc.rust-lang.org/std/option/#representation + LIBANDROID_ASHAREDMEMORY_CREATE = + std::mem::transmute(libc::dlsym(handle, LIBANDROID_ASHAREDMEMORY_CREATE_NAME)); + LIBANDROID_ASHAREDMEMORY_GETSIZE = + std::mem::transmute(libc::dlsym(handle, LIBANDROID_ASHAREDMEMORY_GETSIZE_NAME)); + LIBANDROID_ASHAREDMEMORY_SETPROT = + std::mem::transmute(libc::dlsym(handle, LIBANDROID_ASHAREDMEMORY_SETPROT_NAME)); + }); +} + +/// See [ASharedMemory_create NDK documentation](https://developer.android.com/ndk/reference/group/memory#asharedmemory_create) +/// +/// # Safety +/// +/// Directly calls C or kernel APIs. +#[allow(non_snake_case)] +pub unsafe fn ASharedMemory_create(name: *const libc::c_char, size: libc::size_t) -> libc::c_int { + const ASHMEM_NAME_DEF: *const libc::c_char = "/dev/ashmem\0".as_ptr() as _; + const ASHMEM_NAME_LEN: usize = 256; + const ASHMEM_SET_NAME: libc::c_int = iow!( + __ASHMEMIOC, + 1, + std::mem::size_of::<[libc::c_char; ASHMEM_NAME_LEN]>() + ) as _; + const ASHMEM_SET_SIZE: libc::c_int = + iow!(__ASHMEMIOC, 3, std::mem::size_of::<libc::size_t>()) as _; + + maybe_init(); + if let Some(fun) = LIBANDROID_ASHAREDMEMORY_CREATE { + return fun(name, size); + } + + let fd = libc::open(ASHMEM_NAME_DEF, libc::O_RDWR, 0o600); + if fd < 0 { + return fd; + } + + if !name.is_null() { + // NOTE: libcutils uses a local stack copy of `name`. + let r = libc::ioctl(fd, ASHMEM_SET_NAME, name); + if r != 0 { + libc::close(fd); + return -1; + } + } + + let r = libc::ioctl(fd, ASHMEM_SET_SIZE, size); + if r != 0 { + libc::close(fd); + return -1; + } + + fd +} + +/// See [ASharedMemory_getSize NDK documentation](https://developer.android.com/ndk/reference/group/memory#asharedmemory_getsize) +/// +/// # Safety +/// +/// Directly calls C or kernel APIs. +#[allow(non_snake_case)] +pub unsafe fn ASharedMemory_getSize(fd: libc::c_int) -> libc::size_t { + const ASHMEM_GET_SIZE: libc::c_int = io!(__ASHMEMIOC, 4) as _; + + maybe_init(); + if let Some(fun) = LIBANDROID_ASHAREDMEMORY_GETSIZE { + return fun(fd); + } + + libc::ioctl(fd, ASHMEM_GET_SIZE) as libc::size_t +} + +/// See [ASharedMemory_setProt NDK documentation](https://developer.android.com/ndk/reference/group/memory#asharedmemory_setprot) +/// +/// # Safety +/// +/// Directly calls C or kernel APIs. +#[allow(non_snake_case)] +pub unsafe fn ASharedMemory_setProt(fd: libc::c_int, prot: libc::c_int) -> libc::c_int { + const ASHMEM_SET_PROT_MASK: libc::c_int = + iow!(__ASHMEMIOC, 5, std::mem::size_of::<libc::c_ulong>()) as _; + + maybe_init(); + if let Some(fun) = LIBANDROID_ASHAREDMEMORY_SETPROT { + return fun(fd, prot); + } + + let r = libc::ioctl(fd, ASHMEM_SET_PROT_MASK, prot); + if r != 0 { + return -1; + } + r +} + +#[cfg(test)] +mod tests { + #[test] + fn basic() { + unsafe { + let name = std::ffi::CString::new("/test-ashmem").unwrap(); + let fd = super::ASharedMemory_create(name.as_ptr(), 128); + assert!(fd >= 0); + assert_eq!(super::ASharedMemory_getSize(fd), 128); + assert_eq!(super::ASharedMemory_setProt(fd, 0), 0); + libc::close(fd); + } + } + + #[test] + fn anonymous() { + unsafe { + let fd = super::ASharedMemory_create(std::ptr::null(), 128); + assert!(fd >= 0); + libc::close(fd); + } + } +} |