kernel: fix signal race
authorAlan Cox <alan@linux.intel.com>
Thu, 5 Oct 2017 23:06:06 +0000 (00:06 +0100)
committerAlan Cox <alan@linux.intel.com>
Thu, 5 Oct 2017 23:06:06 +0000 (00:06 +0100)
Without this we can have the following occur

kill(pid, foo)
queues signal processing for foo
signal(SIGFOO, SIG_IGN)
executes pending signal and jumps to lala land

Kernel/TODO.md
Kernel/syscall_proc.c

index d595871..ce1014f 100644 (file)
@@ -86,8 +86,10 @@ Other
 -----
 - [IP] Check safety of changes to allow interrupts during swapper
 
-- [ ]  Check we don't have any races of the form
+- [x]  Check we don't have any races of the form
        kill()
                checks signal has handler
        signal(x, SIG_DFL)
                signal serviced
+
+       (We now clear the cached signal in this and the mask case)
index eb37a1b..47fd979 100644 (file)
@@ -476,8 +476,10 @@ arg_t _signal(void)
        retval = (arg_t) udata.u_sigvec[sig];
        if (sig != SIGKILL && sig != SIGSTOP)
                udata.u_sigvec[sig] = func;
+       /* Force recalculation of signal pending in the syscall return path */
+       udata.u_cursig = 0;
        irqrestore(irq);
-
+       
        return (retval);
 
 nogood:
@@ -506,6 +508,8 @@ arg_t _sigdisp(void)
                udata.u_ptab->p_held |= sigmask(sig);
        else
                udata.u_ptab->p_held &= ~sigmask(sig);
+       /* Force recalculation of signal pending in the syscall return path */
+       udata.u_cursig = 0;
        return 0;
 }