Closed etam closed 4 years ago
The reason is that since glibc 2.30, it's no longer possible to dlopen
/LD_PRELOAD PIE objects.
So to fix this, we need to split up the LD_PRELOAD library and the main executable.
Fixed in 8e10ef2d1d76ba8835735eaab167e77de34df88a.
Thanks for working on this, but it's still not working:
$ ./ip2unix -r in,path=/tmp/test.socket env
ERROR: ld.so: object './ip2unix' from LD_PRELOAD cannot be preloaded (cannot dynamically load executable): ignored.
...
LD_PRELOAD=./ip2unix
__IP2UNIX_RULES=i!!!!/tmp/test.socket&f!f!ff
~I think it's because dladdr
is in ip2unix.cc
, which is compiled in the main executable, not in shared library (like in the example on StackOverflow you referenced in commit message).~
Edit: Nope. I was wrong. __ip2unix__
function is in shared library, so it should work.
Another idea:
$ python3 ./scripts/gensyms.py ./src/preload.cc
{
global: "__ip2unix__)(void"; [...]
local: *;
};
Edit: nope again. I did this simple workaround, to make regex match, but still I have no idea, why it's not working for me.
diff --git a/src/ip2unix.cc b/src/ip2unix.cc
index f8a0ac6..c319a38 100644
--- a/src/ip2unix.cc
+++ b/src/ip2unix.cc
@@ -13,7 +13,7 @@
extern char **environ;
-extern "C" const char *__ip2unix__(void);
+extern "C" const char *__ip2unix__(int);
static std::optional<std::string> get_preload_libpath(void)
{
@@ -33,7 +33,7 @@ static bool run_preload(std::vector<Rule> &rules, char *argv[])
char *buf, *preload;
std::optional<std::string> libpath;
- libversion = __ip2unix__();
+ libversion = __ip2unix__(0);
if (!(libpath = get_preload_libpath())) {
return false;
diff --git a/src/preload.cc b/src/preload.cc
index 4104953..8660bbe 100644
--- a/src/preload.cc
+++ b/src/preload.cc
@@ -68,7 +68,7 @@ static void init_rules(void)
g_rules = std::make_shared<std::vector<Rule>>(rules.value());
}
-extern "C" const char *WRAP_SYM(__ip2unix__)(void)
+extern "C" const char* WRAP_SYM(__ip2unix__)(int i)
{
return VERSION;
}
Got any idea why there are different addresses 0x4252e0 <__ip2unix__@plt>
and 0x7ffff7f5ad2f <__ip2unix__(int)>
?
$ gdb --args ./ip2unix -r in,path=/tmp/test.socket env
[...]
Reading symbols from ./ip2unix...
(gdb) b get_preload_libpath
Breakpoint 1 at 0x42b064: file ../src/ip2unix.cc, line 22.
(gdb) r
Starting program: /home/etam/tmp/ip2unix/build/ip2unix -r in,path=/tmp/test.socket env
Breakpoint 1, get_preload_libpath () at ../src/ip2unix.cc:22
22 if (dladdr(reinterpret_cast<void*>(__ip2unix__), &info) < 0) {
(gdb) n
27 return std::string(info.dli_fname);
(gdb) p info
$1 = {
dli_fname = 0x7fffffffdf97 "/home/etam/tmp/ip2unix/build/ip2unix",
dli_fbase = 0x400000,
dli_sname = 0x418878 "__ip2unix__",
dli_saddr = 0x4252e0 <__ip2unix__@plt>
}
(gdb) p __ip2unix__
$2 = {const char *(int)} 0x7ffff7f5ad2f <__ip2unix__(int)>
I got it!
Here's the problem: https://stackoverflow.com/questions/5469274/what-does-plt-mean-here
Here's the solution: use meson -Db_pie=true build
I'm using openSUSE Tumbleweed (rolling release distro). It currently has gcc 9.3.1 and glibc 2.31.
I successfully built ip2unix version 2.1.1, but I get this error, when trying to use it: