Introduce intermediate locking for fork, so that the dynamic linker is in a consistent state. This most importantly avoids races between dlopen and friends and fork, potentially resulting in dead locks in the child when it itself tries to acquire locks.diff -r1.12 -r1.13 src/lib/libc/gen/pthread_atfork.c
(joerg)
--- src/lib/libc/gen/pthread_atfork.c 2020/02/01 18:14:16 1.12
+++ src/lib/libc/gen/pthread_atfork.c 2020/04/16 14:39:58 1.13
@@ -1,14 +1,14 @@ | @@ -1,14 +1,14 @@ | |||
1 | /* $NetBSD: pthread_atfork.c,v 1.12 2020/02/01 18:14:16 kamil Exp $ */ | 1 | /* $NetBSD: pthread_atfork.c,v 1.13 2020/04/16 14:39:58 joerg Exp $ */ | |
2 | 2 | |||
3 | /*- | 3 | /*- | |
4 | * Copyright (c) 2002 The NetBSD Foundation, Inc. | 4 | * Copyright (c) 2002 The NetBSD Foundation, Inc. | |
5 | * All rights reserved. | 5 | * All rights reserved. | |
6 | * | 6 | * | |
7 | * This code is derived from software contributed to The NetBSD Foundation | 7 | * This code is derived from software contributed to The NetBSD Foundation | |
8 | * by Nathan J. Williams. | 8 | * by Nathan J. Williams. | |
9 | * | 9 | * | |
10 | * Redistribution and use in source and binary forms, with or without | 10 | * Redistribution and use in source and binary forms, with or without | |
11 | * modification, are permitted provided that the following conditions | 11 | * modification, are permitted provided that the following conditions | |
12 | * are met: | 12 | * are met: | |
13 | * 1. Redistributions of source code must retain the above copyright | 13 | * 1. Redistributions of source code must retain the above copyright | |
14 | * notice, this list of conditions and the following disclaimer. | 14 | * notice, this list of conditions and the following disclaimer. | |
@@ -21,43 +21,50 @@ | @@ -21,43 +21,50 @@ | |||
21 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | 21 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
22 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | 22 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | |
23 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | 23 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |
24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | 24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | |
25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | 25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |
26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | 26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | |
27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | 28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
29 | * POSSIBILITY OF SUCH DAMAGE. | 29 | * POSSIBILITY OF SUCH DAMAGE. | |
30 | */ | 30 | */ | |
31 | 31 | |||
32 | #include <sys/cdefs.h> | 32 | #include <sys/cdefs.h> | |
33 | #if defined(LIBC_SCCS) && !defined(lint) | 33 | #if defined(LIBC_SCCS) && !defined(lint) | |
34 | __RCSID("$NetBSD: pthread_atfork.c,v 1.12 2020/02/01 18:14:16 kamil Exp $"); | 34 | __RCSID("$NetBSD: pthread_atfork.c,v 1.13 2020/04/16 14:39:58 joerg Exp $"); | |
35 | #endif /* LIBC_SCCS and not lint */ | 35 | #endif /* LIBC_SCCS and not lint */ | |
36 | 36 | |||
37 | #include "namespace.h" | 37 | #include "namespace.h" | |
38 | 38 | |||
39 | #include <errno.h> | 39 | #include <errno.h> | |
40 | #include <stdlib.h> | 40 | #include <stdlib.h> | |
41 | #include <unistd.h> | 41 | #include <unistd.h> | |
42 | #include <sys/queue.h> | 42 | #include <sys/queue.h> | |
43 | #include "reentrant.h" | 43 | #include "reentrant.h" | |
44 | 44 | |||
45 | #ifdef __weak_alias | 45 | #ifdef __weak_alias | |
46 | __weak_alias(pthread_atfork, _pthread_atfork) | 46 | __weak_alias(pthread_atfork, _pthread_atfork) | |
47 | __weak_alias(fork, _fork) | 47 | __weak_alias(fork, _fork) | |
48 | #endif /* __weak_alias */ | 48 | #endif /* __weak_alias */ | |
49 | 49 | |||
50 | pid_t __fork(void); /* XXX */ | 50 | pid_t __fork(void); /* XXX */ | |
51 | pid_t __atomic_fork(void) __weak; /* XXX */ | |||
52 | ||||
53 | pid_t | |||
54 | __atomic_fork(void) | |||
55 | { | |||
56 | return __fork(); | |||
57 | } | |||
51 | 58 | |||
52 | struct atfork_callback { | 59 | struct atfork_callback { | |
53 | SIMPLEQ_ENTRY(atfork_callback) next; | 60 | SIMPLEQ_ENTRY(atfork_callback) next; | |
54 | void (*fn)(void); | 61 | void (*fn)(void); | |
55 | }; | 62 | }; | |
56 | 63 | |||
57 | /* | 64 | /* | |
58 | * Hypothetically, we could protect the queues with a rwlock which is | 65 | * Hypothetically, we could protect the queues with a rwlock which is | |
59 | * write-locked by pthread_atfork() and read-locked by fork(), but | 66 | * write-locked by pthread_atfork() and read-locked by fork(), but | |
60 | * since the intended use of the functions is obtaining locks to hold | 67 | * since the intended use of the functions is obtaining locks to hold | |
61 | * across the fork, forking is going to be serialized anyway. | 68 | * across the fork, forking is going to be serialized anyway. | |
62 | */ | 69 | */ | |
63 | static struct atfork_callback atfork_builtin; | 70 | static struct atfork_callback atfork_builtin; | |
@@ -147,27 +154,27 @@ pthread_atfork(void (*prepare)(void), vo | @@ -147,27 +154,27 @@ pthread_atfork(void (*prepare)(void), vo | |||
147 | return 0; | 154 | return 0; | |
148 | } | 155 | } | |
149 | 156 | |||
150 | pid_t | 157 | pid_t | |
151 | fork(void) | 158 | fork(void) | |
152 | { | 159 | { | |
153 | struct atfork_callback *iter; | 160 | struct atfork_callback *iter; | |
154 | pid_t ret; | 161 | pid_t ret; | |
155 | 162 | |||
156 | mutex_lock(&atfork_lock); | 163 | mutex_lock(&atfork_lock); | |
157 | SIMPLEQ_FOREACH(iter, &prepareq, next) | 164 | SIMPLEQ_FOREACH(iter, &prepareq, next) | |
158 | (*iter->fn)(); | 165 | (*iter->fn)(); | |
159 | 166 | |||
160 | ret = __fork(); | 167 | ret = __atomic_fork(); | |
161 | 168 | |||
162 | if (ret != 0) { | 169 | if (ret != 0) { | |
163 | /* | 170 | /* | |
164 | * We are the parent. It doesn't matter here whether | 171 | * We are the parent. It doesn't matter here whether | |
165 | * the fork call succeeded or failed. | 172 | * the fork call succeeded or failed. | |
166 | */ | 173 | */ | |
167 | SIMPLEQ_FOREACH(iter, &parentq, next) | 174 | SIMPLEQ_FOREACH(iter, &parentq, next) | |
168 | (*iter->fn)(); | 175 | (*iter->fn)(); | |
169 | mutex_unlock(&atfork_lock); | 176 | mutex_unlock(&atfork_lock); | |
170 | } else { | 177 | } else { | |
171 | /* We are the child */ | 178 | /* We are the child */ | |
172 | SIMPLEQ_FOREACH(iter, &childq, next) | 179 | SIMPLEQ_FOREACH(iter, &childq, next) | |
173 | (*iter->fn)(); | 180 | (*iter->fn)(); |
--- src/libexec/ld.elf_so/rtld.c 2020/03/04 01:21:17 1.203
+++ src/libexec/ld.elf_so/rtld.c 2020/04/16 14:39:58 1.204
@@ -1,14 +1,14 @@ | @@ -1,14 +1,14 @@ | |||
1 | /* $NetBSD: rtld.c,v 1.203 2020/03/04 01:21:17 thorpej Exp $ */ | 1 | /* $NetBSD: rtld.c,v 1.204 2020/04/16 14:39:58 joerg Exp $ */ | |
2 | 2 | |||
3 | /* | 3 | /* | |
4 | * Copyright 1996 John D. Polstra. | 4 | * Copyright 1996 John D. Polstra. | |
5 | * Copyright 1996 Matt Thomas <matt@3am-software.com> | 5 | * Copyright 1996 Matt Thomas <matt@3am-software.com> | |
6 | * Copyright 2002 Charles M. Hannum <root@ihack.net> | 6 | * Copyright 2002 Charles M. Hannum <root@ihack.net> | |
7 | * All rights reserved. | 7 | * All rights reserved. | |
8 | * | 8 | * | |
9 | * Redistribution and use in source and binary forms, with or without | 9 | * Redistribution and use in source and binary forms, with or without | |
10 | * modification, are permitted provided that the following conditions | 10 | * modification, are permitted provided that the following conditions | |
11 | * are met: | 11 | * are met: | |
12 | * 1. Redistributions of source code must retain the above copyright | 12 | * 1. Redistributions of source code must retain the above copyright | |
13 | * notice, this list of conditions and the following disclaimer. | 13 | * notice, this list of conditions and the following disclaimer. | |
14 | * 2. Redistributions in binary form must reproduce the above copyright | 14 | * 2. Redistributions in binary form must reproduce the above copyright | |
@@ -30,27 +30,27 @@ | @@ -30,27 +30,27 @@ | |||
30 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 30 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
31 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | 31 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | |
32 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 32 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
33 | */ | 33 | */ | |
34 | 34 | |||
35 | /* | 35 | /* | |
36 | * Dynamic linker for ELF. | 36 | * Dynamic linker for ELF. | |
37 | * | 37 | * | |
38 | * John Polstra <jdp@polstra.com>. | 38 | * John Polstra <jdp@polstra.com>. | |
39 | */ | 39 | */ | |
40 | 40 | |||
41 | #include <sys/cdefs.h> | 41 | #include <sys/cdefs.h> | |
42 | #ifndef lint | 42 | #ifndef lint | |
43 | __RCSID("$NetBSD: rtld.c,v 1.203 2020/03/04 01:21:17 thorpej Exp $"); | 43 | __RCSID("$NetBSD: rtld.c,v 1.204 2020/04/16 14:39:58 joerg Exp $"); | |
44 | #endif /* not lint */ | 44 | #endif /* not lint */ | |
45 | 45 | |||
46 | #include <sys/param.h> | 46 | #include <sys/param.h> | |
47 | #include <sys/atomic.h> | 47 | #include <sys/atomic.h> | |
48 | #include <sys/mman.h> | 48 | #include <sys/mman.h> | |
49 | #include <err.h> | 49 | #include <err.h> | |
50 | #include <errno.h> | 50 | #include <errno.h> | |
51 | #include <fcntl.h> | 51 | #include <fcntl.h> | |
52 | #include <lwp.h> | 52 | #include <lwp.h> | |
53 | #include <stdarg.h> | 53 | #include <stdarg.h> | |
54 | #include <stdio.h> | 54 | #include <stdio.h> | |
55 | #include <stdlib.h> | 55 | #include <stdlib.h> | |
56 | #include <string.h> | 56 | #include <string.h> | |
@@ -1522,26 +1522,41 @@ __dl_cxa_refcount(void *addr, ssize_t de | @@ -1522,26 +1522,41 @@ __dl_cxa_refcount(void *addr, ssize_t de | |||
1522 | ++obj->refcount; | 1522 | ++obj->refcount; | |
1523 | obj->cxa_refcount += delta; | 1523 | obj->cxa_refcount += delta; | |
1524 | dbg(("new reference count: %zu", obj->cxa_refcount)); | 1524 | dbg(("new reference count: %zu", obj->cxa_refcount)); | |
1525 | if (obj->cxa_refcount == 0) { | 1525 | if (obj->cxa_refcount == 0) { | |
1526 | --obj->refcount; | 1526 | --obj->refcount; | |
1527 | if (obj->refcount == 0) | 1527 | if (obj->refcount == 0) | |
1528 | _rtld_unload_object(&mask, obj, true); | 1528 | _rtld_unload_object(&mask, obj, true); | |
1529 | } | 1529 | } | |
1530 | } | 1530 | } | |
1531 | 1531 | |||
1532 | _rtld_exclusive_exit(&mask); | 1532 | _rtld_exclusive_exit(&mask); | |
1533 | } | 1533 | } | |
1534 | 1534 | |||
1535 | pid_t __fork(void); | |||
1536 | ||||
1537 | __dso_public pid_t | |||
1538 | __atomic_fork(void) | |||
1539 | { | |||
1540 | sigset_t mask; | |||
1541 | pid_t result; | |||
1542 | ||||
1543 | _rtld_exclusive_enter(&mask); | |||
1544 | result = __fork(); | |||
1545 | _rtld_exclusive_exit(&mask); | |||
1546 | ||||
1547 | return result; | |||
1548 | } | |||
1549 | ||||
1535 | /* | 1550 | /* | |
1536 | * Error reporting function. Use it like printf. If formats the message | 1551 | * Error reporting function. Use it like printf. If formats the message | |
1537 | * into a buffer, and sets things up so that the next call to dlerror() | 1552 | * into a buffer, and sets things up so that the next call to dlerror() | |
1538 | * will return the message. | 1553 | * will return the message. | |
1539 | */ | 1554 | */ | |
1540 | void | 1555 | void | |
1541 | _rtld_error(const char *fmt,...) | 1556 | _rtld_error(const char *fmt,...) | |
1542 | { | 1557 | { | |
1543 | static char buf[512]; | 1558 | static char buf[512]; | |
1544 | va_list ap; | 1559 | va_list ap; | |
1545 | 1560 | |||
1546 | va_start(ap, fmt); | 1561 | va_start(ap, fmt); | |
1547 | xvsnprintf(buf, sizeof buf, fmt, ap); | 1562 | xvsnprintf(buf, sizeof buf, fmt, ap); |
--- src/libexec/ld.elf_so/rtld.h 2020/02/29 04:24:33 1.138
+++ src/libexec/ld.elf_so/rtld.h 2020/04/16 14:39:58 1.139
@@ -1,14 +1,14 @@ | @@ -1,14 +1,14 @@ | |||
1 | /* $NetBSD: rtld.h,v 1.138 2020/02/29 04:24:33 kamil Exp $ */ | 1 | /* $NetBSD: rtld.h,v 1.139 2020/04/16 14:39:58 joerg Exp $ */ | |
2 | 2 | |||
3 | /* | 3 | /* | |
4 | * Copyright 1996 John D. Polstra. | 4 | * Copyright 1996 John D. Polstra. | |
5 | * Copyright 1996 Matt Thomas <matt@3am-software.com> | 5 | * Copyright 1996 Matt Thomas <matt@3am-software.com> | |
6 | * All rights reserved. | 6 | * All rights reserved. | |
7 | * | 7 | * | |
8 | * Redistribution and use in source and binary forms, with or without | 8 | * Redistribution and use in source and binary forms, with or without | |
9 | * modification, are permitted provided that the following conditions | 9 | * modification, are permitted provided that the following conditions | |
10 | * are met: | 10 | * are met: | |
11 | * 1. Redistributions of source code must retain the above copyright | 11 | * 1. Redistributions of source code must retain the above copyright | |
12 | * notice, this list of conditions and the following disclaimer. | 12 | * notice, this list of conditions and the following disclaimer. | |
13 | * 2. Redistributions in binary form must reproduce the above copyright | 13 | * 2. Redistributions in binary form must reproduce the above copyright | |
14 | * notice, this list of conditions and the following disclaimer in the | 14 | * notice, this list of conditions and the following disclaimer in the | |
@@ -360,26 +360,28 @@ extern u_int _rtld_objgen; | @@ -360,26 +360,28 @@ extern u_int _rtld_objgen; | |||
360 | /* rtld.c */ | 360 | /* rtld.c */ | |
361 | __dso_public char *dlerror(void); | 361 | __dso_public char *dlerror(void); | |
362 | __dso_public void *dlopen(const char *, int); | 362 | __dso_public void *dlopen(const char *, int); | |
363 | __dso_public void *dlsym(void *, const char *); | 363 | __dso_public void *dlsym(void *, const char *); | |
364 | __dso_public int dlclose(void *); | 364 | __dso_public int dlclose(void *); | |
365 | __dso_public int dladdr(const void *, Dl_info *); | 365 | __dso_public int dladdr(const void *, Dl_info *); | |
366 | __dso_public int dlinfo(void *, int, void *); | 366 | __dso_public int dlinfo(void *, int, void *); | |
367 | __dso_public int dl_iterate_phdr(int (*)(struct dl_phdr_info *, size_t, void *), | 367 | __dso_public int dl_iterate_phdr(int (*)(struct dl_phdr_info *, size_t, void *), | |
368 | void *); | 368 | void *); | |
369 | 369 | |||
370 | __dso_public void *_dlauxinfo(void) __pure; | 370 | __dso_public void *_dlauxinfo(void) __pure; | |
371 | __dso_public void __dl_cxa_refcount(void *addr, ssize_t delta); | 371 | __dso_public void __dl_cxa_refcount(void *addr, ssize_t delta); | |
372 | 372 | |||
373 | __dso_public pid_t __atomic_fork(void); | |||
374 | ||||
373 | #if defined(__ARM_EABI__) && !defined(__ARM_DWARF_EH__) | 375 | #if defined(__ARM_EABI__) && !defined(__ARM_DWARF_EH__) | |
374 | /* | 376 | /* | |
375 | * This is used by libgcc to find the start and length of the exception table | 377 | * This is used by libgcc to find the start and length of the exception table | |
376 | * associated with a PC. | 378 | * associated with a PC. | |
377 | */ | 379 | */ | |
378 | __dso_public _Unwind_Ptr __gnu_Unwind_Find_exidx(_Unwind_Ptr, int *); | 380 | __dso_public _Unwind_Ptr __gnu_Unwind_Find_exidx(_Unwind_Ptr, int *); | |
379 | #endif | 381 | #endif | |
380 | 382 | |||
381 | /* These aren't exported */ | 383 | /* These aren't exported */ | |
382 | void _rtld_error(const char *, ...) __printflike(1,2); | 384 | void _rtld_error(const char *, ...) __printflike(1,2); | |
383 | void _rtld_die(void) __dead; | 385 | void _rtld_die(void) __dead; | |
384 | void *_rtld_objmain_sym(const char *); | 386 | void *_rtld_objmain_sym(const char *); | |
385 | __dso_public void _rtld_debug_state(void) __noinline; | 387 | __dso_public void _rtld_debug_state(void) __noinline; |
--- src/libexec/ld.elf_so/symbols.map 2017/07/11 15:21:35 1.2
+++ src/libexec/ld.elf_so/symbols.map 2020/04/16 14:39:58 1.3
@@ -13,15 +13,16 @@ | @@ -13,15 +13,16 @@ | |||
13 | dladdr; | 13 | dladdr; | |
14 | __dladdr; | 14 | __dladdr; | |
15 | dlinfo; | 15 | dlinfo; | |
16 | __dlinfo; | 16 | __dlinfo; | |
17 | dl_iterate_phdr; | 17 | dl_iterate_phdr; | |
18 | ____dl_iterate_phdr; | 18 | ____dl_iterate_phdr; | |
19 | _dlauxinfo; | 19 | _dlauxinfo; | |
20 | _rtld_tls_allocate; | 20 | _rtld_tls_allocate; | |
21 | _rtld_tls_free; | 21 | _rtld_tls_free; | |
22 | __tls_get_addr; | 22 | __tls_get_addr; | |
23 | ___tls_get_addr; | 23 | ___tls_get_addr; | |
24 | __gnu_Unwind_Find_exidx; | 24 | __gnu_Unwind_Find_exidx; | |
25 | __dl_cxa_refcount; | 25 | __dl_cxa_refcount; | |
26 | __atomic_fork; | |||
26 | local: *; | 27 | local: *; | |
27 | }; | 28 | }; |