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.
This commit is contained in:
joerg 2020-04-16 14:39:58 +00:00
parent 4422eacfa3
commit 11954c74b6
4 changed files with 31 additions and 6 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: pthread_atfork.c,v 1.12 2020/02/01 18:14:16 kamil Exp $ */
/* $NetBSD: pthread_atfork.c,v 1.13 2020/04/16 14:39:58 joerg Exp $ */
/*-
* Copyright (c) 2002 The NetBSD Foundation, Inc.
@ -31,7 +31,7 @@
#include <sys/cdefs.h>
#if defined(LIBC_SCCS) && !defined(lint)
__RCSID("$NetBSD: pthread_atfork.c,v 1.12 2020/02/01 18:14:16 kamil Exp $");
__RCSID("$NetBSD: pthread_atfork.c,v 1.13 2020/04/16 14:39:58 joerg Exp $");
#endif /* LIBC_SCCS and not lint */
#include "namespace.h"
@ -48,6 +48,13 @@ __weak_alias(fork, _fork)
#endif /* __weak_alias */
pid_t __fork(void); /* XXX */
pid_t __atomic_fork(void) __weak; /* XXX */
pid_t
__atomic_fork(void)
{
return __fork();
}
struct atfork_callback {
SIMPLEQ_ENTRY(atfork_callback) next;
@ -157,7 +164,7 @@ fork(void)
SIMPLEQ_FOREACH(iter, &prepareq, next)
(*iter->fn)();
ret = __fork();
ret = __atomic_fork();
if (ret != 0) {
/*

View File

@ -1,4 +1,4 @@
/* $NetBSD: rtld.c,v 1.203 2020/03/04 01:21:17 thorpej Exp $ */
/* $NetBSD: rtld.c,v 1.204 2020/04/16 14:39:58 joerg Exp $ */
/*
* Copyright 1996 John D. Polstra.
@ -40,7 +40,7 @@
#include <sys/cdefs.h>
#ifndef lint
__RCSID("$NetBSD: rtld.c,v 1.203 2020/03/04 01:21:17 thorpej Exp $");
__RCSID("$NetBSD: rtld.c,v 1.204 2020/04/16 14:39:58 joerg Exp $");
#endif /* not lint */
#include <sys/param.h>
@ -1532,6 +1532,21 @@ __dl_cxa_refcount(void *addr, ssize_t delta)
_rtld_exclusive_exit(&mask);
}
pid_t __fork(void);
__dso_public pid_t
__atomic_fork(void)
{
sigset_t mask;
pid_t result;
_rtld_exclusive_enter(&mask);
result = __fork();
_rtld_exclusive_exit(&mask);
return result;
}
/*
* Error reporting function. Use it like printf. If formats the message
* into a buffer, and sets things up so that the next call to dlerror()

View File

@ -1,4 +1,4 @@
/* $NetBSD: rtld.h,v 1.138 2020/02/29 04:24:33 kamil Exp $ */
/* $NetBSD: rtld.h,v 1.139 2020/04/16 14:39:58 joerg Exp $ */
/*
* Copyright 1996 John D. Polstra.
@ -370,6 +370,8 @@ __dso_public int dl_iterate_phdr(int (*)(struct dl_phdr_info *, size_t, void *),
__dso_public void *_dlauxinfo(void) __pure;
__dso_public void __dl_cxa_refcount(void *addr, ssize_t delta);
__dso_public pid_t __atomic_fork(void);
#if defined(__ARM_EABI__) && !defined(__ARM_DWARF_EH__)
/*
* This is used by libgcc to find the start and length of the exception table

View File

@ -23,5 +23,6 @@
___tls_get_addr;
__gnu_Unwind_Find_exidx;
__dl_cxa_refcount;
__atomic_fork;
local: *;
};