所有人!
假设我有一个程序(Usemalloc),如下所示:
#include <stdio.h>
#include <stdlib.h>
#define USER_BYTES_SIZE 100
int main(void){
char* userbytes = (char*)malloc(USER_BYTES_SIZE*sizeof(char));
if(!userbytes)
return 1;
for(int i = 0; i <= USER_BYTES_SIZE; i++){ // "i <= USER_BYTES_SIZE" leads to an off-by-one memory overrun.
userbytes[i] = 0;
}
return 0;
}正如您所看到的,存在一个off-by-one错误,它会导致内存溢出。我想在运行时检测到这样的bug。LD_PRELOADed库非常适合我的工作。我已经制作了一个名为libhijack.so的库来劫持对real malloc的调用,并将其替换为对我自己的自定义malloc的调用,该调用调用真正的malloc,并在由真正的malloc分配的内存条的末端添加红色区域。Libhijack.so的代码如下:
void* (*real_malloc) (size_t size);
void* malloc(size_t size){
real_malloc = ((void*)(*)(size_t))dlsym(RTLD_NEXT, "malloc");
void* allocbytes = (void*)real_malloc(size + 4); //put 2 bytes at each end, call them red zones
return (allocbytes + 2);
}我使用以下命令在库中运行主程序:
LD_PRELOAD=./libhijack.so ./usemalloc然后,如果在红色区域中可以访问内存,我会检测到它们,并将它们视为内存溢出错误。
当主进程包含对LD_PRELOAD的调用时,此malloc解决方案工作得很好,但当forked的子进程执行此操作时,则会失败。
例如,我们按如下方式更改"usemalloc“:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h> // +
#define USER_BYTES_SIZE 100
int main(void){
pid_t child = fork();
if(child < 0)
exit(1);
if(child == 0){ //child process
char* userbytes = (char*)malloc(USER_BYTES_SIZE*sizeof(char));
if(!userbytes)
return 1;
for(int i = 0; i <= USER_BYTES_SIZE; i++){ // "i <= USER_BYTES_SIZE" leads to an off-by-one memory overrun.
userbytes[i] = 0;
}
}
else { //the current process
wait(NULL);
}
return 0;
}LD_PRELOADed库不会检测到子进程中出现的溢出错误。
所以我的问题是:如何使用LD_PRELOADed库检测子进程中的溢出错误?这(使用LD_PRELOADed库)可能吗?如果没有,还有其他选择吗?任何建议我们都非常感谢!
发布于 2013-01-01 22:44:10
我希望我没有吹毛求疵地指出libhijack代码实际上并没有分配任何内存?pthread_mutex_lock需要一个pthread_mutex_t *参数,并返回一个整数,表示互斥锁是否成功?
此外,您正在fork()‘子进程,这与创建线程有一点不同,因此pthread函数可能不是您真正想要的…?
另一个技巧是,虽然已经演示了导致问题的代码,但您如何检查您的“红色区域”?
发布于 2013-01-02 17:56:02
使用valgrind检测内存泄漏和其他内存问题。它工作得很好,而且你不需要实现任何东西。
发布于 2013-05-31 06:14:48
我不认为你的问题与fork()和LD_PRELOAD有任何关系。我认为这可能是您代码中其他地方的错误。我尝试使用以下测试用例重现您的问题:
// preloadlib.c
#define _GNU_SOURCE
#include <dlfcn.h>
#include <unistd.h>
void* malloc(size_t size)
{
write(1, "malloc\n", 7);
void *(*real_malloc)(size_t) = dlsym(RTLD_NEXT, "malloc");
return real_malloc(size);
}。
// example.c
#include <unistd.h>
#include <stdlib.h>
int main()
{
if (fork()) {
write(1, "A\n", 2);
malloc(1337);
write(1, "B\n", 2);
} else {
write(1, "C\n", 2);
malloc(1337);
write(1, "D\n", 2);
}
return 0;
}。
# run.sh
gcc -Wall -Wextra -o example example.c
gcc -Wall -Wextra -fPIC -o preloadlib.so -shared preloadlib.c -ldl
LD_PRELOAD=$PWD/preloadlib.so ./example这是我得到的输出:
$ bash run.sh
A
malloc
C
B
malloc
D这是在64位Kubuntu 12.04 (libc版本2.15-0ubuntu10.4)上。
https://stackoverflow.com/questions/14111056
复制相似问题