问题描述
我正在RUST中编写一个开源LD_PRELOAD库,该库可跟踪文件系统的活动。 我还使用RUST tokio跟踪箱来对库启用跟踪。 我能够成功拦截和跟踪许多libc API,例如open(),execvp等。 当我启用posix_spawnp的拦截时,启用了跟踪,它将失败。 如果启用posix_spawnp的拦截功能,并且禁用/注释了交易代码,则测试有效。
测试是将以下代码定义为生成例如libpreload.so的cargo项目。将其复制到目标/调试之外。 然后运行
cargo clean; LD_PRELOAD=libpreload.so cargo build
它挂了。 完整代码如下
extern crate core;
extern crate libc;
extern crate tracing;
extern crate tracing_appender;
extern crate tracing_subscriber;
use std::env;
use core::cell::Cell;
use libc::{c_void,c_char,c_int,size_t,ssize_t};
use tracing::{Level,event,};
use tracing::dispatcher::{with_default,dispatch};
use tracing_appender::non_blocking::WorkerGuard;
use tracing_subscriber::FmtSubscriber;
use std::sync::atomic;
#[cfg(any(target_os = "macos",target_os = "ios"))]
pub mod dyld_insert_libraries;
/* Some Rust library functionality (e.g.,jemalloc) initializes
* lazily,after the hooking library has inserted itself into the call
* path. If the initialization uses any hooked functions,this will lead
* to an infinite loop. Work around this by running some initialization
* code in a static constructor,and bypassing all hooks until it has
* completed. */
static INIT_STATE: atomic::AtomicBool = atomic::AtomicBool::new(false);
pub fn initialized() -> bool {
INIT_STATE.load(atomic::Ordering::SeqCst)
}
extern "C" fn initialize() {
Box::new(0u8);
INIT_STATE.store(true,atomic::Ordering::SeqCst);
}
#[link(name = "dl")]
extern "C" {
fn dlsym(handle: *const c_void,symbol: *const c_char) -> *const c_void;
}
const RTLD_NEXT: *const c_void = -1isize as *const c_void;
pub unsafe fn dlsym_next(symbol: &'static str) -> *const u8 {
let ptr = dlsym(RTLD_NEXT,symbol.as_ptr() as *const c_char);
if ptr.is_null() {
panic!("redhook: Unable to find underlying function for {}",symbol);
}
ptr as *const u8
}
/* Rust doesn't directly expose __attribute__((constructor)),but this
* is how GNU implements it. */
#[link_section = ".init_array"]
pub static INITIALIZE_CTOR: extern "C" fn() = ::initialize;
pub fn make_dispatch(tracevar: &str) -> (bool,dispatch,WorkerGuard) {
let file_appender;
let tracing;
if let Ok(tracefile) = env::var(tracevar) {
file_appender = tracing_appender::rolling::never("",tracefile);
tracing = true
} else {
file_appender = tracing_appender::rolling::never("","/dev/null");
tracing = false
}
let (non_blocking,guard) = tracing_appender::non_blocking(file_appender);
let subscriber = FmtSubscriber::builder()
.with_max_level(Level::TRACE)
.with_writer(non_blocking)
.finish();
(tracing,dispatch::new(subscriber),guard)
}
thread_local! {
#[allow(nonstandard_style)]
static MY_disPATCH_initialized: ::core::cell::Cell<bool> = false.into();
}
thread_local! {
static MY_disPATCH: (bool,WorkerGuard) = {
let ret = make_dispatch("WISK_TRACE");
// println!("Tracing: {}",ret.0);
MY_disPATCH_initialized.with(|it| it.set(true));
ret
};
}
#[allow(non_camel_case_types)]
pub struct posix_spawnp {__private_field: ()}
#[allow(non_upper_case_globals)]
static posix_spawnp: posix_spawnp = posix_spawnp {__private_field: ()};
impl posix_spawnp {
fn get(&self) -> unsafe extern fn (pid: *mut libc::pid_t,file: *const libc::c_char,file_actions: *const libc::posix_spawn_file_actions_t,attrp: *const libc::posix_spawnattr_t,argv: *const *const libc::c_char,envp: *const *const libc::c_char) -> libc::c_int {
use ::std::sync::Once;
static mut REAL: *const u8 = 0 as *const u8;
static mut ONCE: Once = Once::new();
unsafe {
ONCE.call_once(|| {
REAL = dlsym_next(concat!("posix_spawnp","\0"));
});
::std::mem::transmute(REAL)
}
}
#[no_mangle]
pub unsafe extern "C" fn posix_spawnp(pid: *mut libc::pid_t,envp: *const *const libc::c_char) -> libc::c_int {
if initialized() {
::std::panic::catch_unwind(|| my_posix_spawnp ( pid,file,file_actions,attrp,argv,envp )).ok()
} else {
None
}.unwrap_or_else(|| posix_spawnp.get() ( pid,envp ))
}
}
pub unsafe fn my_posix_spawnp(pid: *mut libc::pid_t,envp: *const *const libc::c_char) -> libc::c_int {
MY_disPATCH.with(|(tracing,my_dispatch,_guard)| {
with_default(&my_dispatch,|| {
posix_spawnp.get()(pid,envp)
})
})
}
需要将货物编译为.so
[package]
name = "readlink"
version = "0.1.0"
authors = ["Saravanan Shanmugham <sarvi@cisco.com>"]
# See more keys and their deFinitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[lib]
name = "readlink"
crate_type = ["dylib"]
[dependencies]
libc = "0.2"
分层显示
statx(AT_FDCWD,"/users/sarvi/.rustup/toolchains/nightly-x86_64-unkNown-linux-gnu/bin/rustc",AT_STATX_SYNC_AS_STAT,STATX_ALL,{stx_mask=STATX_BASIC_STATS,stx_attributes=0,stx_mode=S_IFREG|0755,stx_size=2707888,...}) = 0
openat(AT_FDCWD,"/ws/sarvi-sjc/redhook/examples/readlink/target/.rustc_info.json",O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD,"/dev/null",O_RDONLY|O_CLOEXEC) = 3
pipe2([4,5],O_CLOEXEC) = 0
pipe2([6,7],O_CLOEXEC) = 0
futex(0x7f01c70f50e8,FUTEX_WAKE_PRIVATE,2147483647) = 0
prlimit64(0,RLIMIT_NOFILE,NULL,{rlim_cur=4*1024,rlim_max=4*1024}) = 0
prlimit64(0,rlim_max=4*1024}) = 0
futex(0x5621cf2c9fa0,FUTEX_WAIT_PRIVATE,2,NULL
如果我改变
MY_disPATCH.with(|(tracing,envp)
})
})
下面的内容只是使跟踪变得不完整,但实际上并没有生成任何跟踪,它仍然挂起
MY_disPATCH.with(|(tracing,_guard)| {
posix_spawnp.get()(pid,envp)
})
这不会挂起并且可以正常工作
posix_spawnp.get()(pid,envp)
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)