Struct mmap_rs::MmapOptions
source · pub struct MmapOptions { /* private fields */ }
Expand description
Represents the options for the memory mapping.
Implementations§
source§impl MmapOptions
impl MmapOptions
sourcepub fn new(size: usize) -> Result<Self, Error>
pub fn new(size: usize) -> Result<Self, Error>
Constructs the MmapOptions
builder. The size specified is the size of the mapping to be
allocated in bytes.
Examples found in repository?
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
fn main() -> Result<(), Error> {
// Allocate a single page of anonymous memory that is private and mutable.
let mut mapping = MmapOptions::new(MmapOptions::page_size())?
.with_flags(MmapFlags::COPY_ON_WRITE)
.map_mut()?;
mapping[0..4].copy_from_slice(b"test");
let mapping = match mapping.make_read_only() {
Ok(mapping) => mapping,
Err((_, e)) => return Err(e),
};
println!("mapping: {:x?}", &mapping[0..4]);
Ok(())
}
sourcepub fn page_size() -> usize
pub fn page_size() -> usize
Returns the smallest possible page size for the current platform. The allocation size must be aligned to the page size for the allocation to succeed.
Examples found in repository?
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
fn main() -> Result<(), Error> {
// Allocate a single page of anonymous memory that is private and mutable.
let mut mapping = MmapOptions::new(MmapOptions::page_size())?
.with_flags(MmapFlags::COPY_ON_WRITE)
.map_mut()?;
mapping[0..4].copy_from_slice(b"test");
let mapping = match mapping.make_read_only() {
Ok(mapping) => mapping,
Err((_, e)) => return Err(e),
};
println!("mapping: {:x?}", &mapping[0..4]);
Ok(())
}
sourcepub fn page_sizes() -> Result<PageSizes, Error>
pub fn page_sizes() -> Result<PageSizes, Error>
Returns the set of supported page sizes for the current platform.
sourcepub fn allocation_granularity() -> usize
pub fn allocation_granularity() -> usize
Returns the allocation granularity for the current platform. On some platforms the
allocation granularity may be a multiple of the page size. The start address of the
allocation must be aligned to max(allocation_granularity, page_size)
.
sourcepub fn with_address(self, address: usize) -> Self
pub fn with_address(self, address: usize) -> Self
The desired address at which the memory should be mapped.
sourcepub unsafe fn with_file(self, file: File, offset: u64) -> Self
pub unsafe fn with_file(self, file: File, offset: u64) -> Self
Whether the memory mapping should be backed by a File
or not. If the memory mapping
should be mapped by a File
, then the user can also specify the offset within the file
at which the mapping should start.
On Microsoft Windows, it may not be possible to extend the protection beyond the access
mask that has been used to open the file. For instance, if a file has been opened with read
access, then Mmap::make_mut()
will not work. Furthermore, std::fs::OpenOptions
does
not in itself provide a standardized way to open the file with executable access. However,
if the file is not opened with executable access, then it may not be possible to use
Mmap::make_exec()
. Fortunately, Rust provides OpenOptionsExt
that allows you to
open the file with executable access rights. See access_mode
for more information.
This function is marked as unsafe as the user should be aware that even in the case that a file is mapped as immutable in the address space of the current process, it does not guarantee that there does not exist any other mutable mapping to the file.
On Microsoft Windows, it is possible to limit the access to shared reading or to be fully
exclusive using share_mode
.
On most Unix systems, it is possible to use nix::fcntl::flock
. However, keep in mind
that this provides an advisory locking scheme, and that implementations are therefore
required to be co-operative.
On Linux, it is also possible to mark the file as immutable. See man 2 ioctl_iflags
and
man 1 chattr
for more information.
sourcepub fn with_flags(self, flags: MmapFlags) -> Self
pub fn with_flags(self, flags: MmapFlags) -> Self
The desired configuration of the mapping. See MmapFlags
for available options.
Examples found in repository?
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
fn main() -> Result<(), Error> {
// Allocate a single page of anonymous memory that is private and mutable.
let mut mapping = MmapOptions::new(MmapOptions::page_size())?
.with_flags(MmapFlags::COPY_ON_WRITE)
.map_mut()?;
mapping[0..4].copy_from_slice(b"test");
let mapping = match mapping.make_read_only() {
Ok(mapping) => mapping,
Err((_, e)) => return Err(e),
};
println!("mapping: {:x?}", &mapping[0..4]);
Ok(())
}
sourcepub unsafe fn with_unsafe_flags(self, flags: UnsafeMmapFlags) -> Self
pub unsafe fn with_unsafe_flags(self, flags: UnsafeMmapFlags) -> Self
The desired configuration of the mapping. See UnsafeMmapFlags
for available options.
Note this function is unsafe as the flags that can be passed to this function have unsafe behavior associated with them.
sourcepub fn with_page_size(self, page_size: PageSize) -> Self
pub fn with_page_size(self, page_size: PageSize) -> Self
Whether this memory mapped should be backed by a specific page size or not.
sourcepub fn map_mut(self) -> Result<MmapMut, Error>
pub fn map_mut(self) -> Result<MmapMut, Error>
Maps the memory as mutable.
Examples found in repository?
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
fn main() -> Result<(), Error> {
// Allocate a single page of anonymous memory that is private and mutable.
let mut mapping = MmapOptions::new(MmapOptions::page_size())?
.with_flags(MmapFlags::COPY_ON_WRITE)
.map_mut()?;
mapping[0..4].copy_from_slice(b"test");
let mapping = match mapping.make_read_only() {
Ok(mapping) => mapping,
Err((_, e)) => return Err(e),
};
println!("mapping: {:x?}", &mapping[0..4]);
Ok(())
}
sourcepub unsafe fn map_exec_mut(self) -> Result<MmapMut, Error>
pub unsafe fn map_exec_mut(self) -> Result<MmapMut, Error>
Maps the memory as executable and mutable. While this may seem useful for self-modifying
code and JIT engines, it is instead recommended to convert between mutable and executable
mappings using Mmap::make_mut()
and MmapMut::make_exec()
instead.
As it may be tempting to use this function, this function has been marked as unsafe.
Make sure to read the text below to understand the complications of this function before
using it. The UnsafeMmapFlags::JIT
flag must be set for this function to succeed.
RWX pages are an interesting targets to attackers, e.g. for buffer overflow attacks, as RWX mappings can potentially simplify such attacks. Without RWX mappings, attackers instead have to resort to return-oriented programming (ROP) gadgets. To prevent buffer overflow attacks, contemporary CPUs allow pages to be marked as non-executable which is then used by the operating system to ensure that pages are either marked as writeable or as executable, but not both. This is also known as W^X.
While the x86 and x86-64 architectures guarantee cache coherency between the L1 instruction and the L1 data cache, other architectures such as Arm and AArch64 do not. If the user modified the pages, then executing the code may result in undefined behavior. To ensure correct behavior a user has to flush the instruction cache after modifying and before executing the page.