mlock

Function mlock 

Source
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

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),
}
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
Hide additional 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, advise the kernel not to include the mapping in core dumps.
45    #[cfg(target_os = "linux")]
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(MADV_DONTDUMP) applied"),
50            Err(e) if e.kind() == io::ErrorKind::Unsupported => {
51                println!("madvise(MADV_DONTDUMP) 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}