Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Clear DF_1_NODELETE flag only for failed to load library.
https://sourceware.org/bugzilla/show_bug.cgi?id=18778

If dlopen fails to load an object that has triggered loading libpthread it
causes ld.so to unload libpthread because its DF_1_NODELETE flags has been
forcefully cleared. The next call to __rtdl_unlock_lock_recursive will crash
since pthread_mutex_unlock no longer exists.

This patch moves l->l_flags_1 &= ~DF_1_NODELETE out of loop through all loaded
libraries and performs the action only on inconsistent one.

	[BZ #18778]
	* elf/Makefile (tests): Add Add tst-nodelete2.
	(modules-names): Add tst-nodelete2mod.
	(tst-nodelete2mod.so-no-z-defs): New.
	($(objpfx)tst-nodelete2): Likewise.
	($(objpfx)tst-nodelete2.out): Likewise.
	(LDFLAGS-tst-nodelete2): Likewise.
	* elf/dl-close.c (_dl_close_worker): Move DF_1_NODELETE clearing
	out of loop through all loaded libraries.
	* elf/tst-nodelete2.c: New file.
	* elf/tst-nodelete2mod.c: Likewise.
  • Loading branch information
Maxim Ostapenko authored and Andreas Schwab committed Aug 11, 2015
1 parent dc8a7ff commit f25238f
Show file tree
Hide file tree
Showing 6 changed files with 71 additions and 11 deletions.
14 changes: 14 additions & 0 deletions ChangeLog
@@ -1,3 +1,17 @@
2015-08-10 Maxim Ostapenko <m.ostapenko@partner.samsung.com>

[BZ #18778]
* elf/Makefile (tests): Add Add tst-nodelete2.
(modules-names): Add tst-nodelete2mod.
(tst-nodelete2mod.so-no-z-defs): New.
($(objpfx)tst-nodelete2): Likewise.
($(objpfx)tst-nodelete2.out): Likewise.
(LDFLAGS-tst-nodelete2): Likewise.
* elf/dl-close.c (_dl_close_worker): Move DF_1_NODELETE clearing
out of loop through all loaded libraries.
* elf/tst-nodelete2.c: New file.
* elf/tst-nodelete2mod.c: Likewise.

2015-08-11 Andreas Schwab <schwab@suse.de>

* sysdeps/unix/sysv/linux/openat.c (OPENAT_NOT_CANCEL): Don't define.
Expand Down
2 changes: 1 addition & 1 deletion NEWS
Expand Up @@ -10,7 +10,7 @@ Version 2.23
* The following bugs are resolved with this release:

16517, 16519, 17905, 18265, 18480, 18525, 18618, 18647, 18661, 18674,
18781, 18787, 18789, 18790.
18778, 18781, 18787, 18789, 18790.

Version 2.22

Expand Down
11 changes: 9 additions & 2 deletions elf/Makefile
Expand Up @@ -148,7 +148,8 @@ tests += loadtest restest1 preloadtest loadfail multiload origtest resolvfail \
tst-unique1 tst-unique2 $(if $(CXX),tst-unique3 tst-unique4 \
tst-nodelete) \
tst-initorder tst-initorder2 tst-relsort1 tst-null-argv \
tst-ptrguard1 tst-tlsalign tst-tlsalign-extern tst-nodelete-opened
tst-ptrguard1 tst-tlsalign tst-tlsalign-extern tst-nodelete-opened \
tst-nodelete2
# reldep9
ifeq ($(build-hardcoded-path-in-tests),yes)
tests += tst-dlopen-aout
Expand Down Expand Up @@ -218,7 +219,7 @@ modules-names = testobj1 testobj2 testobj3 testobj4 testobj5 testobj6 \
tst-initorder2d \
tst-relsort1mod1 tst-relsort1mod2 tst-array2dep \
tst-array5dep tst-null-argv-lib \
tst-tlsalign-lib tst-nodelete-opened-lib
tst-tlsalign-lib tst-nodelete-opened-lib tst-nodelete2mod
ifeq (yes,$(have-protected-data))
modules-names += tst-protected1moda tst-protected1modb
tests += tst-protected1a tst-protected1b
Expand Down Expand Up @@ -594,6 +595,7 @@ tst-auditmod9b.so-no-z-defs = yes
tst-nodelete-uniquemod.so-no-z-defs = yes
tst-nodelete-rtldmod.so-no-z-defs = yes
tst-nodelete-zmod.so-no-z-defs = yes
tst-nodelete2mod.so-no-z-defs = yes

ifeq ($(build-shared),yes)
# Build all the modules even when not actually running test programs.
Expand Down Expand Up @@ -1164,6 +1166,11 @@ $(objpfx)tst-nodelete.out: $(objpfx)tst-nodelete-uniquemod.so \
LDFLAGS-tst-nodelete = -rdynamic
LDFLAGS-tst-nodelete-zmod.so = -Wl,--enable-new-dtags,-z,nodelete

$(objpfx)tst-nodelete2: $(libdl)
$(objpfx)tst-nodelete2.out: $(objpfx)tst-nodelete2mod.so

LDFLAGS-tst-nodelete2 = -rdynamic

$(objpfx)tst-initorder-cmp.out: tst-initorder.exp $(objpfx)tst-initorder.out
cmp $^ > $@; \
$(evaluate-test)
Expand Down
15 changes: 8 additions & 7 deletions elf/dl-close.c
Expand Up @@ -144,6 +144,14 @@ _dl_close_worker (struct link_map *map, bool force)
char done[nloaded];
struct link_map *maps[nloaded];

/* Clear DF_1_NODELETE to force object deletion. We don't need to touch
l_tls_dtor_count because forced object deletion only happens when an
error occurs during object load. Destructor registration for TLS
non-POD objects should not have happened till then for this
object. */
if (force)
map->l_flags_1 &= ~DF_1_NODELETE;

/* Run over the list and assign indexes to the link maps and enter
them into the MAPS array. */
int idx = 0;
Expand All @@ -153,13 +161,6 @@ _dl_close_worker (struct link_map *map, bool force)
maps[idx] = l;
++idx;

/* Clear DF_1_NODELETE to force object deletion. We don't need to touch
l_tls_dtor_count because forced object deletion only happens when an
error occurs during object load. Destructor registration for TLS
non-POD objects should not have happened till then for this
object. */
if (force)
l->l_flags_1 &= ~DF_1_NODELETE;
}
assert (idx == nloaded);

Expand Down
37 changes: 37 additions & 0 deletions elf/tst-nodelete2.c
@@ -0,0 +1,37 @@
#include "../dlfcn/dlfcn.h"
#include <stdio.h>
#include <stdlib.h>
#include <gnu/lib-names.h>

static int
do_test (void)
{
int result = 0;

printf ("\nOpening pthread library.\n");
void *pthread = dlopen (LIBPTHREAD_SO, RTLD_LAZY);

/* This is a test for correct DF_1_NODELETE clearing when dlopen failure
happens. We should clear DF_1_NODELETE for failed library only, because
doing this for others (e.g. libpthread) might cause them to be unloaded,
that may lead to some global references (e.g. __rtld_lock_unlock) to be
broken. The dlopen should fail because of undefined symbols in shared
library, that cause DF_1_NODELETE to be cleared. For libpthread, this
flag should be set, because if not, SIGSEGV will happen in dlclose. */
if (dlopen ("tst-nodelete2mod.so", RTLD_NOW) != NULL)
{
printf ("Unique symbols test failed\n");
result = 1;
}

if (pthread)
dlclose (pthread);

if (result == 0)
printf ("SUCCESS\n");

return result;
}

#define TEST_FUNCTION do_test ()
#include "../test-skeleton.c"
3 changes: 2 additions & 1 deletion elf/tst-znodelete-zlib.cc → elf/tst-nodelete2mod.c
@@ -1,6 +1,7 @@
/* Undefined symbol. */
extern int not_exist (void);

int foo (void)
{
return not_exist ();
return not_exist ();
}

0 comments on commit f25238f

Please sign in to comment.