Skip to content

Commit

Permalink
Use mmap and mremap to allow multi-thread static key modifying. Add c…
Browse files Browse the repository at this point in the history
…lear cache for linux OS
  • Loading branch information
Evian-Zhang committed Aug 9, 2024
1 parent 5b06d7f commit 022a7f9
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 9 deletions.
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ maintenance = { status = "actively-developed" }

[target.'cfg(target_os = "linux")'.dependencies]
libc = { version = "0.2", default-features = false }
clear-cache = "0.1"

[target.'cfg(target_os = "macos")'.dependencies]
mach2 = "0.4"
Expand Down
48 changes: 39 additions & 9 deletions src/os/linux.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,26 +40,56 @@ impl CodeManipulator for ArchCodeManipulator {
} else {
page_size
};
let res = unsafe {
libc::mprotect(
aligned_addr,

// Create a temp mmap, which will store updated content of corresponding pages
let mmaped_addr = unsafe {
libc::mmap(
core::ptr::null_mut(),
aligned_length,
libc::PROT_READ | libc::PROT_WRITE | libc::PROT_EXEC,
libc::PROT_READ | libc::PROT_WRITE,
libc::MAP_PRIVATE | libc::MAP_ANONYMOUS,
-1,
0,
)
};
if res != 0 {
panic!("Unable to make code region writable");
if mmaped_addr == libc::MAP_FAILED {
panic!("Failed to create temp mappings");
}
unsafe {
let addr_in_mmap = mmaped_addr.offset(addr.offset_from(aligned_addr));
core::ptr::copy_nonoverlapping(aligned_addr, mmaped_addr, aligned_length);
core::ptr::copy_nonoverlapping(data.as_ptr(), addr_in_mmap.cast(), L);
}
core::ptr::copy_nonoverlapping(data.as_ptr(), addr.cast(), L);
let res = unsafe {
libc::mprotect(
aligned_addr,
mmaped_addr,
aligned_length,
libc::PROT_READ | libc::PROT_EXEC,
)
};
if res != 0 {
panic!("Unable to restore code region to non-writable");
panic!("Unable to make mmaped mapping executable.");
}
// Remap the created temp mmaping to replace old mapping
let res = unsafe {
libc::mremap(
mmaped_addr,
aligned_length,
aligned_length,
libc::MREMAP_MAYMOVE | libc::MREMAP_FIXED,
// Any previous mapping at the address range specified by new_address and new_size is unmapped.
// So, no memory leak
aligned_addr,
)
};
if res == libc::MAP_FAILED {
panic!("Failed to mremap.");
}
let res = unsafe {
clear_cache::clear_cache(addr, addr.add(L));
};
if !res {
panic!("Failed to clear cache.");
}
}
}

0 comments on commit 022a7f9

Please sign in to comment.