diff options
author | 2012-04-10 20:39:37 +0000 | |
---|---|---|
committer | 2012-04-10 20:39:37 +0000 | |
commit | 3dc69f04efcdf2424af361c826a050b1c476d12e (patch) | |
tree | 2734b06301921c7c1aff6d28e30075a52739d3cb | |
parent | prevent dpb trace handler from getting in the way of normal usage error reports. (diff) | |
download | wireguard-openbsd-3dc69f04efcdf2424af361c826a050b1c476d12e.tar.xz wireguard-openbsd-3dc69f04efcdf2424af361c826a050b1c476d12e.zip |
Add a start record to the ktrace and use a special magic string "KTR"
to identify ktrace files. kdump(1) will now refuse to operate on
trace data without the start record and as a bonus will print only
PID, unless an -H flag is specified to print PID/TID pairs. Initial
diff, input from and ok deraadt, guenther.
-rw-r--r-- | sys/kern/kern_ktrace.c | 93 | ||||
-rw-r--r-- | sys/sys/ktrace.h | 15 | ||||
-rw-r--r-- | usr.bin/file/magdir/ktrace | 8 | ||||
-rw-r--r-- | usr.bin/kdump/kdump.1 | 8 | ||||
-rw-r--r-- | usr.bin/kdump/kdump.c | 27 |
5 files changed, 98 insertions, 53 deletions
diff --git a/sys/kern/kern_ktrace.c b/sys/kern/kern_ktrace.c index cc69df31a6a..80f167670f1 100644 --- a/sys/kern/kern_ktrace.c +++ b/sys/kern/kern_ktrace.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kern_ktrace.c,v 1.57 2012/03/19 09:05:39 guenther Exp $ */ +/* $OpenBSD: kern_ktrace.c,v 1.58 2012/04/10 20:39:37 mikeb Exp $ */ /* $NetBSD: kern_ktrace.c,v 1.23 1996/02/09 18:59:36 christos Exp $ */ /* @@ -53,11 +53,14 @@ #include <uvm/uvm_extern.h> void ktrinitheader(struct ktr_header *, struct proc *, int); +void ktrstart(struct proc *, struct vnode *, struct ucred *); int ktrops(struct proc *, struct process *, int, int, struct vnode *, struct ucred *); int ktrsetchildren(struct proc *, struct process *, int, int, struct vnode *, struct ucred *); -int ktrwrite(struct proc *, struct ktr_header *); +int ktrwrite(struct proc *, struct ktr_header *, void *); +int ktrwriteraw(struct proc *, struct vnode *, struct ucred *, + struct ktr_header *, void *); int ktrcanset(struct proc *, struct process *); /* @@ -121,9 +124,25 @@ ktrinitheader(struct ktr_header *kth, struct proc *p, int type) { bzero(kth, sizeof (struct ktr_header)); kth->ktr_type = type; - microtime(&kth->ktr_time); - kth->ktr_pid = p->p_pid; - bcopy(p->p_comm, kth->ktr_comm, MAXCOMLEN); + nanotime(&kth->ktr_time); + kth->ktr_pid = p->p_p->ps_pid; + kth->ktr_tid = p->p_pid + THREAD_PID_OFFSET; + bcopy(p->p_comm, kth->ktr_comm, MAXCOMLEN); +} + +void +ktrstart(struct proc *p, struct vnode *vp, struct ucred *cred) +{ + struct ktr_header kth; + + bzero(&kth, sizeof (kth)); + kth.ktr_type = htobe32(KTR_START); + nanotime(&kth.ktr_time); + kth.ktr_pid = (pid_t)-1; + kth.ktr_tid = (pid_t)-1; + atomic_setbits_int(&p->p_flag, P_INKTR); + ktrwriteraw(p, vp, cred, &kth, NULL); + atomic_clearbits_int(&p->p_flag, P_INKTR); } void @@ -157,9 +176,8 @@ ktrsyscall(struct proc *p, register_t code, size_t argsize, register_t args[]) nargs && copyin((void *)args[0], argp, nargs * sizeof(int))) bzero(argp, nargs * sizeof(int)); - kth.ktr_buf = (caddr_t)ktp; kth.ktr_len = len; - ktrwrite(p, &kth); + ktrwrite(p, &kth, ktp); free(ktp, M_TEMP); atomic_clearbits_int(&p->p_flag, P_INKTR); } @@ -176,10 +194,9 @@ ktrsysret(struct proc *p, register_t code, int error, register_t retval) ktp.ktr_error = error; ktp.ktr_retval = error == 0 ? retval : 0; - kth.ktr_buf = (caddr_t)&ktp; kth.ktr_len = sizeof(struct ktr_sysret); - ktrwrite(p, &kth); + ktrwrite(p, &kth, &ktp); atomic_clearbits_int(&p->p_flag, P_INKTR); } @@ -191,9 +208,8 @@ ktrnamei(struct proc *p, char *path) atomic_setbits_int(&p->p_flag, P_INKTR); ktrinitheader(&kth, p, KTR_NAMEI); kth.ktr_len = strlen(path); - kth.ktr_buf = path; - ktrwrite(p, &kth); + ktrwrite(p, &kth, path); atomic_clearbits_int(&p->p_flag, P_INKTR); } @@ -205,9 +221,8 @@ ktremul(struct proc *p, char *emul) atomic_setbits_int(&p->p_flag, P_INKTR); ktrinitheader(&kth, p, KTR_EMUL); kth.ktr_len = strlen(emul); - kth.ktr_buf = emul; - ktrwrite(p, &kth); + ktrwrite(p, &kth, emul); atomic_clearbits_int(&p->p_flag, P_INKTR); } @@ -233,8 +248,6 @@ ktrgenio(struct proc *p, int fd, enum uio_rw rw, struct iovec *iov, int len, ktp->ktr_fd = fd; ktp->ktr_rw = rw; - kth.ktr_buf = (caddr_t)ktp; - cp = (caddr_t)((char *)ktp + sizeof (struct ktr_genio)); buflen -= sizeof(struct ktr_genio); @@ -254,7 +267,7 @@ ktrgenio(struct proc *p, int fd, enum uio_rw rw, struct iovec *iov, int len, kth.ktr_len = count + sizeof(struct ktr_genio); - if (ktrwrite(p, &kth) != 0) + if (ktrwrite(p, &kth, ktp) != 0) break; iov->iov_len -= count; @@ -268,7 +281,6 @@ ktrgenio(struct proc *p, int fd, enum uio_rw rw, struct iovec *iov, int len, free(ktp, M_TEMP); atomic_clearbits_int(&p->p_flag, P_INKTR); - } void @@ -285,10 +297,9 @@ ktrpsig(struct proc *p, int sig, sig_t action, int mask, int code, kp.mask = mask; kp.code = code; kp.si = *si; - kth.ktr_buf = (caddr_t)&kp; kth.ktr_len = sizeof(struct ktr_psig); - ktrwrite(p, &kth); + ktrwrite(p, &kth, &kp); atomic_clearbits_int(&p->p_flag, P_INKTR); } @@ -302,10 +313,9 @@ ktrcsw(struct proc *p, int out, int user) ktrinitheader(&kth, p, KTR_CSW); kc.out = out; kc.user = user; - kth.ktr_buf = (caddr_t)&kc; kth.ktr_len = sizeof(struct ktr_csw); - ktrwrite(p, &kth); + ktrwrite(p, &kth, &kc); atomic_clearbits_int(&p->p_flag, P_INKTR); } @@ -328,10 +338,9 @@ ktrstruct(struct proc *p, const char *name, const void *data, size_t datalen) buf = malloc(buflen, M_TEMP, M_WAITOK); strlcpy(buf, name, buflen); bcopy(data, buf + strlen(name) + 1, datalen); - kth.ktr_buf = buf; kth.ktr_len = buflen; - ktrwrite(p, &kth); + ktrwrite(p, &kth, buf); free(buf, M_TEMP); atomic_clearbits_int(&p->p_flag, P_INKTR); } @@ -403,9 +412,12 @@ sys_ktrace(struct proc *curp, void *v, register_t *retval) error = EINVAL; goto done; } - if (ops == KTROP_SET && suser(curp, 0) == 0) - facs |= KTRFAC_ROOT; - /* + if (ops == KTROP_SET) { + if (suser(curp, 0) == 0) + facs |= KTRFAC_ROOT; + ktrstart(curp, vp, cred); + } + /* * do it */ if (SCARG(uap, pid) < 0) { @@ -421,10 +433,9 @@ sys_ktrace(struct proc *curp, void *v, register_t *retval) if (descend) ret |= ktrsetchildren(curp, pr, ops, facs, vp, cred); - else + else ret |= ktrops(curp, pr, ops, facs, vp, cred); } - } else { /* * by pid @@ -514,16 +525,28 @@ ktrsetchildren(struct proc *curp, struct process *top, int ops, int facs, } int -ktrwrite(struct proc *p, struct ktr_header *kth) +ktrwrite(struct proc *p, struct ktr_header *kth, void *aux) { - struct uio auio; - struct iovec aiov[2]; - int error; struct vnode *vp = p->p_p->ps_tracevp; struct ucred *cred = p->p_p->ps_tracecred; + int error; if (vp == NULL) return 0; + crhold(cred); + error = ktrwriteraw(p, vp, cred, kth, aux); + crfree(cred); + return (error); +} + +int +ktrwriteraw(struct proc *p, struct vnode *vp, struct ucred *cred, + struct ktr_header *kth, void *aux) +{ + struct uio auio; + struct iovec aiov[2]; + int error; + auio.uio_iov = &aiov[0]; auio.uio_offset = 0; auio.uio_segflg = UIO_SYSSPACE; @@ -535,14 +558,12 @@ ktrwrite(struct proc *p, struct ktr_header *kth) auio.uio_procp = p; if (kth->ktr_len > 0) { auio.uio_iovcnt++; - aiov[1].iov_base = kth->ktr_buf; + aiov[1].iov_base = aux; aiov[1].iov_len = kth->ktr_len; auio.uio_resid += kth->ktr_len; } - crhold(cred); vget(vp, LK_EXCLUSIVE | LK_RETRY, p); error = VOP_WRITE(vp, &auio, IO_UNIT|IO_APPEND, cred); - crfree(cred); if (!error) { vput(vp); return (0); @@ -553,7 +574,7 @@ ktrwrite(struct proc *p, struct ktr_header *kth) log(LOG_NOTICE, "ktrace write failed, errno %d, tracing stopped\n", error); LIST_FOREACH(p, &allproc, p_list) - if (p->p_p->ps_tracevp == vp) + if (p->p_p->ps_tracevp == vp && p->p_p->ps_tracecred == cred) ktrcleartrace(p->p_p); vput(vp); diff --git a/sys/sys/ktrace.h b/sys/sys/ktrace.h index b30a93a1677..ceb453a802c 100644 --- a/sys/sys/ktrace.h +++ b/sys/sys/ktrace.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ktrace.h,v 1.13 2012/03/19 09:05:39 guenther Exp $ */ +/* $OpenBSD: ktrace.h,v 1.14 2012/04/10 20:39:37 mikeb Exp $ */ /* $NetBSD: ktrace.h,v 1.12 1996/02/04 02:12:29 christos Exp $ */ /* @@ -48,12 +48,12 @@ * ktrace record header */ struct ktr_header { - size_t ktr_len; /* length of buf */ + uint ktr_type; /* trace record type */ pid_t ktr_pid; /* process id */ + pid_t ktr_tid; /* thread id */ + struct timespec ktr_time; /* timestamp */ char ktr_comm[MAXCOMLEN+1]; /* command name */ - short ktr_type; /* trace record type */ - struct timeval ktr_time; /* timestamp */ - caddr_t ktr_buf; + size_t ktr_len; /* length of buf */ }; /* @@ -66,6 +66,11 @@ struct ktr_header { * ktrace record types */ + /* + * KTR_START - start of trace record, one per ktrace(KTROP_SET) syscall + */ +#define KTR_START 0x4b545200 /* "KTR" */ + /* * KTR_SYSCALL - system call record */ diff --git a/usr.bin/file/magdir/ktrace b/usr.bin/file/magdir/ktrace new file mode 100644 index 00000000000..c5578e4323c --- /dev/null +++ b/usr.bin/file/magdir/ktrace @@ -0,0 +1,8 @@ +# $OpenBSD: ktrace,v 1.1 2012/04/10 20:39:37 mikeb Exp $ + +#------------------------------------------------------------------------------ +# OpenBSD ktrace(1) output data +# +0 belong 0x4b545200 +>4 long 0xffffffff +>8 long 0xffffffff OpenBSD kernel trace data diff --git a/usr.bin/kdump/kdump.1 b/usr.bin/kdump/kdump.1 index 419ed3ab0ad..fad59ab85bf 100644 --- a/usr.bin/kdump/kdump.1 +++ b/usr.bin/kdump/kdump.1 @@ -1,4 +1,4 @@ -.\" $OpenBSD: kdump.1,v 1.21 2011/07/28 10:33:36 otto Exp $ +.\" $OpenBSD: kdump.1,v 1.22 2012/04/10 20:39:37 mikeb Exp $ .\" .\" Copyright (c) 1990, 1993 .\" The Regents of the University of California. All rights reserved. @@ -29,7 +29,7 @@ .\" .\" from: @(#)kdump.1 8.1 (Berkeley) 6/6/93 .\" -.Dd $Mdocdate: July 28 2011 $ +.Dd $Mdocdate: April 10 2012 $ .Dt KDUMP 1 .Os .Sh NAME @@ -38,7 +38,7 @@ .Sh SYNOPSIS .Nm kdump .Bk -words -.Op Fl dlnRrTXx +.Op Fl dHlnRrTXx .Op Fl e Ar emulation .Op Fl f Ar file .Op Fl m Ar maxdata @@ -69,6 +69,8 @@ For example, to view trace output from a Linux binary, use .It Fl f Ar file Display the specified file instead of .Pa ktrace.out . +.It Fl H +Display thread identifiers. .It Fl l Loop reading the trace file, once the end-of-file is reached, waiting for more data. diff --git a/usr.bin/kdump/kdump.c b/usr.bin/kdump/kdump.c index 3ef74ad4f57..57643d0aff2 100644 --- a/usr.bin/kdump/kdump.c +++ b/usr.bin/kdump/kdump.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kdump.c,v 1.66 2012/03/31 18:59:14 deraadt Exp $ */ +/* $OpenBSD: kdump.c,v 1.67 2012/04/10 20:39:37 mikeb Exp $ */ /*- * Copyright (c) 1988, 1993 @@ -73,7 +73,8 @@ #include "kdump_subr.h" #include "extern.h" -int timestamp, decimal, iohex, fancy = 1, tail, maxdata = INT_MAX, resolv; +int timestamp, decimal, iohex, fancy = 1, maxdata = INT_MAX; +int needtid, resolv, tail; char *tracefile = DEF_TRACEFILE; struct ktr_header ktr_header; pid_t pid = -1; @@ -167,7 +168,7 @@ main(int argc, char *argv[]) def_emul = current = &emulations[0]; /* native */ - while ((ch = getopt(argc, argv, "e:f:dlm:nrRp:Tt:xX")) != -1) + while ((ch = getopt(argc, argv, "e:f:dHlm:nrRp:Tt:xX")) != -1) switch (ch) { case 'e': setemul(optarg); @@ -179,6 +180,9 @@ main(int argc, char *argv[]) case 'd': decimal = 1; break; + case 'H': + needtid = 1; + break; case 'l': tail = 1; break; @@ -222,6 +226,9 @@ main(int argc, char *argv[]) err(1, NULL); if (!freopen(tracefile, "r", stdin)) err(1, "%s", tracefile); + if (fread_tail(&ktr_header, sizeof(struct ktr_header), 1) == 0 || + ktr_header.ktr_type != htobe32(KTR_START)) + errx(1, "%s: not a dump", tracefile); while (fread_tail(&ktr_header, sizeof(struct ktr_header), 1)) { silent = 0; if (pe_size == 0) @@ -329,9 +336,9 @@ fread_tail(void *buf, size_t size, size_t num) static void dumpheader(struct ktr_header *kth) { - static struct timeval prevtime; + static struct timespec prevtime; char unknown[64], *type; - struct timeval temp; + struct timespec temp; switch (kth->ktr_type) { case KTR_SYSCALL: @@ -364,15 +371,17 @@ dumpheader(struct ktr_header *kth) type = unknown; } - (void)printf("%6ld %-8.*s ", (long)kth->ktr_pid, MAXCOMLEN, - kth->ktr_comm); + (void)printf("%6ld", (long)kth->ktr_pid); + if (needtid) + (void)printf("/%-5ld", (long)kth->ktr_tid - THREAD_PID_OFFSET); + (void)printf(" %-8.*s ", MAXCOMLEN, kth->ktr_comm); if (timestamp) { if (timestamp == 2) { - timersub(&kth->ktr_time, &prevtime, &temp); + timespecsub(&kth->ktr_time, &prevtime, &temp); prevtime = kth->ktr_time; } else temp = kth->ktr_time; - (void)printf("%ld.%06ld ", temp.tv_sec, temp.tv_usec); + (void)printf("%ld.%06ld ", temp.tv_sec, temp.tv_nsec / 1000); } (void)printf("%s ", type); } |