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(¤t->sighand->siglock); + while (dequeue_signal(current, ¤t->blocked, &info)); + spin_unlock_irq(¤t->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

