Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cannot dynamically load position-independent executable #9

Closed
etam opened this issue May 9, 2020 · 7 comments
Closed

cannot dynamically load position-independent executable #9

etam opened this issue May 9, 2020 · 7 comments

Comments

@etam
Copy link
Contributor

etam commented May 9, 2020

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:

ERROR: ld.so: object '/home/etam/tmp/ip2unix-2.1.1/build/ip2unix' from LD_PRELOAD cannot be preloaded (cannot dynamically load position-independent executable): ignored.
@aszlig
Copy link
Contributor

aszlig commented May 27, 2020

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.

@aszlig
Copy link
Contributor

aszlig commented May 27, 2020

Fixed in 8e10ef2.

@aszlig aszlig closed this as completed May 27, 2020
@etam
Copy link
Contributor Author

etam commented May 27, 2020

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

@etam
Copy link
Contributor Author

etam commented May 27, 2020

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.

@etam
Copy link
Contributor Author

etam commented May 27, 2020

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;
 }

@etam
Copy link
Contributor Author

etam commented May 27, 2020

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)>

@etam
Copy link
Contributor Author

etam commented May 27, 2020

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants