diff --git a/ChangeLog b/ChangeLog index 7a8895bcc6..d363be4620 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,13 @@ +2019-02-08 Florian Weimer + + [BZ #24161] + * sysdeps/nptl/fork.h (__run_fork_handlers): Add multiple_threads + argument. + * nptl/register-atfork.c (__run_fork_handlers): Only perform + locking if the new do_locking argument is true. + * sysdeps/nptl/fork.c (__libc_fork): Pass multiple_threads to + __run_fork_handlers. + 2019-02-07 Stefan Liebler [BZ #24180] diff --git a/NEWS b/NEWS index 1f0fc4b3cb..dbcdd48502 100644 --- a/NEWS +++ b/NEWS @@ -11,6 +11,7 @@ The following bugs are resolved with this release: [24155] x32 memcmp can treat positive length as 0 (if sign bit in RDX is set) (CVE-2019-7309) [24164] Systemtap probes need to use "nr" constraint on 32-bit Arm + [24161] __run_fork_handlers self-deadlocks in malloc/tst-mallocfork2 Security related changes: diff --git a/nptl/register-atfork.c b/nptl/register-atfork.c index bc797b761a..80a1becb5f 100644 --- a/nptl/register-atfork.c +++ b/nptl/register-atfork.c @@ -107,13 +107,14 @@ __unregister_atfork (void *dso_handle) } void -__run_fork_handlers (enum __run_fork_handler_type who) +__run_fork_handlers (enum __run_fork_handler_type who, _Bool do_locking) { struct fork_handler *runp; if (who == atfork_run_prepare) { - lll_lock (atfork_lock, LLL_PRIVATE); + if (do_locking) + lll_lock (atfork_lock, LLL_PRIVATE); size_t sl = fork_handler_list_size (&fork_handlers); for (size_t i = sl; i > 0; i--) { @@ -133,7 +134,8 @@ __run_fork_handlers (enum __run_fork_handler_type who) else if (who == atfork_run_parent && runp->parent_handler) runp->parent_handler (); } - lll_unlock (atfork_lock, LLL_PRIVATE); + if (do_locking) + lll_unlock (atfork_lock, LLL_PRIVATE); } } diff --git a/sysdeps/nptl/fork.c b/sysdeps/nptl/fork.c index bd68f18b45..14b69a6f89 100644 --- a/sysdeps/nptl/fork.c +++ b/sysdeps/nptl/fork.c @@ -55,7 +55,7 @@ __libc_fork (void) but our current fork implementation is not. */ bool multiple_threads = THREAD_GETMEM (THREAD_SELF, header.multiple_threads); - __run_fork_handlers (atfork_run_prepare); + __run_fork_handlers (atfork_run_prepare, multiple_threads); /* If we are not running multiple threads, we do not have to preserve lock state. If fork runs from a signal handler, only @@ -134,7 +134,7 @@ __libc_fork (void) __rtld_lock_initialize (GL(dl_load_lock)); /* Run the handlers registered for the child. */ - __run_fork_handlers (atfork_run_child); + __run_fork_handlers (atfork_run_child, multiple_threads); } else { @@ -149,7 +149,7 @@ __libc_fork (void) } /* Run the handlers registered for the parent. */ - __run_fork_handlers (atfork_run_parent); + __run_fork_handlers (atfork_run_parent, multiple_threads); } return pid; diff --git a/sysdeps/nptl/fork.h b/sysdeps/nptl/fork.h index a1c3b26b68..99ed76034b 100644 --- a/sysdeps/nptl/fork.h +++ b/sysdeps/nptl/fork.h @@ -52,9 +52,11 @@ enum __run_fork_handler_type - atfork_run_child: run all the CHILD_HANDLER and unlocks the internal lock. - atfork_run_parent: run all the PARENT_HANDLER and unlocks the internal - lock. */ -extern void __run_fork_handlers (enum __run_fork_handler_type who) - attribute_hidden; + lock. + + Perform locking only if DO_LOCKING. */ +extern void __run_fork_handlers (enum __run_fork_handler_type who, + _Bool do_locking) attribute_hidden; /* C library side function to register new fork handlers. */ extern int __register_atfork (void (*__prepare) (void),