Reputation: 422
I want to intercept clone calls made by a simple pthread program. I am trying to use the LD_PRELOAD to achieve this. But could not get handle to the clone calls. When I run strace on pthread program, I can see that
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
But the clone signature of linux as well as the one I used in shared object is
int clone(int (*fn)(void *), void *stack, int flags, void *arg, ...
/* pid_t *parent_tid, void *tls, pid_t *child_tid */ );
Is the reason for not getting handle to clone is due to the difference in clone signature between straced one and linux manual?
or
LD_PRELOAD is not the correct way to intercept clone system calls made by pthread program?
shared object code
#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
}
compiled it using
gcc -Wall -fPIC -shared -o myclone.so myclone.c -ldl
Upvotes: 1
Views: 381
Reputation: 213879
I want to intercept clone calls made by a simple pthread program.
If you disassemble libpthread.so.0
(the do_clone()
function), you'll discover that it doesn't call clone()
, it calls __clone()
.
You can also observe this in nm -D libpthread.so.0
output:
nm -D /lib/x86_64-linux-gnu/libpthread.so.0 | grep clone
U __clone@GLIBC_2.2.5
Changing myclone.c
to provide int __clone(...)
on a system with GLIBC 2.31 results in:
LD_PRELOAD=./myclone.so ./a.out
called my clone
Note that the code you commented out:
//removed rest of the code
is severely restricted in what it can do -- this code is called while holding several GLIBC-internal locks, the newly-created thread has not been fully initialized, etc. etc.
If you call into GLIBC at that point, you should expect deadlocks, crashes and/or mystery bugs.
Upvotes: 3