diff options
author | Tycho Nightingale <tychon@FreeBSD.org> | 2017-03-30 18:21:36 +0000 |
---|---|---|
committer | Tycho Nightingale <tychon@FreeBSD.org> | 2017-03-30 18:21:36 +0000 |
commit | 86be94fca32cba783d836da0200837f914d56cac (patch) | |
tree | 1a2ed8405fd580e6f366465bdd678a59a2155940 /sys/kern | |
parent | 1fb4382cb22e201435107888c19bb7fd1daa13e3 (diff) | |
download | src-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.c | 36 | ||||
-rw-r--r-- | sys/kern/kern_sig.c | 28 | ||||
-rw-r--r-- | sys/kern/sys_process.c | 4 |
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) |