Specifying an invalid LD_AUDIT file can cause the target application to segfault.
First, you want the target program you're using to do something like setlocale
right after it starts. /bin/true and /bin/false are good for this purpose.
Second, prelinking is necessary; I don't know why yet, but it was definitely
necessary to run a prelink -a after updating ld.so to trigger the behaviour.
Third, the auditing bits must be bogus, preferably a non-existent file.
So, something like
Where /blah does not exist turns out to be a good reproducer.
From what I've been able to put together, when LD_AUDIT is specified we call
init_tls earlier than normal:
/* If we have auditing DSOs to load, do it now. */
if (__builtin_expect (audit_list != NULL, 0))
/* Iterate over all entries in the list. The order is important. */
struct audit_ifaces *last_audit = NULL;
struct audit_list *al = audit_list->next;
/* Since we start using the auditing DSOs right away we need to
initialize the data structures now. */
tcbp = init_tls ();
/* Load all the libraries specified by DT_NEEDED entries. If LD_PRELOAD
specified some libraries to load, these are inserted before the actual
dependencies in the executable's searchlist for symbol resolution. */
_dl_map_object_deps (main_map, preloads, npreloads, mode == trace, 0);
HP_TIMING_DIFF (diff, start, stop);
HP_TIMING_ACCUM_NT (load_time, diff);
/* We do not initialize any of the TLS functionality unless any of the
initial modules uses TLS. This makes dynamic loading of modules with
TLS impossible, but to support it requires either eagerly doing setup
now or lazily doing it later. Doing it now makes us incompatible with
an old kernel that can't perform TLS_INIT_TP, even if no TLS is ever
used. Trying to do it lazily is too hairy to try when there could be
multiple threads (from a non-TLS-using libpthread). */
bool was_tls_init_tp_called = tls_init_tp_called;
if (tcbp == NULL)
tcbp = init_tls ();
At the earlier init_tls call we haven't seen a DSO with TLS bits. As a result
init_tls & eventually dl_allocate_tls_init have nothing interesting to do. The
result being the TLS bits in libc.so.6 aren't initialized and all hell breaks
loose in the locale bits as the thread local variables aren't properly
Ideally if the auditing module is bogus we should just ignore it and the application should run normally. Segfaulting is, umm, bad.
I pondered delaying the first init_tls call until we know the auditing module is loadable, but I'm concerned that's simply too late.
I have found that it's not necessary that it needs to be a bogus LD_AUDIT library.
for latrace also it's failing while linking the second level libraries (i.e. dependent libraries of libraries)
You can reproduce this issue by running
> latrace gedit
the above command cause segfault in the application
Looks almost as duplicate of 15199.
(In reply to Ondrej Bilka from comment #2)
> Looks almost as duplicate of 15199.
I doubt it is a duplicate of 15199.
While working on rhel-5.11 / glibc 2.5 I ran into exactly the same issue as Jeff.
You can see that TLS is broken in the code accessing __ctype_b and that the register value is zero.
Florian Weimer and I found that this is somehow also related to prelink. If you undo prelinking then everything works.
It may be that with prelinking the dlmopen code links the same library twice into the same address range and the namespaces conflict?
We may never need to look at this again given that prelink isn't really being actively developed or used by newer distributions.
I won't close this out yet, but we should at some point just close this issue.
(In reply to Carlos O'Donell from comment #3)
> Florian Weimer and I found that this is somehow also related to prelink. If
> you undo prelinking then everything works.
Jeff also noted that as a requirement to expose the bug, which is why I identified our issue as a duplicate.