summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormikeb <mikeb@openbsd.org>2012-04-10 20:39:37 +0000
committermikeb <mikeb@openbsd.org>2012-04-10 20:39:37 +0000
commit3dc69f04efcdf2424af361c826a050b1c476d12e (patch)
tree2734b06301921c7c1aff6d28e30075a52739d3cb
parentprevent dpb trace handler from getting in the way of normal usage error reports. (diff)
downloadwireguard-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.c93
-rw-r--r--sys/sys/ktrace.h15
-rw-r--r--usr.bin/file/magdir/ktrace8
-rw-r--r--usr.bin/kdump/kdump.18
-rw-r--r--usr.bin/kdump/kdump.c27
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);
}