svn commit: r258499 - head/lib/libthr/thread

Konstantin Belousov kib at FreeBSD.org
Sat Nov 23 15:48:18 UTC 2013


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 <vmagerya at gmail.com>
  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;


More information about the svn-src-all mailing list