pub unsafe fn mlock(addr: *const c_void, len: usize) -> Result<()>Available on Unix only.
Expand description
Lock the pages containing the specified memory region to prevent swapping.
Returns:
- Ok(()) on success
- Err(…) with last_os_error() on failure
- Err(Unsupported) on platforms where this call is not available
§Safety
The caller must ensure that (addr, len) refers to a valid, non-null memory region owned by this process for the duration of the call, and that the region is not deallocated, unmapped, or remapped concurrently.
§Examples
no_run
§use std::io;
§fn demo() -> io::Result<()> {
let mut buf = vec![0u8; 4096]; let ptr = buf.as_ptr() as *const std::os::raw::c_void; let len = buf.len(); match unsafe { os_memlock::mlock(ptr, len) } { Ok(()) => { // do work… unsafe { os_memlock::munlock(ptr, len)?; } } Err(e) if e.kind() == std::io::ErrorKind::Unsupported => { // platform/build doesn’t support mlock; proceed without locking } Err(e) => return Err(e), }
§Ok(()) }
Examples found in repository?
examples/locked_vec.rs (line 32)
26 pub fn new(len: usize) -> io::Result<Self> {
27 // Allocate a zeroed buffer. We won't change capacity after locking.
28 let buf = vec![0u8; len];
29
30 // Attempt to lock pages. Treat Unsupported as a non-fatal condition.
31 let ptr = buf.as_ptr() as *const std::os::raw::c_void;
32 let locked = match unsafe { os_memlock::mlock(ptr, buf.len()) } {
33 Ok(()) => true,
34 Err(e) if e.kind() == io::ErrorKind::Unsupported => {
35 eprintln!(
36 "os-memlock: mlock unsupported on this platform/build; continuing unlocked"
37 );
38 false
39 }
40 Err(e) => return Err(e),
41 };
42
43 // Best-effort: on Linux, advise dump exclusion.
44 #[cfg(target_os = "linux")]
45 {
46 let mut_ptr = buf.as_mut_ptr() as *mut std::os::raw::c_void;
47 match unsafe { os_memlock::madvise_dontdump(mut_ptr, buf.len()) } {
48 Ok(()) => (),
49 Err(e) if e.kind() == io::ErrorKind::Unsupported => {
50 // Not supported on this target; ignore gracefully.
51 }
52 Err(e) => {
53 // Non-fatal: just log the error.
54 eprintln!("os-memlock: madvise(MADV_DONTDUMP) failed: {e}");
55 }
56 }
57 }
58
59 Ok(Self { buf, locked })
60 }More examples
examples/simple.rs (line 36)
20fn main() -> io::Result<()> {
21 // Simple buffer representing secret data. Use a page-sized allocation for clarity.
22 // On many systems a page is 4096 bytes; this example uses that common size.
23 const PAGE_LEN: usize = 4096;
24 let mut secret = vec![0u8; PAGE_LEN];
25
26 // Put some dummy secret bytes (for demo only).
27 secret[..16].copy_from_slice(b"super-secret-data");
28
29 let ptr = secret.as_ptr() as *const std::os::raw::c_void;
30
31 let len = secret.len();
32
33 println!("Attempting to lock {} bytes at {:p}", len, ptr);
34
35 // Try to mlock the buffer. This is unsafe and may return Unsupported on some builds/platforms.
36 match unsafe { os_memlock::mlock(ptr, len) } {
37 Ok(()) => println!("mlock succeeded"),
38 Err(e) if e.kind() == io::ErrorKind::Unsupported => {
39 println!("mlock is unsupported on this platform/build; continuing without page-lock")
40 }
41 Err(e) => return Err(e),
42 }
43
44 // Best-effort: on Linux and FreeBSD, advise the kernel not to include the mapping in core dumps.
45 #[cfg(any(target_os = "linux", target_os = "freebsd"))]
46 {
47 let mut_ptr = secret.as_mut_ptr() as *mut std::os::raw::c_void;
48 match unsafe { os_memlock::madvise_dontdump(mut_ptr, len) } {
49 Ok(()) => println!("madvise dump-exclusion hint applied"),
50 Err(e) if e.kind() == io::ErrorKind::Unsupported => {
51 println!("madvise dump-exclusion hint unsupported on this platform/build")
52 }
53 Err(e) => eprintln!("madvise failed: {:#}", e),
54 }
55 }
56
57 // Do some work while memory is (hopefully) locked.
58 println!("Working with secret data (simulated)...");
59 // Sleep briefly to simulate lifetime of locked secret. (In real code avoid sleeping.)
60 thread::sleep(Duration::from_millis(250));
61
62 // Before dropping or unmapping the buffer, munlock.
63 match unsafe { os_memlock::munlock(ptr, len) } {
64 Ok(()) => println!("munlock succeeded"),
65 Err(e) if e.kind() == io::ErrorKind::Unsupported => {
66 println!("munlock unsupported (no-op for this platform/build)")
67 }
68 Err(e) => return Err(e),
69 }
70
71 // Zeroize secret before drop as a good hygiene (example only; use a proper zeroize crate in production).
72 for b in &mut secret {
73 *b = 0;
74 }
75
76 println!("Secret zeroized and example complete.");
77 Ok(())
78}