【发布时间】:2021-08-05 07:27:53
【问题描述】:
我想拦截一个简单的 pthread 程序进行的 clone 调用。我正在尝试使用 LD_PRELOAD 来实现这一点。但无法处理 clone 调用。当我在 pthread 程序上运行 strace 时,我可以看到
clone(child_stack=0x7f15b7fa3ef0, flags=CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_THREAD|CLONE_SYSVSEM|CLONE_SETTLS|CLONE_PARENT_SETTID|CLONE_CHILD_CLEARTID, parent_tid=[8895], tls=0x7f15b7fa4640, child_tidptr=0x7f15b7fa4910) = 8895
但是linux的克隆签名和我在共享对象中使用的一样
int clone(int (*fn)(void *), void *stack, int flags, void *arg, ...
/* pid_t *parent_tid, void *tls, pid_t *child_tid */ );
是不是因为straceed one和linux手册的clone签名不一样,导致无法获取到clone的句柄?
或
LD_PRELOAD不是拦截pthread程序克隆系统调用的正确方法吗?
共享目标代码
#define _GNU_SOURCE
#include <dlfcn.h>
#define _FCNTL_H
#include <sys/types.h>
#include <bits/fcntl.h>
#include <stddef.h>
#include <stdarg.h>
#include <stdio.h>
typedef int (*_clone_f_t)(int (*fn)(void *), void *stack, int flags, void *arg, ...);
static _clone_f_t _clone_f_ = NULL;
void __attribute__((constructor)) my_init();
void __attribute__((destructor)) my_fini();
void my_init(){
_clone_f_ = (_clone_f_t)dlsym(RTLD_NEXT,"clone");
}
void my_fini(){}
int clone(int (*fn)(void *), void *stack, int flags, void *arg, ...){
printf("called my clone\n");
va_list arglist;
pid_t * parent_tid;
void * tls;
pid_t * child_tid;
va_start(arglist,arg);
parent_tid = va_arg(arglist, pid_t*);
tls = va_arg(arglist, void*);
child_tid = va_arg(arglist, pid_t*);
va_end(arglist);
//removed rest of the code
}
编译使用
gcc -Wall -fPIC -shared -o myclone.so myclone.c -ldl
【问题讨论】:
-
strace告诉您进程执行的 系统调用。 LD_PRELOAD 允许您插入库函数调用。两者不一样。使用ltrace而不是strace来跟踪库函数调用,因此您可以找出需要插入的正确函数。 (我希望它是pthread_create(),它是在 C 库中使用 'clone' 系统调用实现的;而不是作为对clone()C 库函数的调用。)要拦截系统调用,您可能需要(编写一个程序来) ptrace 目标进程。
标签: c linux ld-preload