From owner-svn-src-all@FreeBSD.ORG Sat Jun 7 02:45:25 2014 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [8.8.178.115]) (using TLSv1 with cipher ADH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id 7B7FC1CD; Sat, 7 Jun 2014 02:45:25 +0000 (UTC) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 680752DFB; Sat, 7 Jun 2014 02:45:25 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.8/8.14.8) with ESMTP id s572jPtk020847; Sat, 7 Jun 2014 02:45:25 GMT (envelope-from kib@svn.freebsd.org) Received: (from kib@localhost) by svn.freebsd.org (8.14.8/8.14.8/Submit) id s572jONL020842; Sat, 7 Jun 2014 02:45:24 GMT (envelope-from kib@svn.freebsd.org) Message-Id: <201406070245.s572jONL020842@svn.freebsd.org> From: Konstantin Belousov Date: Sat, 7 Jun 2014 02:45:24 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-10@freebsd.org Subject: svn commit: r267200 - in stable/10: lib/libthr/thread libexec/rtld-elf X-SVN-Group: stable-10 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 07 Jun 2014 02:45:25 -0000 Author: kib Date: Sat Jun 7 02:45:24 2014 New Revision: 267200 URL: http://svnweb.freebsd.org/changeset/base/267200 Log: MFC r266609: Change the _rtld_atfork() to lock the bind lock in write mode. Modified: stable/10/lib/libthr/thread/thr_fork.c stable/10/lib/libthr/thread/thr_rtld.c stable/10/libexec/rtld-elf/rtld_lock.c Directory Properties: stable/10/ (props changed) Modified: stable/10/lib/libthr/thread/thr_fork.c ============================================================================== --- stable/10/lib/libthr/thread/thr_fork.c Sat Jun 7 02:38:13 2014 (r267199) +++ stable/10/lib/libthr/thread/thr_fork.c Sat Jun 7 02:45:24 2014 (r267200) @@ -57,6 +57,7 @@ * */ +#include #include "namespace.h" #include #include @@ -174,8 +175,15 @@ _fork(void) was_threaded = 0; } - /* Fork a new process: */ - if ((ret = __sys_fork()) == 0) { + /* + * Fork a new process. + * There is no easy way to pre-resolve the __sys_fork symbol + * without performing the fork. Use the syscall(2) + * indirection, the syscall symbol is resolved in + * _thr_rtld_init() with side-effect free call. + */ + ret = syscall(SYS_fork); + if (ret == 0) { /* Child process */ errsave = errno; curthread->cancel_pending = 0; @@ -250,6 +258,5 @@ _fork(void) } errno = errsave; - /* Return the process ID: */ return (ret); } Modified: stable/10/lib/libthr/thread/thr_rtld.c ============================================================================== --- stable/10/lib/libthr/thread/thr_rtld.c Sat Jun 7 02:38:13 2014 (r267199) +++ stable/10/lib/libthr/thread/thr_rtld.c Sat Jun 7 02:45:24 2014 (r267200) @@ -32,10 +32,12 @@ */ #include #include +#include #include #include #include +#include "libc_private.h" #include "rtld_lock.h" #include "thr_private.h" @@ -207,7 +209,24 @@ _thr_rtld_init(void) li.thread_set_flag = _thr_rtld_set_flag; li.thread_clr_flag = _thr_rtld_clr_flag; li.at_fork = NULL; - + + /* + * Preresolve the symbols needed for the fork interposer. We + * call _rtld_atfork_pre() and _rtld_atfork_post() with NULL + * argument to indicate that no actual locking inside the + * functions should happen. Neither rtld compat locks nor + * libthr rtld locks cannot work there: + * - compat locks do not handle the case of two locks taken + * in write mode (the signal mask for the thread is corrupted); + * - libthr locks would work, but locked rtld_bind_lock prevents + * symbol resolution for _rtld_atfork_post. + */ + _rtld_atfork_pre(NULL); + _rtld_atfork_post(NULL); + _malloc_prefork(); + _malloc_postfork(); + syscall(SYS_getpid); + /* mask signals, also force to resolve __sys_sigprocmask PLT */ _thr_signal_block(curthread); _rtld_thread_init(&li); Modified: stable/10/libexec/rtld-elf/rtld_lock.c ============================================================================== --- stable/10/libexec/rtld-elf/rtld_lock.c Sat Jun 7 02:38:13 2014 (r267199) +++ stable/10/libexec/rtld-elf/rtld_lock.c Sat Jun 7 02:45:24 2014 (r267200) @@ -365,8 +365,19 @@ _rtld_atfork_pre(int *locks) { RtldLockState ls[2]; + if (locks == NULL) + return; + + /* + * Warning: this does not work with the rtld compat locks + * above, since the thread signal mask is corrupted (set to + * all signals blocked) if two locks are taken in write mode. + * The caller of the _rtld_atfork_pre() must provide the + * working implementation of the locks, and libthr locks are + * fine. + */ wlock_acquire(rtld_phdr_lock, &ls[0]); - rlock_acquire(rtld_bind_lock, &ls[1]); + wlock_acquire(rtld_bind_lock, &ls[1]); /* XXXKIB: I am really sorry for this. */ locks[0] = ls[1].lockstate; @@ -378,6 +389,9 @@ _rtld_atfork_post(int *locks) { RtldLockState ls[2]; + if (locks == NULL) + return; + bzero(ls, sizeof(ls)); ls[0].lockstate = locks[2]; ls[1].lockstate = locks[0];