diff options
author | Pavel Kopyl <p.kopyl@samsung.com> | 2015-07-07 18:45:46 +0300 |
---|---|---|
committer | H.J. Lu <hjl.tools@gmail.com> | 2015-07-07 11:06:56 -0700 |
commit | 02d5e5d94a78d32e940dfb3b58ab7f06c31b0f76 (patch) | |
tree | 795f139f2dd266a5ee26d2c8f73af474b745f773 /elf/Makefile | |
parent | 890b7a4b33d482b5c768ab47d70758b80227e9bc (diff) | |
download | glibc-02d5e5d94a78d32e940dfb3b58ab7f06c31b0f76.tar.gz |
Add forced deletion support to _dl_close_worker
https://sourceware.org/bugzilla/show_bug.cgi?id=17833
I've a shared library that contains both undefined and unique symbols.
Then I try to call the following sequence of dlopen:
1. dlopen("./libfoo.so", RTLD_NOW)
2. dlopen("./libfoo.so", RTLD_LAZY | RTLD_GLOBAL)
First dlopen call terminates with error because of undefined symbols,
but STB_GNU_UNIQUE ones set DF_1_NODELETE flag and hence block library
in the memory.
The library goes into inconsistent state as several structures remain
uninitialized. For instance, relocations for GOT table were not performed.
By the time of second dlopen call this library looks like as it would be
fully initialized but this is not true: any call through incorrect GOT
table leads to segmentation fault. On some systems this inconsistency
triggers assertions in the dynamic linker.
This patch adds a parameter to _dl_close_worker to implement forced object
deletion in case of dlopen() failure:
1. Clears DF_1_NODELETE bit if forced, to allow library to be removed from
memory.
2. For each unique symbol that is defined in this object clears
appropriate entry in _ns_unique_sym_table.
[BZ #17833]
* elf/Makefile (tests): Add tst-nodelete.
(modules-names): Add tst-nodelete-uniquemod.
(tst-nodelete-uniquemod.so-no-z-defs): New.
(tst-nodelete-rtldmod.so-no-z-defs): Likewise.
(tst-nodelete-zmod.so-no-z-defs): Likewise.
($(objpfx)tst-nodelete): Likewise.
($(objpfx)tst-nodelete.out): Likewise.
(LDFLAGS-tst-nodelete): Likewise.
(LDFLAGS-tst-nodelete-zmod.so): Likewise.
* elf/dl-close.c (_dl_close_worker): Add a parameter to
implement forced object deletion.
(_dl_close): Pass false to _dl_close_worker.
* elf/dl-open.c (_dl_open): Pass true to _dl_close_worker.
* elf/tst-nodelete.cc: New file.
* elf/tst-nodeletelib.cc: Likewise.
* elf/tst-znodeletelib.cc: Likewise.
* include/dlfcn.h (_dl_close_worker): Add a new parameter.
Diffstat (limited to 'elf/Makefile')
-rw-r--r-- | elf/Makefile | 17 |
1 files changed, 15 insertions, 2 deletions
diff --git a/elf/Makefile b/elf/Makefile index f21276c006..bd0f24dd51 100644 --- a/elf/Makefile +++ b/elf/Makefile @@ -132,7 +132,7 @@ tests += $(tests-static) ifeq (yes,$(build-shared)) tests += loadtest restest1 preloadtest loadfail multiload origtest resolvfail \ constload1 order noload filter unload \ - reldep reldep2 reldep3 reldep4 nodelete nodelete2 \ + reldep reldep2 reldep3 reldep4 nodelete nodelete2 tst-nodelete \ nodlopen nodlopen2 neededtest neededtest2 \ neededtest3 neededtest4 unload2 lateglobal initfirst global \ restest2 next dblload dblunload reldep5 reldep6 reldep7 reldep8 \ @@ -207,7 +207,9 @@ modules-names = testobj1 testobj2 testobj3 testobj4 testobj5 testobj6 \ tst-unique1mod1 tst-unique1mod2 \ tst-unique2mod1 tst-unique2mod2 \ tst-auditmod9a tst-auditmod9b \ - $(if $(CXX),tst-unique3lib tst-unique3lib2 tst-unique4lib) \ + $(if $(CXX),tst-unique3lib tst-unique3lib2 tst-unique4lib \ + tst-nodelete-uniquemod) \ + tst-nodelete-rtldmod tst-nodelete-zmod \ tst-initordera1 tst-initorderb1 \ tst-initordera2 tst-initorderb2 \ tst-initordera3 tst-initordera4 \ @@ -591,6 +593,9 @@ ifuncmod5.so-no-z-defs = yes ifuncmod6.so-no-z-defs = yes tst-auditmod9a.so-no-z-defs = yes 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 ifeq ($(build-shared),yes) # Build all the modules even when not actually running test programs. @@ -1153,6 +1158,14 @@ $(objpfx)tst-unique3.out: $(objpfx)tst-unique3lib2.so $(objpfx)tst-unique4: $(objpfx)tst-unique4lib.so +$(objpfx)tst-nodelete: $(libdl) +$(objpfx)tst-nodelete.out: $(objpfx)tst-nodelete-uniquemod.so \ + $(objpfx)tst-nodelete-rtldmod.so \ + $(objpfx)tst-nodelete-zmod.so + +LDFLAGS-tst-nodelete = -rdynamic +LDFLAGS-tst-nodelete-zmod.so = -Wl,--enable-new-dtags,-z,nodelete + $(objpfx)tst-initorder-cmp.out: tst-initorder.exp $(objpfx)tst-initorder.out cmp $^ > $@; \ $(evaluate-test) |