Module Name:    src
Committed By:   kamil
Date:           Fri Jan  6 22:53:17 UTC 2017

Modified Files:
        src/sys/kern: core_elf32.c core_netbsd.c kern_sig.c sys_ptrace_common.c
        src/sys/sys: ptrace.h signalvar.h

Log Message:
Introduce new ptrace(2) interface: PT_SET_SIGINFO and PT_GET_SIGINFO

This interface is designed to read signal information emited to tracee and
fake this signal with new value.

This functionality is required to distinguish types of events that occured
in the tracee and intercepted by a debugger.

These accessors introduce a new structure type ptrace_siginfo:
/*
 * 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;

Include <sys/siginfo.h> in <sys/ptrace.h> in order to not break existing
software due to unknown symbol siginfo_t.

This interface has been proposed to the tech-kern@ mailing list.

Sponsored by <The NetBSD Foundation>


To generate a diff of this commit:
cvs rdiff -u -r1.49 -r1.50 src/sys/kern/core_elf32.c
cvs rdiff -u -r1.22 -r1.23 src/sys/kern/core_netbsd.c
cvs rdiff -u -r1.331 -r1.332 src/sys/kern/kern_sig.c
cvs rdiff -u -r1.7 -r1.8 src/sys/kern/sys_ptrace_common.c
cvs rdiff -u -r1.51 -r1.52 src/sys/sys/ptrace.h
cvs rdiff -u -r1.87 -r1.88 src/sys/sys/signalvar.h

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/kern/core_elf32.c
diff -u src/sys/kern/core_elf32.c:1.49 src/sys/kern/core_elf32.c:1.50
--- src/sys/kern/core_elf32.c:1.49	Thu Sep 29 20:40:53 2016
+++ src/sys/kern/core_elf32.c	Fri Jan  6 22:53:17 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: core_elf32.c,v 1.49 2016/09/29 20:40:53 christos Exp $	*/
+/*	$NetBSD: core_elf32.c,v 1.50 2017/01/06 22:53:17 kamil Exp $	*/
 
 /*
  * Copyright (c) 2001 Wasabi Systems, Inc.
@@ -40,7 +40,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(1, "$NetBSD: core_elf32.c,v 1.49 2016/09/29 20:40:53 christos Exp $");
+__KERNEL_RCSID(1, "$NetBSD: core_elf32.c,v 1.50 2017/01/06 22:53:17 kamil Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_coredump.h"
@@ -357,8 +357,8 @@ coredump_note_procinfo(struct lwp *l, st
 	/* 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: src/sys/kern/core_netbsd.c
diff -u src/sys/kern/core_netbsd.c:1.22 src/sys/kern/core_netbsd.c:1.23
--- src/sys/kern/core_netbsd.c:1.22	Tue Jan  7 07:59:03 2014
+++ src/sys/kern/core_netbsd.c	Fri Jan  6 22:53:17 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: core_netbsd.c,v 1.22 2014/01/07 07:59:03 dsl Exp $	*/
+/*	$NetBSD: core_netbsd.c,v 1.23 2017/01/06 22:53:17 kamil Exp $	*/
 
 /*
  * Copyright (c) 1997 Charles D. Cranor and Washington University.
@@ -45,7 +45,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: core_netbsd.c,v 1.22 2014/01/07 07:59:03 dsl Exp $");
+__KERNEL_RCSID(0, "$NetBSD: core_netbsd.c,v 1.23 2017/01/06 22:53:17 kamil Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_coredump.h"
@@ -88,8 +88,8 @@ CORENAME(coredump_netbsd)(struct lwp *l,
 	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: src/sys/kern/kern_sig.c
diff -u src/sys/kern/kern_sig.c:1.331 src/sys/kern/kern_sig.c:1.332
--- src/sys/kern/kern_sig.c:1.331	Sun Dec  4 16:40:43 2016
+++ src/sys/kern/kern_sig.c	Fri Jan  6 22:53:17 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: kern_sig.c,v 1.331 2016/12/04 16:40:43 christos Exp $	*/
+/*	$NetBSD: kern_sig.c,v 1.332 2017/01/06 22:53:17 kamil Exp $	*/
 
 /*-
  * Copyright (c) 2006, 2007, 2008 The NetBSD Foundation, Inc.
@@ -70,7 +70,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: kern_sig.c,v 1.331 2016/12/04 16:40:43 christos Exp $");
+__KERNEL_RCSID(0, "$NetBSD: kern_sig.c,v 1.332 2017/01/06 22:53:17 kamil Exp $");
 
 #include "opt_ptrace.h"
 #include "opt_dtrace.h"
@@ -1240,8 +1240,7 @@ kpsignal2(struct proc *p, ksiginfo_t *ks
 
 	/* 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.
@@ -1860,8 +1859,16 @@ postsig(int signo)
 	l->l_ru.ru_nsignals++;
 	if (l->l_sigpendset == NULL) {
 		/* From the debugger */
-		if (!siggetinfo(&l->l_sigpend, &ksi, signo))
-			(void)siggetinfo(&p->p_sigpend, &ksi, signo);
+		if (p->p_sigctx.ps_faked &&
+		    signo == p->p_sigctx.ps_info._signo) {
+			KSI_INIT(&ksi);
+			ksi.ksi_info = p->p_sigctx.ps_info;
+			ksi.ksi_lid = p->p_sigctx.ps_lwp;
+			p->p_sigctx.ps_faked = false;
+		} else {
+			if (!siggetinfo(&l->l_sigpend, &ksi, signo))
+				(void)siggetinfo(&p->p_sigpend, &ksi, signo);
+		}
 	} else
 		sigget(l->l_sigpendset, &ksi, signo, NULL);
 
@@ -1947,8 +1954,7 @@ sendsig_reset(struct lwp *l, int signo)
 	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 +2059,9 @@ sigexit(struct lwp *l, int signo)
 
 	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: src/sys/kern/sys_ptrace_common.c
diff -u src/sys/kern/sys_ptrace_common.c:1.7 src/sys/kern/sys_ptrace_common.c:1.8
--- src/sys/kern/sys_ptrace_common.c:1.7	Thu Dec 15 12:04:18 2016
+++ src/sys/kern/sys_ptrace_common.c	Fri Jan  6 22:53:17 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: sys_ptrace_common.c,v 1.7 2016/12/15 12:04:18 kamil Exp $	*/
+/*	$NetBSD: sys_ptrace_common.c,v 1.8 2017/01/06 22:53:17 kamil Exp $	*/
 
 /*-
  * Copyright (c) 2008, 2009 The NetBSD Foundation, Inc.
@@ -118,7 +118,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: sys_ptrace_common.c,v 1.7 2016/12/15 12:04:18 kamil Exp $");
+__KERNEL_RCSID(0, "$NetBSD: sys_ptrace_common.c,v 1.8 2017/01/06 22:53:17 kamil Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_ptrace.h"
@@ -210,6 +210,8 @@ ptrace_listener_cb(kauth_cred_t cred, ka
 	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 @@ do_ptrace(struct ptrace_methods *ptm, st
 	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 @@ do_ptrace(struct ptrace_methods *ptm, st
 	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 @@ do_ptrace(struct ptrace_methods *ptm, st
 				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 @@ do_ptrace(struct ptrace_methods *ptm, st
 			 * 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,65 @@ do_ptrace(struct ptrace_methods *ptm, st
 		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;
+
+		/* Check that the data is a valid signal number or zero. */
+		if (psi.psi_siginfo.si_signo < 0 ||
+		    psi.psi_siginfo.si_signo >= NSIG) {
+			error = EINVAL;
+			break;
+		}
+
+		tmp = psi.psi_lwpid;
+		if (tmp != 0)
+			lwp_delref(lt);
+
+		mutex_enter(t->p_lock);
+
+		if (tmp != 0) {
+			lt = lwp_find(t, tmp);
+			if (lt == NULL) {
+				mutex_exit(t->p_lock);
+				error = ESRCH;
+				break;
+			}
+			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: src/sys/sys/ptrace.h
diff -u src/sys/sys/ptrace.h:1.51 src/sys/sys/ptrace.h:1.52
--- src/sys/sys/ptrace.h:1.51	Thu Dec 15 20:04:36 2016
+++ src/sys/sys/ptrace.h	Fri Jan  6 22:53:17 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: ptrace.h,v 1.51 2016/12/15 20:04:36 martin Exp $	*/
+/*	$NetBSD: ptrace.h,v 1.52 2017/01/06 22:53:17 kamil Exp $	*/
 
 /*-
  * Copyright (c) 1984, 1993
@@ -34,6 +34,8 @@
 #ifndef	_SYS_PTRACE_H_
 #define	_SYS_PTRACE_H_
 
+#include <sys/siginfo.h>
+
 #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/ptrace.h>		/* 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 @@ typedef struct ptrace_watchpoint {
 #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: src/sys/sys/signalvar.h
diff -u src/sys/sys/signalvar.h:1.87 src/sys/sys/signalvar.h:1.88
--- src/sys/sys/signalvar.h:1.87	Thu Aug  4 06:43:43 2016
+++ src/sys/sys/signalvar.h	Fri Jan  6 22:53:17 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: signalvar.h,v 1.87 2016/08/04 06:43:43 christos Exp $	*/
+/*	$NetBSD: signalvar.h,v 1.88 2017/01/06 22:53:17 kamil Exp $	*/
 
 /*
  * Copyright (c) 1991, 1993
@@ -37,6 +37,7 @@
 #include <sys/siginfo.h>
 #include <sys/queue.h>
 #include <sys/mutex.h>
+#include <sys/stdbool.h>
 
 /*
  * Kernel signal definitions and data structures,
@@ -74,12 +75,12 @@ typedef struct sigpend {
  * 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 */

Reply via email to