Date: Thu, 16 Mar 2017 13:03:31 +0000 (UTC) From: Eric Badger <badger@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r315412 - in head: sys/kern tests/sys/kern Message-ID: <201703161303.v2GD3V3m044721@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: badger Date: Thu Mar 16 13:03:31 2017 New Revision: 315412 URL: https://svnweb.freebsd.org/changeset/base/315412 Log: Don't clear p_ptevents on normal SIGKILL delivery The ptrace() user has the option of discarding the signal. In such a case, p_ptevents should not be modified. If the ptrace() user decides to send a SIGKILL, ptevents will be cleared in ptracestop(). procfs events do not have the capability to discard the signal, so continue to clear the mask in that case. Reviewed by: jhb (initial revision) MFC after: 1 week Sponsored by: Dell EMC Differential Revision: https://reviews.freebsd.org/D9939 Modified: head/sys/kern/kern_sig.c head/tests/sys/kern/ptrace_test.c Modified: head/sys/kern/kern_sig.c ============================================================================== --- head/sys/kern/kern_sig.c Thu Mar 16 13:01:23 2017 (r315411) +++ head/sys/kern/kern_sig.c Thu Mar 16 13:03:31 2017 (r315412) @@ -2179,11 +2179,9 @@ tdsendsignal(struct proc *p, struct thre if (action == SIG_HOLD && !((prop & SIGPROP_CONT) && (p->p_flag & P_STOPPED_SIG))) return (ret); - /* - * SIGKILL: Remove procfs STOPEVENTs and ptrace events. - */ + + /* SIGKILL: Remove procfs STOPEVENTs. */ if (sig == SIGKILL) { - p->p_ptevents = 0; /* from procfs_ioctl.c: PIOCBIC */ p->p_stops = 0; /* from procfs_ioctl.c: PIOCCONT */ Modified: head/tests/sys/kern/ptrace_test.c ============================================================================== --- head/tests/sys/kern/ptrace_test.c Thu Mar 16 13:01:23 2017 (r315411) +++ head/tests/sys/kern/ptrace_test.c Thu Mar 16 13:03:31 2017 (r315412) @@ -2919,6 +2919,79 @@ ATF_TC_BODY(ptrace__parent_terminate_wit terminate_with_pending_sigstop(false); } +/* + * Verify that after ptrace() discards a SIGKILL signal, the event mask + * is not modified. + */ +ATF_TC_WITHOUT_HEAD(ptrace__event_mask_sigkill_discard); +ATF_TC_BODY(ptrace__event_mask_sigkill_discard, tc) +{ + struct ptrace_lwpinfo pl; + pid_t fpid, wpid; + int status, event_mask, new_event_mask; + + ATF_REQUIRE((fpid = fork()) != -1); + if (fpid == 0) { + trace_me(); + raise(SIGSTOP); + exit(0); + } + + /* The first wait() should report the stop from trace_me(). */ + wpid = waitpid(fpid, &status, 0); + ATF_REQUIRE(wpid == fpid); + ATF_REQUIRE(WIFSTOPPED(status)); + ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP); + + /* Set several unobtrusive event bits. */ + event_mask = PTRACE_EXEC | PTRACE_FORK | PTRACE_LWP; + ATF_REQUIRE(ptrace(PT_SET_EVENT_MASK, wpid, (caddr_t)&event_mask, + sizeof(event_mask)) == 0); + + /* Send a SIGKILL without using ptrace. */ + ATF_REQUIRE(kill(fpid, SIGKILL) == 0); + + /* Continue the child ignoring the SIGSTOP. */ + ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0); + + /* The next stop should be due to the SIGKILL. */ + wpid = waitpid(fpid, &status, 0); + ATF_REQUIRE(wpid == fpid); + ATF_REQUIRE(WIFSTOPPED(status)); + ATF_REQUIRE(WSTOPSIG(status) == SIGKILL); + + ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1); + ATF_REQUIRE(pl.pl_flags & PL_FLAG_SI); + ATF_REQUIRE(pl.pl_siginfo.si_signo == SIGKILL); + + /* Continue the child ignoring the SIGKILL. */ + ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0); + + /* The next wait() should report the stop from SIGSTOP. */ + wpid = waitpid(fpid, &status, 0); + ATF_REQUIRE(wpid == fpid); + ATF_REQUIRE(WIFSTOPPED(status)); + ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP); + + /* Check the current event mask. It should not have changed. */ + new_event_mask = 0; + ATF_REQUIRE(ptrace(PT_GET_EVENT_MASK, wpid, (caddr_t)&new_event_mask, + sizeof(new_event_mask)) == 0); + ATF_REQUIRE(event_mask == new_event_mask); + + /* Continue the child to let it exit. */ + ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0); + + /* The last event should be for the child process's exit. */ + wpid = waitpid(fpid, &status, 0); + ATF_REQUIRE(WIFEXITED(status)); + ATF_REQUIRE(WEXITSTATUS(status) == 0); + + wpid = wait(&status); + ATF_REQUIRE(wpid == -1); + ATF_REQUIRE(errno == ECHILD); +} + ATF_TP_ADD_TCS(tp) { @@ -2965,6 +3038,7 @@ ATF_TP_ADD_TCS(tp) ATF_TP_ADD_TC(tp, ptrace__PT_CONTINUE_with_signal_thread_sigmask); ATF_TP_ADD_TC(tp, ptrace__parent_terminate_with_pending_sigstop1); ATF_TP_ADD_TC(tp, ptrace__parent_terminate_with_pending_sigstop2); + ATF_TP_ADD_TC(tp, ptrace__event_mask_sigkill_discard); return (atf_no_error()); }
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201703161303.v2GD3V3m044721>