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 }