我正在尝试使用一个旧程序(只有一个二进制文件可用),在使用旧的glibc版本的系统时,这个程序只会在Debian Buster的IO上被卡住。有人发现问题与通过
https://sourceware.org/bugzilla/show_bug.cgi?id=1190
系统的glibc显示了上述修复更改的两个功能,因此我假设它们可以被自己的功能替换,从而有效地撤消修复:
$ readelf -a /lib/x86_64-linux-gnu/libc.so.6 | grep underflow
1544: 000000000007ed60 86 FUNC GLOBAL DEFAULT 13 _IO_str_underflow@@GLIBC_2.2.5
1597: 0000000000074550 346 FUNC GLOBAL DEFAULT 13 __wunderflow@@GLIBC_2.2.5
1604: 00000000000753d0 1603 FUNC GLOBAL DEFAULT 13 _IO_wfile_underflow@@GLIBC_2.2.5
2152: 000000000007c520 705 FUNC GLOBAL DEFAULT 13 _IO_file_underflow@@GLIBC_2.2.5
2216: 000000000007d420 258 FUNC GLOBAL DEFAULT 13 __underflow@@GLIBC_2.2.5
我还设法截获了
所以我编写了一个小的共享库来拦截更改后的函数。不幸的是,这并没有成功,因为我的替换函数从未被调用过。作为测试,我添加了
fread
和
fwrite
以同样的方式
那些
被叫来了。所以我的方法是有效的。
更多细节:
_IO_new_file_underflow
在glibc's
iolib/fileops.c
_IO_old_file_underflow
在里面
iolib/oldfileops.c
-我编写了两个替换函数来撤消修复,然后调用原始函数:
int
_IO_new_file_underflow (FILE *fp)
{
int (*next)(FILE *fp) = dlsym(RTLD_NEXT, "_IO_new_file_underflow");
fprintf(stderr, "%s: called\n", __func__);
if (fp->_flags & _IO_EOF_SEEN)
fp->_flags &= ~_IO_EOF_SEEN;
return next(fp);
}
int
_IO_old_file_underflow (FILE *fp)
{
int (*next)(FILE *fp) = dlsym(RTLD_NEXT, "_IO_old_file_underflow");
fprintf(stderr, "%s: called\n", __func__);
if (fp->_flags & _IO_EOF_SEEN)
fp->_flags &= ~_IO_EOF_SEEN;
return next(fp);
}
-
用编译
gcc -o x.so -shared x.c -ldl -fPIC
-
LD_PRELOAD=/path/to/x.so faultyprogram
-
结果:从未调用替换函数,程序失败。
-
这些符号在.so文件中:
$ readelf -a x.so | grep underflow
8: 000000000000118a 117 FUNC GLOBAL DEFAULT 12 _IO_old_file_underflow
9: 0000000000001115 117 FUNC GLOBAL DEFAULT 12 _IO_new_file_underflow
47: 0000000000001115 117 FUNC GLOBAL DEFAULT 12 _IO_new_file_underflow
50: 000000000000118a 117 FUNC GLOBAL DEFAULT 12 _IO_old_file_underflow
$ cat version
VERSION {
GLIBC_2.2.5 {
global: *;
};
$ gcc -o x.so -shared x.c -ldl -fPIC version
$ readelf -a x.so | grep underflow
8: 0000000000001115 117 FUNC GLOBAL DEFAULT 13 _IO_new_file_underflow@@GLIBC_2.2.5
9: 000000000000118a 117 FUNC GLOBAL DEFAULT 13 _IO_old_file_underflow@@GLIBC_2.2.5
48: 0000000000001115 117 FUNC GLOBAL DEFAULT 13 _IO_new_file_underflow
51: 000000000000118a 117 FUNC GLOBAL DEFAULT 13 _IO_old_file_underflow
但这也不管用。
在程序上运行ldd
LD_DEBUG=all
我现在想知道我是否遗漏了一些必要的东西,或者是否通常不可能实现对这两个函数的LD_PRELOAD替换。
更新:增加了gdb体验,修复了输入错误