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