svn commit: r341800 - in head: sys/kern tests/sys/kern

John Baldwin jhb at FreeBSD.org
Mon Dec 10 19:39:25 UTC 2018


Author: jhb
Date: Mon Dec 10 19:39:24 2018
New Revision: 341800
URL: https://svnweb.freebsd.org/changeset/base/341800

Log:
  Don't report stale signal information for non-signal events in ptrace_lwpinfo.
  
  Once a signal's siginfo was copied to 'td_si' as part of the signal
  exchange in issignal(), it was never cleared.  This caused future
  thread events that are reported as SIGTRAP events without signal
  information to report the stale siginfo in 'td_si'.  For example, if a
  debugger created a new process and used SIGSTOP to stop it after
  PT_ATTACH, future system call entry / exit events would set PL_FLAG_SI
  with the SIGSTOP siginfo in pl_siginfo.  This broke 'catch syscall' in
  current versions of gdb as it assumed PL_FLAG_SI with SIGTRAP
  indicates a breakpoint or single step trap.
  
  Reviewed by:	kib
  MFC after:	1 week
  Differential Revision:	https://reviews.freebsd.org/D18487

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	Mon Dec 10 16:23:11 2018	(r341799)
+++ head/sys/kern/kern_sig.c	Mon Dec 10 19:39:24 2018	(r341800)
@@ -2847,6 +2847,8 @@ issignal(struct thread *td)
 			sig = ptracestop(td, sig, &ksi);
 			mtx_lock(&ps->ps_mtx);
 
+			td->td_si.si_signo = 0;
+
 			/* 
 			 * Keep looking if the debugger discarded or
 			 * replaced the signal.

Modified: head/tests/sys/kern/ptrace_test.c
==============================================================================
--- head/tests/sys/kern/ptrace_test.c	Mon Dec 10 16:23:11 2018	(r341799)
+++ head/tests/sys/kern/ptrace_test.c	Mon Dec 10 19:39:24 2018	(r341800)
@@ -3772,6 +3772,78 @@ ATF_TC_BODY(ptrace__PT_CONTINUE_different_thread, tc)
 }
 #endif
 
+/*
+ * Verify that PT_LWPINFO doesn't return stale siginfo.
+ */
+ATF_TC_WITHOUT_HEAD(ptrace__PT_LWPINFO_stale_siginfo);
+ATF_TC_BODY(ptrace__PT_LWPINFO_stale_siginfo, tc)
+{
+	struct ptrace_lwpinfo pl;
+	pid_t fpid, wpid;
+	int events, status;
+
+	ATF_REQUIRE((fpid = fork()) != -1);
+	if (fpid == 0) {
+		trace_me();
+		raise(SIGABRT);
+		exit(1);
+	}
+
+	/* The first 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);
+
+	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
+
+	/* The next stop should report the SIGABRT in the child body. */
+	wpid = waitpid(fpid, &status, 0);
+	ATF_REQUIRE(wpid == fpid);
+	ATF_REQUIRE(WIFSTOPPED(status));
+	ATF_REQUIRE(WSTOPSIG(status) == SIGABRT);
+
+	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 == SIGABRT);
+
+	/*
+	 * Continue the process ignoring the signal, but enabling
+	 * syscall traps.
+	 */
+	ATF_REQUIRE(ptrace(PT_SYSCALL, fpid, (caddr_t)1, 0) == 0);
+
+	/*
+	 * The next stop should report a system call entry from
+	 * exit().  PL_FLAGS_SI should not be set.
+	 */
+	wpid = waitpid(fpid, &status, 0);
+	ATF_REQUIRE(wpid == fpid);
+	ATF_REQUIRE(WIFSTOPPED(status));
+	ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP);
+
+	ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
+	ATF_REQUIRE(pl.pl_flags & PL_FLAG_SCE);
+	ATF_REQUIRE((pl.pl_flags & PL_FLAG_SI) == 0);
+
+	/* Disable syscall tracing and continue the child to let it exit. */
+	ATF_REQUIRE(ptrace(PT_GET_EVENT_MASK, fpid, (caddr_t)&events,
+	    sizeof(events)) == 0);
+	events &= ~PTRACE_SYSCALL;
+	ATF_REQUIRE(ptrace(PT_SET_EVENT_MASK, fpid, (caddr_t)&events,
+	    sizeof(events)) == 0);
+	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) == 1);
+
+	wpid = wait(&status);
+	ATF_REQUIRE(wpid == -1);
+	ATF_REQUIRE(errno == ECHILD);
+}
+
 ATF_TP_ADD_TCS(tp)
 {
 
@@ -3831,6 +3903,7 @@ ATF_TP_ADD_TCS(tp)
 #if defined(HAVE_BREAKPOINT) && defined(SKIP_BREAK)
 	ATF_TP_ADD_TC(tp, ptrace__PT_CONTINUE_different_thread);
 #endif
+	ATF_TP_ADD_TC(tp, ptrace__PT_LWPINFO_stale_siginfo);
 
 	return (atf_no_error());
 }


More information about the svn-src-all mailing list