c - LD_PRELOAD and clone() -
i'm using script run program ld_preload library created me intercept calls, works @ point process calls clone() , lose ability intercept what's next (the program run again without library), there way overcome this? call
clone(child_stack, clone_vm | clone_fs | clone_files | clone_sighand | clone_thread | clone_sysvsem | clone_settls | clone_parent_settid | clone_child_cleartid, parent_tidptr, tls, child_tidptr)
looking on parameters of clone saw there ability trace child process well, nothing pertaining preloading.
i should mention i'm trying intercept calls on specific file descriptor , process clones file descriptors i'm not sure if possible want without flag clone (problem don't understand of them).
update: i'm using trying log activity done qemu-dm (which run xen)
#define _largefile64_source #define _gnu_source #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> #include <dlfcn.h> #include <stdio.h> #include <stdarg.h> #define dprintf(...) if(__debug__) { char tmp[256]; int cnt = sprintf(tmp, __va_args__); _write_f_(2, tmp, cnt); _write_f_(__outfile__, tmp, cnt); } typedef int (*_open_f_t_)(const char *path, int flags, ...); typedef int (*_open64_f_t_)(const char *path, int flags, ...); typedef file *(*_fopen_f_t_)(const char *path, const char *mode); typedef int (*_close_f_t_)(int fd); typedef ssize_t (*_read_f_t_)(int fd, void *buf, size_t count); typedef ssize_t (*_write_f_t_)(int fd, const void *buf, size_t count); typedef off_t (*_lseek_f_t_)(int fd, off_t offset, int whence); static _open_f_t_ _open_f_ = null; static _open64_f_t_ _open64_f_ = null; static _fopen_f_t_ _fopen_f_ = null; static _close_f_t_ _close_f_ = null; static _read_f_t_ _read_f_ = null; static _write_f_t_ _write_f_ = null; static _lseek_f_t_ _lseek_f_ = null; static int __outfile__ = null; static int __debug__ = 0; void __init__ () { _open_f_ = (_open_f_t_)dlsym(rtld_next, "open"); _open64_f_ = (_open64_f_t_)dlsym(rtld_next, "open64"); _fopen_f_ = (_fopen_f_t_)dlsym(rtld_next, "fopen"); _close_f_ = (_close_f_t_)dlsym(rtld_next, "close"); _read_f_ = (_read_f_t_)dlsym(rtld_next, "read"); _write_f_ = (_write_f_t_)dlsym(rtld_next, "write"); _lseek_f_ = (_lseek_f_t_)dlsym(rtld_next, "lseek"); unlink("/tmp/qemu-dm-preload.log"); __outfile__ = _open_f_("/tmp/out-0", o_wronly | o_creat | o_append); __debug__ = 1; } void __fini__ () { __debug__ = 0; fsync(__outfile__); _close_f_(__outfile__); } int open(const char *path, int flags, ...) { //replace int result; if (flags & o_creat) { va_list arg; int mode = 0; va_start (arg, flags); mode = va_arg (arg, int); va_end (arg); result = _open_f_(path, flags, mode); dprintf("open(%s, %d, %d) => %d\n", path, flags, mode, result); } else { result = _open_f_(path, flags); dprintf("open(%s, %d) => %d\n", path, flags, result); } return result; } int open64(const char *path, int flags, ...) { //replace int result; if (flags & o_creat) { va_list arg; int mode = 0; va_start (arg, flags); mode = va_arg (arg, int); va_end (arg); result = _open64_f_(path, flags, mode); dprintf("open(%s, %d, %d) => %d\n", path, flags, mode, result); } else { result = _open64_f_(path, flags); dprintf("open(%s, %d) => %d\n", path, flags, result); } return result; } file * fopen(const char *path, const char *mode) { file *result = _fopen_f_(path, mode); dprintf("fopen(%s, %s) => %p\n", path, mode, result); return result; } int close(int fd) { //replace int result = _close_f_(fd); dprintf("close(%d) => %d\n", fd, result); return result; } ssize_t read(int fd, void *buf, size_t count) { // replace ssize_t result = _read_f_(fd, buf, count); dprintf("read(%d, %p, %lu) => %ld\n", fd, buf, count, result); return result; } ssize_t write(int fd, const void *buf, size_t count) { // replace ssize_t result = _write_f_(fd, buf, count); dprintf("write(%d, %p, %lu) => %ld\n", fd, buf, count, result); return result; } off_t lseek(int fd, off_t offset, int whence) { // replace off_t result = _lseek_f_(fd, offset, whence); dprintf("lseek(%d, %ld, %d) => %ld\n", fd, offset, whence, result); return result; }
compiled gcc -ggdb -shared -fpic -wl,-init,__init__ -wl,-fini,__fini__ -o fileaccesshooks.so -ldl fileaccesshooks.c
wrapper script contents:
#!/bin/bash export ld_preload=/home/xception/work/fileaccesshooks.so exec /usr/lib/xen/bin/qemu-dm-orig "$@"
as observed in comments below environment same task , process (ld_preload same both /proc/8408/task/8526/environ , /proc/8408/environ) after call clone no more data logged grep -e "testfile" -e "(11" /tmp/out-0
open(/root/testfile.raw, 2) => 11 read(11, 0x7fffb7259d00, 512) => 512 read(11, 0x7fba6e341200, 512) => 512 read(11, 0x7fba6e341200, 512) => 512 read(11, 0x7fba6e341200, 512) => 512 read(11, 0x7fba6e341200, 512) => 512 read(11, 0x7fba6e341200, 512) => 512 read(11, 0x7fba6e341200, 512) => 512
this get, comparatively output of strace -f
run on same executable contains more reads seeks
from clone
parameters of clone_vm
, similar, looks call clone
creating new thread rather new process. wouldn't expect resulting thread reload libraries , therefore not expect preloaded library need act again in new thread - existing function implementations should 'just work'; jump instructions library should remain equally valid in new thread old.
i therefore suspicious not problem , clone
red herring.
my theories are:
- there's
exec
somewhere well - the
__init__
code in library getting called each new thread, though seems unlikely indeed.
one last point regarding qemu - modern qemu
uses coroutines lots of io things. uses various backends depending on what's available on host system - if you're unlucky, creates thread each 1 can result in very, large numbers of threads. read here - http://lists.gnu.org/archive/html/qemu-devel/2011-07/msg02894.html - there's way qemu configure
stuff report coroutine backend it's using. however, suspect xen qemu-dm
might old have coroutine stuff? don't know.
Comments
Post a Comment