Annotation of src/sys/kern/kern_ktrace.c, Revision 1.128.4.2
1.128.4.2! mjf 1: /* $NetBSD: kern_ktrace.c,v 1.132 2007/12/22 11:38:54 dsl Exp $ */
1.125 ad 2:
3: /*-
4: * Copyright (c) 2006, 2007 The NetBSD Foundation, Inc.
5: * All rights reserved.
6: *
7: * This code is derived from software contributed to The NetBSD Foundation
8: * by Andrew Doran.
9: *
10: * Redistribution and use in source and binary forms, with or without
11: * modification, are permitted provided that the following conditions
12: * are met:
13: * 1. Redistributions of source code must retain the above copyright
14: * notice, this list of conditions and the following disclaimer.
15: * 2. Redistributions in binary form must reproduce the above copyright
16: * notice, this list of conditions and the following disclaimer in the
17: * documentation and/or other materials provided with the distribution.
18: * 3. All advertising materials mentioning features or use of this software
19: * must display the following acknowledgement:
20: * This product includes software developed by the NetBSD
21: * Foundation, Inc. and its contributors.
22: * 4. Neither the name of The NetBSD Foundation nor the names of its
23: * contributors may be used to endorse or promote products derived
24: * from this software without specific prior written permission.
25: *
26: * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
27: * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28: * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29: * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
30: * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36: * POSSIBILITY OF SUCH DAMAGE.
37: */
1.11 cgd 38:
1.1 cgd 39: /*
1.9 cgd 40: * Copyright (c) 1989, 1993
41: * The Regents of the University of California. All rights reserved.
1.1 cgd 42: *
43: * Redistribution and use in source and binary forms, with or without
44: * modification, are permitted provided that the following conditions
45: * are met:
46: * 1. Redistributions of source code must retain the above copyright
47: * notice, this list of conditions and the following disclaimer.
48: * 2. Redistributions in binary form must reproduce the above copyright
49: * notice, this list of conditions and the following disclaimer in the
50: * documentation and/or other materials provided with the distribution.
1.77 agc 51: * 3. Neither the name of the University nor the names of its contributors
1.1 cgd 52: * may be used to endorse or promote products derived from this software
53: * without specific prior written permission.
54: *
55: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
56: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
57: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
58: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
59: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
60: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
61: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
62: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
63: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
64: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
65: * SUCH DAMAGE.
66: *
1.25 fvdl 67: * @(#)kern_ktrace.c 8.5 (Berkeley) 5/14/95
1.1 cgd 68: */
1.55 lukem 69:
70: #include <sys/cdefs.h>
1.128.4.2! mjf 71: __KERNEL_RCSID(0, "$NetBSD: kern_ktrace.c,v 1.132 2007/12/22 11:38:54 dsl Exp $");
1.1 cgd 72:
1.7 mycroft 73: #include <sys/param.h>
1.13 cgd 74: #include <sys/systm.h>
1.7 mycroft 75: #include <sys/proc.h>
76: #include <sys/file.h>
77: #include <sys/namei.h>
78: #include <sys/vnode.h>
1.93 enami 79: #include <sys/kernel.h>
80: #include <sys/kthread.h>
1.7 mycroft 81: #include <sys/ktrace.h>
1.114 ad 82: #include <sys/kmem.h>
1.7 mycroft 83: #include <sys/syslog.h>
1.28 christos 84: #include <sys/filedesc.h>
1.42 sommerfe 85: #include <sys/ioctl.h>
1.93 enami 86: #include <sys/callout.h>
1.103 elad 87: #include <sys/kauth.h>
1.1 cgd 88:
1.13 cgd 89: #include <sys/mount.h>
90: #include <sys/syscallargs.h>
1.22 christos 91:
1.93 enami 92: /*
1.121 ad 93: * TODO:
1.93 enami 94: * - need better error reporting?
95: * - userland utility to sort ktrace.out by timestamp.
96: * - keep minimum information in ktrace_entry when rest of alloc failed.
97: * - per trace control of configurable parameters.
98: */
99:
100: struct ktrace_entry {
101: TAILQ_ENTRY(ktrace_entry) kte_list;
1.114 ad 102: struct ktr_header kte_kth;
103: void *kte_buf;
104: size_t kte_bufsz;
105: #define KTE_SPACE 32
106: uint8_t kte_space[KTE_SPACE];
1.93 enami 107: };
108:
109: struct ktr_desc {
110: TAILQ_ENTRY(ktr_desc) ktd_list;
111: int ktd_flags;
112: #define KTDF_WAIT 0x0001
113: #define KTDF_DONE 0x0002
114: #define KTDF_BLOCKING 0x0004
115: #define KTDF_INTERACTIVE 0x0008
116: int ktd_error;
117: #define KTDE_ENOMEM 0x0001
118: #define KTDE_ENOSPC 0x0002
119: int ktd_errcnt;
120: int ktd_ref; /* # of reference */
121: int ktd_qcount; /* # of entry in the queue */
122:
123: /*
124: * Params to control behaviour.
125: */
126: int ktd_delayqcnt; /* # of entry allowed to delay */
127: int ktd_wakedelay; /* delay of wakeup in *tick* */
128: int ktd_intrwakdl; /* ditto, but when interactive */
129:
130: struct file *ktd_fp; /* trace output file */
1.125 ad 131: lwp_t *ktd_lwp; /* our kernel thread */
1.93 enami 132: TAILQ_HEAD(, ktrace_entry) ktd_queue;
1.124 ad 133: callout_t ktd_wakch; /* delayed wakeup */
1.114 ad 134: kcondvar_t ktd_sync_cv;
135: kcondvar_t ktd_cv;
1.93 enami 136: };
137:
1.125 ad 138: static int ktealloc(struct ktrace_entry **, void **, lwp_t *, int,
1.114 ad 139: size_t);
1.93 enami 140: static void ktrwrite(struct ktr_desc *, struct ktrace_entry *);
1.125 ad 141: static int ktrace_common(lwp_t *, int, int, int, struct file *);
142: static int ktrops(lwp_t *, struct proc *, int, int,
1.93 enami 143: struct ktr_desc *);
1.125 ad 144: static int ktrsetchildren(lwp_t *, struct proc *, int, int,
1.93 enami 145: struct ktr_desc *);
1.125 ad 146: static int ktrcanset(lwp_t *, struct proc *);
1.93 enami 147: static int ktrsamefile(struct file *, struct file *);
1.125 ad 148: static void ktr_kmem(lwp_t *, int, const void *, size_t);
149: static void ktr_io(lwp_t *, int, enum uio_rw, struct iovec *, size_t);
1.93 enami 150:
151: static struct ktr_desc *
152: ktd_lookup(struct file *);
153: static void ktdrel(struct ktr_desc *);
154: static void ktdref(struct ktr_desc *);
1.125 ad 155: static void ktraddentry(lwp_t *, struct ktrace_entry *, int);
1.93 enami 156: /* Flags for ktraddentry (3rd arg) */
157: #define KTA_NOWAIT 0x0000
158: #define KTA_WAITOK 0x0001
159: #define KTA_LARGE 0x0002
160: static void ktefree(struct ktrace_entry *);
161: static void ktd_logerrl(struct ktr_desc *, int);
162: static void ktrace_thread(void *);
1.114 ad 163: static int ktrderefall(struct ktr_desc *, int);
1.93 enami 164:
165: /*
166: * Default vaules.
167: */
168: #define KTD_MAXENTRY 1000 /* XXX: tune */
169: #define KTD_TIMEOUT 5 /* XXX: tune */
170: #define KTD_DELAYQCNT 100 /* XXX: tune */
171: #define KTD_WAKEDELAY 5000 /* XXX: tune */
172: #define KTD_INTRWAKDL 100 /* XXX: tune */
173:
174: /*
175: * Patchable variables.
176: */
177: int ktd_maxentry = KTD_MAXENTRY; /* max # of entry in the queue */
178: int ktd_timeout = KTD_TIMEOUT; /* timeout in seconds */
179: int ktd_delayqcnt = KTD_DELAYQCNT; /* # of entry allowed to delay */
180: int ktd_wakedelay = KTD_WAKEDELAY; /* delay of wakeup in *ms* */
181: int ktd_intrwakdl = KTD_INTRWAKDL; /* ditto, but when interactive */
182:
1.125 ad 183: kmutex_t ktrace_lock;
184: int ktrace_on;
1.93 enami 185: static TAILQ_HEAD(, ktr_desc) ktdq = TAILQ_HEAD_INITIALIZER(ktdq);
186:
187: MALLOC_DEFINE(M_KTRACE, "ktrace", "ktrace data buffer");
188: POOL_INIT(kte_pool, sizeof(struct ktrace_entry), 0, 0, 0,
1.120 ad 189: "ktepl", &pool_allocator_nointr, IPL_NONE);
1.93 enami 190:
1.121 ad 191: static void
1.93 enami 192: ktd_wakeup(struct ktr_desc *ktd)
193: {
194:
195: callout_stop(&ktd->ktd_wakch);
1.121 ad 196: cv_signal(&ktd->ktd_cv);
197: }
198:
199: static void
200: ktd_callout(void *arg)
201: {
202:
1.128.4.1 mjf 203: mutex_enter(&ktrace_lock);
1.121 ad 204: ktd_wakeup(arg);
1.128.4.1 mjf 205: mutex_exit(&ktrace_lock);
1.93 enami 206: }
207:
208: static void
209: ktd_logerrl(struct ktr_desc *ktd, int error)
210: {
211:
212: ktd->ktd_error |= error;
213: ktd->ktd_errcnt++;
214: }
215:
1.114 ad 216: #if 0
1.93 enami 217: static void
218: ktd_logerr(struct proc *p, int error)
219: {
1.114 ad 220: struct ktr_desc *ktd;
221:
1.125 ad 222: KASSERT(mutex_owned(&ktrace_lock));
1.93 enami 223:
1.114 ad 224: ktd = p->p_tracep;
1.93 enami 225: if (ktd == NULL)
226: return;
227:
228: ktd_logerrl(ktd, error);
1.114 ad 229: }
230: #endif
231:
232: static inline int
1.125 ad 233: ktrenter(lwp_t *l)
1.114 ad 234: {
235:
236: if ((l->l_pflag & LP_KTRACTIVE) != 0)
237: return 1;
238: l->l_pflag |= LP_KTRACTIVE;
239: return 0;
240: }
241:
242: static inline void
1.125 ad 243: ktrexit(lwp_t *l)
1.114 ad 244: {
245:
246: l->l_pflag &= ~LP_KTRACTIVE;
247: }
248:
249: /*
250: * Initialise the ktrace system.
251: */
252: void
253: ktrinit(void)
254: {
255:
1.125 ad 256: mutex_init(&ktrace_lock, MUTEX_DEFAULT, IPL_NONE);
1.93 enami 257: }
258:
259: /*
1.125 ad 260: * Release a reference. Called with ktrace_lock held.
1.93 enami 261: */
262: void
263: ktdrel(struct ktr_desc *ktd)
264: {
265:
1.125 ad 266: KASSERT(mutex_owned(&ktrace_lock));
1.114 ad 267:
1.93 enami 268: KDASSERT(ktd->ktd_ref != 0);
269: KASSERT(ktd->ktd_ref > 0);
1.125 ad 270: KASSERT(ktrace_on > 0);
271: ktrace_on--;
1.93 enami 272: if (--ktd->ktd_ref <= 0) {
273: ktd->ktd_flags |= KTDF_DONE;
1.121 ad 274: cv_signal(&ktd->ktd_cv);
1.93 enami 275: }
276: }
277:
278: void
279: ktdref(struct ktr_desc *ktd)
280: {
281:
1.125 ad 282: KASSERT(mutex_owned(&ktrace_lock));
1.114 ad 283:
1.93 enami 284: ktd->ktd_ref++;
1.125 ad 285: ktrace_on++;
1.93 enami 286: }
287:
288: struct ktr_desc *
289: ktd_lookup(struct file *fp)
290: {
291: struct ktr_desc *ktd;
292:
1.125 ad 293: KASSERT(mutex_owned(&ktrace_lock));
1.114 ad 294:
1.93 enami 295: for (ktd = TAILQ_FIRST(&ktdq); ktd != NULL;
296: ktd = TAILQ_NEXT(ktd, ktd_list)) {
297: if (ktrsamefile(ktd->ktd_fp, fp)) {
1.125 ad 298: ktdref(ktd);
1.93 enami 299: break;
300: }
301: }
1.114 ad 302:
1.93 enami 303: return (ktd);
304: }
305:
306: void
1.125 ad 307: ktraddentry(lwp_t *l, struct ktrace_entry *kte, int flags)
1.93 enami 308: {
1.98 christos 309: struct proc *p = l->l_proc;
1.93 enami 310: struct ktr_desc *ktd;
311: #ifdef DEBUG
1.104 kardel 312: struct timeval t1, t2;
1.93 enami 313: #endif
314:
1.125 ad 315: mutex_enter(&ktrace_lock);
1.114 ad 316:
1.93 enami 317: if (p->p_traceflag & KTRFAC_TRC_EMUL) {
318: /* Add emulation trace before first entry for this process */
319: p->p_traceflag &= ~KTRFAC_TRC_EMUL;
1.125 ad 320: mutex_exit(&ktrace_lock);
1.114 ad 321: ktrexit(l);
1.125 ad 322: ktremul();
1.114 ad 323: (void)ktrenter(l);
1.125 ad 324: mutex_enter(&ktrace_lock);
1.93 enami 325: }
326:
1.125 ad 327: /* Tracing may have been cancelled. */
1.93 enami 328: ktd = p->p_tracep;
329: if (ktd == NULL)
330: goto freekte;
331:
332: /*
333: * Bump reference count so that the object will remain while
334: * we are here. Note that the trace is controlled by other
335: * process.
336: */
337: ktdref(ktd);
338:
339: if (ktd->ktd_flags & KTDF_DONE)
340: goto relktd;
341:
342: if (ktd->ktd_qcount > ktd_maxentry) {
343: ktd_logerrl(ktd, KTDE_ENOSPC);
344: goto relktd;
345: }
346: TAILQ_INSERT_TAIL(&ktd->ktd_queue, kte, kte_list);
347: ktd->ktd_qcount++;
348: if (ktd->ktd_flags & KTDF_BLOCKING)
349: goto skip_sync;
350:
351: if (flags & KTA_WAITOK &&
352: (/* flags & KTA_LARGE */0 || ktd->ktd_flags & KTDF_WAIT ||
353: ktd->ktd_qcount > ktd_maxentry >> 1))
354: /*
355: * Sync with writer thread since we're requesting rather
356: * big one or many requests are pending.
357: */
358: do {
359: ktd->ktd_flags |= KTDF_WAIT;
360: ktd_wakeup(ktd);
361: #ifdef DEBUG
1.104 kardel 362: getmicrouptime(&t1);
1.93 enami 363: #endif
1.125 ad 364: if (cv_timedwait(&ktd->ktd_sync_cv, &ktrace_lock,
1.114 ad 365: ktd_timeout * hz) != 0) {
1.93 enami 366: ktd->ktd_flags |= KTDF_BLOCKING;
367: /*
368: * Maybe the writer thread is blocking
369: * completely for some reason, but
370: * don't stop target process forever.
371: */
372: log(LOG_NOTICE, "ktrace timeout\n");
373: break;
374: }
375: #ifdef DEBUG
1.104 kardel 376: getmicrouptime(&t2);
377: timersub(&t2, &t1, &t2);
378: if (t2.tv_sec > 0)
1.93 enami 379: log(LOG_NOTICE,
380: "ktrace long wait: %ld.%06ld\n",
1.104 kardel 381: t2.tv_sec, t2.tv_usec);
1.93 enami 382: #endif
383: } while (p->p_tracep == ktd &&
384: (ktd->ktd_flags & (KTDF_WAIT | KTDF_DONE)) == KTDF_WAIT);
385: else {
386: /* Schedule delayed wakeup */
387: if (ktd->ktd_qcount > ktd->ktd_delayqcnt)
388: ktd_wakeup(ktd); /* Wakeup now */
389: else if (!callout_pending(&ktd->ktd_wakch))
390: callout_reset(&ktd->ktd_wakch,
391: ktd->ktd_flags & KTDF_INTERACTIVE ?
392: ktd->ktd_intrwakdl : ktd->ktd_wakedelay,
1.121 ad 393: ktd_callout, ktd);
1.93 enami 394: }
395:
396: skip_sync:
397: ktdrel(ktd);
1.125 ad 398: mutex_exit(&ktrace_lock);
1.114 ad 399: ktrexit(l);
1.93 enami 400: return;
401:
402: relktd:
403: ktdrel(ktd);
404:
405: freekte:
1.125 ad 406: mutex_exit(&ktrace_lock);
1.93 enami 407: ktefree(kte);
1.114 ad 408: ktrexit(l);
1.93 enami 409: }
410:
411: void
412: ktefree(struct ktrace_entry *kte)
413: {
414:
1.114 ad 415: KERNEL_LOCK(1, curlwp); /* XXXSMP */
416: if (kte->kte_buf != kte->kte_space)
417: kmem_free(kte->kte_buf, kte->kte_bufsz);
1.93 enami 418: pool_put(&kte_pool, kte);
1.114 ad 419: KERNEL_UNLOCK_ONE(curlwp); /* XXXSMP */
1.93 enami 420: }
1.44 sommerfe 421:
422: /*
423: * "deep" compare of two files for the purposes of clearing a trace.
424: * Returns true if they're the same open file, or if they point at the
425: * same underlying vnode/socket.
426: */
427:
428: int
1.89 enami 429: ktrsamefile(struct file *f1, struct file *f2)
1.44 sommerfe 430: {
1.88 enami 431:
1.44 sommerfe 432: return ((f1 == f2) ||
1.45 sommerfe 433: ((f1 != NULL) && (f2 != NULL) &&
434: (f1->f_type == f2->f_type) &&
1.44 sommerfe 435: (f1->f_data == f2->f_data)));
436: }
1.22 christos 437:
1.28 christos 438: void
1.89 enami 439: ktrderef(struct proc *p)
1.28 christos 440: {
1.93 enami 441: struct ktr_desc *ktd = p->p_tracep;
442:
1.125 ad 443: KASSERT(mutex_owned(&ktrace_lock));
1.114 ad 444:
1.42 sommerfe 445: p->p_traceflag = 0;
1.93 enami 446: if (ktd == NULL)
1.28 christos 447: return;
1.84 dsl 448: p->p_tracep = NULL;
449:
1.114 ad 450: cv_broadcast(&ktd->ktd_sync_cv);
1.93 enami 451: ktdrel(ktd);
1.28 christos 452: }
453:
454: void
1.89 enami 455: ktradref(struct proc *p)
1.28 christos 456: {
1.93 enami 457: struct ktr_desc *ktd = p->p_tracep;
1.28 christos 458:
1.125 ad 459: KASSERT(mutex_owned(&ktrace_lock));
1.114 ad 460:
1.93 enami 461: ktdref(ktd);
1.28 christos 462: }
463:
1.114 ad 464: int
465: ktrderefall(struct ktr_desc *ktd, int auth)
466: {
1.125 ad 467: lwp_t *curl = curlwp;
1.114 ad 468: struct proc *p;
469: int error = 0;
470:
1.119 ad 471: mutex_enter(&proclist_lock);
1.114 ad 472: PROCLIST_FOREACH(p, &allproc) {
473: if (p->p_tracep != ktd)
474: continue;
475: mutex_enter(&p->p_mutex);
1.125 ad 476: mutex_enter(&ktrace_lock);
1.114 ad 477: if (p->p_tracep == ktd) {
478: if (!auth || ktrcanset(curl, p))
479: ktrderef(p);
480: else
481: error = EPERM;
482: }
1.125 ad 483: mutex_exit(&ktrace_lock);
1.114 ad 484: mutex_exit(&p->p_mutex);
485: }
1.119 ad 486: mutex_exit(&proclist_lock);
1.114 ad 487:
488: return error;
489: }
490:
491: int
1.125 ad 492: ktealloc(struct ktrace_entry **ktep, void **bufp, lwp_t *l, int type,
1.114 ad 493: size_t sz)
1.1 cgd 494: {
1.98 christos 495: struct proc *p = l->l_proc;
1.114 ad 496: struct ktrace_entry *kte;
497: struct ktr_header *kth;
498: void *buf;
499:
500: if (ktrenter(l))
501: return EAGAIN;
1.1 cgd 502:
1.114 ad 503: KERNEL_LOCK(1, l); /* XXXSMP */
504: kte = pool_get(&kte_pool, PR_WAITOK);
505: if (sz > sizeof(kte->kte_space)) {
506: if ((buf = kmem_alloc(sz, KM_SLEEP)) == NULL) {
507: pool_put(&kte_pool, kte);
508: KERNEL_UNLOCK_ONE(l); /* XXXSMP */
509: ktrexit(l);
510: return ENOMEM;
511: }
512: } else
513: buf = kte->kte_space;
514: KERNEL_UNLOCK_ONE(l); /* XXXSMP */
515:
516: kte->kte_bufsz = sz;
517: kte->kte_buf = buf;
518:
519: kth = &kte->kte_kth;
1.90 christos 520: (void)memset(kth, 0, sizeof(*kth));
1.114 ad 521: kth->ktr_len = sz;
1.1 cgd 522: kth->ktr_type = type;
523: kth->ktr_pid = p->p_pid;
1.32 perry 524: memcpy(kth->ktr_comm, p->p_comm, MAXCOMLEN);
1.98 christos 525: kth->ktr_version = KTRFAC_VERSION(p->p_traceflag);
526:
527: switch (KTRFAC_VERSION(p->p_traceflag)) {
528: case 0:
529: /* This is the original format */
530: microtime(&kth->ktr_tv);
531: break;
532: case 1:
533: kth->ktr_lid = l->l_lid;
534: nanotime(&kth->ktr_time);
535: break;
536: default:
537: break;
538: }
1.114 ad 539:
540: *ktep = kte;
541: *bufp = buf;
542:
543: return 0;
1.1 cgd 544: }
545:
1.93 enami 546: void
1.125 ad 547: ktr_syscall(register_t code, register_t realcode,
1.128.4.2! mjf 548: const struct sysent *callp, const register_t args[])
1.1 cgd 549: {
1.125 ad 550: lwp_t *l = curlwp;
1.98 christos 551: struct proc *p = l->l_proc;
1.93 enami 552: struct ktrace_entry *kte;
1.72 darrenr 553: struct ktr_syscall *ktp;
1.17 cgd 554: register_t *argp;
1.93 enami 555: int argsize;
1.57 fvdl 556: size_t len;
1.60 thorpej 557: u_int i;
1.57 fvdl 558:
1.125 ad 559: if (!KTRPOINT(p, KTR_SYSCALL))
560: return;
561:
1.66 manu 562: if (callp == NULL)
563: callp = p->p_emul->e_sysent;
1.88 enami 564:
1.76 drochner 565: argsize = callp[code].sy_argsize;
1.86 mrg 566: #ifdef _LP64
1.115 pavel 567: if (p->p_flag & PK_32)
1.86 mrg 568: argsize = argsize << 1;
569: #endif
1.57 fvdl 570: len = sizeof(struct ktr_syscall) + argsize;
1.1 cgd 571:
1.114 ad 572: if (ktealloc(&kte, (void *)&ktp, l, KTR_SYSCALL, len))
573: return;
1.93 enami 574:
1.61 manu 575: ktp->ktr_code = realcode;
1.17 cgd 576: ktp->ktr_argsize = argsize;
1.93 enami 577: argp = (register_t *)(ktp + 1);
1.31 perry 578: for (i = 0; i < (argsize / sizeof(*argp)); i++)
1.1 cgd 579: *argp++ = args[i];
1.93 enami 580:
1.98 christos 581: ktraddentry(l, kte, KTA_WAITOK);
1.1 cgd 582: }
583:
1.93 enami 584: void
1.125 ad 585: ktr_sysret(register_t code, int error, register_t *retval)
1.1 cgd 586: {
1.125 ad 587: lwp_t *l = curlwp;
1.93 enami 588: struct ktrace_entry *kte;
589: struct ktr_sysret *ktp;
1.1 cgd 590:
1.125 ad 591: if (!KTRPOINT(l->l_proc, KTR_SYSRET))
592: return;
593:
1.114 ad 594: if (ktealloc(&kte, (void *)&ktp, l, KTR_SYSRET,
595: sizeof(struct ktr_sysret)))
596: return;
1.93 enami 597:
598: ktp->ktr_code = code;
599: ktp->ktr_eosys = 0; /* XXX unused */
600: ktp->ktr_error = error;
601: ktp->ktr_retval = retval ? retval[0] : 0;
602: ktp->ktr_retval_1 = retval ? retval[1] : 0;
1.1 cgd 603:
1.98 christos 604: ktraddentry(l, kte, KTA_WAITOK);
1.1 cgd 605: }
606:
1.93 enami 607: void
1.125 ad 608: ktr_namei(const char *path, size_t pathlen)
1.122 dsl 609: {
1.125 ad 610: lwp_t *l = curlwp;
611:
612: if (!KTRPOINT(l->l_proc, KTR_NAMEI))
613: return;
614:
615: ktr_kmem(l, KTR_NAMEI, path, pathlen);
1.122 dsl 616: }
617:
618: void
1.125 ad 619: ktr_namei2(const char *eroot, size_t erootlen,
620: const char *path, size_t pathlen)
1.1 cgd 621: {
1.125 ad 622: lwp_t *l = curlwp;
1.122 dsl 623: struct ktrace_entry *kte;
624: void *buf;
1.1 cgd 625:
1.125 ad 626: if (!KTRPOINT(l->l_proc, KTR_NAMEI))
627: return;
628:
1.122 dsl 629: if (ktealloc(&kte, &buf, l, KTR_NAMEI, erootlen + pathlen))
630: return;
631: memcpy(buf, eroot, erootlen);
632: buf = (char *)buf + erootlen;
633: memcpy(buf, path, pathlen);
634: ktraddentry(l, kte, KTA_WAITOK);
1.18 christos 635: }
636:
1.93 enami 637: void
1.125 ad 638: ktr_emul(void)
1.18 christos 639: {
1.125 ad 640: lwp_t *l = curlwp;
1.98 christos 641: const char *emul = l->l_proc->p_emul->e_name;
1.1 cgd 642:
1.125 ad 643: if (!KTRPOINT(l->l_proc, KTR_EMUL))
644: return;
645:
646: ktr_kmem(l, KTR_EMUL, emul, strlen(emul));
1.1 cgd 647: }
648:
1.93 enami 649: void
1.125 ad 650: ktr_execarg(const void *bf, size_t len)
651: {
652: lwp_t *l = curlwp;
653:
654: if (!KTRPOINT(l->l_proc, KTR_EXEC_ARG))
655: return;
656:
657: ktr_kmem(l, KTR_EXEC_ARG, bf, len);
658: }
659:
660: void
661: ktr_execenv(const void *bf, size_t len)
662: {
663: lwp_t *l = curlwp;
664:
665: if (!KTRPOINT(l->l_proc, KTR_EXEC_ENV))
666: return;
667:
668: ktr_kmem(l, KTR_EXEC_ENV, bf, len);
669: }
670:
671: static void
672: ktr_kmem(lwp_t *l, int type, const void *bf, size_t len)
1.75 dsl 673: {
1.93 enami 674: struct ktrace_entry *kte;
1.114 ad 675: void *buf;
1.75 dsl 676:
1.114 ad 677: if (ktealloc(&kte, &buf, l, type, len))
678: return;
679: memcpy(buf, bf, len);
1.98 christos 680: ktraddentry(l, kte, KTA_WAITOK);
1.75 dsl 681: }
682:
1.125 ad 683: static void
684: ktr_io(lwp_t *l, int fd, enum uio_rw rw, struct iovec *iov, size_t len)
1.1 cgd 685: {
1.93 enami 686: struct ktrace_entry *kte;
1.28 christos 687: struct ktr_genio *ktp;
1.125 ad 688: size_t resid = len, cnt, buflen;
1.118 christos 689: void *cp;
1.39 thorpej 690:
1.114 ad 691: next:
1.93 enami 692: buflen = min(PAGE_SIZE, resid + sizeof(struct ktr_genio));
1.39 thorpej 693:
1.114 ad 694: if (ktealloc(&kte, (void *)&ktp, l, KTR_GENIO, buflen))
695: return;
1.93 enami 696:
1.1 cgd 697: ktp->ktr_fd = fd;
698: ktp->ktr_rw = rw;
1.39 thorpej 699:
1.118 christos 700: cp = (void *)(ktp + 1);
1.39 thorpej 701: buflen -= sizeof(struct ktr_genio);
1.114 ad 702: kte->kte_kth.ktr_len = sizeof(struct ktr_genio);
1.93 enami 703:
704: while (buflen > 0) {
705: cnt = min(iov->iov_len, buflen);
706: if (copyin(iov->iov_base, cp, cnt) != 0)
707: goto out;
1.114 ad 708: kte->kte_kth.ktr_len += cnt;
1.93 enami 709: buflen -= cnt;
710: resid -= cnt;
711: iov->iov_len -= cnt;
712: if (iov->iov_len == 0)
713: iov++;
714: else
1.118 christos 715: iov->iov_base = (char *)iov->iov_base + cnt;
1.93 enami 716: }
1.39 thorpej 717:
1.93 enami 718: /*
719: * Don't push so many entry at once. It will cause kmem map
720: * shortage.
721: */
1.98 christos 722: ktraddentry(l, kte, KTA_WAITOK | KTA_LARGE);
1.93 enami 723: if (resid > 0) {
1.114 ad 724: if (curcpu()->ci_schedstate.spc_flags & SPCF_SHOULDYIELD) {
725: (void)ktrenter(l);
726: preempt();
727: ktrexit(l);
728: }
1.39 thorpej 729:
1.93 enami 730: goto next;
731: }
1.39 thorpej 732:
1.93 enami 733: return;
1.39 thorpej 734:
1.93 enami 735: out:
736: ktefree(kte);
1.114 ad 737: ktrexit(l);
1.1 cgd 738: }
739:
1.93 enami 740: void
1.125 ad 741: ktr_genio(int fd, enum uio_rw rw, const void *addr, size_t len, int error)
742: {
743: lwp_t *l = curlwp;
744: struct iovec iov;
745:
746: if (!KTRPOINT(l->l_proc, KTR_GENIO) || error != 0)
747: return;
748: iov.iov_base = __UNCONST(addr);
749: iov.iov_len = len;
750: ktr_io(l, fd, rw, &iov, len);
751: }
752:
753: void
754: ktr_geniov(int fd, enum uio_rw rw, struct iovec *iov, size_t len, int error)
755: {
756: lwp_t *l = curlwp;
757:
758: if (!KTRPOINT(l->l_proc, KTR_GENIO) || error != 0)
759: return;
760: ktr_io(l, fd, rw, iov, len);
761: }
762:
763: void
764: ktr_mibio(int fd, enum uio_rw rw, const void *addr, size_t len, int error)
765: {
766: lwp_t *l = curlwp;
767: struct iovec iov;
768:
769: if (!KTRPOINT(l->l_proc, KTR_MIB) || error != 0)
770: return;
771: iov.iov_base = __UNCONST(addr);
772: iov.iov_len = len;
773: ktr_io(l, fd, rw, &iov, len);
774: }
775:
776: void
777: ktr_psig(int sig, sig_t action, const sigset_t *mask,
778: const ksiginfo_t *ksi)
1.1 cgd 779: {
1.93 enami 780: struct ktrace_entry *kte;
1.125 ad 781: lwp_t *l = curlwp;
1.78 christos 782: struct {
783: struct ktr_psig kp;
784: siginfo_t si;
1.93 enami 785: } *kbuf;
1.1 cgd 786:
1.125 ad 787: if (!KTRPOINT(l->l_proc, KTR_PSIG))
788: return;
789:
1.114 ad 790: if (ktealloc(&kte, (void *)&kbuf, l, KTR_PSIG, sizeof(*kbuf)))
791: return;
1.93 enami 792:
793: kbuf->kp.signo = (char)sig;
794: kbuf->kp.action = action;
795: kbuf->kp.mask = *mask;
1.114 ad 796:
1.78 christos 797: if (ksi) {
1.93 enami 798: kbuf->kp.code = KSI_TRAPCODE(ksi);
799: (void)memset(&kbuf->si, 0, sizeof(kbuf->si));
800: kbuf->si._info = ksi->ksi_info;
1.114 ad 801: kte->kte_kth.ktr_len = sizeof(*kbuf);
1.78 christos 802: } else {
1.93 enami 803: kbuf->kp.code = 0;
1.114 ad 804: kte->kte_kth.ktr_len = sizeof(struct ktr_psig);
1.78 christos 805: }
1.93 enami 806:
1.98 christos 807: ktraddentry(l, kte, KTA_WAITOK);
1.9 cgd 808: }
809:
1.93 enami 810: void
1.125 ad 811: ktr_csw(int out, int user)
1.9 cgd 812: {
1.125 ad 813: lwp_t *l = curlwp;
1.98 christos 814: struct proc *p = l->l_proc;
1.93 enami 815: struct ktrace_entry *kte;
816: struct ktr_csw *kc;
1.9 cgd 817:
1.125 ad 818: if (!KTRPOINT(p, KTR_CSW))
819: return;
820:
1.114 ad 821: /*
822: * Don't record context switches resulting from blocking on
823: * locks; it's too easy to get duff results.
824: */
1.117 yamt 825: if (l->l_syncobj == &mutex_syncobj || l->l_syncobj == &rw_syncobj)
1.114 ad 826: return;
1.9 cgd 827:
1.93 enami 828: /*
829: * We can't sleep if we're already going to sleep (if original
830: * condition is met during sleep, we hang up).
1.114 ad 831: *
832: * XXX This is not ideal: it would be better to maintain a pool
833: * of ktes and actually push this to the kthread when context
834: * switch happens, however given the points where we are called
835: * from that is difficult to do.
1.93 enami 836: */
1.114 ad 837: if (out) {
838: if (ktrenter(l))
839: return;
840:
841: switch (KTRFAC_VERSION(p->p_traceflag)) {
842: case 0:
843: /* This is the original format */
844: microtime(&l->l_ktrcsw.tv);
845: l->l_pflag |= LP_KTRCSW;
846: break;
847: case 1:
848: nanotime(&l->l_ktrcsw.ts);
849: l->l_pflag |= LP_KTRCSW;
850: break;
851: default:
852: break;
853: }
854:
855: if (user)
856: l->l_pflag |= LP_KTRCSWUSER;
857: else
858: l->l_pflag &= ~LP_KTRCSWUSER;
859:
860: ktrexit(l);
861: return;
1.93 enami 862: }
863:
1.114 ad 864: /*
865: * On the way back in, we need to record twice: once for entry, and
866: * once for exit.
867: */
868: if ((l->l_pflag & LP_KTRCSW) != 0) {
869: l->l_pflag &= ~LP_KTRCSW;
870:
871: if (ktealloc(&kte, (void *)&kc, l, KTR_CSW, sizeof(*kc)))
872: return;
873:
874: kc->out = 1;
875: kc->user = ((l->l_pflag & LP_KTRCSWUSER) != 0);
876:
877: switch (KTRFAC_VERSION(p->p_traceflag)) {
878: case 0:
879: /* This is the original format */
880: memcpy(&kte->kte_kth.ktr_tv, &l->l_ktrcsw.tv,
881: sizeof(kte->kte_kth.ktr_tv));
882: break;
883: case 1:
884: memcpy(&kte->kte_kth.ktr_time, &l->l_ktrcsw.ts,
885: sizeof(kte->kte_kth.ktr_time));
886: break;
887: default:
888: break;
889: }
890:
891: ktraddentry(l, kte, KTA_WAITOK);
1.93 enami 892: }
1.114 ad 893:
894: if (ktealloc(&kte, (void *)&kc, l, KTR_CSW, sizeof(*kc)))
895: return;
896:
897: kc->out = 0;
1.93 enami 898: kc->user = user;
899:
1.114 ad 900: ktraddentry(l, kte, KTA_WAITOK);
1.1 cgd 901: }
902:
1.125 ad 903: bool
1.126 dsl 904: ktr_point(int fac_bit)
1.125 ad 905: {
1.126 dsl 906: return curlwp->l_proc->p_traceflag & fac_bit;
1.125 ad 907: }
908:
1.110 christos 909: int
1.125 ad 910: ktruser(const char *id, void *addr, size_t len, int ustr)
1.51 jdolecek 911: {
1.93 enami 912: struct ktrace_entry *kte;
1.51 jdolecek 913: struct ktr_user *ktp;
1.125 ad 914: lwp_t *l = curlwp;
1.118 christos 915: void *user_dta;
1.110 christos 916: int error;
917:
1.125 ad 918: if (!KTRPOINT(l->l_proc, KTR_USER))
919: return 0;
920:
1.110 christos 921: if (len > KTR_USER_MAXLEN)
922: return ENOSPC;
1.51 jdolecek 923:
1.114 ad 924: error = ktealloc(&kte, (void *)&ktp, l, KTR_USER, sizeof(*ktp) + len);
925: if (error != 0)
926: return error;
1.93 enami 927:
1.51 jdolecek 928: if (ustr) {
929: if (copyinstr(id, ktp->ktr_id, KTR_USER_MAXIDLEN, NULL) != 0)
930: ktp->ktr_id[0] = '\0';
931: } else
932: strncpy(ktp->ktr_id, id, KTR_USER_MAXIDLEN);
933: ktp->ktr_id[KTR_USER_MAXIDLEN-1] = '\0';
934:
1.118 christos 935: user_dta = (void *)(ktp + 1);
1.110 christos 936: if ((error = copyin(addr, (void *)user_dta, len)) != 0)
1.51 jdolecek 937: len = 0;
938:
1.98 christos 939: ktraddentry(l, kte, KTA_WAITOK);
1.110 christos 940: return error;
1.51 jdolecek 941: }
942:
1.93 enami 943: void
1.125 ad 944: ktr_kuser(const char *id, void *addr, size_t len)
1.123 dsl 945: {
946: struct ktrace_entry *kte;
947: struct ktr_user *ktp;
1.125 ad 948: lwp_t *l = curlwp;
1.123 dsl 949: int error;
950:
1.125 ad 951: if (!KTRPOINT(l->l_proc, KTR_USER))
952: return;
953:
1.123 dsl 954: if (len > KTR_USER_MAXLEN)
955: return;
956:
957: error = ktealloc(&kte, (void *)&ktp, l, KTR_USER, sizeof(*ktp) + len);
958: if (error != 0)
959: return;
960:
961: strlcpy(ktp->ktr_id, id, KTR_USER_MAXIDLEN);
962:
963: memcpy(ktp + 1, addr, len);
964:
965: ktraddentry(l, kte, KTA_WAITOK);
966: }
967:
968: void
1.125 ad 969: ktr_mmsg(const void *msgh, size_t size)
1.62 manu 970: {
1.125 ad 971: lwp_t *l = curlwp;
972:
973: if (!KTRPOINT(l->l_proc, KTR_MMSG))
974: return;
975:
976: ktr_kmem(l, KTR_MMSG, msgh, size);
1.62 manu 977: }
1.83 manu 978:
1.93 enami 979: void
1.125 ad 980: ktr_mool(const void *kaddr, size_t size, const void *uaddr)
1.83 manu 981: {
1.93 enami 982: struct ktrace_entry *kte;
1.83 manu 983: struct ktr_mool *kp;
1.97 christos 984: struct ktr_mool *bf;
1.125 ad 985: lwp_t *l = curlwp;
986:
987: if (!KTRPOINT(l->l_proc, KTR_MOOL))
988: return;
1.83 manu 989:
1.114 ad 990: if (ktealloc(&kte, (void *)&kp, l, KTR_MOOL, size + sizeof(*kp)))
991: return;
1.83 manu 992:
993: kp->uaddr = uaddr;
994: kp->size = size;
1.97 christos 995: bf = kp + 1; /* Skip uaddr and size */
996: (void)memcpy(bf, kaddr, size);
1.88 enami 997:
1.98 christos 998: ktraddentry(l, kte, KTA_WAITOK);
1.83 manu 999: }
1000:
1.98 christos 1001: void
1.125 ad 1002: ktr_mib(const int *name, u_int namelen)
1.98 christos 1003: {
1004: struct ktrace_entry *kte;
1.106 manu 1005: int *namep;
1006: size_t size;
1.125 ad 1007: lwp_t *l = curlwp;
1008:
1009: if (!KTRPOINT(l->l_proc, KTR_MIB))
1010: return;
1.106 manu 1011:
1.114 ad 1012: size = namelen * sizeof(*name);
1013:
1014: if (ktealloc(&kte, (void *)&namep, l, KTR_MIB, size))
1015: return;
1.106 manu 1016:
1017: (void)memcpy(namep, name, namelen * sizeof(*name));
1018:
1019: ktraddentry(l, kte, KTA_WAITOK);
1020: }
1021:
1.1 cgd 1022: /* Interface and common routines */
1023:
1.17 cgd 1024: int
1.125 ad 1025: ktrace_common(lwp_t *curl, int ops, int facs, int pid, struct file *fp)
1.28 christos 1026: {
1.105 ad 1027: struct proc *curp;
1.93 enami 1028: struct proc *p;
1029: struct pgrp *pg;
1030: struct ktr_desc *ktd = NULL;
1.74 fvdl 1031: int ret = 0;
1.72 darrenr 1032: int error = 0;
1.42 sommerfe 1033: int descend;
1.28 christos 1034:
1.105 ad 1035: curp = curl->l_proc;
1.42 sommerfe 1036: descend = ops & KTRFLAG_DESCEND;
1037: facs = facs & ~((unsigned) KTRFAC_ROOT);
1.28 christos 1038:
1.114 ad 1039: (void)ktrenter(curl);
1040:
1.93 enami 1041: switch (KTROP(ops)) {
1042:
1043: case KTROP_CLEARFILE:
1044: /*
1045: * Clear all uses of the tracefile
1046: */
1.125 ad 1047: mutex_enter(&ktrace_lock);
1.93 enami 1048: ktd = ktd_lookup(fp);
1.125 ad 1049: mutex_exit(&ktrace_lock);
1.93 enami 1050: if (ktd == NULL)
1051: goto done;
1.114 ad 1052: error = ktrderefall(ktd, 1);
1.28 christos 1053: goto done;
1.42 sommerfe 1054:
1.93 enami 1055: case KTROP_SET:
1.125 ad 1056: mutex_enter(&ktrace_lock);
1.93 enami 1057: ktd = ktd_lookup(fp);
1.125 ad 1058: mutex_exit(&ktrace_lock);
1.93 enami 1059: if (ktd == NULL) {
1.114 ad 1060: ktd = kmem_alloc(sizeof(*ktd), KM_SLEEP);
1.93 enami 1061: TAILQ_INIT(&ktd->ktd_queue);
1.124 ad 1062: callout_init(&ktd->ktd_wakch, 0);
1.114 ad 1063: cv_init(&ktd->ktd_cv, "ktrwait");
1064: cv_init(&ktd->ktd_sync_cv, "ktrsync");
1.125 ad 1065: ktd->ktd_flags = 0;
1066: ktd->ktd_qcount = 0;
1067: ktd->ktd_error = 0;
1068: ktd->ktd_errcnt = 0;
1.93 enami 1069: ktd->ktd_delayqcnt = ktd_delayqcnt;
1070: ktd->ktd_wakedelay = mstohz(ktd_wakedelay);
1071: ktd->ktd_intrwakdl = mstohz(ktd_intrwakdl);
1.125 ad 1072: ktd->ktd_ref = 0;
1073: mutex_enter(&ktrace_lock);
1074: ktdref(ktd);
1075: mutex_exit(&ktrace_lock);
1076:
1.93 enami 1077: /*
1078: * XXX: not correct. needs an way to detect
1079: * whether ktruss or ktrace.
1080: */
1081: if (fp->f_type == DTYPE_PIPE)
1082: ktd->ktd_flags |= KTDF_INTERACTIVE;
1083:
1.128 ad 1084: error = kthread_create(PRI_NONE, 0, NULL,
1.124 ad 1085: ktrace_thread, ktd, &ktd->ktd_lwp, "ktrace");
1.93 enami 1086: if (error != 0) {
1.114 ad 1087: kmem_free(ktd, sizeof(*ktd));
1.93 enami 1088: goto done;
1089: }
1090:
1.127 ad 1091: mutex_enter(&fp->f_lock);
1.93 enami 1092: fp->f_count++;
1.127 ad 1093: mutex_exit(&fp->f_lock);
1.93 enami 1094: ktd->ktd_fp = fp;
1095:
1.125 ad 1096: mutex_enter(&ktrace_lock);
1.114 ad 1097: if (ktd_lookup(fp) != NULL) {
1098: ktdrel(ktd);
1099: ktd = NULL;
1100: } else
1101: TAILQ_INSERT_TAIL(&ktdq, ktd, ktd_list);
1.124 ad 1102: if (ktd == NULL)
1.125 ad 1103: cv_wait(&lbolt, &ktrace_lock);
1104: mutex_exit(&ktrace_lock);
1.124 ad 1105: if (ktd == NULL)
1.114 ad 1106: goto done;
1.93 enami 1107: }
1108: break;
1.42 sommerfe 1109:
1.93 enami 1110: case KTROP_CLEAR:
1111: break;
1.43 sommerfe 1112: }
1.88 enami 1113:
1.28 christos 1114: /*
1115: * need something to (un)trace (XXX - why is this here?)
1116: */
1117: if (!facs) {
1118: error = EINVAL;
1119: goto done;
1120: }
1.93 enami 1121:
1.88 enami 1122: /*
1.28 christos 1123: * do it
1124: */
1.119 ad 1125: mutex_enter(&proclist_lock);
1.42 sommerfe 1126: if (pid < 0) {
1.28 christos 1127: /*
1128: * by process group
1129: */
1.114 ad 1130: pg = pg_find(-pid, PFIND_LOCKED);
1131: if (pg == NULL)
1.28 christos 1132: error = ESRCH;
1.114 ad 1133: else {
1134: LIST_FOREACH(p, &pg->pg_members, p_pglist) {
1135: if (descend)
1136: ret |= ktrsetchildren(curl, p, ops,
1137: facs, ktd);
1138: else
1139: ret |= ktrops(curl, p, ops, facs,
1140: ktd);
1141: }
1.39 thorpej 1142: }
1.88 enami 1143:
1.28 christos 1144: } else {
1145: /*
1146: * by pid
1147: */
1.114 ad 1148: p = p_find(pid, PFIND_LOCKED);
1149: if (p == NULL)
1.28 christos 1150: error = ESRCH;
1.114 ad 1151: else if (descend)
1.105 ad 1152: ret |= ktrsetchildren(curl, p, ops, facs, ktd);
1.28 christos 1153: else
1.105 ad 1154: ret |= ktrops(curl, p, ops, facs, ktd);
1.28 christos 1155: }
1.121 ad 1156: mutex_exit(&proclist_lock);
1.114 ad 1157: if (error == 0 && !ret)
1.28 christos 1158: error = EPERM;
1159: done:
1.96 christos 1160: if (ktd != NULL) {
1.125 ad 1161: mutex_enter(&ktrace_lock);
1.96 christos 1162: if (error != 0) {
1163: /*
1164: * Wakeup the thread so that it can be die if we
1165: * can't trace any process.
1166: */
1167: ktd_wakeup(ktd);
1168: }
1.121 ad 1169: if (KTROP(ops) == KTROP_SET || KTROP(ops) == KTROP_CLEARFILE)
1.114 ad 1170: ktdrel(ktd);
1.125 ad 1171: mutex_exit(&ktrace_lock);
1.93 enami 1172: }
1.114 ad 1173: ktrexit(curl);
1.28 christos 1174: return (error);
1175: }
1176:
1177: /*
1.93 enami 1178: * fktrace system call
1.28 christos 1179: */
1180: /* ARGSUSED */
1181: int
1.128.4.2! mjf 1182: sys_fktrace(struct lwp *l, const struct sys_fktrace_args *uap, register_t *retval)
1.42 sommerfe 1183: {
1.128.4.2! mjf 1184: /* {
1.42 sommerfe 1185: syscallarg(int) fd;
1186: syscallarg(int) ops;
1187: syscallarg(int) facs;
1188: syscallarg(int) pid;
1.128.4.2! mjf 1189: } */
1.42 sommerfe 1190: struct file *fp = NULL;
1.98 christos 1191: struct filedesc *fdp = l->l_proc->p_fd;
1.70 yamt 1192: int error;
1.42 sommerfe 1193:
1.105 ad 1194: fdp = l->l_proc->p_fd;
1.54 thorpej 1195: if ((fp = fd_getfile(fdp, SCARG(uap, fd))) == NULL)
1196: return (EBADF);
1197:
1.70 yamt 1198: FILE_USE(fp);
1199:
1.54 thorpej 1200: if ((fp->f_flag & FWRITE) == 0)
1.70 yamt 1201: error = EBADF;
1202: else
1.105 ad 1203: error = ktrace_common(l, SCARG(uap, ops),
1.70 yamt 1204: SCARG(uap, facs), SCARG(uap, pid), fp);
1205:
1.98 christos 1206: FILE_UNUSE(fp, l);
1.42 sommerfe 1207:
1.70 yamt 1208: return error;
1.42 sommerfe 1209: }
1210:
1211: /*
1212: * ktrace system call
1213: */
1214: /* ARGSUSED */
1215: int
1.128.4.2! mjf 1216: sys_ktrace(struct lwp *l, const struct sys_ktrace_args *uap, register_t *retval)
1.19 thorpej 1217: {
1.128.4.2! mjf 1218: /* {
1.24 mycroft 1219: syscallarg(const char *) fname;
1.13 cgd 1220: syscallarg(int) ops;
1221: syscallarg(int) facs;
1222: syscallarg(int) pid;
1.128.4.2! mjf 1223: } */
1.28 christos 1224: struct vnode *vp = NULL;
1.42 sommerfe 1225: struct file *fp = NULL;
1.98 christos 1226: struct nameidata nd;
1.74 fvdl 1227: int error = 0;
1.98 christos 1228: int fd;
1.1 cgd 1229:
1.114 ad 1230: if (ktrenter(l))
1231: return EAGAIN;
1232:
1.102 christos 1233: if (KTROP(SCARG(uap, ops)) != KTROP_CLEAR) {
1.1 cgd 1234: /*
1235: * an operation which requires a file argument.
1236: */
1.128.4.2! mjf 1237: NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, fname));
1.22 christos 1238: if ((error = vn_open(&nd, FREAD|FWRITE, 0)) != 0) {
1.114 ad 1239: ktrexit(l);
1.1 cgd 1240: return (error);
1.9 cgd 1241: }
1.1 cgd 1242: vp = nd.ni_vp;
1.25 fvdl 1243: VOP_UNLOCK(vp, 0);
1.1 cgd 1244: if (vp->v_type != VREG) {
1.105 ad 1245: (void) vn_close(vp, FREAD|FWRITE, l->l_cred, l);
1.114 ad 1246: ktrexit(l);
1.1 cgd 1247: return (EACCES);
1248: }
1249: /*
1.42 sommerfe 1250: * XXX This uses up a file descriptor slot in the
1251: * tracing process for the duration of this syscall.
1252: * This is not expected to be a problem. If
1253: * falloc(NULL, ...) DTRT we could skip that part, but
1254: * that would require changing its interface to allow
1255: * the caller to pass in a ucred..
1256: *
1.88 enami 1257: * This will FILE_USE the fp it returns, if any.
1.42 sommerfe 1258: * Keep it in use until we return.
1.1 cgd 1259: */
1.105 ad 1260: if ((error = falloc(l, &fp, &fd)) != 0)
1.1 cgd 1261: goto done;
1.88 enami 1262:
1.93 enami 1263: fp->f_flag = FWRITE;
1.42 sommerfe 1264: fp->f_type = DTYPE_VNODE;
1265: fp->f_ops = &vnops;
1.118 christos 1266: fp->f_data = (void *)vp;
1.54 thorpej 1267: FILE_SET_MATURE(fp);
1.42 sommerfe 1268: vp = NULL;
1269: }
1.105 ad 1270: error = ktrace_common(l, SCARG(uap, ops), SCARG(uap, facs),
1.42 sommerfe 1271: SCARG(uap, pid), fp);
1.88 enami 1272: done:
1.1 cgd 1273: if (vp != NULL)
1.105 ad 1274: (void) vn_close(vp, FWRITE, l->l_cred, l);
1.42 sommerfe 1275: if (fp != NULL) {
1.98 christos 1276: FILE_UNUSE(fp, l); /* release file */
1277: fdrelease(l, fd); /* release fd table slot */
1.42 sommerfe 1278: }
1.1 cgd 1279: return (error);
1280: }
1281:
1.4 andrew 1282: int
1.125 ad 1283: ktrops(lwp_t *curl, struct proc *p, int ops, int facs,
1.93 enami 1284: struct ktr_desc *ktd)
1.1 cgd 1285: {
1.98 christos 1286: int vers = ops & KTRFAC_VER_MASK;
1.114 ad 1287: int error = 0;
1288:
1289: mutex_enter(&p->p_mutex);
1.125 ad 1290: mutex_enter(&ktrace_lock);
1.98 christos 1291:
1.105 ad 1292: if (!ktrcanset(curl, p))
1.114 ad 1293: goto out;
1.98 christos 1294:
1295: switch (vers) {
1296: case KTRFACv0:
1297: case KTRFACv1:
1298: break;
1299: default:
1.114 ad 1300: error = EINVAL;
1301: goto out;
1.98 christos 1302: }
1303:
1.28 christos 1304: if (KTROP(ops) == KTROP_SET) {
1.93 enami 1305: if (p->p_tracep != ktd) {
1.1 cgd 1306: /*
1307: * if trace file already in use, relinquish
1308: */
1.28 christos 1309: ktrderef(p);
1.93 enami 1310: p->p_tracep = ktd;
1.28 christos 1311: ktradref(p);
1.1 cgd 1312: }
1313: p->p_traceflag |= facs;
1.113 elad 1314: if (kauth_authorize_generic(curl->l_cred,
1315: KAUTH_GENERIC_ISSUSER, NULL) == 0)
1.1 cgd 1316: p->p_traceflag |= KTRFAC_ROOT;
1.88 enami 1317: } else {
1.1 cgd 1318: /* KTROP_CLEAR */
1319: if (((p->p_traceflag &= ~facs) & KTRFAC_MASK) == 0) {
1320: /* no more tracing */
1.28 christos 1321: ktrderef(p);
1.1 cgd 1322: }
1323: }
1.21 christos 1324:
1.98 christos 1325: if (p->p_traceflag)
1326: p->p_traceflag |= vers;
1.21 christos 1327: /*
1328: * Emit an emulation record, every time there is a ktrace
1.88 enami 1329: * change/attach request.
1.21 christos 1330: */
1331: if (KTRPOINT(p, KTR_EMUL))
1.84 dsl 1332: p->p_traceflag |= KTRFAC_TRC_EMUL;
1.49 martin 1333: #ifdef __HAVE_SYSCALL_INTERN
1.48 mycroft 1334: (*p->p_emul->e_syscall_intern)(p);
1.49 martin 1335: #endif
1.1 cgd 1336:
1.114 ad 1337: out:
1.125 ad 1338: mutex_exit(&ktrace_lock);
1.114 ad 1339: mutex_exit(&p->p_mutex);
1340:
1.1 cgd 1341: return (1);
1342: }
1343:
1.22 christos 1344: int
1.125 ad 1345: ktrsetchildren(lwp_t *curl, struct proc *top, int ops, int facs,
1.93 enami 1346: struct ktr_desc *ktd)
1.1 cgd 1347: {
1.28 christos 1348: struct proc *p;
1349: int ret = 0;
1.1 cgd 1350:
1.119 ad 1351: KASSERT(mutex_owned(&proclist_lock));
1.114 ad 1352:
1.1 cgd 1353: p = top;
1354: for (;;) {
1.105 ad 1355: ret |= ktrops(curl, p, ops, facs, ktd);
1.1 cgd 1356: /*
1357: * If this process has children, descend to them next,
1358: * otherwise do any siblings, and if done with this level,
1359: * follow back up the tree (but not past top).
1360: */
1.82 dsl 1361: if (LIST_FIRST(&p->p_children) != NULL) {
1.39 thorpej 1362: p = LIST_FIRST(&p->p_children);
1.82 dsl 1363: continue;
1364: }
1365: for (;;) {
1.1 cgd 1366: if (p == top)
1367: return (ret);
1.39 thorpej 1368: if (LIST_NEXT(p, p_sibling) != NULL) {
1369: p = LIST_NEXT(p, p_sibling);
1.1 cgd 1370: break;
1371: }
1.12 mycroft 1372: p = p->p_pptr;
1.1 cgd 1373: }
1374: }
1375: /*NOTREACHED*/
1376: }
1377:
1.93 enami 1378: void
1379: ktrwrite(struct ktr_desc *ktd, struct ktrace_entry *kte)
1.1 cgd 1380: {
1.74 fvdl 1381: struct uio auio;
1.93 enami 1382: struct iovec aiov[64], *iov;
1383: struct ktrace_entry *top = kte;
1384: struct ktr_header *kth;
1385: struct file *fp = ktd->ktd_fp;
1386: int error;
1387: next:
1388: auio.uio_iov = iov = &aiov[0];
1.1 cgd 1389: auio.uio_offset = 0;
1390: auio.uio_rw = UIO_WRITE;
1.93 enami 1391: auio.uio_resid = 0;
1392: auio.uio_iovcnt = 0;
1.101 yamt 1393: UIO_SETUP_SYSSPACE(&auio);
1.93 enami 1394: do {
1395: kth = &kte->kte_kth;
1.98 christos 1396:
1397: if (kth->ktr_version == 0) {
1398: /*
1399: * Convert back to the old format fields
1400: */
1401: TIMESPEC_TO_TIMEVAL(&kth->ktr_tv, &kth->ktr_time);
1402: kth->ktr_unused = NULL;
1403: }
1.118 christos 1404: iov->iov_base = (void *)kth;
1.93 enami 1405: iov++->iov_len = sizeof(struct ktr_header);
1406: auio.uio_resid += sizeof(struct ktr_header);
1.1 cgd 1407: auio.uio_iovcnt++;
1.93 enami 1408: if (kth->ktr_len > 0) {
1409: iov->iov_base = kte->kte_buf;
1410: iov++->iov_len = kth->ktr_len;
1411: auio.uio_resid += kth->ktr_len;
1412: auio.uio_iovcnt++;
1413: }
1414: } while ((kte = TAILQ_NEXT(kte, kte_list)) != NULL &&
1415: auio.uio_iovcnt < sizeof(aiov) / sizeof(aiov[0]) - 1);
1416:
1417: again:
1.127 ad 1418: mutex_enter(&fp->f_lock);
1.93 enami 1419: FILE_USE(fp);
1420: error = (*fp->f_ops->fo_write)(fp, &fp->f_offset, &auio,
1421: fp->f_cred, FOF_UPDATE_OFFSET);
1422: FILE_UNUSE(fp, NULL);
1423: switch (error) {
1424:
1425: case 0:
1426: if (auio.uio_resid > 0)
1427: goto again;
1428: if (kte != NULL)
1429: goto next;
1430: break;
1431:
1432: case EWOULDBLOCK:
1.116 thorpej 1433: kpause("ktrzzz", false, 1, NULL);
1.93 enami 1434: goto again;
1435:
1436: default:
1437: /*
1438: * If error encountered, give up tracing on this
1439: * vnode. Don't report EPIPE as this can easily
1440: * happen with fktrace()/ktruss.
1441: */
1442: #ifndef DEBUG
1443: if (error != EPIPE)
1444: #endif
1445: log(LOG_NOTICE,
1446: "ktrace write failed, errno %d, tracing stopped\n",
1447: error);
1.114 ad 1448: (void)ktrderefall(ktd, 0);
1.93 enami 1449: }
1450:
1451: while ((kte = top) != NULL) {
1452: top = TAILQ_NEXT(top, kte_list);
1453: ktefree(kte);
1454: }
1455: }
1456:
1457: void
1458: ktrace_thread(void *arg)
1459: {
1460: struct ktr_desc *ktd = arg;
1461: struct file *fp = ktd->ktd_fp;
1462: struct ktrace_entry *kte;
1463: int ktrerr, errcnt;
1464:
1.125 ad 1465: mutex_enter(&ktrace_lock);
1.93 enami 1466: for (;;) {
1467: kte = TAILQ_FIRST(&ktd->ktd_queue);
1468: if (kte == NULL) {
1469: if (ktd->ktd_flags & KTDF_WAIT) {
1470: ktd->ktd_flags &= ~(KTDF_WAIT | KTDF_BLOCKING);
1.114 ad 1471: cv_broadcast(&ktd->ktd_sync_cv);
1.93 enami 1472: }
1473: if (ktd->ktd_ref == 0)
1474: break;
1.125 ad 1475: cv_wait(&ktd->ktd_cv, &ktrace_lock);
1.93 enami 1476: continue;
1477: }
1478: TAILQ_INIT(&ktd->ktd_queue);
1479: ktd->ktd_qcount = 0;
1480: ktrerr = ktd->ktd_error;
1481: errcnt = ktd->ktd_errcnt;
1482: ktd->ktd_error = ktd->ktd_errcnt = 0;
1.125 ad 1483: mutex_exit(&ktrace_lock);
1.93 enami 1484:
1485: if (ktrerr) {
1486: log(LOG_NOTICE,
1487: "ktrace failed, fp %p, error 0x%x, total %d\n",
1488: fp, ktrerr, errcnt);
1489: }
1490: ktrwrite(ktd, kte);
1.125 ad 1491: mutex_enter(&ktrace_lock);
1.1 cgd 1492: }
1.93 enami 1493:
1494: TAILQ_REMOVE(&ktdq, ktd, ktd_list);
1.125 ad 1495: mutex_exit(&ktrace_lock);
1.28 christos 1496:
1.127 ad 1497: mutex_enter(&fp->f_lock);
1.42 sommerfe 1498: FILE_USE(fp);
1499:
1.1 cgd 1500: /*
1.93 enami 1501: * ktrace file descriptor can't be watched (are not visible to
1502: * userspace), so no kqueue stuff here
1503: * XXX: The above comment is wrong, because the fktrace file
1504: * descriptor is available in userland.
1.1 cgd 1505: */
1.93 enami 1506: closef(fp, NULL);
1507:
1508: callout_stop(&ktd->ktd_wakch);
1.124 ad 1509: callout_destroy(&ktd->ktd_wakch);
1.114 ad 1510: kmem_free(ktd, sizeof(*ktd));
1.39 thorpej 1511:
1.93 enami 1512: kthread_exit(0);
1.1 cgd 1513: }
1514:
1515: /*
1516: * Return true if caller has permission to set the ktracing state
1517: * of target. Essentially, the target can't possess any
1518: * more permissions than the caller. KTRFAC_ROOT signifies that
1.88 enami 1519: * root previously set the tracing status on the target process, and
1.1 cgd 1520: * so, only root may further change it.
1521: *
1522: * TODO: check groups. use caller effective gid.
1523: */
1.22 christos 1524: int
1.125 ad 1525: ktrcanset(lwp_t *calll, struct proc *targetp)
1.1 cgd 1526: {
1.119 ad 1527: KASSERT(mutex_owned(&targetp->p_mutex));
1.125 ad 1528: KASSERT(mutex_owned(&ktrace_lock));
1.114 ad 1529:
1.112 elad 1530: if (kauth_authorize_process(calll->l_cred, KAUTH_PROCESS_CANKTRACE,
1531: targetp, NULL, NULL, NULL) == 0)
1.1 cgd 1532: return (1);
1533:
1534: return (0);
1535: }
1.51 jdolecek 1536:
1537: /*
1538: * Put user defined entry to ktrace records.
1539: */
1540: int
1.128.4.2! mjf 1541: sys_utrace(struct lwp *l, const struct sys_utrace_args *uap, register_t *retval)
1.51 jdolecek 1542: {
1.128.4.2! mjf 1543: /* {
1.52 jdolecek 1544: syscallarg(const char *) label;
1.51 jdolecek 1545: syscallarg(void *) addr;
1546: syscallarg(size_t) len;
1.128.4.2! mjf 1547: } */
1.53 jdolecek 1548:
1.125 ad 1549: return ktruser(SCARG(uap, label), SCARG(uap, addr),
1.110 christos 1550: SCARG(uap, len), 1);
1.51 jdolecek 1551: }
CVSweb <webmaster@jp.NetBSD.org>