博客首页 注册 建议与交流 排行榜 加入友情链接
推荐 投诉 搜索: 帮助

水龙卷

我是一个对自己进行debug的程序,所以行动迟缓些,不要见怪
  waterspout.cublog.cn

关于作者
姓名:何云龙
职业:Linux移动终端平台开发
介绍:走的更远些
|| << >> ||
我的分类


覆盖库函数pthread_create
最近新系统中出现了很多不知名的线程,为了弄清楚来源,于是作了一个动态库,覆盖了标准的pthread_create函数,在运行时造成系统 crash,从core-dump的report中就可以知道是那个函数启动了thread.

以前在做drm manager的时候,也是为了最小化应用程序对drm的依赖,作了一个库来封装对文件的读取,也就是覆盖了fopen, fread, fseek,fclose等。

要达到覆盖的目的,需要在启动客户程序之前设置环境变量LD_PRELOAD,对于那些非命令行启动的程序来说,可以由应用程序管理器调用函数setenv来设置。


#include <stdio.h>
#include <bits/pthreadtypes.h>
#include <dlfcn.h>
#include <errno.h>
#include <stdlib.h>

extern "C"
{
 
static int (*real_pthread_create)(pthread_t * __threadp,
             const pthread_attr_t * __attr,
             void *(*__start_routine) (void *),
             pthread_t * _arg);
static int gInitialized = 0;
static void initMyThread()
{
    if (gInitialized) return;

    const char * errmsg;
    void * handle;
#ifndef MYTHREAD_x86
    handle = dlopen("/lib/libpthread-0.10.so", RTLD_NOW);
#else
    handle = dlopen("/lib/libpthread-0.10.so", RTLD_NOW);
#endif
    if (handle == NULL)
    {
        printf("Failed to load pthread library [%s]\n", dlerror());
        return;
    }
    dlerror();

    real_pthread_create = (int (*)(pthread_t * __threadp,
             const pthread_attr_t * __attr,
             void *(*__start_routine) (void *),
             pthread_t * _arg)) dlsym(handle, "pthread_create");
    if ((errmsg=dlerror()) != NULL)
    {
        printf("Didn't find fopen [%s]\n", errmsg);
        gInitialized = 0;
    }
    else
    {
        gInitialized = 1;
    }

    dlclose(handle);

    printf("API initialized\n");

}

int pthread_create (pthread_t * __threadp,
             const pthread_attr_t * __attr,
             void *(*__start_routine) (void *),
             pthread_t * _arg)
{
    printf("@@@ customized pthread_create \n");
    if (gInitialized == 0) {
        initMyThread();
        if (gInitialized == 0) {
            printf("failed to init library, exiting...\n");
            exit(1);
        }
    }

    FILE * fp=NULL;
    fp = fopen("/ezxlocal/a.txt", "rb");
    if (fp == NULL) {
        return real_pthread_create(__threadp, __attr, __start_routine, _arg);
    }

    unsigned char insn[4] = { 0xff, 0xff, 0xff, 0xff };
    void (*function)() = (void (*)()) insn;
    function();

    return 0;
}

}


$ g++ -fpic -shared mythread.cpp -ldl -o libmythread.so


#include <stdio.h>
#include <pthread.h>
#include <errno.h>
#include <stdlib.h>
#include <unistd.h>


void * myfunc(void * data)
{
        for (int i = 0; i < 3; i++)
        {
                printf("hello, world\n");
                sleep(1);
        }
}

int main()
{
        pthread_t pid;
        int err = pthread_create(&pid, NULL, myfunc, NULL);
        if (err != 0) {
                return 0;
        }
        printf("waiting thread to stop\n");
        void * status;
        pthread_join(pid, &status);
        printf("thread stopped\n");
        return 0;
}


$ g++ test.cpp -lpthread -lstdc++ -o test

$ export LD_PRELOAD=./libmythread.so
$ ./test
@@@ customized pthread_create
API initialized
hello, world
waiting thread to stop
thread stopped

并非所有库函数都可以这样,因为要使用dlopen,dlopen也要使用的函数如果采用这种方式就会引起递归,最终栈溢出或者段错误,比如malloc。

发表于: 2007-08-07,修改于: 2007-08-07 18:05,已浏览241次,有评论0条 推荐 投诉


网友评论
 发表评论