linker_hook.rs (2110B) - raw
1 use std::{collections::HashMap, ffi::{c_void, CStr}, sync::Mutex}; 2 3 use jni::{objects::{JByteArray, JString}, JNIEnv}; 4 use nix::libc; 5 use once_cell::sync::Lazy; 6 7 use crate::{def_hook, dobby_hook_sym}; 8 9 static SHARED_LIBRARIES: Lazy<Mutex<HashMap<String, Box<Vec<i8>>>>> = Lazy::new(|| Mutex::new(HashMap::new())); 10 11 def_hook!( 12 linker_openat, 13 i32, 14 |dir_fd: i32, pathname: *mut u8, flags: i32, mode: i32| { 15 let pathname_str = CStr::from_ptr(pathname).to_str().unwrap().to_string(); 16 17 if let Some(content) = SHARED_LIBRARIES.lock().unwrap().remove(&pathname_str) { 18 let memfd = libc::syscall(libc::SYS_memfd_create, "jit-cache\0".as_ptr(), 0) as i32; 19 let content = content.into_boxed_slice(); 20 21 if libc::write(memfd, content.as_ptr() as *const c_void, content.len() as libc::size_t) == -1 { 22 panic!("failed to write to memfd"); 23 } 24 25 if libc::lseek(memfd, 0, libc::SEEK_SET) == -1 { 26 panic!("failed to seek memfd"); 27 } 28 29 std::mem::forget(content); 30 31 info!("opened shared library: {}", pathname_str); 32 return memfd; 33 } 34 35 linker_openat_original.unwrap()(dir_fd, pathname, flags, mode) 36 } 37 ); 38 39 pub fn add_linker_shared_library(mut env: JNIEnv, _: *mut c_void, path: JString, content: JByteArray) { 40 let path = env.get_string(&path).unwrap().to_str().unwrap().to_string(); 41 let content_length = env.get_array_length(&content).expect("Failed to get array length"); 42 let mut content_buffer = Box::new(vec![0i8; content_length as usize]); 43 44 env.get_byte_array_region(content, 0, content_buffer.as_mut_slice()).expect("Failed to get byte array region"); 45 46 debug!("added shared library: {}", path); 47 48 SHARED_LIBRARIES.lock().unwrap().insert(path, content_buffer); 49 } 50 51 pub fn init() { 52 #[cfg(target_arch = "aarch64")] 53 { 54 dobby_hook_sym!("linker64", "__dl___openat", linker_openat); 55 } 56 #[cfg(target_arch = "arm")] 57 { 58 dobby_hook_sym!("linker", "__dl___openat", linker_openat); 59 } 60 }