Skip to content

Commit

Permalink
sys::mman: adding few madvise flags. (#2559)
Browse files Browse the repository at this point in the history
* sys::mman: adding few madvise flags.

- `MADV_PAGEOUT` which reclaim the address range, swapping it out
if the page is anonymous or written back to disk if it's backed up
by a file.
- `MADV_COLD` which deactivate the address range but as a hint.
- `MADV_WIPEONFORK` after `fork()`, the address range is wiped out
to avoid sharing sensible data between processes.
- `MADV_KEEPONFORK` disables `MADV_WIPEONFORK` workflow.

* Update changelog/2559.added.md

---------

Co-authored-by: SteveLauC <stevelauc@outlook.com>
  • Loading branch information
devnexen and SteveLauC authored Dec 13, 2024
1 parent c017285 commit b003c2f
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 0 deletions.
1 change: 1 addition & 0 deletions changelog/2559.added.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Add `sys::mman::MmapAdvise` `MADV_PAGEOUT`, `MADV_COLD`, `MADV_WIPEONFORK`, `MADV_KEEPONFORK` for Linux and Android targets
12 changes: 12 additions & 0 deletions src/sys/mman.rs
Original file line number Diff line number Diff line change
Expand Up @@ -316,6 +316,18 @@ libc_enum! {
#[cfg(apple_targets)]
#[allow(missing_docs)]
MADV_CAN_REUSE,
/// Reclaim the address range when applicable.
#[cfg(linux_android)]
MADV_PAGEOUT,
/// Deactivate the address range when applicable.
#[cfg(linux_android)]
MADV_COLD,
/// After fork, the adress range is zero filled.
#[cfg(linux_android)]
MADV_WIPEONFORK,
/// Undo `MADV_WIPEONFORK` when it applied.
#[cfg(linux_android)]
MADV_KEEPONFORK,
}
}

Expand Down
42 changes: 42 additions & 0 deletions test/sys/test_mman.rs
Original file line number Diff line number Diff line change
Expand Up @@ -156,3 +156,45 @@ fn test_mremap_dontunmap() {
std::slice::from_raw_parts_mut(mem.cast().as_ptr(), 10 * ONE_K)
};
}

#[test]
#[cfg(target_os = "linux")]
fn test_madv_wipeonfork() {
use nix::libc::size_t;
use nix::sys::mman::{madvise, MmapAdvise};
use nix::unistd::{fork, ForkResult};
use std::num::NonZeroUsize;

const ONE_K: size_t = 1024;
let ten_one_k = NonZeroUsize::new(10 * ONE_K).unwrap();
let slice: &mut [u8] = unsafe {
let mem = mmap_anonymous(
None,
ten_one_k,
ProtFlags::PROT_READ | ProtFlags::PROT_WRITE,
MapFlags::MAP_PRIVATE,
)
.unwrap();
madvise(mem, ONE_K, MmapAdvise::MADV_WIPEONFORK)
.expect("madvise failed");
std::slice::from_raw_parts_mut(mem.as_ptr().cast(), ONE_K)
};
slice[ONE_K - 1] = 0xFF;
let _m = crate::FORK_MTX.lock();

unsafe {
let res = fork().expect("fork failed");
match res {
ForkResult::Child => {
// that s the whole point of MADV_WIPEONFORK
assert_eq!(slice[ONE_K - 1], 0x00);
libc::_exit(0);
}
ForkResult::Parent { child } => {
nix::sys::signal::kill(child, nix::sys::signal::SIGTERM)
.unwrap();
let _ = nix::sys::wait::wait().unwrap();
}
}
}
}

0 comments on commit b003c2f

Please sign in to comment.