From d41cec56d5c04d88aa2d06986b692cd1fa279748 Mon Sep 17 00:00:00 2001 From: Waldemar Brodkorb Date: Sun, 3 Jan 2016 19:44:54 +0100 Subject: pthread_atfork handlers not removed during dlclose Invoke pthread_atfork handler cleanup when removing the associated DSO... If a program loads a DSO (dlopen) that sets up a pthread_atfork handler(s), and then subsequently closes the DSO, the handler(s) are left in place. If fork() is subsequently called, the handlers are invoked even though the DSO has been removed causing crashes or unpredictable code execution. This is because the code in __cxa_finalize(atexit.c)to invoke the unregister_atfork() routine is ifdef'd out with the comment that it hasn't been "looked into this yet...". Refs.: http://bugs.busybox.net/show_bug.cgi?id=8211 http://sourceware.org/bugzilla/show_bug.cgi?id=13502 Add test-case, enable cleanup for NPTL only. Signed-off-by: John Ata Signed-off-by: Leonid Lisovskiy --- test/nptl/Makefile.in | 8 +++++++- test/nptl/libatfork.c | 27 +++++++++++++++++++++++++++ test/nptl/tst-atfork2.c | 24 ++++++++++++++++++++++++ 3 files changed, 58 insertions(+), 1 deletion(-) create mode 100644 test/nptl/libatfork.c create mode 100644 test/nptl/tst-atfork2.c (limited to 'test') diff --git a/test/nptl/Makefile.in b/test/nptl/Makefile.in index 09e2804a6..ac2aa8b1e 100644 --- a/test/nptl/Makefile.in +++ b/test/nptl/Makefile.in @@ -42,7 +42,8 @@ TESTS := tst-align tst-align2 tst-atfork1 tst-attr1 tst-attr2 tst-attr3 \ tst-oddstacklimit tst-oncex3 tst-oncex4 tst-rwlock2a \ tst-basic7 tst-signal7 tst-vfork1x tst-vfork2x tst-sem10 tst-sem11 \ tst-sem12 tst-typesizes tst-initializers1-c89 tst-initializers1-c99 \ - tst-initializers1-gnu89 tst-initializers1-gnu99 + tst-initializers1-gnu89 tst-initializers1-gnu99 \ + tst-atfork2 # # These are for the RT library and POSIX timers. @@ -151,6 +152,8 @@ CFLAGS_tst-initializers1-gnu99 = $(CFLAGS-tst-initializers1) -std=gnu99 EXTRA_LDFLAGS = $(if $(findstring -lpthread,$(LDFLAGS_$@)),,-lpthread) +LDFLAGS_tst-atfork2 := -ldl +LDFLAGS_libatfork.so := -shared -static-libgcc -lpthread LDFLAGS_tst-cleanup4 := tst-cleanup4aux.o LDFLAGS_tst-cleanupx4 := tst-cleanup4aux.o LDFLAGS_tst-clock2 := -lrt @@ -207,6 +210,9 @@ tst-tls5: tst-tls5mod.so tst-cleanupx4 : tst-cleanup4aux.o tst-fini1: tst-fini1mod.so +tst-atfork2: libatfork.so +tst-atfork2_glibc: libatfork.so.glibc + OPTS_tst-cancel7 = -c ./tst-cancel7 OPTS_tst-mqueue7 = -- ./tst-mqueue7 OPTS_tst-exec4 = ./tst-exec4 diff --git a/test/nptl/libatfork.c b/test/nptl/libatfork.c new file mode 100644 index 000000000..f4ddca057 --- /dev/null +++ b/test/nptl/libatfork.c @@ -0,0 +1,27 @@ +#include +#include + +static void atfork_prepare(void) +{ + /* nothing to do */ +} + +static void atfork_parent(void) +{ + /* nothing to do */ +} + +static void atfork_child(void) +{ + /* nothing to do */ +} + +static __attribute__((constructor)) void init(void) +{ + pthread_atfork(atfork_prepare, atfork_parent, atfork_child); +} + +static __attribute__((destructor)) void done(void) +{ + /* nothing to do */ +} diff --git a/test/nptl/tst-atfork2.c b/test/nptl/tst-atfork2.c new file mode 100644 index 000000000..1c303de63 --- /dev/null +++ b/test/nptl/tst-atfork2.c @@ -0,0 +1,24 @@ +#include +#include +#include + +int main(int argc, char *argv[]) +{ + void *h; + pid_t pid; + + h = dlopen("libatfork.so", RTLD_NOW); + if (!h) + { + printf("Failed to open libatfork.so\n"); + return 1; + } + dlclose(h); + + if ((pid = fork()) < 0) { + printf("Fork failed\n"); + return 1; + } + + return 0; +} -- cgit v1.2.3