Skip to content

Commit b003c2f

Browse files
devnexenSteveLauC
andauthored
sys::mman: adding few madvise flags. (#2559)
* 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>
1 parent c017285 commit b003c2f

File tree

3 files changed

+55
-0
lines changed

3 files changed

+55
-0
lines changed

changelog/2559.added.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Add `sys::mman::MmapAdvise` `MADV_PAGEOUT`, `MADV_COLD`, `MADV_WIPEONFORK`, `MADV_KEEPONFORK` for Linux and Android targets

src/sys/mman.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -316,6 +316,18 @@ libc_enum! {
316316
#[cfg(apple_targets)]
317317
#[allow(missing_docs)]
318318
MADV_CAN_REUSE,
319+
/// Reclaim the address range when applicable.
320+
#[cfg(linux_android)]
321+
MADV_PAGEOUT,
322+
/// Deactivate the address range when applicable.
323+
#[cfg(linux_android)]
324+
MADV_COLD,
325+
/// After fork, the adress range is zero filled.
326+
#[cfg(linux_android)]
327+
MADV_WIPEONFORK,
328+
/// Undo `MADV_WIPEONFORK` when it applied.
329+
#[cfg(linux_android)]
330+
MADV_KEEPONFORK,
319331
}
320332
}
321333

test/sys/test_mman.rs

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,3 +156,45 @@ fn test_mremap_dontunmap() {
156156
std::slice::from_raw_parts_mut(mem.cast().as_ptr(), 10 * ONE_K)
157157
};
158158
}
159+
160+
#[test]
161+
#[cfg(target_os = "linux")]
162+
fn test_madv_wipeonfork() {
163+
use nix::libc::size_t;
164+
use nix::sys::mman::{madvise, MmapAdvise};
165+
use nix::unistd::{fork, ForkResult};
166+
use std::num::NonZeroUsize;
167+
168+
const ONE_K: size_t = 1024;
169+
let ten_one_k = NonZeroUsize::new(10 * ONE_K).unwrap();
170+
let slice: &mut [u8] = unsafe {
171+
let mem = mmap_anonymous(
172+
None,
173+
ten_one_k,
174+
ProtFlags::PROT_READ | ProtFlags::PROT_WRITE,
175+
MapFlags::MAP_PRIVATE,
176+
)
177+
.unwrap();
178+
madvise(mem, ONE_K, MmapAdvise::MADV_WIPEONFORK)
179+
.expect("madvise failed");
180+
std::slice::from_raw_parts_mut(mem.as_ptr().cast(), ONE_K)
181+
};
182+
slice[ONE_K - 1] = 0xFF;
183+
let _m = crate::FORK_MTX.lock();
184+
185+
unsafe {
186+
let res = fork().expect("fork failed");
187+
match res {
188+
ForkResult::Child => {
189+
// that s the whole point of MADV_WIPEONFORK
190+
assert_eq!(slice[ONE_K - 1], 0x00);
191+
libc::_exit(0);
192+
}
193+
ForkResult::Parent { child } => {
194+
nix::sys::signal::kill(child, nix::sys::signal::SIGTERM)
195+
.unwrap();
196+
let _ = nix::sys::wait::wait().unwrap();
197+
}
198+
}
199+
}
200+
}

0 commit comments

Comments
 (0)