aboutsummaryrefslogtreecommitdiff
path: root/sys/kern
diff options
context:
space:
mode:
authorTycho Nightingale <tychon@FreeBSD.org>2017-03-30 18:21:36 +0000
committerTycho Nightingale <tychon@FreeBSD.org>2017-03-30 18:21:36 +0000
commit86be94fca32cba783d836da0200837f914d56cac (patch)
tree1a2ed8405fd580e6f366465bdd678a59a2155940 /sys/kern
parent1fb4382cb22e201435107888c19bb7fd1daa13e3 (diff)
downloadsrc-86be94fca32cba783d836da0200837f914d56cac.tar.gz
src-86be94fca32cba783d836da0200837f914d56cac.zip
Add support for capturing 'struct ptrace_lwpinfo' for signals
resulting in a process dumping core in the corefile. Also extend procstat to view select members of 'struct ptrace_lwpinfo' from the contents of the note. Sponsored by: Dell EMC Isilon
Notes
Notes: svn path=/head/; revision=316286
Diffstat (limited to 'sys/kern')
-rw-r--r--sys/kern/imgact_elf.c36
-rw-r--r--sys/kern/kern_sig.c28
-rw-r--r--sys/kern/sys_process.c4
3 files changed, 61 insertions, 7 deletions
diff --git a/sys/kern/imgact_elf.c b/sys/kern/imgact_elf.c
index ad5c3acf4dd9..dedc3660e172 100644
--- a/sys/kern/imgact_elf.c
+++ b/sys/kern/imgact_elf.c
@@ -1,4 +1,5 @@
/*-
+ * Copyright (c) 2017 Dell EMC
* Copyright (c) 2000 David O'Brien
* Copyright (c) 1995-1996 Søren Schmidt
* Copyright (c) 1996 Peter Wemm
@@ -52,6 +53,7 @@ __FBSDID("$FreeBSD$");
#include <sys/pioctl.h>
#include <sys/proc.h>
#include <sys/procfs.h>
+#include <sys/ptrace.h>
#include <sys/racct.h>
#include <sys/resourcevar.h>
#include <sys/rwlock.h>
@@ -1202,6 +1204,7 @@ static void __elfN(note_prpsinfo)(void *, struct sbuf *, size_t *);
static void __elfN(note_prstatus)(void *, struct sbuf *, size_t *);
static void __elfN(note_threadmd)(void *, struct sbuf *, size_t *);
static void __elfN(note_thrmisc)(void *, struct sbuf *, size_t *);
+static void __elfN(note_ptlwpinfo)(void *, struct sbuf *, size_t *);
static void __elfN(note_procstat_auxv)(void *, struct sbuf *, size_t *);
static void __elfN(note_procstat_proc)(void *, struct sbuf *, size_t *);
static void __elfN(note_procstat_psstrings)(void *, struct sbuf *, size_t *);
@@ -1628,6 +1631,8 @@ __elfN(prepare_notes)(struct thread *td, struct note_info_list *list,
__elfN(note_fpregset), thr);
size += register_note(list, NT_THRMISC,
__elfN(note_thrmisc), thr);
+ size += register_note(list, NT_PTLWPINFO,
+ __elfN(note_ptlwpinfo), thr);
size += register_note(list, -1,
__elfN(note_threadmd), thr);
@@ -2018,6 +2023,37 @@ __elfN(note_thrmisc)(void *arg, struct sbuf *sb, size_t *sizep)
*sizep = sizeof(thrmisc);
}
+static void
+__elfN(note_ptlwpinfo)(void *arg, struct sbuf *sb, size_t *sizep)
+{
+ struct thread *td;
+ size_t size;
+ int structsize;
+ struct ptrace_lwpinfo pl;
+
+ td = (struct thread *)arg;
+ size = sizeof(structsize) + sizeof(struct ptrace_lwpinfo);
+ if (sb != NULL) {
+ KASSERT(*sizep == size, ("invalid size"));
+ structsize = sizeof(struct ptrace_lwpinfo);
+ sbuf_bcat(sb, &structsize, sizeof(structsize));
+ bzero(&pl, sizeof(pl));
+ pl.pl_lwpid = td->td_tid;
+ pl.pl_event = PL_EVENT_NONE;
+ pl.pl_sigmask = td->td_sigmask;
+ pl.pl_siglist = td->td_siglist;
+ if (td->td_si.si_signo != 0) {
+ pl.pl_event = PL_EVENT_SIGNAL;
+ pl.pl_flags |= PL_FLAG_SI;
+ pl.pl_siginfo = td->td_si;
+ }
+ strcpy(pl.pl_tdname, td->td_name);
+ /* XXX TODO: supply more information in struct ptrace_lwpinfo*/
+ sbuf_bcat(sb, &pl, sizeof(struct ptrace_lwpinfo));
+ }
+ *sizep = size;
+}
+
/*
* Allow for MD specific notes, as well as any MD
* specific preparations for writing MI notes.
diff --git a/sys/kern/kern_sig.c b/sys/kern/kern_sig.c
index 6f102ceb6c68..e43cd6b8482f 100644
--- a/sys/kern/kern_sig.c
+++ b/sys/kern/kern_sig.c
@@ -1226,6 +1226,19 @@ sys_sigwaitinfo(struct thread *td, struct sigwaitinfo_args *uap)
return (error);
}
+static void
+proc_td_siginfo_capture(struct thread *td, siginfo_t *si)
+{
+ struct thread *thr;
+
+ FOREACH_THREAD_IN_PROC(td->td_proc, thr) {
+ if (thr == td)
+ thr->td_si = *si;
+ else
+ thr->td_si.si_signo = 0;
+ }
+}
+
int
kern_sigtimedwait(struct thread *td, sigset_t waitset, ksiginfo_t *ksi,
struct timespec *timeout)
@@ -1334,8 +1347,10 @@ kern_sigtimedwait(struct thread *td, sigset_t waitset, ksiginfo_t *ksi,
ktrpsig(sig, action, &td->td_sigmask, ksi->ksi_code);
}
#endif
- if (sig == SIGKILL)
+ if (sig == SIGKILL) {
+ proc_td_siginfo_capture(td, &ksi->ksi_info);
sigexit(td, sig);
+ }
}
PROC_UNLOCK(p);
return (error);
@@ -2756,6 +2771,7 @@ issignal(struct thread *td)
struct sigqueue *queue;
sigset_t sigpending;
int sig, prop;
+ ksiginfo_t ksi;
p = td->td_proc;
ps = p->p_sigacts;
@@ -2811,14 +2827,15 @@ issignal(struct thread *td)
* be thrown away.
*/
queue = &td->td_sigqueue;
- td->td_dbgksi.ksi_signo = 0;
- if (sigqueue_get(queue, sig, &td->td_dbgksi) == 0) {
+ ksiginfo_init(&ksi);
+ if (sigqueue_get(queue, sig, &ksi) == 0) {
queue = &p->p_sigqueue;
- sigqueue_get(queue, sig, &td->td_dbgksi);
+ sigqueue_get(queue, sig, &ksi);
}
+ td->td_si = ksi.ksi_info;
mtx_unlock(&ps->ps_mtx);
- sig = ptracestop(td, sig, &td->td_dbgksi);
+ sig = ptracestop(td, sig, &ksi);
mtx_lock(&ps->ps_mtx);
/*
@@ -2989,6 +3006,7 @@ postsig(sig)
* the process. (Other cases were ignored above.)
*/
mtx_unlock(&ps->ps_mtx);
+ proc_td_siginfo_capture(td, &ksi.ksi_info);
sigexit(td, sig);
/* NOTREACHED */
} else {
diff --git a/sys/kern/sys_process.c b/sys/kern/sys_process.c
index ded874ac9819..7bb167a14ef2 100644
--- a/sys/kern/sys_process.c
+++ b/sys/kern/sys_process.c
@@ -1306,7 +1306,7 @@ kern_ptrace(struct thread *td, int req, pid_t pid, void *addr, int data)
pl->pl_flags = 0;
if (td2->td_dbgflags & TDB_XSIG) {
pl->pl_event = PL_EVENT_SIGNAL;
- if (td2->td_dbgksi.ksi_signo != 0 &&
+ if (td2->td_si.si_signo != 0 &&
#ifdef COMPAT_FREEBSD32
((!wrap32 && data >= offsetof(struct ptrace_lwpinfo,
pl_siginfo) + sizeof(pl->pl_siginfo)) ||
@@ -1318,7 +1318,7 @@ kern_ptrace(struct thread *td, int req, pid_t pid, void *addr, int data)
#endif
){
pl->pl_flags |= PL_FLAG_SI;
- pl->pl_siginfo = td2->td_dbgksi.ksi_info;
+ pl->pl_siginfo = td2->td_si;
}
}
if ((pl->pl_flags & PL_FLAG_SI) == 0)