#[cfg(unix)]
pub fn mlock_buffer(ptr: *const u8, len: usize) -> Result<(), std::io::Error> {
if len == 0 || ptr.is_null() {
return Ok(());
}
if cfg!(miri) {
return Ok(());
}
let ret = unsafe { libc::mlock(ptr as *const libc::c_void, len) };
if ret == 0 {
Ok(())
} else {
Err(std::io::Error::last_os_error())
}
}
#[cfg(unix)]
pub fn munlock_buffer(ptr: *const u8, len: usize) -> Result<(), std::io::Error> {
if len == 0 || ptr.is_null() {
return Ok(());
}
if cfg!(miri) {
return Ok(());
}
let ret = unsafe { libc::munlock(ptr as *const libc::c_void, len) };
if ret == 0 {
Ok(())
} else {
Err(std::io::Error::last_os_error())
}
}
#[cfg(windows)]
pub fn mlock_buffer(ptr: *const u8, len: usize) -> Result<(), std::io::Error> {
if len == 0 || ptr.is_null() {
return Ok(());
}
let ret = unsafe {
windows_sys::Win32::System::Memory::VirtualLock(ptr as *mut core::ffi::c_void, len)
};
if ret != 0 {
Ok(()) } else {
Err(std::io::Error::last_os_error())
}
}
#[cfg(windows)]
pub fn munlock_buffer(ptr: *const u8, len: usize) -> Result<(), std::io::Error> {
if len == 0 || ptr.is_null() {
return Ok(());
}
let ret = unsafe {
windows_sys::Win32::System::Memory::VirtualUnlock(ptr as *mut core::ffi::c_void, len)
};
if ret != 0 {
Ok(()) } else {
Err(std::io::Error::last_os_error())
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_mlock_empty_buffer() {
assert!(mlock_buffer(std::ptr::null(), 0).is_ok());
}
#[test]
#[cfg_attr(miri, ignore)]
fn test_mlock_munlock_roundtrip() {
let data = vec![0xABu8; 4096];
let ptr = data.as_ptr();
let len = data.len();
let lock_result = mlock_buffer(ptr, len);
if lock_result.is_ok() {
assert!(munlock_buffer(ptr, len).is_ok());
}
}
#[test]
#[cfg_attr(miri, ignore)]
fn test_mlock_small_key_material() {
let key = [0u8; 32];
let result = mlock_buffer(key.as_ptr(), key.len());
if result.is_ok() {
assert!(munlock_buffer(key.as_ptr(), key.len()).is_ok());
}
}
}