You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Linux Kernel 6.1下LD_PRELOAD无法拦截pthread_create问题求助

问题原因与解决方案

核心原因:glibc 2.34+ 中 pthread_create 的实现变更

从 glibc 2.34 版本开始,pthread_create 被重构为内联(inline)函数,其定义直接内联到调用者代码中,实际执行的是 glibc 内部的私有符号 __pthread_create,而非原来的公开导出符号 pthread_create。

在 glibc 2.31 中,pthread_create 是普通的导出函数,二进制会直接引用这个符号,因此你的 LD_PRELOAD 库可以正常拦截。但到了 glibc 2.36,当目标二进制编译时使用了新版头文件,代码会直接展开为对 __pthread_create 的调用,完全绕过公开的 pthread_create 符号,导致拦截代码失效。

而 pthread_mutex_init 等函数并未做此变更,仍保持公开导出符号的实现,所以拦截依然有效。

验证方法

你可以通过 nm 命令检查目标二进制引用的符号:

nm -D <你的目标二进制文件> | grep pthread_create

如果输出是 U __pthread_create,说明二进制确实直接引用了内部私有符号,而非 pthread_create。

修复方案

修改拦截库,改为拦截内部符号 __pthread_create,同时通过 dlsym(RTLD_NEXT) 获取真正的函数实现以避免递归调用:

修改后的拦截代码

#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif
#include <pthread.h>
#include <stdio.h>
#include <dlfcn.h>

// 拦截 glibc 内部的 __pthread_create 符号
int __pthread_create(pthread_t *thread, const pthread_attr_t *attr,
                   void *(*start_routine)(void *), void *arg) {

    printf("[p] pthread_create (intercepted)\n");

    // 获取真正的 __pthread_create 函数指针
    static int (*real_pthread_create)(pthread_t*, const pthread_attr_t*, void*(*)(void*), void*) = NULL;
    if (!real_pthread_create) {
        real_pthread_create = dlsym(RTLD_NEXT, "__pthread_create");
        if (!real_pthread_create) {
            fprintf(stderr, "Failed to get real __pthread_create: %s\n", dlerror());
            return -1;
        }
    }

    return real_pthread_create(thread, attr, start_routine, arg);
}

int pthread_mutex_init(pthread_mutex_t *mutex,
                       const pthread_mutexattr_t *attr) {
                        
    printf("[p] pthread_mutex_init\n");

    static int (*real_mutex_init)(pthread_mutex_t*, const pthread_mutexattr_t*) = NULL;
    if (!real_mutex_init) {
        real_mutex_init = dlsym(RTLD_NEXT, "pthread_mutex_init");
    }

    return real_mutex_init(mutex, attr);
}

编译命令

编译时需要链接 dl 库以使用 dlsym:

gcc -shared -fPIC -o intercept.so intercept.c -ldl

额外说明

部分场景下,glibc 可能还保留了 pthread_create 的符号版本(如 pthread_create@GLIBC_2.2.5),但这仅为兼容旧二进制使用。如果你的目标二进制是基于新版 glibc 编译的,依然会优先使用内联调用 __pthread_create,因此拦截内部符号是最可靠的方案。

内容的提问来源于stack exchange,提问作者Victor

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.17 20:22:51