[2.6.26 PATCH] BZ#469684 utrace: make sure utrace_report_syscall_entry() can't lose TIF_SIGPENDING

Oleg Nesterov oleg at redhat.com
Mon Dec 1 00:56:11 UTC 2008


(apologies to all, re-send to fedora-kernel-list at redhat.com)

(the patch targets 2.6.26 fedora kernels, don't know what should be
 in SUBJECT).

See https://bugzilla.redhat.com/show_bug.cgi?id=469684

utrace_report_syscall_entry() must recalc_sigpending() unconditionally.
While we slept in TASK_TRACED the new signals can be queued, but in that
case TIF_SIGPENDING is not set. See the (correct) task_is_stopped_or_traced()
check in wants_signal().

Signed-off-by: Oleg Nesterov <oleg at redhat.com>

--- linux-2.6.26.x86_64/kernel/utrace.c~UTRACE_SIGLOST	2008-10-09 17:47:14.000000000 +0200
+++ linux-2.6.26.x86_64/kernel/utrace.c	2008-11-30 23:15:33.000000000 +0100
@@ -1383,20 +1383,21 @@ bool utrace_report_syscall_entry(struct 
 	if (unlikely(report.result == UTRACE_SYSCALL_ABORT))
 		return true;
 
-	if (signal_pending(task)) {
-		/*
-		 * Clear TIF_SIGPENDING if it no longer needs to be set.
-		 * It may have been set as part of quiescence, and won't
-		 * ever have been cleared by another thread.  For other
-		 * reports, we can just leave it set and will go through
-		 * utrace_get_signal() to reset things.  But here we are
-		 * about to enter a syscall, which might bail out with an
-		 * -ERESTART* error if it's set now.
-		 */
-		spin_lock_irq(&task->sighand->siglock);
-		recalc_sigpending();
-		spin_unlock_irq(&task->sighand->siglock);
-	}
+	/*
+	 * Clear TIF_SIGPENDING if it no longer needs to be set.
+	 * It may have been set as part of quiescence, and won't
+	 * ever have been cleared by another thread.  For other
+	 * reports, we can just leave it set and will go through
+	 * utrace_get_signal() to reset things.  But here we are
+	 * about to enter a syscall, which might bail out with an
+	 * -ERESTART* error if it's set now.
+	 *
+	 * Or, set TIF_SIGPENDING if the signal was queued while
+	 * we were stopped in TASK_TRACED.
+	 */
+	spin_lock_irq(&task->sighand->siglock);
+	recalc_sigpending();
+	spin_unlock_irq(&task->sighand->siglock);
 
 	return false;
 }




More information about the kernel mailing list