我在最新的 Ubuntu Linux 上。
这里是一个共享库,里面有加载和卸载时调用的函数:
shared.c
:
#include <fcntl.h>
#include <sys/stat.h>
void init() {
open("init", O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
}
void fini() {
open("fini", O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
}
这是用
编译的gcc -shared -fPIC -Wl,-init=init -Wl,-fini=fini shared.c -o shared.so
然后我这样做:
$ rm init fini
$ LD_PRELOAD=$PWD/shared.so dash /dev/null
$ echo $?
0
$ ls init
init
$ ls fini
ls: cannot access 'fini': No such file or directory
所以...调用了加载函数,但没有调用卸载函数
如果我将
dash
替换为 bash
,两者都会被调用。
使用
__attribute__((destructor))
没有区别。
为什么不调用
dash
的卸载功能?
根据 Marco Bonelli 的要求添加:
$ file $(which dash)
/usr/bin/dash: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=f7ab02fc1b8ff61b41647c1e16ec9d95ba5de9f0, for GNU/Linux 3.2.0, stripped
$ ldd $(which dash)
linux-vdso.so.1 (0x00007ffd931c0000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f6b19e84000)
/lib64/ld-linux-x86-64.so.2 (0x00007f6b1a0ec000)
为什么在预加载到 dash 时不调用共享库 fini 函数?
因为 dash 调用
_exit
here 调用 exit_group 系统调用 here 立即终止程序。
我们也来做个小例子:
# Makefile
all:
gcc -shared -fPIC -Wl,-init=init -Wl,-fini=fini -Wl,-soname,shared.so shared.c -o shared.so
gcc main.c -o main.out
LD_PRELOAD=$(PWD)/shared.so ./main.out /dev/null
# main.c
#include <unistd.h>
int main() {
_exit(0);
}
# shared.c
#include <fcntl.h>
#include <sys/stat.h>
#include <unistd.h>
#include <string.h>
void out(const char *str) {
int fd = open("/dev/tty", O_WRONLY);
write(fd, str, strlen(str));
close(fd);
}
void init() {
out("\nstart\n\n");
}
void fini() {
out("\nstop\n\n");
}
执行时不输出停止:
$ make
gcc -shared -fPIC -Wl,-init=init -Wl,-fini=fini -Wl,-soname,shared.so shared.c -o shared.so
gcc main.c -o main.out
LD_PRELOAD=..../shared.so ./main.out /dev/null
start
我应该把它作为评论,但我把它作为格式化目的的答案。
问题不在于
redirection
和touch
之间的区别,因为在你的dash/touch运行中,shared.so被加载了两次,一次用于dash,一次用于touch。
fini
只用 touch
开火。
你可以看到这两个运行的差异:
$ LD_PRELOAD=$PWD/shared.so dash /dev/null
# fini is not called
$ LD_PRELOAD=$PWD/shared.so touch /dev/null
# fini is called
所以这与
dash
有关。
希望这能为你的调查提供更多的材料。