From owner-svn-src-head@FreeBSD.ORG Sat Nov 23 15:48:18 2013 Return-Path: Delivered-To: svn-src-head@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 54C0B912; Sat, 23 Nov 2013 15:48:18 +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)) (No client certificate requested) by mx1.freebsd.org (Postfix) with ESMTPS id 3584D2DD3; Sat, 23 Nov 2013 15:48:18 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.7/8.14.7) with ESMTP id rANFmI6e056238; Sat, 23 Nov 2013 15:48:18 GMT (envelope-from kib@svn.freebsd.org) Received: (from kib@localhost) by svn.freebsd.org (8.14.7/8.14.5/Submit) id rANFmHeJ056236; Sat, 23 Nov 2013 15:48:17 GMT (envelope-from kib@svn.freebsd.org) Message-Id: <201311231548.rANFmHeJ056236@svn.freebsd.org> From: Konstantin Belousov Date: Sat, 23 Nov 2013 15:48:17 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r258499 - head/lib/libthr/thread X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.16 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 23 Nov 2013 15:48:18 -0000 Author: kib Date: Sat Nov 23 15:48:17 2013 New Revision: 258499 URL: http://svnweb.freebsd.org/changeset/base/258499 Log: If check_deferred_signal() execution needs binding of PLT symbol, unlocking the rtld bind lock results in the processing of ast and recursing into the check_deferred_signal(). Nested execution of check_deferred_signal() delivers the signal to user code and clears si_signo. On return, top-level check_deferred_signal() frame continues delivering the same signal one more time, but now with zero si_signo. Fix this by adding a flag to indicate that deferred delivery is running, so check_deferred_signal() should avoid doing anything. Since user signal handler is allowed to modify the passed machine context to make return from the signal handler to cause arbitrary jump, or do longjmp(). For this case, also clear the flag in thr_sighandler(), since kernel signal delivery means that nested delivery code should not run right now. Reported by: Vitaly Magerya Reviewed by: davidxu, jilles Tested by: pho Sponsored by: The FreeBSD Foundation MFC after: 1 week Modified: head/lib/libthr/thread/thr_private.h head/lib/libthr/thread/thr_sig.c Modified: head/lib/libthr/thread/thr_private.h ============================================================================== --- head/lib/libthr/thread/thr_private.h Sat Nov 23 14:54:20 2013 (r258498) +++ head/lib/libthr/thread/thr_private.h Sat Nov 23 15:48:17 2013 (r258499) @@ -433,6 +433,9 @@ struct pthread { /* the sigaction should be used for deferred signal. */ struct sigaction deferred_sigact; + /* deferred signal delivery is performed, do not reenter. */ + int deferred_run; + /* Force new thread to exit. */ int force_exit; Modified: head/lib/libthr/thread/thr_sig.c ============================================================================== --- head/lib/libthr/thread/thr_sig.c Sat Nov 23 14:54:20 2013 (r258498) +++ head/lib/libthr/thread/thr_sig.c Sat Nov 23 15:48:17 2013 (r258499) @@ -162,6 +162,7 @@ thr_sighandler(int sig, siginfo_t *info, act = _thr_sigact[sig-1].sigact; _thr_rwl_unlock(&_thr_sigact[sig-1].lock); errno = err; + curthread->deferred_run = 0; /* * if a thread is in critical region, for example it holds low level locks, @@ -320,14 +321,18 @@ check_deferred_signal(struct pthread *cu siginfo_t info; int uc_len; - if (__predict_true(curthread->deferred_siginfo.si_signo == 0)) + if (__predict_true(curthread->deferred_siginfo.si_signo == 0 || + curthread->deferred_run)) return; + curthread->deferred_run = 1; uc_len = __getcontextx_size(); uc = alloca(uc_len); getcontext(uc); - if (curthread->deferred_siginfo.si_signo == 0) + if (curthread->deferred_siginfo.si_signo == 0) { + curthread->deferred_run = 0; return; + } __fillcontextx2((char *)uc); act = curthread->deferred_sigact; uc->uc_sigmask = curthread->deferred_sigmask;