public inbox for glibc-bugs@sourceware.org
help / color / mirror / Atom feed
* [Bug dynamic-link/28248] New: is there a way to LD_PRELOAD library before other dynamic libraries?
@ 2021-08-19 12:57 mail at milianw dot de
  2021-08-31 17:41 ` [Bug dynamic-link/28248] " amonakov at gmail dot com
                   ` (5 more replies)
  0 siblings, 6 replies; 7+ messages in thread
From: mail at milianw dot de @ 2021-08-19 12:57 UTC (permalink / raw)
  To: glibc-bugs

https://sourceware.org/bugzilla/show_bug.cgi?id=28248

            Bug ID: 28248
           Summary: is there a way to LD_PRELOAD library before other
                    dynamic libraries?
           Product: glibc
           Version: 2.33
            Status: UNCONFIRMED
          Severity: normal
          Priority: P2
         Component: dynamic-link
          Assignee: unassigned at sourceware dot org
          Reporter: mail at milianw dot de
  Target Milestone: ---

Hey there, I hope this is the right place to report this.

I'm the author of heaptrack, which relies on LD_PRELOAD to intercept calls to
malloc and friends. Only recently, I realized my assumption about LD_PRELOAD
behavior is wrong - I thought it would be loaded _before_ all other dynamic
libraries, but that isn't the case.

See documentation over at
https://www.man7.org/linux/man-pages/man8/ld.so.8.html:

>    LD_PRELOAD
>              A list of additional, user-specified, ELF shared objects
>              to be loaded before all others.

But as can be seen by the below, the preloaded library will be loaded after
other dependencies of the binary we are executing, i.e.:

```
$ cat preload_dump.c:
#include <stdio.h>

void __attribute__ ((constructor)) init(void)
{
    fprintf(stderr, "preload init!\n"); 
}

void __attribute__ ((destructor)) cleanup(void)
{
    fprintf(stderr, "preload cleanup!\n"); 
}
$ gcc -shared -fPIC -o preload_dump.so preload_dump.c
```

```
$ readelf -d $(which bash) | grep NEEDED
 0x0000000000000001 (NEEDED)             Shared library: [libtinfo.so.5]
 0x0000000000000001 (NEEDED)             Shared library: [libdl.so.2]
 0x0000000000000001 (NEEDED)             Shared library: [libc.so.6]
```

```
LD_DEBUG=files LD_PRELOAD=$PWD/preload_dump.so bash --version
        83:
        83:     file=/opt/craft/preload_dump.so [0];  needed by bash [0]
        83:     file=/opt/craft/preload_dump.so [0];  generating link map
        83:       dynamic: 0x00007fb5dbbd3dd0  base: 0x00007fb5dbbd2000   size:
0x0000000000002029
        83:         entry: 0x00007fb5dbbd2000  phdr: 0x00007fb5dbbd2040  phnum:
                 8
        83:
        83:
        83:     file=libtinfo.so.5 [0];  needed by bash [0]
        83:     file=libtinfo.so.5 [0];  generating link map
        83:       dynamic: 0x00007fb5db9b3d10  base: 0x00007fb5db78b000   size:
0x0000000000229f00
        83:         entry: 0x00007fb5db797e40  phdr: 0x00007fb5db78b040  phnum:
                 7
        83:
        83:
        83:     file=libdl.so.2 [0];  needed by bash [0]
        83:     file=libdl.so.2 [0];  generating link map
        83:       dynamic: 0x00007fb5db789d68  base: 0x00007fb5db587000   size:
0x0000000000203130
        83:         entry: 0x00007fb5db587e50  phdr: 0x00007fb5db587040  phnum:
                 7
        83:
        83:
        83:     file=libc.so.6 [0];  needed by bash [0]
        83:     file=libc.so.6 [0];  generating link map
        83:       dynamic: 0x00007fb5db57fb60  base: 0x00007fb5db1b9000   size:
0x00000000003cd200
        83:         entry: 0x00007fb5db1db660  phdr: 0x00007fb5db1b9040  phnum:
                10
        83:
        83:
        83:     calling init: /lib64/libc.so.6
        83:
        83:
        83:     calling init: /lib64/libdl.so.2
        83:
        83:
        83:     calling init: /lib64/libtinfo.so.5
        83:
        83:
        83:     calling init: /opt/craft/preload_dump.so
        83:
preload init!
        83:
        83:     initialize program: bash
        83:
        83:
        83:     transferring control: bash
        83:
GNU bash, version 4.2.46(2)-release (x86_64-redhat-linux-gnu)
Copyright (C) 2011 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>

This is free software; you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
        83:
        83:     calling fini: bash [0]
        83:
        83:
        83:     calling fini: /opt/craft/preload_dump.so [0]
        83:
preload cleanup!
        83:
        83:     calling fini: /lib64/libtinfo.so.5 [0]
        83:
        83:
        83:     calling fini: /lib64/libdl.so.2 [0]
        83:

```

Note how the needed libs of the binary are loaded before the LD_PRELOAD'ed
library. And note how that then obviously means the fini call for preload_dump
happens before e.g. libtinfo.so's fini call.

Is there a way for me to inject a library into the dynamic loader in such a
way, that it is loaded first before any other dependency of the executable?

In my case, the main reason why I want the above behavior is actually to
enforce proper shutdown semantics: As a memory profiler, I have an atexit
handler which is calling `__libc_freeres` and `__gnu_cxx::__freeres`, similar
to and inspired by valgrind. But because my preloaded library is loaded *after*
the other libraries, its cleanup code will run *before* that of other
libraries.

Combined, this can lead to crashes when another fini of some other library
calls code that depends on resources that get freed by the freeres calls.

so, tl;dr;

- is there a way to force something like LD_PRELOAD, but load the library
before all others?
- is there an alternative way to force an atexit handler call at the very end
of the shutdown semantics, after all other libraries got unloaded?

Many thanks!

-- 
You are receiving this mail because:
You are on the CC list for the bug.

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2022-08-29  9:53 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-08-19 12:57 [Bug dynamic-link/28248] New: is there a way to LD_PRELOAD library before other dynamic libraries? mail at milianw dot de
2021-08-31 17:41 ` [Bug dynamic-link/28248] " amonakov at gmail dot com
2021-09-06  8:19 ` mail at milianw dot de
2021-09-06  8:32 ` fweimer at redhat dot com
2021-09-09  8:35 ` mail at milianw dot de
2021-09-09  8:54 ` mail at milianw dot de
2022-08-29  9:53 ` fweimer at redhat dot com

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).