Index: sys/arch/powerpc/booke/trap.c =================================================================== RCS file: /cvsroot/src/sys/arch/powerpc/booke/trap.c,v retrieving revision 1.26 diff -u -r1.26 trap.c --- sys/arch/powerpc/booke/trap.c 31 Jul 2014 12:11:37 -0000 1.26 +++ sys/arch/powerpc/booke/trap.c 3 Apr 2017 07:55:21 -0000 @@ -884,7 +884,7 @@ * uncaught. */ if (cpu_printfataltraps - && (p->p_slflag & PSL_TRACED) == 0 + && !P_TRACEDSIG(p, ksi.ksi_signo) && !sigismember(&p->p_sigctx.ps_sigcatch, ksi.ksi_signo)) { printf("%s: pid %d.%d (%s):" Index: sys/arch/powerpc/powerpc/trap.c =================================================================== RCS file: /cvsroot/src/sys/arch/powerpc/powerpc/trap.c,v retrieving revision 1.153 diff -u -r1.153 trap.c --- sys/arch/powerpc/powerpc/trap.c 16 Mar 2017 16:13:20 -0000 1.153 +++ sys/arch/powerpc/powerpc/trap.c 3 Apr 2017 07:55:21 -0000 @@ -253,7 +253,7 @@ } ci->ci_ev_udsi_fatal.ev_count++; if (cpu_printfataltraps - && (p->p_slflag & PSL_TRACED) == 0 + && !P_TRACEDSIG(p, SIGSEGV) && !sigismember(&p->p_sigctx.ps_sigcatch, SIGSEGV)) { printf("trap: pid %d.%d (%s): user %s DSI trap @ %#lx " "by %#lx (DSISR %#x, err=%d)\n", @@ -326,7 +326,7 @@ } ci->ci_ev_isi_fatal.ev_count++; if (cpu_printfataltraps - && (p->p_slflag & PSL_TRACED) == 0 + && !P_TRACEDSIG(p, SIGSEGV) && !sigismember(&p->p_sigctx.ps_sigcatch, SIGSEGV)) { printf("trap: pid %d.%d (%s): user ISI trap @ %#lx " "(SRR1=%#lx)\n", p->p_pid, l->l_lid, p->p_comm, @@ -351,7 +351,7 @@ if (fix_unaligned(l, tf) != 0) { ci->ci_ev_ali_fatal.ev_count++; if (cpu_printfataltraps - && (p->p_slflag & PSL_TRACED) == 0 + && !P_TRACEDSIG(p, SIGBUS) && !sigismember(&p->p_sigctx.ps_sigcatch, SIGBUS)) { printf("trap: pid %d.%d (%s): user ALI trap @ " "%#lx by %#lx (DSISR %#x)\n", @@ -377,7 +377,7 @@ break; #else if (cpu_printfataltraps - && (p->p_slflag & PSL_TRACED) == 0 + && !P_TRACEDSIG(p, SIGILL) && !sigismember(&p->p_sigctx.ps_sigcatch, SIGILL)) { printf("trap: pid %d.%d (%s): user VEC trap @ %#lx " "(SRR1=%#lx)\n", @@ -395,7 +395,7 @@ case EXC_MCHK|EXC_USER: ci->ci_ev_umchk.ev_count++; if (cpu_printfataltraps - && (p->p_slflag & PSL_TRACED) == 0 + && !P_TRACEDSIG(p, SIGBUS) && !sigismember(&p->p_sigctx.ps_sigcatch, SIGBUS)) { printf("trap: pid %d (%s): user MCHK trap @ %#lx " "(SRR1=%#lx)\n", @@ -441,7 +441,7 @@ } else ksi.ksi_code = ILL_ILLOPC; if (cpu_printfataltraps - && (p->p_slflag & PSL_TRACED) == 0 + && !P_TRACEDSIG(p, ksi.ksi_signo) && !sigismember(&p->p_sigctx.ps_sigcatch, ksi.ksi_signo)) { printf("trap: pid %d.%d (%s): user PGM trap @" Index: sys/arch/vax/vax/trap.c =================================================================== RCS file: /cvsroot/src/sys/arch/vax/vax/trap.c,v retrieving revision 1.134 diff -u -r1.134 trap.c --- sys/arch/vax/vax/trap.c 7 Jul 2016 06:55:39 -0000 1.134 +++ sys/arch/vax/vax/trap.c 3 Apr 2017 07:55:27 -0000 @@ -339,7 +339,7 @@ ksiginfo_t ksi; if ((sig == SIGSEGV || sig == SIGILL) && cpu_printfataltraps - && (p->p_slflag & PSL_TRACED) == 0 + && !P_TRACEDSIG(p, sig) && !sigismember(&p->p_sigctx.ps_sigcatch, sig)) printf("pid %d.%d (%s): sig %d: type %lx, code %lx, pc %lx, psl %lx\n", p->p_pid, l->l_lid, p->p_comm, sig, tf->tf_trap, Index: sys/kern/kern_fork.c =================================================================== RCS file: /cvsroot/src/sys/kern/kern_fork.c,v retrieving revision 1.201 diff -u -r1.201 kern_fork.c --- sys/kern/kern_fork.c 31 Mar 2017 08:50:54 -0000 1.201 +++ sys/kern/kern_fork.c 3 Apr 2017 07:55:32 -0000 @@ -292,6 +292,13 @@ memcpy(&p2->p_startcopy, &p1->p_startcopy, (unsigned) ((char *)&p2->p_endcopy - (char *)&p2->p_startcopy)); + /* + * Setup signal pass mask + * This is used by debuggers to mark uninteresting signals, + * by default all are interesting. + */ + sigemptyset(&p2->p_sigpass); + TAILQ_INIT(&p2->p_sigpend.sp_info); LIST_INIT(&p2->p_lwps); Index: sys/kern/kern_sig.c =================================================================== RCS file: /cvsroot/src/sys/kern/kern_sig.c,v retrieving revision 1.335 diff -u -r1.335 kern_sig.c --- sys/kern/kern_sig.c 31 Mar 2017 08:47:04 -0000 1.335 +++ sys/kern/kern_sig.c 3 Apr 2017 07:55:32 -0000 @@ -907,7 +907,7 @@ mask = &l->l_sigmask; ps = p->p_sigacts; - if ((p->p_slflag & PSL_TRACED) == 0 && + if (!P_TRACEDSIG(p, signo) && sigismember(&p->p_sigctx.ps_sigcatch, signo) && !sigismember(mask, signo)) { mutex_exit(proc_lock); @@ -1238,7 +1238,7 @@ * exiting, then just drop the signal here and bail out. */ if (p->p_stat == SIDL && signo == SIGTRAP - && (p->p_slflag & PSL_TRACED)) { + && P_TRACEDSIG(p, SIGTRAP)) { /* allow an initial SIGTRAP for traced processes */ debtrap = true; } else if (p->p_stat != SACTIVE && p->p_stat != SSTOP) { @@ -1265,7 +1265,7 @@ /* * If proc is traced, always give parent a chance. */ - if (p->p_slflag & PSL_TRACED) { + if (P_TRACEDSIG(p, signo)) { action = SIG_DFL; if (lid == 0) { @@ -1379,7 +1379,7 @@ * or for an SA process. */ if (p->p_stat == SACTIVE && (p->p_sflag & PS_STOPPING) == 0) { - if ((p->p_slflag & PSL_TRACED) != 0) + if (P_TRACEDSIG(p, signo)) goto deliver; /* @@ -1395,7 +1395,7 @@ * - If traced, then no action is needed, unless killing. * - Run the process only if sending SIGCONT or SIGKILL. */ - if ((p->p_slflag & PSL_TRACED) != 0 && signo != SIGKILL) { + if (P_TRACEDSIG(p, signo) && signo != SIGKILL) { goto out; } if ((prop & SA_CONT) != 0 || signo == SIGKILL) { @@ -1407,7 +1407,7 @@ p->p_pptr->p_nstopchild--; p->p_stat = SACTIVE; p->p_sflag &= ~PS_STOPPING; - if (p->p_slflag & PSL_TRACED) { + if (P_TRACEDSIG(p, signo)) { KASSERT(signo == SIGKILL); goto deliver; } @@ -1438,7 +1438,7 @@ /* * Make signal pending. */ - KASSERT((p->p_slflag & PSL_TRACED) == 0); + KASSERT(!P_TRACEDSIG(p, signo)); if ((error = sigput(&p->p_sigpend, p, kp)) != 0) goto out; deliver: @@ -1613,7 +1613,7 @@ * If we are no longer being traced, or the parent didn't * give us a signal, or we're stopping, look for more signals. */ - if ((p->p_slflag & PSL_TRACED) == 0 || p->p_xsig == 0 || + if (!P_TRACEDSIG(p, p->p_xsig) || p->p_xsig == 0 || (p->p_sflag & PS_STOPPING) != 0) return 0; @@ -1713,7 +1713,7 @@ * we are being traced. */ if (sigismember(&p->p_sigctx.ps_sigignore, signo) && - (p->p_slflag & PSL_TRACED) == 0) { + !P_TRACEDSIG(p, signo)) { /* Discard the signal. */ continue; } @@ -1723,7 +1723,7 @@ * by the debugger. If the our parent process is waiting * for us, don't hang as we could deadlock. */ - if ((p->p_slflag & PSL_TRACED) != 0 && + if (P_TRACEDSIG(p, signo) && (p->p_lflag & PL_PPWAIT) == 0 && signo != SIGKILL) { /* * Take the signal, but don't remove it from the @@ -1781,7 +1781,7 @@ * XXX Don't hold proc_lock for p_lflag, * but it's not a big deal. */ - if (p->p_slflag & PSL_TRACED || + if (P_TRACEDSIG(p, signo) || ((p->p_lflag & PL_ORPHANPG) != 0 && prop & SA_TTYSTOP)) { /* Ignore the signal. */ @@ -1810,7 +1810,7 @@ * than SIGCONT, unless process is traced. */ if ((prop & SA_CONT) == 0 && - (p->p_slflag & PSL_TRACED) == 0) + !P_TRACEDSIG(p, signo)) printf_nolog("issignal\n"); #endif continue; Index: sys/kern/kern_synch.c =================================================================== RCS file: /cvsroot/src/sys/kern/kern_synch.c,v retrieving revision 1.311 diff -u -r1.311 kern_synch.c --- sys/kern/kern_synch.c 3 Jul 2016 14:24:58 -0000 1.311 +++ sys/kern/kern_synch.c 3 Apr 2017 07:55:37 -0000 @@ -907,7 +907,7 @@ * If we're being traced (possibly because someone attached us * while we were stopped), check for a signal from the debugger. */ - if ((p->p_slflag & PSL_TRACED) != 0 && p->p_xsig != 0) + if (P_TRACEDSIG(p, p->p_xsig) && p->p_xsig != 0) signotify(l); p->p_nrlwps++; break; Index: sys/kern/sys_ptrace_common.c =================================================================== RCS file: /cvsroot/src/sys/kern/sys_ptrace_common.c,v retrieving revision 1.20 diff -u -r1.20 sys_ptrace_common.c --- sys/kern/sys_ptrace_common.c 29 Mar 2017 22:48:03 -0000 1.20 +++ sys/kern/sys_ptrace_common.c 3 Apr 2017 07:55:37 -0000 @@ -215,6 +215,8 @@ case PT_GET_SIGINFO: case PT_SET_SIGMASK: case PT_GET_SIGMASK: + case PT_SET_SIGPASS: + case PT_GET_SIGPASS: #ifdef __HAVE_PTRACE_MACHDEP PTRACE_MACHDEP_REQUEST_CASES #endif @@ -408,6 +410,8 @@ case PT_GET_SIGINFO: case PT_SET_SIGMASK: case PT_GET_SIGMASK: + case PT_SET_SIGPASS: + case PT_GET_SIGPASS: #ifdef PT_GETREGS case PT_GETREGS: #endif @@ -818,6 +822,9 @@ /* not being traced any more */ t->p_opptr = NULL; + + /* Reset signal pass mask */ + sigemptyset(&t->p_sigpass); } sendsig: t->p_fpid = 0; @@ -1136,6 +1143,26 @@ } break; + case PT_SET_SIGPASS: + write = 1; + + case PT_GET_SIGPASS: + /* write = 0 done above. */ + + if (data != sizeof(sigset_t)) { + DPRINTF(("ptrace(%d): %d != %zu\n", req, data, + sizeof(sigset_t))); + error = EINVAL; + break; + } + + if (write == 1) + error = copyin(addr, &t->p_sigpass, sizeof(sigset_t)); + else + error = copyout(&t->p_sigpass, addr, sizeof(sigset_t)); + + break; + #ifdef PT_SETREGS case PT_SETREGS: write = 1; Index: sys/miscfs/procfs/procfs_ctl.c =================================================================== RCS file: /cvsroot/src/sys/miscfs/procfs/procfs_ctl.c,v retrieving revision 1.48 diff -u -r1.48 procfs_ctl.c --- sys/miscfs/procfs/procfs_ctl.c 4 Apr 2016 20:47:57 -0000 1.48 +++ sys/miscfs/procfs/procfs_ctl.c 3 Apr 2017 07:55:37 -0000 @@ -311,6 +311,9 @@ p->p_opptr = NULL; CLR(p->p_slflag, PSL_TRACED|PSL_FSTRACE); p->p_waited = 0; /* XXXSMP */ + + /* Reset signal pass mask */ + sigemptyset(&p->p_sigpass); } sendsig: Index: sys/sys/proc.h =================================================================== RCS file: /cvsroot/src/sys/sys/proc.h,v retrieving revision 1.340 diff -u -r1.340 proc.h --- sys/sys/proc.h 30 Mar 2017 20:17:11 -0000 1.340 +++ sys/sys/proc.h 3 Apr 2017 07:55:40 -0000 @@ -346,6 +346,7 @@ struct mdproc p_md; /* p: Any machine-dependent fields */ vaddr_t p_stackbase; /* :: ASLR randomized stack base */ struct kdtrace_proc *p_dtrace; /* :: DTrace-specific data. */ + sigset_t p_sigpass; /* :: signals to pass to tracee */ }; #define p_rlimit p_limit->pl_rlimit @@ -433,6 +434,12 @@ #if defined(_KMEMUSER) || defined(_KERNEL) /* + * Macro to compute if a signal is traced by a debugger + */ +#define P_TRACEDSIG(p, signo) \ + (((p)->p_slflag & PSL_TRACED) && !sigismember(&(p)->p_sigpass, (signo))) + +/* * Macro to compute the exit signal to be delivered. */ #define P_EXITSIG(p) \ Index: sys/sys/ptrace.h =================================================================== RCS file: /cvsroot/src/sys/sys/ptrace.h,v retrieving revision 1.60 diff -u -r1.60 ptrace.h --- sys/sys/ptrace.h 24 Mar 2017 17:40:44 -0000 1.60 +++ sys/sys/ptrace.h 3 Apr 2017 07:55:40 -0000 @@ -59,6 +59,8 @@ #define PT_GET_SIGMASK 22 /* get signal mask */ #define PT_RESUME 23 /* allow execution of the LWP */ #define PT_SUSPEND 24 /* prevent execution of the LWP */ +#define PT_SET_SIGPASS 25 /* set signal pass mask */ +#define PT_GET_SIGPASS 26 /* get signal pass mask */ #define PT_FIRSTMACH 32 /* for machine-specific requests */ #include /* machine-specific requests, if any */ Index: tests/lib/libc/sys/t_ptrace_wait.c =================================================================== RCS file: /cvsroot/src/tests/lib/libc/sys/t_ptrace_wait.c,v retrieving revision 1.1 diff -u -r1.1 t_ptrace_wait.c --- tests/lib/libc/sys/t_ptrace_wait.c 2 Apr 2017 21:44:00 -0000 1.1 +++ tests/lib/libc/sys/t_ptrace_wait.c 3 Apr 2017 07:55:47 -0000 @@ -6472,7 +6472,7 @@ ATF_TC_HEAD(getsigmask1, tc) { atf_tc_set_md_var(tc, "descr", - "Verify that plain PT_SET_SIGMASK can be called"); + "Verify that plain PT_GET_SIGMASK can be called"); } ATF_TC_BODY(getsigmask1, tc) @@ -6524,7 +6524,7 @@ ATF_TC_HEAD(getsigmask2, tc) { atf_tc_set_md_var(tc, "descr", - "Verify that PT_SET_SIGMASK reports correct mask from tracee"); + "Verify that PT_GET_SIGMASK reports correct mask from tracee"); } ATF_TC_BODY(getsigmask2, tc) @@ -7446,6 +7446,325 @@ TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); } +ATF_TC(getsigpass1); +ATF_TC_HEAD(getsigpass1, tc) +{ + atf_tc_set_md_var(tc, "descr", + "Verify that plain PT_GET_SIGPASS can be called"); +} + +ATF_TC_BODY(getsigpass1, tc) +{ + const int exitval = 5; + const int sigval = SIGSTOP; + pid_t child, wpid; +#if defined(TWAIT_HAVE_STATUS) + int status; +#endif + sigset_t mask; + + printf("Before forking process PID=%d\n", getpid()); + ATF_REQUIRE((child = fork()) != -1); + if (child == 0) { + printf("Before calling PT_TRACE_ME from child %d\n", getpid()); + FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); + + printf("Before raising %s from child\n", strsignal(sigval)); + FORKEE_ASSERT(raise(sigval) == 0); + + printf("Before exiting of the child process\n"); + _exit(exitval); + } + printf("Parent process PID=%d, child's PID=%d\n", getpid(), child); + + printf("Before calling %s() for the child\n", TWAIT_FNAME); + TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); + + validate_status_stopped(status, sigval); + + printf("Before calling PT_GET_SIGPASS\n"); + ATF_REQUIRE(ptrace(PT_GET_SIGPASS, child, &mask, sizeof(mask)) != -1); + + printf("Before resuming the child process where it left off and " + "without signal to be sent\n"); + ATF_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); + + printf("Before calling %s() for the child\n", TWAIT_FNAME); + TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); + + validate_status_exited(status, exitval); + + printf("Before calling %s() for the child\n", TWAIT_FNAME); + TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); +} + +ATF_TC(setsigpass1); +ATF_TC_HEAD(setsigpass1, tc) +{ + atf_tc_set_md_var(tc, "descr", + "Verify that plain PT_SET_SIGPASS can be called with empty mask"); +} + +ATF_TC_BODY(setsigpass1, tc) +{ + const int exitval = 5; + const int sigval = SIGSTOP; + pid_t child, wpid; +#if defined(TWAIT_HAVE_STATUS) + int status; +#endif + sigset_t mask; + ATF_REQUIRE(sigemptyset(&mask) == 0); + + printf("Before forking process PID=%d\n", getpid()); + ATF_REQUIRE((child = fork()) != -1); + if (child == 0) { + printf("Before calling PT_TRACE_ME from child %d\n", getpid()); + FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); + + printf("Before raising %s from child\n", strsignal(sigval)); + FORKEE_ASSERT(raise(sigval) == 0); + + printf("Before exiting of the child process\n"); + _exit(exitval); + } + printf("Parent process PID=%d, child's PID=%d\n", getpid(), child); + + printf("Before calling %s() for the child\n", TWAIT_FNAME); + TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); + + validate_status_stopped(status, sigval); + + printf("Before calling PT_SET_SIGPASS for empty mask\n"); + ATF_REQUIRE(ptrace(PT_SET_SIGPASS, child, &mask, sizeof(mask)) != -1); + + printf("Before resuming the child process where it left off and " + "without signal to be sent\n"); + ATF_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); + + printf("Before calling %s() for the child\n", TWAIT_FNAME); + TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); + + validate_status_exited(status, exitval); + + printf("Before calling %s() for the child\n", TWAIT_FNAME); + TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); +} + +ATF_TC(setsigpass2); +ATF_TC_HEAD(setsigpass2, tc) +{ + atf_tc_set_md_var(tc, "descr", + "Verify that sigmask is preserved between PT_GET_SIGPASS and " + "PT_SET_SIGPASS"); +} + +ATF_TC_BODY(setsigpass2, tc) +{ + const int exitval = 5; + const int sigval = SIGSTOP; + pid_t child, wpid; +#if defined(TWAIT_HAVE_STATUS) + int status; +#endif + sigset_t new_mask; + sigset_t mask; + ATF_REQUIRE(sigemptyset(&new_mask) == 0); + ATF_REQUIRE(sigemptyset(&mask) == 0); + ATF_REQUIRE(sigaddset(&mask, SIGINT) == 0); + + printf("Before forking process PID=%d\n", getpid()); + ATF_REQUIRE((child = fork()) != -1); + if (child == 0) { + printf("Before calling PT_TRACE_ME from child %d\n", getpid()); + FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); + + printf("Before raising %s from child\n", strsignal(sigval)); + FORKEE_ASSERT(raise(sigval) == 0); + + printf("Before exiting of the child process\n"); + _exit(exitval); + } + printf("Parent process PID=%d, child's PID=%d\n", getpid(), child); + + printf("Before calling %s() for the child\n", TWAIT_FNAME); + TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); + + validate_status_stopped(status, sigval); + + printf("Before calling PT_SET_SIGPASS for new mask with SIGINT\n"); + ATF_REQUIRE(ptrace(PT_SET_SIGPASS, child, &mask, sizeof(mask)) != -1); + + printf("Before calling PT_GET_SIGPASS to store it in new_mask\n"); + ATF_REQUIRE(ptrace(PT_GET_SIGPASS, child, &new_mask, sizeof(mask)) + != -1); + + ATF_REQUIRE(memcmp(&mask, &new_mask, sizeof(sigset_t)) == 0); + + printf("Before resuming the child process where it left off and " + "without signal to be sent\n"); + ATF_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); + + printf("Before calling %s() for the child\n", TWAIT_FNAME); + TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); + + validate_status_exited(status, exitval); + + printf("Before calling %s() for the child\n", TWAIT_FNAME); + TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); +} + +ATF_TC(setsigpass3); +ATF_TC_HEAD(setsigpass3, tc) +{ + atf_tc_set_md_var(tc, "descr", + "Verify that sigmask is preserved between PT_GET_SIGPASS, process " + "resumed and PT_SET_SIGPASS"); +} + +ATF_TC_BODY(setsigpass3, tc) +{ + const int exitval = 5; + const int sigval = SIGSTOP; + pid_t child, wpid; +#if defined(TWAIT_HAVE_STATUS) + int status; +#endif + sigset_t new_mask; + sigset_t mask; + ATF_REQUIRE(sigemptyset(&new_mask) == 0); + ATF_REQUIRE(sigemptyset(&mask) == 0); + ATF_REQUIRE(sigaddset(&mask, SIGINT) == 0); + + printf("Before forking process PID=%d\n", getpid()); + ATF_REQUIRE((child = fork()) != -1); + if (child == 0) { + printf("Before calling PT_TRACE_ME from child %d\n", getpid()); + FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); + + printf("Before raising %s from child\n", strsignal(sigval)); + FORKEE_ASSERT(raise(sigval) == 0); + + printf("Before raising %s from child\n", strsignal(sigval)); + FORKEE_ASSERT(raise(sigval) == 0); + + printf("Before exiting of the child process\n"); + _exit(exitval); + } + printf("Parent process PID=%d, child's PID=%d\n", getpid(), child); + + printf("Before calling %s() for the child\n", TWAIT_FNAME); + TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); + + validate_status_stopped(status, sigval); + + printf("Before calling PT_SET_SIGPASS for new mask with SIGINT\n"); + ATF_REQUIRE(ptrace(PT_SET_SIGPASS, child, &mask, sizeof(mask)) != -1); + + printf("Before resuming the child process where it left off and " + "without signal to be sent\n"); + ATF_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); + + printf("Before calling %s() for the child\n", TWAIT_FNAME); + TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); + + validate_status_stopped(status, sigval); + + printf("Before calling PT_GET_SIGPASS to store it in new_mask\n"); + ATF_REQUIRE(ptrace(PT_GET_SIGPASS, child, &new_mask, sizeof(new_mask)) + != -1); + + ATF_REQUIRE(memcmp(&mask, &new_mask, sizeof(sigset_t)) == 0); + + printf("Before resuming the child process where it left off and " + "without signal to be sent\n"); + ATF_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); + + printf("Before calling %s() for the child\n", TWAIT_FNAME); + TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); + + validate_status_exited(status, exitval); + + printf("Before calling %s() for the child\n", TWAIT_FNAME); + TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); +} + +ATF_TC(setsigpass4); +ATF_TC_HEAD(setsigpass4, tc) +{ + atf_tc_set_md_var(tc, "descr", + "Verify that masked signal is not caught by the tracer"); +} + +static int setsigpass4_caught = 0; + +static void +setsigpass4_sighandler(int sig) +{ + FORKEE_ASSERT_EQ(sig, SIGINT); + + ++setsigpass4_caught; +} + +ATF_TC_BODY(setsigpass4, tc) +{ + const int exitval = 5; + const int sigval = SIGSTOP; + const int sigmasked = SIGINT; + pid_t child, wpid; + struct sigaction sa; +#if defined(TWAIT_HAVE_STATUS) + int status; +#endif + sigset_t mask; + ATF_REQUIRE(sigemptyset(&mask) == 0); + ATF_REQUIRE(sigaddset(&mask, sigmasked) == 0); + + printf("Before forking process PID=%d\n", getpid()); + ATF_REQUIRE((child = fork()) != -1); + if (child == 0) { + printf("Before calling PT_TRACE_ME from child %d\n", getpid()); + FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); + + sa.sa_handler = setsigpass4_sighandler; + sa.sa_flags = SA_SIGINFO; + sigemptyset(&sa.sa_mask); + + FORKEE_ASSERT(sigaction(sigmasked, &sa, NULL) != -1); + + printf("Before raising %s from child\n", strsignal(sigval)); + FORKEE_ASSERT(raise(sigval) == 0); + + raise(sigmasked); + + FORKEE_ASSERT_EQ(setsigpass4_caught, 1); + + printf("Before exiting of the child process\n"); + _exit(exitval); + } + printf("Parent process PID=%d, child's PID=%d\n", getpid(), child); + + printf("Before calling %s() for the child\n", TWAIT_FNAME); + TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); + + validate_status_stopped(status, sigval); + + printf("Before calling PT_SET_SIGPASS for new mask with SIGINT\n"); + ATF_REQUIRE(ptrace(PT_SET_SIGPASS, child, &mask, sizeof(mask)) != -1); + + printf("Before resuming the child process where it left off and " + "without signal to be sent\n"); + ATF_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); + + printf("Before calling %s() for the child\n", TWAIT_FNAME); + TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); + + validate_status_exited(status, exitval); + + printf("Before calling %s() for the child\n", TWAIT_FNAME); + TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); +} + #include "t_ptrace_amd64_wait.h" #include "t_ptrace_i386_wait.h" #include "t_ptrace_x86_wait.h" @@ -7582,6 +7901,13 @@ ATF_TP_ADD_TC(tp, syscallemu1); + ATF_TP_ADD_TC(tp, getsigpass1); + + ATF_TP_ADD_TC(tp, setsigpass1); + ATF_TP_ADD_TC(tp, setsigpass2); + ATF_TP_ADD_TC(tp, setsigpass3); + ATF_TP_ADD_TC(tp, setsigpass4); + ATF_TP_ADD_TCS_PTRACE_WAIT_AMD64(); ATF_TP_ADD_TCS_PTRACE_WAIT_I386(); ATF_TP_ADD_TCS_PTRACE_WAIT_X86();