
From: Roland McGrath <roland@redhat.com>

In all my cogitation about signals, I think I've always assumed that the
TIF_SIGPENDING flag is reliably rechecked on the way back to user mode. 
But this is not really true, on i386 and mips at least, in the case when
some signals were just processed.  This not only has the deterministic
problem in the case where an attempt at signal handling itself posts an
additional pending signal, but I believe it has races in general.

When do_notify_resume calls do_signal and thus get_signal_to_deliver, it
will take and release the siglock (at least once) with spin_{,un}lock_irq. 
So, before do_signal returns, it will have reenabled interrupts. 
Interrupts may come in here, either an IPI from another CPU doing
kick_process (from signal_wake_up), or timer or device interrupts posting
timer signals or SIGIO, and set TIF_SIGPENDING.  Since those interrupts
came in kernel mode, their return won't do any signal checks, just pick up
where it was in the return path of do_signal.  However, the return path
from do_notify_resume does not check again for pending work.  So you will
return to user mode with TIF_SIGPENDING set, and not see those signals
until the next time you enter and leave the kernel for some other reason.

So I think the really right fix here is the following, for i386.  The mips
change is similar from what I can see, but I won't presume to write a patch
for mips assembly code.  From a quick look, x86_64, ppc, ppc64 seem to do
this right already, and I didn't try to grok the assembly for other
machines.

Signed-off-by: Roland McGrath <roland@redhat.com>
Acked-by: Ingo Molnar <mingo@elte.hu>
Signed-off-by: Andrew Morton <akpm@osdl.org>
---

 arch/i386/kernel/entry.S |    4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)

diff -puN arch/i386/kernel/entry.S~i386-dont-miss-pending-signals-returning-to-user-mode-after-signal-processing arch/i386/kernel/entry.S
--- devel/arch/i386/kernel/entry.S~i386-dont-miss-pending-signals-returning-to-user-mode-after-signal-processing	2005-09-11 23:49:16.000000000 -0700
+++ devel-akpm/arch/i386/kernel/entry.S	2005-09-11 23:49:16.000000000 -0700
@@ -319,7 +319,7 @@ work_notifysig:				# deal with pending s
 					# vm86-space
 	xorl %edx, %edx
 	call do_notify_resume
-	jmp restore_all
+	jmp resume_userspace
 
 	ALIGN
 work_notifysig_v86:
@@ -329,7 +329,7 @@ work_notifysig_v86:
 	movl %eax, %esp
 	xorl %edx, %edx
 	call do_notify_resume
-	jmp restore_all
+	jmp resume_userspace
 
 	# perform syscall exit tracing
 	ALIGN
_
