ANDROID: ashmem_rust: add toggle for PROT_READ

The memfd type simulates SET_PROT_MASK using file seals, but there's no
file seal to prevent mapping readable memory. Thus, add a toggle that
removes the ability to unset the PROT_READ bit on an ashmem file.

Bug: 370906207
Change-Id: I2d0347ce124d7d6d543cff765f77b28202cf327f
Signed-off-by: Alice Ryhl <aliceryhl@google.com>
This commit is contained in:
Alice Ryhl
2024-12-10 14:37:57 +00:00
committed by Suren Baghdasaryan
parent 5e60c48050
commit e8bed58ffd
2 changed files with 25 additions and 4 deletions
+10 -2
View File
@@ -13,7 +13,7 @@
use core::{
ffi::c_int,
pin::Pin,
sync::atomic::{AtomicUsize, Ordering},
sync::atomic::{AtomicBool, AtomicUsize, Ordering},
};
use kernel::{
bindings::{self, ASHMEM_GET_PIN_STATUS, ASHMEM_PIN, ASHMEM_UNPIN},
@@ -50,7 +50,7 @@ mod shmem;
use shmem::ShmemFile;
mod ashmem_toggle;
use ashmem_toggle::{AshmemToggleMisc, AshmemToggleShrinker};
use ashmem_toggle::{AshmemToggleMisc, AshmemToggleRead, AshmemToggleShrinker};
/// Does PROT_READ imply PROT_EXEC for this task?
fn read_implies_exec(task: &Task) -> bool {
@@ -66,6 +66,7 @@ fn has_cap_sys_admin() -> bool {
}
static NUM_PIN_IOCTLS_WAITING: AtomicUsize = AtomicUsize::new(0);
static IGNORE_UNSET_PROT_READ: AtomicBool = AtomicBool::new(false);
fn shrinker_should_stop() -> bool {
NUM_PIN_IOCTLS_WAITING.load(Ordering::Relaxed) > 0
@@ -82,6 +83,7 @@ module! {
struct AshmemModule {
_misc: Pin<Box<MiscDeviceRegistration<Ashmem>>>,
_toggle_unpin: Pin<Box<MiscDeviceRegistration<AshmemToggleMisc<AshmemToggleShrinker>>>>,
_toggle_read: Pin<Box<MiscDeviceRegistration<AshmemToggleMisc<AshmemToggleRead>>>>,
}
impl kernel::Module for AshmemModule {
@@ -105,6 +107,7 @@ impl kernel::Module for AshmemModule {
GFP_KERNEL,
)?,
_toggle_unpin: AshmemToggleMisc::<AshmemToggleShrinker>::new()?,
_toggle_read: AshmemToggleMisc::<AshmemToggleRead>::new()?,
})
}
}
@@ -340,6 +343,11 @@ impl Ashmem {
prot |= PROT_EXEC;
}
if IGNORE_UNSET_PROT_READ.load(Ordering::Relaxed) {
// Add back PROT_READ if asma.prot_mask has it.
prot |= asma.prot_mask & PROT_READ;
}
// The user can only remove, not add, protection bits.
if (asma.prot_mask & prot) != prot {
return Err(EINVAL);
+15 -2
View File
@@ -4,8 +4,8 @@
//! Provides knobs for Rust ashmem.
use crate::ashmem_range;
use core::marker::PhantomData;
use crate::{ashmem_range, IGNORE_UNSET_PROT_READ};
use core::{marker::PhantomData, sync::atomic::Ordering};
use kernel::{
c_str,
error::to_result,
@@ -79,3 +79,16 @@ impl AshmemToggle for AshmemToggleShrinker {
ashmem_range::get_shrinker_enabled()
}
}
pub(crate) struct AshmemToggleRead;
impl AshmemToggle for AshmemToggleRead {
const NAME: &'static CStr = c_str!("ashmem_ignore_unset_prot_read");
fn set(enabled: bool) -> Result<()> {
IGNORE_UNSET_PROT_READ.store(enabled, Ordering::Relaxed);
Ok(())
}
fn get() -> bool {
IGNORE_UNSET_PROT_READ.load(Ordering::Relaxed)
}
}