ANDROID: ashmem_rust: add toggle for PROT_EXEC
The memfd type simulates SET_PROT_MASK using file seals, but there's no file seal to prevent mapping executable memory. Thus, add a toggle that removes the ability to unset the PROT_EXEC bit on an ashmem file. Bug: 370906207 Change-Id: Ia90c2cfca689d152fb1765f2abcf6bb3f60cd05d Signed-off-by: Alice Ryhl <aliceryhl@google.com>
This commit is contained in:
committed by
Suren Baghdasaryan
parent
e8bed58ffd
commit
1c7e6e5ef3
@@ -50,7 +50,7 @@ mod shmem;
|
||||
use shmem::ShmemFile;
|
||||
|
||||
mod ashmem_toggle;
|
||||
use ashmem_toggle::{AshmemToggleMisc, AshmemToggleRead, AshmemToggleShrinker};
|
||||
use ashmem_toggle::{AshmemToggleExec, AshmemToggleMisc, AshmemToggleRead, AshmemToggleShrinker};
|
||||
|
||||
/// Does PROT_READ imply PROT_EXEC for this task?
|
||||
fn read_implies_exec(task: &Task) -> bool {
|
||||
@@ -67,6 +67,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);
|
||||
static IGNORE_UNSET_PROT_EXEC: AtomicBool = AtomicBool::new(false);
|
||||
|
||||
fn shrinker_should_stop() -> bool {
|
||||
NUM_PIN_IOCTLS_WAITING.load(Ordering::Relaxed) > 0
|
||||
@@ -84,6 +85,7 @@ struct AshmemModule {
|
||||
_misc: Pin<Box<MiscDeviceRegistration<Ashmem>>>,
|
||||
_toggle_unpin: Pin<Box<MiscDeviceRegistration<AshmemToggleMisc<AshmemToggleShrinker>>>>,
|
||||
_toggle_read: Pin<Box<MiscDeviceRegistration<AshmemToggleMisc<AshmemToggleRead>>>>,
|
||||
_toggle_exec: Pin<Box<MiscDeviceRegistration<AshmemToggleMisc<AshmemToggleExec>>>>,
|
||||
}
|
||||
|
||||
impl kernel::Module for AshmemModule {
|
||||
@@ -108,6 +110,7 @@ impl kernel::Module for AshmemModule {
|
||||
)?,
|
||||
_toggle_unpin: AshmemToggleMisc::<AshmemToggleShrinker>::new()?,
|
||||
_toggle_read: AshmemToggleMisc::<AshmemToggleRead>::new()?,
|
||||
_toggle_exec: AshmemToggleMisc::<AshmemToggleExec>::new()?,
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -348,6 +351,11 @@ impl Ashmem {
|
||||
prot |= asma.prot_mask & PROT_READ;
|
||||
}
|
||||
|
||||
if IGNORE_UNSET_PROT_EXEC.load(Ordering::Relaxed) {
|
||||
// Add back PROT_EXEC if asma.prot_mask has it.
|
||||
prot |= asma.prot_mask & PROT_EXEC;
|
||||
}
|
||||
|
||||
// The user can only remove, not add, protection bits.
|
||||
if (asma.prot_mask & prot) != prot {
|
||||
return Err(EINVAL);
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
//! Provides knobs for Rust ashmem.
|
||||
|
||||
use crate::{ashmem_range, IGNORE_UNSET_PROT_READ};
|
||||
use crate::{ashmem_range, IGNORE_UNSET_PROT_EXEC, IGNORE_UNSET_PROT_READ};
|
||||
use core::{marker::PhantomData, sync::atomic::Ordering};
|
||||
use kernel::{
|
||||
c_str,
|
||||
@@ -92,3 +92,16 @@ impl AshmemToggle for AshmemToggleRead {
|
||||
IGNORE_UNSET_PROT_READ.load(Ordering::Relaxed)
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) struct AshmemToggleExec;
|
||||
|
||||
impl AshmemToggle for AshmemToggleExec {
|
||||
const NAME: &'static CStr = c_str!("ashmem_ignore_unset_prot_exec");
|
||||
fn set(enabled: bool) -> Result<()> {
|
||||
IGNORE_UNSET_PROT_EXEC.store(enabled, Ordering::Relaxed);
|
||||
Ok(())
|
||||
}
|
||||
fn get() -> bool {
|
||||
IGNORE_UNSET_PROT_EXEC.load(Ordering::Relaxed)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user