Thu Apr 16 14:39:58 2020 UTC ()
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.


(joerg)
diff -r1.12 -r1.13 src/lib/libc/gen/pthread_atfork.c
diff -r1.203 -r1.204 src/libexec/ld.elf_so/rtld.c
diff -r1.138 -r1.139 src/libexec/ld.elf_so/rtld.h
diff -r1.2 -r1.3 src/libexec/ld.elf_so/symbols.map

cvs diff -r1.12 -r1.13 src/lib/libc/gen/pthread_atfork.c (expand / switch to unified diff)

--- 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
50pid_t __fork(void); /* XXX */ 50pid_t __fork(void); /* XXX */
 51pid_t __atomic_fork(void) __weak; /* XXX */
 52
 53pid_t
 54__atomic_fork(void)
 55{
 56 return __fork();
 57}
51 58
52struct atfork_callback { 59struct 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 */
63static struct atfork_callback atfork_builtin; 70static 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
150pid_t 157pid_t
151fork(void) 158fork(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)();

cvs diff -r1.203 -r1.204 src/libexec/ld.elf_so/rtld.c (expand / switch to unified diff)

--- 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
 1535pid_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 */
1540void 1555void
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);

cvs diff -r1.138 -r1.139 src/libexec/ld.elf_so/rtld.h (expand / switch to unified diff)

--- 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 */
382void _rtld_error(const char *, ...) __printflike(1,2); 384void _rtld_error(const char *, ...) __printflike(1,2);
383void _rtld_die(void) __dead; 385void _rtld_die(void) __dead;
384void *_rtld_objmain_sym(const char *); 386void *_rtld_objmain_sym(const char *);
385__dso_public void _rtld_debug_state(void) __noinline; 387__dso_public void _rtld_debug_state(void) __noinline;

cvs diff -r1.2 -r1.3 src/libexec/ld.elf_so/symbols.map (expand / switch to unified diff)

--- 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};