Index: sys/kern/core_elf32.c =================================================================== RCS file: /cvsroot/src/sys/kern/core_elf32.c,v retrieving revision 1.49 diff -u -r1.49 core_elf32.c --- sys/kern/core_elf32.c 29 Sep 2016 20:40:53 -0000 1.49 +++ sys/kern/core_elf32.c 3 Jan 2017 04:30:55 -0000 @@ -357,8 +357,8 @@ /* First, write an elfcore_procinfo. */ cpi.cpi_version = NETBSD_ELFCORE_PROCINFO_VERSION; cpi.cpi_cpisize = sizeof(cpi); - cpi.cpi_signo = p->p_sigctx.ps_signo; - cpi.cpi_sigcode = p->p_sigctx.ps_code; + cpi.cpi_signo = p->p_sigctx.ps_info._signo; + cpi.cpi_sigcode = p->p_sigctx.ps_info._code; cpi.cpi_siglwp = p->p_sigctx.ps_lwp; /* Index: sys/kern/core_netbsd.c =================================================================== RCS file: /cvsroot/src/sys/kern/core_netbsd.c,v retrieving revision 1.22 diff -u -r1.22 core_netbsd.c --- sys/kern/core_netbsd.c 7 Jan 2014 07:59:03 -0000 1.22 +++ sys/kern/core_netbsd.c 3 Jan 2017 04:30:55 -0000 @@ -88,8 +88,8 @@ cs.core.c_midmag = 0; strncpy(cs.core.c_name, p->p_comm, MAXCOMLEN); cs.core.c_nseg = 0; - cs.core.c_signo = p->p_sigctx.ps_signo; - cs.core.c_ucode = p->p_sigctx.ps_code; + cs.core.c_signo = p->p_sigctx.ps_info._signo; + cs.core.c_ucode = p->p_sigctx.ps_info._code; cs.core.c_cpusize = 0; cs.core.c_tsize = (u_long)ctob(vm->vm_tsize); cs.core.c_dsize = (u_long)ctob(vm->vm_dsize); Index: sys/kern/kern_sig.c =================================================================== RCS file: /cvsroot/src/sys/kern/kern_sig.c,v retrieving revision 1.331 diff -u -r1.331 kern_sig.c --- sys/kern/kern_sig.c 4 Dec 2016 16:40:43 -0000 1.331 +++ sys/kern/kern_sig.c 3 Jan 2017 04:30:55 -0000 @@ -1240,8 +1240,7 @@ /* XXX for core dump/debugger */ p->p_sigctx.ps_lwp = ksi->ksi_lid; - p->p_sigctx.ps_signo = ksi->ksi_signo; - p->p_sigctx.ps_code = ksi->ksi_trap; + p->p_sigctx.ps_info = ksi->ksi_info; /* * Notify any interested parties of the signal. @@ -1947,8 +1946,7 @@ KASSERT(mutex_owned(p->p_lock)); p->p_sigctx.ps_lwp = 0; - p->p_sigctx.ps_code = 0; - p->p_sigctx.ps_signo = 0; + memset(&p->p_sigctx.ps_info, 0, sizeof(p->p_sigctx.ps_info)); mutex_enter(&ps->sa_mutex); sigplusset(&SIGACTION_PS(ps, signo).sa_mask, &l->l_sigmask); @@ -2053,7 +2051,9 @@ exitsig = signo; p->p_acflag |= AXSIG; - p->p_sigctx.ps_signo = signo; + memset(&p->p_sigctx.ps_info, 0, sizeof(p->p_sigctx.ps_info)); + p->p_sigctx.ps_info._signo = signo; + p->p_sigctx.ps_info._code = SI_NOINFO; if (docore) { mutex_exit(p->p_lock); Index: sys/kern/sys_ptrace_common.c =================================================================== RCS file: /cvsroot/src/sys/kern/sys_ptrace_common.c,v retrieving revision 1.7 diff -u -r1.7 sys_ptrace_common.c --- sys/kern/sys_ptrace_common.c 15 Dec 2016 12:04:18 -0000 1.7 +++ sys/kern/sys_ptrace_common.c 3 Jan 2017 04:30:55 -0000 @@ -210,6 +210,8 @@ case PT_SET_EVENT_MASK: case PT_GET_EVENT_MASK: case PT_GET_PROCESS_STATE: + case PT_SET_SIGINFO: + case PT_GET_SIGINFO: #ifdef __HAVE_PTRACE_MACHDEP PTRACE_MACHDEP_REQUEST_CASES #endif @@ -300,6 +302,7 @@ struct ptrace_event pe; struct ptrace_state ps; struct ptrace_lwpinfo pl; + struct ptrace_siginfo psi; #ifdef __HAVE_PTRACE_WATCHPOINTS struct ptrace_watchpoint pw; #endif @@ -448,6 +451,8 @@ case PT_SET_EVENT_MASK: case PT_GET_EVENT_MASK: case PT_GET_PROCESS_STATE: + case PT_SET_SIGINFO: + case PT_GET_SIGINFO: /* * You can't do what you want to the process if: * (1) It's not being traced at all, @@ -797,6 +802,16 @@ proc_unstop(t); else lwp_unstop(lt); + } else if (t->p_sigctx.ps_faked) { + if (signo != t->p_sigctx.ps_info._signo) { + error = EINVAL; + break; + } + t->p_sigctx.ps_faked = false; + KSI_INIT_EMPTY(&ksi); + ksi.ksi_info = t->p_sigctx.ps_info; + ksi.ksi_lid = t->p_sigctx.ps_lwp; + kpsignal2(t, &ksi); } else if (signo != 0) { KSI_INIT_EMPTY(&ksi); ksi.ksi_signo = signo; @@ -911,7 +926,8 @@ * check ps_signo too. */ if (lt->l_lid == t->p_sigctx.ps_lwp - || (t->p_sigctx.ps_lwp == 0 && t->p_sigctx.ps_signo)) + || (t->p_sigctx.ps_lwp == 0 && + t->p_sigctx.ps_info._signo)) pl.pl_event = PL_EVENT_SIGNAL; } mutex_exit(t->p_lock); @@ -919,6 +935,64 @@ error = copyout(&pl, addr, sizeof(pl)); break; + case PT_SET_SIGINFO: + if (data != sizeof(psi)) { + DPRINTF(("ptrace(%d): %d != %zu\n", req, data, + sizeof(psi))); + error = EINVAL; + break; + } + + error = copyin(addr, &psi, sizeof(psi)); + if (error) + break; + + tmp = psi.psi_lwpid; + mutex_enter(t->p_lock); + if (tmp != 0) { + lwp_delref(lt); + lt = lwp_find(t, tmp); { + mutex_exit(t->p_lock); + error = ESRCH; + break; + } + } + + /* Check that the data is a valid signal number or zero. */ + if (psi.psi_siginfo.si_signo < 0 || + psi.psi_siginfo.si_signo >= NSIG) { + mutex_exit(t->p_lock); + error = EINVAL; + break; + } + + if (lt) { + lwp_addref(lt); + t->p_sigctx.ps_faked = true; + t->p_sigctx.ps_info = psi.psi_siginfo._info; + t->p_sigctx.ps_lwp = psi.psi_lwpid; + } + mutex_exit(t->p_lock); + break; + + case PT_GET_SIGINFO: + if (data != sizeof(psi)) { + DPRINTF(("ptrace(%d): %d != %zu\n", req, data, + sizeof(psi))); + error = EINVAL; + break; + } + mutex_enter(t->p_lock); + psi.psi_siginfo._info = t->p_sigctx.ps_info; + psi.psi_lwpid = t->p_sigctx.ps_lwp; + mutex_exit(t->p_lock); + + error = copyout(&psi, addr, sizeof(psi)); + if (error) + break; + + break; + #ifdef PT_SETREGS case PT_SETREGS: write = 1; Index: sys/sys/ptrace.h =================================================================== RCS file: /cvsroot/src/sys/sys/ptrace.h,v retrieving revision 1.51 diff -u -r1.51 ptrace.h --- sys/sys/ptrace.h 15 Dec 2016 20:04:36 -0000 1.51 +++ sys/sys/ptrace.h 3 Jan 2017 04:30:55 -0000 @@ -34,6 +34,8 @@ #ifndef _SYS_PTRACE_H_ #define _SYS_PTRACE_H_ +#include + #define PT_TRACE_ME 0 /* child declares it's being traced */ #define PT_READ_I 1 /* read word in child's I space */ #define PT_READ_D 2 /* read word in child's D space */ @@ -51,6 +53,8 @@ #define PT_SET_EVENT_MASK 16 /* set the event mask, defined below */ #define PT_GET_EVENT_MASK 17 /* get the event mask, defined below */ #define PT_GET_PROCESS_STATE 18 /* get process state, defined below */ +#define PT_SET_SIGINFO 19 /* set signal state, defined below */ +#define PT_GET_SIGINFO 20 /* get signal state, defined below */ #define PT_FIRSTMACH 32 /* for machine-specific requests */ #include /* machine-specific requests, if any */ @@ -74,7 +78,9 @@ /* 15 */ "PT_SYSCALLEMU", \ /* 16 */ "PT_SET_EVENT_MASK", \ /* 17 */ "PT_GET_EVENT_MASK", \ -/* 18 */ "PT_GET_PROCESS_STATE", +/* 18 */ "PT_GET_PROCESS_STATE", \ +/* 19 */ "PT_SET_SIGINFO", \ +/* 20 */ "PT_GET_SIGINFO", /* PT_{G,S}EVENT_MASK */ typedef struct ptrace_event { @@ -131,6 +137,16 @@ #endif } ptrace_watchpoint_t; +/* + * Signal Information structure + */ +typedef struct ptrace_siginfo { + siginfo_t psi_siginfo; /* signal information structure */ + lwpid_t psi_lwpid; /* destination LWP of the signal + * value 0 means the whole process + * (route signal to all LWPs) */ +} ptrace_siginfo_t; + #ifdef _KERNEL #if defined(PT_GETREGS) || defined(PT_SETREGS) Index: sys/sys/signalvar.h =================================================================== RCS file: /cvsroot/src/sys/sys/signalvar.h,v retrieving revision 1.87 diff -u -r1.87 signalvar.h --- sys/sys/signalvar.h 4 Aug 2016 06:43:43 -0000 1.87 +++ sys/sys/signalvar.h 3 Jan 2017 04:30:55 -0000 @@ -37,6 +37,7 @@ #include #include #include +#include /* * Kernel signal definitions and data structures, @@ -74,12 +75,12 @@ * Process signal state. */ struct sigctx { - int ps_signo; /* for core dump/debugger XXX */ - int ps_code; /* for core dump/debugger XXX */ - int ps_lwp; /* for core dump/debugger XXX */ + struct _ksiginfo ps_info; /* for core dump/debugger XXX */ + int ps_lwp; /* for core dump/debugger XXX */ + bool ps_faked; /* for core dump/debugger XXX */ void *ps_sigcode; /* address of signal trampoline */ - sigset_t ps_sigignore; /* Signals being ignored. */ - sigset_t ps_sigcatch; /* Signals being caught by user. */ + sigset_t ps_sigignore; /* Signals being ignored. */ + sigset_t ps_sigcatch; /* Signals being caught by user. */ }; /* additional signal action values, used only temporarily/internally */ Index: tests/kernel/t_ptrace_wait.c =================================================================== RCS file: /cvsroot/src/tests/kernel/t_ptrace_wait.c,v retrieving revision 1.48 diff -u -r1.48 t_ptrace_wait.c --- tests/kernel/t_ptrace_wait.c 2 Jan 2017 21:02:03 -0000 1.48 +++ tests/kernel/t_ptrace_wait.c 3 Jan 2017 04:30:55 -0000 @@ -4458,6 +4458,127 @@ } #endif +#if defined(HAVE_SIGINFO) +ATF_TC(siginfo1); +ATF_TC_HEAD(siginfo1, tc) +{ + atf_tc_set_md_var(tc, "descr", + "Verify basic PT_GET_SIGINFO call for SIGSTOP from tracee"); +} + +ATF_TC_BODY(siginfo1, tc) +{ + const int exitval = 5; + const int sigval = SIGSTOP; + pid_t child, wpid; +#if defined(TWAIT_HAVE_STATUS) + int status; +#endif + struct ptrace_siginfo info; + memset(&info, 0, sizeof(info)); + + 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 ptrace(2) with PT_GET_SIGINFO for child\n"); + ATF_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); + + printf("Signal traced to lwpid=%d\n", info.psi_lwpid); + printf("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", + info.psi_siginfo.si_signo, info.psi_siginfo.si_code, + info.psi_siginfo.si_errno); + + 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)); +} +#endif + +#if defined(HAVE_SIGINFO) +ATF_TC(siginfo2); +ATF_TC_HEAD(siginfo2, tc) +{ + atf_tc_set_md_var(tc, "descr", + "Verify basic PT_GET_SIGINFO and PT_SET_SIGINFO calls without " + "modification of SIGSTOP from tracee"); +} + +ATF_TC_BODY(siginfo2, tc) +{ + const int exitval = 5; + const int sigval = SIGSTOP; + pid_t child, wpid; +#if defined(TWAIT_HAVE_STATUS) + int status; +#endif + struct ptrace_siginfo info; + memset(&info, 0, sizeof(info)); + + 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 ptrace(2) with PT_GET_SIGINFO for child\n"); + ATF_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); + + printf("Signal traced to lwpid=%d\n", info.psi_lwpid); + printf("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", + info.psi_siginfo.si_signo, info.psi_siginfo.si_code, + info.psi_siginfo.si_errno); + + 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)); +} +#endif + ATF_TP_ADD_TCS(tp) { setvbuf(stdout, NULL, _IONBF, 0); @@ -4540,5 +4661,7 @@ ATF_TP_ADD_TC(tp, lwpinfo1); ATF_TP_ADD_TC_HAVE_PID(tp, lwpinfo2); + ATF_TP_ADD_TC_HAVE_SIGINFO(tp, siginfo1); + return atf_no_error(); } Index: tests/kernel/t_ptrace_wait.h =================================================================== RCS file: /cvsroot/src/tests/kernel/t_ptrace_wait.h,v retrieving revision 1.5 diff -u -r1.5 t_ptrace_wait.h --- tests/kernel/t_ptrace_wait.h 30 Dec 2016 17:29:34 -0000 1.5 +++ tests/kernel/t_ptrace_wait.h 3 Jan 2017 04:30:55 -0000 @@ -196,6 +196,12 @@ #define HAVE_DBREGS #endif +/* Add guards for siginfo_t accessors */ +#if defined(PT_GET_SIGINFO) \ + && defined(PT_SET_SIGINFO) +#define HAVE_SIGINFO +#endif + /* * If waitid(2) returns because one or more processes have a state change to * report, 0 is returned. If an error is detected, a value of -1 is returned @@ -424,6 +430,12 @@ #define ATF_TP_ADD_TC_PT_STEP(a,b) #endif +#if defined(HAVE_SIGINFO) +#define ATF_TP_ADD_TC_HAVE_SIGINFO(a,b) ATF_TP_ADD_TC(a,b) +#else +#define ATF_TP_ADD_TC_HAVE_SIGINFO(a,b) +#endif + #if defined(__HAVE_PTRACE_WATCHPOINTS) #define ATF_TP_ADD_TC_HAVE_PTRACE_WATCHPOINTS(a,b) ATF_TP_ADD_TC(a,b) #else