Skip to content

Commit

Permalink
Merge branch 'Evian-Zhang:master' into master
Browse files Browse the repository at this point in the history
  • Loading branch information
Godones authored Aug 9, 2024
2 parents 9755973 + f2563d4 commit 192f5e8
Show file tree
Hide file tree
Showing 5 changed files with 53 additions and 16 deletions.
3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,13 @@ 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"

[target.'cfg(target_os = "windows")'.dependencies]
windows = { version = "0.58", features = ["Win32_System_SystemInformation", "Win32_System_Memory"] }
windows = { version = "0.58", features = ["Win32_System_SystemInformation", "Win32_System_Memory", "Win32_System_Threading", "Win32_System_Diagnostics_Debug"] }

[dev-dependencies]
trybuild = "1"
7 changes: 4 additions & 3 deletions src/arch/x86.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,16 +43,17 @@ macro_rules! arch_static_key_init_nop_asm_template {
};
}

// The `0x90,0x90,0x90` are three NOPs, which is to make sure the `jmp {0}` is at least 5 bytes long.
// Here we do not use `jmp {0}` because it may be compiled into a 3-byte jmp instead of 5 byte.
// See https://stackoverflow.com/q/74771372/10005095
#[doc(hidden)]
#[macro_export]
macro_rules! arch_static_key_init_jmp_asm_template {
() => {
::core::concat!(
r#"
2:
jmp {0}
.byte 0x90,0x90,0x90
.byte 0xe9
.long ({0} - 4) - .
.pushsection "#,
$crate::os_static_key_sec_name_attr!(),
r#"
Expand Down
7 changes: 4 additions & 3 deletions src/arch/x86_64.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,16 +43,17 @@ macro_rules! arch_static_key_init_nop_asm_template {
};
}

// The `0x90,0x90,0x90` are three NOPs, which is to make sure the `jmp {0}` is at least 5 bytes long.
// Here we do not use `jmp {0}` because it may be compiled into a 3-byte jmp instead of 5 byte.
// See https://stackoverflow.com/q/74771372/10005095
#[doc(hidden)]
#[macro_export]
macro_rules! arch_static_key_init_jmp_asm_template {
() => {
::core::concat!(
r#"
2:
jmp {0}
.byte 0x90,0x90,0x90
.byte 0xe9
.long ({0} - 4) - .
.pushsection "#,
$crate::os_static_key_sec_name_attr!(),
r#"
Expand Down
46 changes: 37 additions & 9 deletions src/os/linux.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,26 +40,54 @@ 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.");
}
}
}
6 changes: 6 additions & 0 deletions src/os/windows.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
//! Windows-specific implementations
use windows::Win32::System::{
Diagnostics::Debug::FlushInstructionCache,
Memory::{VirtualProtect, PAGE_EXECUTE_READWRITE, PAGE_PROTECTION_FLAGS},
SystemInformation::{GetSystemInfo, SYSTEM_INFO},
Threading::GetCurrentProcess,
};

use crate::{code_manipulate::CodeManipulator, JumpEntry};
Expand Down Expand Up @@ -69,5 +71,9 @@ impl CodeManipulator for ArchCodeManipulator {
if res.is_err() {
panic!("Unable to restore code region to non-writable");
}
let res = unsafe { FlushInstructionCache(GetCurrentProcess(), Some(addr), L) };
if res.is_err() {
panic!("Failed to flush instruction cache");
}
}
}

0 comments on commit 192f5e8

Please sign in to comment.