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
This commit is contained in:
parent
8911b8bd0f
commit
643b691b05
@ -2179,11 +2179,9 @@ tdsendsignal(struct proc *p, struct thread *td, int sig, ksiginfo_t *ksi)
|
||||
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 */
|
||||
|
@ -2919,6 +2919,79 @@ ATF_TC_BODY(ptrace__parent_terminate_with_pending_sigstop2, tc)
|
||||
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());
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user