LD_PRELOAD和clone()

LD_PRELOAD和clone(),第1张

概述我正在使用一个脚本运行一个带有LD_PRELOAD的程序和一个由我创建的库拦截一些调用,它运行良好但是在某些时候进程调用clone()并且我失去了拦截下一步的能力(程序运行)再没有我的图书馆),有什么方法可以克服这个问题吗? 打电话是 clone(child_stack, CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | CLONE_TH 我正在使用一个脚本运行一个带有LD_PRELOAD的程序和一个由我创建的库拦截一些调用,它运行良好但是在某些时候进程调用clone()并且我失去了拦截下一步的能力(程序运行)再没有我的图书馆),有什么方法可以克服这个问题吗?
打电话是

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)

查看克隆的参数我发现有能力跟踪子进程,但没有任何与预加载有关的内容.

我还要提一下,我试图拦截特定文件描述符上的所有调用和进程克隆文件描述符,所以我甚至不确定是否有可能做我想要的而没有一些标记来克隆(问题是我不明白所有这些).

更新:
我正在使用这个尝试记录qemu-dm完成的所有活动(由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__,cnt); }typedef int (*_open_f_t_)(const char *path,int flags,...);typedef int (*_open64_f_t_)(const char *path,...);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,...){    //replace this    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,mode,result);    } else {        result = _open_f_(path,flags);        dprintf("open(%s,result);    }    return result;}int open64(const char *path,int);        va_end (arg);        result = _open64_f_(path,result);    } else {        result = _open64_f_(path,result);    }    return result;}file * fopen(const char *path,const char *mode){    file *result = _fopen_f_(path,mode);    dprintf("fopen(%s,%s) => %p\n",result);    return result;}int close(int fd){    //replace this    int result = _close_f_(fd);    dprintf("close(%d) => %d\n",fd,result);    return result;}ssize_t read(int fd,size_t count){    // replace this    ssize_t result = _read_f_(fd,buf,count);    dprintf("read(%d,%p,%lu) => %ld\n",count,result);    return result;}ssize_t write(int fd,size_t count){    // replace this    ssize_t result = _write_f_(fd,count);    dprintf("write(%d,result);    return result;}off_t lseek(int fd,int whence){    // replace this    off_t result = _lseek_f_(fd,offset,whence);    dprintf("lseek(%d,%ld,%d) => %ld\n",whence,result);    return result;}

使用gcc -ggdb -shared -fPIC -Wl编译,-init,__ init__ -Wl,-fini,__ fini__ -o fileaccesshooks.so -ldl fileaccesshooks.c

包装脚本内容:

#!/bin/bashexport LD_PRELOAD=/home/xception/work/fileaccesshooks.soexec /usr/lib/xen/bin/qemu-dm-orig "$@"

正如在下面的评论中所观察到的,环境对于任务和过程实际上是相同的(LD_PRELOAD对于/ proc / 8408 / task / 8526 / environ和/ proc / 8408 / environ都是相同的)但是在调用克隆之后不再记录数据
grep -e“testfile”-e“(11”/ tmp / out-0

open(/root/testfile.raw,2) => 11read(11,0x7fffb7259d00,512) => 512read(11,0x7fba6e341200,512) => 512

这就是我得到的,但相对而言,相同的可执行文件上运行的strace -f的输出包含更多的读取和搜索

解决方法 从CLONE_VM的克隆参数和类似的,看起来这个克隆调用只是创建一个新的线程而不是一个新的进程.我不希望结果线程重新加载任何库,因此我不希望你的预加载库需要在新线程中再次行动 – 你现有的函数实现应该’正常工作’;所有跳转到库中的指令应该在旧线程中保持同样有效.

因此,我怀疑这不是你的问题,克隆是一个红鲱鱼.

我唯一的理论是:

>某个地方也有一名执行官
>为每个新线程调用库中的__init__代码,尽管这似乎不太可能.

关于qemu的最后一点 – 现代qemu使用协同程序来处理许多IO事物.它使用各种后端,具体取决于主机系统上的可用内容 – 如果你运气不好,它会为每个后端创建一个线程,这可能会产生非常非常大量的线程.在这里阅读 – http://lists.gnu.org/archive/html/qemu-devel/2011-07/msg02894.html – 有一些方法可以让qemu配置东西报告它正在使用的协程后端.但是,我怀疑Xen qemu-dm可能太老而无法获得这些协同程序的东西?我不知道.

总结

以上是内存溢出为你收集整理的LD_PRELOAD和clone()全部内容,希望文章能够帮你解决LD_PRELOAD和clone()所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/langs/1215276.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-05
下一篇 2022-06-05

发表评论

登录后才能评论

评论列表(0条)

保存