问题描述
注意::声称的dupe不会以任何方式回答此问题;特别是,可以通过使用-fPIC
进行编译来轻松地修复线程局部示例,就像下面已经提到的bugzilla示例一样。其余只是未征求的意见和毫无根据的主张。
在最近的Linux系统(如Debian 10,RHEL 8等)中,您可以创建一个ELF文件,该文件既是位置独立的可执行文件(PIE),又是动态加载的库/共享对象。
这非常有用,并且有很多应用程序,例如创建包装器程序,这些程序预加载自身,然后执行另一个程序(请参见下面的图2 ),或者将虚拟机/语言环境作为单个对象,可以嵌入或嵌入作为独立的解释器运行。所有这些都无需处理固定的安装目录,symlink漏洞,$ORIGIN
或其他此类安全性和文件系统策略的噩梦。
但是,在glibc中更改2c75b54会破坏它:
elf:拒绝dlopen PIE对象[BZ#24323]
另一个可执行文件已经被映射,因此动态链接器 无法为第二个可执行文件正确执行重定位
还在discussion中声称导致该事实:
也没有办法正确执行第二个可执行文件的ELF构造器
但这似乎是伪造的。如下面的图1 所示,构造函数,重定位和线程局部变量似乎可以正常工作。
复制重定位不起作用,但是是否有任何理由还要中断那些不使用复制重定位的程序,如使用-fPIC
? (特别是,只需使用-fPIC
进行编译,即可轻松修复testcase中的discussion。)
此更改在FreeBSD 12.2中也为picked,给出的主要原因是“ glibc也这样做”。它仍然可以在NetBSD 9.1和OpenBSD 6.8中使用(尽管构造函数在OpenBSD中不能使用)。
那么,以这种方式使用PIE不起作用的技术原因是什么?清除这种情况的清晰场景(请参阅图1和图2中的挑战)会很好。
展览1
直接执行 a)或 b) dl加载为共享库并通过其{{1 }}通过libexe
来实现。
面临的挑战是展示main
可以使用的功能,这些功能会阻止 a)或 b)或使其工作方式不同,无法轻易修复。
loader
图2
这个小程序会自动加载,然后运行另一个可执行文件。与典型的libexe
不同,它在Linux上也可以通过fexecve
/ execveat(AT_EMPTY_PATH)
正常运行,就像在执行memfd_create
d文件时一样。经过测试可在Debian> = 9,Centos / RHEL> = 7等上运行。
面临的挑战是演示一个可执行文件,当以这种方式执行链时,该可执行文件将失败,但是当预加载的代码位于单独的库中时(如stdbuf
/libstdbuf.so
),该可执行文件将正常工作。
cat <<'EOT' > libexe.c
#include <stdio.h>
#include <errno.h>
#include <err.h>
__thread int var;
void set_errno(int e){ errno = e; }
__attribute__((weak))
int main(void){
set_errno(EPIPE); warn("%s var=%d",__FILE__,var);
}
__attribute__((constructor))
static void init(void){
var = 33;
fprintf(stderr,"%s's constructor\n",__FILE__);
}
EOT
cat <<'EOT' > loader.c
#include <dlfcn.h>
#include <stdio.h>
#include <err.h>
#include <errno.h>
int main(void){
void *dl; char *lib = "./libexe";
if(!(dl = dlopen(lib,RTLD_LAZY)))
errx(1,"dlopen: %s",dlerror());
printf("var=%d in %s\n",*(int*)dlsym(dl,"var"),__FILE__);
((void(*)(int))dlsym(dl,"set_errno"))(EBADF); warn("%s",__FILE__);
return ((int(*)(void))dlsym(dl,"main"))();
}
__attribute__((constructor))
static void init(void){
fprintf(stderr,__FILE__);
}
EOT
cc -pie -fPIC -Wl,-E libexe.c -o libexe
cc loader.c -o loader -ldl
############
$ ./loader
loader.c's constructor
libexe.c's constructor
var=33 in loader.c
loader: loader.c: Bad file descriptor
loader: libexe.c var=33: Broken pipe
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)