This fixes rr. It doesn't quite fix the provided testcase, because the testcase 
fails to wait on the tracee after awakening from the nanosleep. Instead the 
testcase immediately does a PTHREAD_CONT, discarding the PTHREAD_EVENT_EXIT. 
The slightly modified testcase at 
https://gist.github.com/khuey/3c43ac247c72cef8c956c does pass.

I don't see any obvious way to dequeue only the fatal signal, so instead I 
dequeue them all. Since none of these signals will ever be delivered it 
shouldn't affect the executing task.

Suggested-by: Robert O'Callahan <[email protected]>
Signed-off-by: Kyle Huey <[email protected]>
---
 kernel/seccomp.c | 14 +++++++++++++-
 1 file changed, 13 insertions(+), 1 deletion(-)

diff --git a/kernel/seccomp.c b/kernel/seccomp.c
index ef6c6c3..728074d 100644
--- a/kernel/seccomp.c
+++ b/kernel/seccomp.c
@@ -609,8 +609,20 @@ static int __seccomp_filter(int this_syscall, const struct 
seccomp_data *sd,
                 * Terminating the task now avoids executing a system
                 * call that may not be intended.
                 */
-               if (fatal_signal_pending(current))
+               if (fatal_signal_pending(current)) {
+                       /*
+                        * Swallow the signals we will never deliver.
+                        * If we do not do this, the PTRACE_EVENT_EXIT will
+                        * be suppressed by those signals.
+                        */
+                       siginfo_t info;
+
+                       spin_lock_irq(&current->sighand->siglock);
+                       while (dequeue_signal(current, &current->blocked, 
&info));
+                       spin_unlock_irq(&current->sighand->siglock);
+
                        do_exit(SIGSYS);
+               }
                /* Check if the tracer forced the syscall to be skipped. */
                this_syscall = syscall_get_nr(current, task_pt_regs(current));
                if (this_syscall < 0)
-- 
2.7.4

Reply via email to