如何使用LD_PRELOAD捕获posix_spawnp()?

时间:2018-08-21 16:29:27

标签: ld-preload

我能够捕获所有低级函数,例如open(),fopen()等,并使用dlsym(RTLD_NEXT,“ ...”)调用原始函数,但是我无法使用posix_spawnp做到这一点(),因为我的可执行文件崩溃了。为什么会这样以及如何捕获此功能?

很抱歉延迟。这是我在运行Linux的某些嵌入式设备上尝试的代码:

int posix_spawnp(pid_t * pid, const char * file, const posix_spawn_file_actions_t * file_actions, const posix_spawnattr_t * attrp, char * const argv[], char * const envp[])
{
    orig_fopen_t orig_fopen = (orig_fopen_t)dlsym(RTLD_NEXT, "fopen");
    FILE * fp = orig_fopen("/tmp/DiagnosticsAgent.log", "a");
    fprintf(fp, "*** posix_spawnp(..., {");
    int i;
    for (i = 0; argv[i] != 0; ++ i)
        fprintf(fp, "%s, ", argv[i]);
    fprintf(fp, "}, ...)\n");
    fclose(fp);

    void * handle = dlopen("libpthread.so.0", RTLD_LAZY);
    orig_posix_spawnp_t orig_posix_spawnp = (orig_posix_spawnp_t)dlsym(handle, "posix_spawnp");
    return orig_posix_spawnp(pid, file, file_actions, attrp, argv, envp);
}

1 个答案:

答案 0 :(得分:0)

我的linux / glibc可以正常工作。这是一个工作示例:

#!/bin/sh -eu

cat > main.c <<EOF
#include <spawn.h>
#include <sys/wait.h>
int main(int C, char **V)
{
    pid_t pid;
    if(0!=posix_spawnp(&pid,V[1],NULL,NULL,V+1,NULL))
        return 1;
    wait(0);
}
EOF
gcc main.c

cat > libspawn.c <<EOF
#define _GNU_SOURCE
#include <spawn.h>
#include <dlfcn.h>
#include <stdio.h>
typedef int spawnp_signature(pid_t *pid, const char *file,
                   const posix_spawn_file_actions_t *file_actions,
                   const posix_spawnattr_t *attrp,
                   char *const argv[], char *const envp[]);
spawnp_signature posix_spwanp;
int posix_spawnp(pid_t *pid, const char *file,
                   const posix_spawn_file_actions_t *file_actions,
                   const posix_spawnattr_t *attrp,
                   char *const argv[], char *const envp[])

{
    fprintf(stderr, "OVERRIDE\n");
    spawnp_signature *real = dlsym(RTLD_NEXT,__func__);
    return real(pid,file,file_actions,attrp,argv,envp);

}
EOF
gcc -shared -fpic -o libspawn.so libspawn.c -ldl

./a.out echo hello world
LD_PRELOAD=$PWD/libspawn.so ./a.out echo hello world

第二个输出将按预期方式打印OVERRIDE一词。

编辑: 使您的示例可编译后,它也对我有用。也许某些未经检查的调用在您的计算机上失败了,或者您忘记了链接dl库。

#!/bin/sh -eu

cat > main.c <<EOF
#include <spawn.h>
#include <sys/wait.h>
int main(int C, char **V)
{
    pid_t pid;
    if(0!=posix_spawnp(&pid,V[1],NULL,NULL,V+1,NULL))
        return 1;
    wait(0);
}
EOF
gcc main.c

cat > libspawn.c <<EOF
#define _GNU_SOURCE
#include <spawn.h>
#include <dlfcn.h>
#include <stdio.h>
typedef int spawnp_signature(pid_t *pid, const char *file,
                   const posix_spawn_file_actions_t *file_actions,
                   const posix_spawnattr_t *attrp,
                   char *const argv[], char *const envp[]);
spawnp_signature posix_spwanp;
int posix_spawnp(pid_t *pid, const char *file,
                   const posix_spawn_file_actions_t *file_actions,
                   const posix_spawnattr_t *attrp,
                   char *const argv[], char *const envp[])

{
    fprintf(stderr, "OVERRIDE\n");
    spawnp_signature *real = dlsym(RTLD_NEXT,__func__);
    return real(pid,file,file_actions,attrp,argv,envp);

}
EOF
cat >libspawn.c <<EOF
#define _GNU_SOURCE
#include <spawn.h>
#include <dlfcn.h>
#include <stdio.h>
typedef int (*orig_posix_spawnp_t)(pid_t *pid, const char *file,
                   const posix_spawn_file_actions_t *file_actions,
                   const posix_spawnattr_t *attrp,
                   char *const argv[], char *const envp[]);
typedef FILE *(*orig_fopen_t)(char const*, char const*);
int posix_spawnp(pid_t * pid, const char * file, const posix_spawn_file_actions_t * file_actions, const posix_spawnattr_t * attrp, char * const argv[], char * const envp[])
{
    orig_fopen_t orig_fopen = (orig_fopen_t)dlsym(RTLD_NEXT, "fopen");
    FILE * fp = orig_fopen("/tmp/DiagnosticsAgent.log", "a");
    fprintf(fp, "*** posix_spawnp(..., {");
    int i;
    for (i = 0; argv[i] != 0; ++ i)
        fprintf(fp, "%s, ", argv[i]);
    fprintf(fp, "}, ...)\n");
    fclose(fp);

    void * handle = dlopen("libpthread.so.0", RTLD_LAZY);
    if(!handle) { perror(0); return -1; }
    orig_posix_spawnp_t orig_posix_spawnp = (orig_posix_spawnp_t)dlsym(handle, "posix_spawnp");
    fprintf(stderr,"OVERRIDE\t");
    return orig_posix_spawnp(pid, file, file_actions, attrp, argv, envp);
}
EOF
gcc -shared -fpic -o libspawn.so libspawn.c -ldl

./a.out echo hello world
LD_PRELOAD=$PWD/libspawn.so ./a.out echo hello world