Annotation of src/sys/kern/kern_ktrace.c, Revision 1.74.2.13
1.74.2.13! skrll 1: /* $NetBSD: kern_ktrace.c,v 1.74.2.12 2005/02/15 18:04:48 skrll Exp $ */
1.11 cgd 2:
1.1 cgd 3: /*
1.9 cgd 4: * Copyright (c) 1989, 1993
5: * The Regents of the University of California. All rights reserved.
1.1 cgd 6: *
7: * Redistribution and use in source and binary forms, with or without
8: * modification, are permitted provided that the following conditions
9: * are met:
10: * 1. Redistributions of source code must retain the above copyright
11: * notice, this list of conditions and the following disclaimer.
12: * 2. Redistributions in binary form must reproduce the above copyright
13: * notice, this list of conditions and the following disclaimer in the
14: * documentation and/or other materials provided with the distribution.
1.74.2.3 skrll 15: * 3. Neither the name of the University nor the names of its contributors
1.1 cgd 16: * may be used to endorse or promote products derived from this software
17: * without specific prior written permission.
18: *
19: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29: * SUCH DAMAGE.
30: *
1.25 fvdl 31: * @(#)kern_ktrace.c 8.5 (Berkeley) 5/14/95
1.1 cgd 32: */
1.55 lukem 33:
34: #include <sys/cdefs.h>
1.74.2.13! skrll 35: __KERNEL_RCSID(0, "$NetBSD: kern_ktrace.c,v 1.74.2.12 2005/02/15 18:04:48 skrll Exp $");
1.29 thorpej 36:
37: #include "opt_ktrace.h"
1.62 manu 38: #include "opt_compat_mach.h"
1.1 cgd 39:
1.7 mycroft 40: #include <sys/param.h>
1.13 cgd 41: #include <sys/systm.h>
1.7 mycroft 42: #include <sys/proc.h>
43: #include <sys/file.h>
44: #include <sys/namei.h>
45: #include <sys/vnode.h>
1.74.2.8 skrll 46: #include <sys/kernel.h>
47: #include <sys/kthread.h>
1.7 mycroft 48: #include <sys/ktrace.h>
49: #include <sys/malloc.h>
50: #include <sys/syslog.h>
1.28 christos 51: #include <sys/filedesc.h>
1.42 sommerfe 52: #include <sys/ioctl.h>
1.74.2.8 skrll 53: #include <sys/callout.h>
1.1 cgd 54:
1.13 cgd 55: #include <sys/mount.h>
1.67 thorpej 56: #include <sys/sa.h>
1.13 cgd 57: #include <sys/syscallargs.h>
1.22 christos 58:
1.51 jdolecek 59: #ifdef KTRACE
60:
1.74.2.8 skrll 61: /*
62: * XXX:
63: * - need better error reporting?
64: * - p->p_tracep access lock. lock p_lock, lock ktd if !NULL, inc ref.
65: * - userland utility to sort ktrace.out by timestamp.
66: * - keep minimum information in ktrace_entry when rest of alloc failed.
67: * - enlarge ktrace_entry so that small entry won't require additional
68: * alloc?
69: * - per trace control of configurable parameters.
70: */
71:
72: struct ktrace_entry {
73: TAILQ_ENTRY(ktrace_entry) kte_list;
1.74.2.12 skrll 74: struct ktr_header kte_kth;
1.74.2.9 skrll 75: void *kte_buf;
1.74.2.8 skrll 76: };
77:
78: struct ktr_desc {
79: TAILQ_ENTRY(ktr_desc) ktd_list;
80: int ktd_flags;
81: #define KTDF_WAIT 0x0001
82: #define KTDF_DONE 0x0002
83: #define KTDF_BLOCKING 0x0004
84: #define KTDF_INTERACTIVE 0x0008
85: int ktd_error;
86: #define KTDE_ENOMEM 0x0001
87: #define KTDE_ENOSPC 0x0002
88: int ktd_errcnt;
89: int ktd_ref; /* # of reference */
90: int ktd_qcount; /* # of entry in the queue */
91:
92: /*
93: * Params to control behaviour.
94: */
95: int ktd_delayqcnt; /* # of entry allowed to delay */
96: int ktd_wakedelay; /* delay of wakeup in *tick* */
97: int ktd_intrwakdl; /* ditto, but when interactive */
98:
99: struct file *ktd_fp; /* trace output file */
100: struct proc *ktd_proc; /* our kernel thread */
101: TAILQ_HEAD(, ktrace_entry) ktd_queue;
102: struct callout ktd_wakch; /* delayed wakeup */
103: struct simplelock ktd_slock;
104: };
105:
106: static void ktrinitheader(struct ktr_header *, struct lwp *, int);
107: static void ktrwrite(struct ktr_desc *, struct ktrace_entry *);
108: static int ktrace_common(struct proc *, int, int, int, struct file *);
109: static int ktrops(struct proc *, struct proc *, int, int,
110: struct ktr_desc *);
111: static int ktrsetchildren(struct proc *, struct proc *, int, int,
112: struct ktr_desc *);
113: static int ktrcanset(struct proc *, struct proc *);
114: static int ktrsamefile(struct file *, struct file *);
115:
116: static struct ktr_desc *
117: ktd_lookup(struct file *);
118: static void ktdrel(struct ktr_desc *);
119: static void ktdref(struct ktr_desc *);
120: static void ktraddentry(struct lwp *, struct ktrace_entry *, int);
121: /* Flags for ktraddentry (3rd arg) */
122: #define KTA_NOWAIT 0x0000
123: #define KTA_WAITOK 0x0001
124: #define KTA_LARGE 0x0002
125: static void ktefree(struct ktrace_entry *);
126: static void ktd_logerrl(struct ktr_desc *, int);
127: static void ktd_logerr(struct proc *, int);
128: static void ktrace_thread(void *);
129:
130: /*
131: * Default vaules.
132: */
133: #define KTD_MAXENTRY 1000 /* XXX: tune */
134: #define KTD_TIMEOUT 5 /* XXX: tune */
135: #define KTD_DELAYQCNT 100 /* XXX: tune */
136: #define KTD_WAKEDELAY 5000 /* XXX: tune */
137: #define KTD_INTRWAKDL 100 /* XXX: tune */
138:
139: /*
140: * Patchable variables.
141: */
142: int ktd_maxentry = KTD_MAXENTRY; /* max # of entry in the queue */
143: int ktd_timeout = KTD_TIMEOUT; /* timeout in seconds */
144: int ktd_delayqcnt = KTD_DELAYQCNT; /* # of entry allowed to delay */
145: int ktd_wakedelay = KTD_WAKEDELAY; /* delay of wakeup in *ms* */
146: int ktd_intrwakdl = KTD_INTRWAKDL; /* ditto, but when interactive */
147:
148: static struct simplelock ktdq_slock = SIMPLELOCK_INITIALIZER;
149: static TAILQ_HEAD(, ktr_desc) ktdq = TAILQ_HEAD_INITIALIZER(ktdq);
150:
151: MALLOC_DEFINE(M_KTRACE, "ktrace", "ktrace data buffer");
152: POOL_INIT(kte_pool, sizeof(struct ktrace_entry), 0, 0, 0,
153: "ktepl", &pool_allocator_nointr);
154:
155: static __inline void
156: ktd_wakeup(struct ktr_desc *ktd)
157: {
158:
159: callout_stop(&ktd->ktd_wakch);
160: wakeup(ktd);
161: }
162:
163: static void
164: ktd_logerrl(struct ktr_desc *ktd, int error)
165: {
166:
167: ktd->ktd_error |= error;
168: ktd->ktd_errcnt++;
169: }
170:
171: static void
172: ktd_logerr(struct proc *p, int error)
173: {
174: struct ktr_desc *ktd = p->p_tracep;
175:
176: if (ktd == NULL)
177: return;
178:
179: simple_lock(&ktd->ktd_slock);
180: ktd_logerrl(ktd, error);
181: simple_unlock(&ktd->ktd_slock);
182: }
183:
184: /*
185: * Release a reference. Called with ktd_slock held.
186: */
187: void
188: ktdrel(struct ktr_desc *ktd)
189: {
190:
191: KDASSERT(ktd->ktd_ref != 0);
192: KASSERT(ktd->ktd_ref > 0);
193: if (--ktd->ktd_ref <= 0) {
194: ktd->ktd_flags |= KTDF_DONE;
195: wakeup(ktd);
196: }
197: simple_unlock(&ktd->ktd_slock);
198: }
199:
200: void
201: ktdref(struct ktr_desc *ktd)
202: {
203:
204: simple_lock(&ktd->ktd_slock);
205: ktd->ktd_ref++;
206: simple_unlock(&ktd->ktd_slock);
207: }
208:
209: struct ktr_desc *
210: ktd_lookup(struct file *fp)
211: {
212: struct ktr_desc *ktd;
213:
214: simple_lock(&ktdq_slock);
215: for (ktd = TAILQ_FIRST(&ktdq); ktd != NULL;
216: ktd = TAILQ_NEXT(ktd, ktd_list)) {
217: simple_lock(&ktd->ktd_slock);
218: if (ktrsamefile(ktd->ktd_fp, fp)) {
219: ktd->ktd_ref++;
220: simple_unlock(&ktd->ktd_slock);
221: break;
222: }
223: simple_unlock(&ktd->ktd_slock);
224: }
225: simple_unlock(&ktdq_slock);
226: return (ktd);
227: }
228:
229: void
230: ktraddentry(struct lwp *l, struct ktrace_entry *kte, int flags)
231: {
232: struct proc *p = l->l_proc;
233: struct ktr_desc *ktd;
234: #ifdef DEBUG
235: struct timeval t;
236: int s;
237: #endif
238:
239: if (p->p_traceflag & KTRFAC_TRC_EMUL) {
240: /* Add emulation trace before first entry for this process */
241: p->p_traceflag &= ~KTRFAC_TRC_EMUL;
242: ktremul(l);
243: }
244:
245: /*
246: * Tracing may be canceled while we were sleeping waiting for
247: * memory.
248: */
249: ktd = p->p_tracep;
250: if (ktd == NULL)
251: goto freekte;
252:
253: /*
254: * Bump reference count so that the object will remain while
255: * we are here. Note that the trace is controlled by other
256: * process.
257: */
258: ktdref(ktd);
259:
260: simple_lock(&ktd->ktd_slock);
261: if (ktd->ktd_flags & KTDF_DONE)
262: goto relktd;
263:
264: if (ktd->ktd_qcount > ktd_maxentry) {
265: ktd_logerrl(ktd, KTDE_ENOSPC);
266: goto relktd;
267: }
268: TAILQ_INSERT_TAIL(&ktd->ktd_queue, kte, kte_list);
269: ktd->ktd_qcount++;
270: if (ktd->ktd_flags & KTDF_BLOCKING)
271: goto skip_sync;
272:
273: if (flags & KTA_WAITOK &&
274: (/* flags & KTA_LARGE */0 || ktd->ktd_flags & KTDF_WAIT ||
275: ktd->ktd_qcount > ktd_maxentry >> 1))
276: /*
277: * Sync with writer thread since we're requesting rather
278: * big one or many requests are pending.
279: */
280: do {
281: ktd->ktd_flags |= KTDF_WAIT;
282: ktd_wakeup(ktd);
283: #ifdef DEBUG
284: s = splclock();
285: t = mono_time;
286: splx(s);
287: #endif
288: if (ltsleep(&ktd->ktd_flags, PWAIT, "ktrsync",
289: ktd_timeout * hz, &ktd->ktd_slock) != 0) {
290: ktd->ktd_flags |= KTDF_BLOCKING;
291: /*
292: * Maybe the writer thread is blocking
293: * completely for some reason, but
294: * don't stop target process forever.
295: */
296: log(LOG_NOTICE, "ktrace timeout\n");
297: break;
298: }
299: #ifdef DEBUG
300: s = splclock();
301: timersub(&mono_time, &t, &t);
302: splx(s);
303: if (t.tv_sec > 0)
304: log(LOG_NOTICE,
305: "ktrace long wait: %ld.%06ld\n",
306: t.tv_sec, t.tv_usec);
307: #endif
308: } while (p->p_tracep == ktd &&
309: (ktd->ktd_flags & (KTDF_WAIT | KTDF_DONE)) == KTDF_WAIT);
310: else {
311: /* Schedule delayed wakeup */
312: if (ktd->ktd_qcount > ktd->ktd_delayqcnt)
313: ktd_wakeup(ktd); /* Wakeup now */
314: else if (!callout_pending(&ktd->ktd_wakch))
315: callout_reset(&ktd->ktd_wakch,
316: ktd->ktd_flags & KTDF_INTERACTIVE ?
317: ktd->ktd_intrwakdl : ktd->ktd_wakedelay,
318: (void (*)(void *))wakeup, ktd);
319: }
320:
321: skip_sync:
322: ktdrel(ktd);
323: return;
324:
325: relktd:
326: ktdrel(ktd);
327:
328: freekte:
329: ktefree(kte);
330: }
331:
332: void
333: ktefree(struct ktrace_entry *kte)
334: {
335:
1.74.2.9 skrll 336: if (kte->kte_buf != NULL)
1.74.2.8 skrll 337: free(kte->kte_buf, M_KTRACE);
338: pool_put(&kte_pool, kte);
339: }
1.44 sommerfe 340:
341: /*
342: * "deep" compare of two files for the purposes of clearing a trace.
343: * Returns true if they're the same open file, or if they point at the
344: * same underlying vnode/socket.
345: */
346:
347: int
1.74.2.3 skrll 348: ktrsamefile(struct file *f1, struct file *f2)
1.44 sommerfe 349: {
1.74.2.3 skrll 350:
1.44 sommerfe 351: return ((f1 == f2) ||
1.45 sommerfe 352: ((f1 != NULL) && (f2 != NULL) &&
353: (f1->f_type == f2->f_type) &&
1.44 sommerfe 354: (f1->f_data == f2->f_data)));
355: }
1.22 christos 356:
1.28 christos 357: void
1.74.2.3 skrll 358: ktrderef(struct proc *p)
1.28 christos 359: {
1.74.2.8 skrll 360: struct ktr_desc *ktd = p->p_tracep;
361:
1.42 sommerfe 362: p->p_traceflag = 0;
1.74.2.8 skrll 363: if (ktd == NULL)
1.28 christos 364: return;
1.74.2.3 skrll 365: p->p_tracep = NULL;
366:
1.74.2.8 skrll 367: simple_lock(&ktd->ktd_slock);
368: wakeup(&ktd->ktd_flags);
369: ktdrel(ktd);
1.28 christos 370: }
371:
372: void
1.74.2.3 skrll 373: ktradref(struct proc *p)
1.28 christos 374: {
1.74.2.8 skrll 375: struct ktr_desc *ktd = p->p_tracep;
1.28 christos 376:
1.74.2.8 skrll 377: ktdref(ktd);
1.28 christos 378: }
379:
1.39 thorpej 380: void
1.74.2.7 skrll 381: ktrinitheader(struct ktr_header *kth, struct lwp *l, int type)
1.1 cgd 382: {
1.74.2.7 skrll 383: struct proc *p = l->l_proc;
1.74.2.9 skrll 384: struct timeval tv;
1.1 cgd 385:
1.74.2.3 skrll 386: (void)memset(kth, 0, sizeof(*kth));
1.1 cgd 387: kth->ktr_type = type;
1.74.2.9 skrll 388: microtime(&tv);
389: TIMEVAL_TO_TIMESPEC(&tv, &kth->ktr_time);
1.1 cgd 390: kth->ktr_pid = p->p_pid;
1.32 perry 391: memcpy(kth->ktr_comm, p->p_comm, MAXCOMLEN);
1.74.2.9 skrll 392:
1.74.2.12 skrll 393: kth->ktr_version = KTRFAC_VERSION(p->p_traceflag);
1.74.2.9 skrll 394:
395: switch (KTRFAC_VERSION(p->p_traceflag)) {
396: case 0:
397: /* This is the original format */
398: break;
399: case 1:
400: kth->ktr_lid = l->l_lid;
401: break;
402: default:
403: break;
404: }
1.1 cgd 405: }
406:
1.74.2.8 skrll 407: void
1.74.2.7 skrll 408: ktrsyscall(struct lwp *l, register_t code, register_t realcode,
1.74.2.3 skrll 409: const struct sysent *callp, register_t args[])
1.1 cgd 410: {
1.74.2.7 skrll 411: struct proc *p = l->l_proc;
1.74.2.8 skrll 412: struct ktrace_entry *kte;
413: struct ktr_header *kth;
1.74.2.6 skrll 414: struct ktr_syscall *ktp;
1.17 cgd 415: register_t *argp;
1.74.2.8 skrll 416: int argsize;
1.57 fvdl 417: size_t len;
1.60 thorpej 418: u_int i;
1.57 fvdl 419:
1.66 manu 420: if (callp == NULL)
421: callp = p->p_emul->e_sysent;
1.74.2.3 skrll 422:
423: argsize = callp[code].sy_argsize;
424: #ifdef _LP64
425: if (p->p_flag & P_32)
426: argsize = argsize << 1;
427: #endif
1.57 fvdl 428: len = sizeof(struct ktr_syscall) + argsize;
1.1 cgd 429:
1.9 cgd 430: p->p_traceflag |= KTRFAC_ACTIVE;
1.74.2.8 skrll 431: kte = pool_get(&kte_pool, PR_WAITOK);
432: kth = &kte->kte_kth;
433: ktrinitheader(kth, l, KTR_SYSCALL);
434:
435: ktp = malloc(len, M_KTRACE, M_WAITOK);
1.61 manu 436: ktp->ktr_code = realcode;
1.17 cgd 437: ktp->ktr_argsize = argsize;
1.74.2.8 skrll 438: argp = (register_t *)(ktp + 1);
1.31 perry 439: for (i = 0; i < (argsize / sizeof(*argp)); i++)
1.1 cgd 440: *argp++ = args[i];
1.74.2.8 skrll 441: kth->ktr_len = len;
442: kte->kte_buf = ktp;
443:
444: ktraddentry(l, kte, KTA_WAITOK);
1.9 cgd 445: p->p_traceflag &= ~KTRFAC_ACTIVE;
1.1 cgd 446: }
447:
1.74.2.8 skrll 448: void
1.74.2.7 skrll 449: ktrsysret(struct lwp *l, register_t code, int error, register_t *retval)
1.1 cgd 450: {
1.74.2.7 skrll 451: struct proc *p = l->l_proc;
1.74.2.8 skrll 452: struct ktrace_entry *kte;
453: struct ktr_header *kth;
454: struct ktr_sysret *ktp;
1.1 cgd 455:
1.9 cgd 456: p->p_traceflag |= KTRFAC_ACTIVE;
1.74.2.8 skrll 457: kte = pool_get(&kte_pool, PR_WAITOK);
458: kth = &kte->kte_kth;
459: ktrinitheader(kth, l, KTR_SYSRET);
460:
461: ktp = malloc(sizeof(struct ktr_sysret), M_KTRACE, M_WAITOK);
462: ktp->ktr_code = code;
463: ktp->ktr_eosys = 0; /* XXX unused */
464: ktp->ktr_error = error;
465: ktp->ktr_retval = retval ? retval[0] : 0;
466: ktp->ktr_retval_1 = retval ? retval[1] : 0;
1.1 cgd 467:
1.74.2.8 skrll 468: kth->ktr_len = sizeof(struct ktr_sysret);
469: kte->kte_buf = ktp;
1.1 cgd 470:
1.74.2.8 skrll 471: ktraddentry(l, kte, KTA_WAITOK);
1.9 cgd 472: p->p_traceflag &= ~KTRFAC_ACTIVE;
1.1 cgd 473: }
474:
1.74.2.8 skrll 475: /*
476: * XXX: ndp->ni_pathlen should be passed.
477: */
478: void
1.74.2.7 skrll 479: ktrnamei(struct lwp *l, char *path)
1.1 cgd 480: {
481:
1.74.2.8 skrll 482: ktrkmem(l, KTR_NAMEI, path, strlen(path));
1.18 christos 483: }
484:
1.74.2.8 skrll 485: void
1.74.2.7 skrll 486: ktremul(struct lwp *l)
1.18 christos 487: {
1.74.2.8 skrll 488: const char *emul = l->l_proc->p_emul->e_name;
1.1 cgd 489:
1.74.2.8 skrll 490: ktrkmem(l, KTR_EMUL, emul, strlen(emul));
1.1 cgd 491: }
492:
1.74.2.8 skrll 493: void
494: ktrkmem(struct lwp *l, int type, const void *buf, size_t len)
1.74.2.3 skrll 495: {
1.74.2.7 skrll 496: struct proc *p = l->l_proc;
1.74.2.8 skrll 497: struct ktrace_entry *kte;
498: struct ktr_header *kth;
1.74.2.3 skrll 499:
500: p->p_traceflag |= KTRFAC_ACTIVE;
1.74.2.8 skrll 501: kte = pool_get(&kte_pool, PR_WAITOK);
502: kth = &kte->kte_kth;
503: ktrinitheader(kth, l, type);
504:
505: kth->ktr_len = len;
506: kte->kte_buf = malloc(len, M_KTRACE, M_WAITOK);
507: memcpy(kte->kte_buf, buf, len);
1.74.2.3 skrll 508:
1.74.2.8 skrll 509: ktraddentry(l, kte, KTA_WAITOK);
1.74.2.3 skrll 510: p->p_traceflag &= ~KTRFAC_ACTIVE;
511: }
512:
1.74.2.8 skrll 513: void
1.74.2.7 skrll 514: ktrgenio(struct lwp *l, int fd, enum uio_rw rw, struct iovec *iov,
1.74.2.3 skrll 515: int len, int error)
1.1 cgd 516: {
1.74.2.7 skrll 517: struct proc *p = l->l_proc;
1.74.2.8 skrll 518: struct ktrace_entry *kte;
519: struct ktr_header *kth;
1.28 christos 520: struct ktr_genio *ktp;
1.74.2.6 skrll 521: int resid = len, cnt;
1.74.2.7 skrll 522: caddr_t cp;
1.39 thorpej 523: int buflen;
524:
1.1 cgd 525: if (error)
1.74.2.8 skrll 526: return;
1.39 thorpej 527:
1.9 cgd 528: p->p_traceflag |= KTRFAC_ACTIVE;
1.39 thorpej 529:
1.74.2.8 skrll 530: next:
531: buflen = min(PAGE_SIZE, resid + sizeof(struct ktr_genio));
532:
533: kte = pool_get(&kte_pool, PR_WAITOK);
534: kth = &kte->kte_kth;
535: ktrinitheader(kth, l, KTR_GENIO);
1.39 thorpej 536:
1.74.2.8 skrll 537: ktp = malloc(buflen, M_KTRACE, M_WAITOK);
1.1 cgd 538: ktp->ktr_fd = fd;
539: ktp->ktr_rw = rw;
1.39 thorpej 540:
1.74.2.8 skrll 541: kte->kte_buf = ktp;
1.39 thorpej 542:
1.74.2.8 skrll 543: cp = (caddr_t)(ktp + 1);
1.39 thorpej 544: buflen -= sizeof(struct ktr_genio);
1.74.2.8 skrll 545: kth->ktr_len = sizeof(struct ktr_genio);
1.39 thorpej 546:
1.74.2.8 skrll 547: while (buflen > 0) {
548: cnt = min(iov->iov_len, buflen);
549: if (copyin(iov->iov_base, cp, cnt) != 0)
550: goto out;
551: kth->ktr_len += cnt;
552: buflen -= cnt;
553: resid -= cnt;
554: iov->iov_len -= cnt;
555: if (iov->iov_len == 0)
556: iov++;
557: else
558: iov->iov_base = (caddr_t)iov->iov_base + cnt;
559: }
560:
561: /*
562: * Don't push so many entry at once. It will cause kmem map
563: * shortage.
564: */
565: ktraddentry(l, kte, KTA_WAITOK | KTA_LARGE);
566: if (resid > 0) {
1.67 thorpej 567: #if 0 /* XXX NJWLWP */
1.46 thorpej 568: KDASSERT(p->p_cpu != NULL);
569: KDASSERT(p->p_cpu == curcpu());
1.67 thorpej 570: #endif
571: /* XXX NJWLWP */
572: if (curcpu()->ci_schedstate.spc_flags & SPCF_SHOULDYIELD)
573: preempt(1);
1.39 thorpej 574:
1.74.2.8 skrll 575: goto next;
1.1 cgd 576: }
577:
1.9 cgd 578: p->p_traceflag &= ~KTRFAC_ACTIVE;
1.74.2.8 skrll 579: return;
580:
581: out:
582: ktefree(kte);
583: p->p_traceflag &= ~KTRFAC_ACTIVE;
1.1 cgd 584: }
585:
1.74.2.8 skrll 586: void
1.74.2.7 skrll 587: ktrpsig(struct lwp *l, int sig, sig_t action, const sigset_t *mask,
1.74.2.3 skrll 588: const ksiginfo_t *ksi)
1.1 cgd 589: {
1.74.2.7 skrll 590: struct proc *p = l->l_proc;
1.74.2.8 skrll 591: struct ktrace_entry *kte;
592: struct ktr_header *kth;
1.74.2.3 skrll 593: struct {
594: struct ktr_psig kp;
595: siginfo_t si;
1.74.2.8 skrll 596: } *kbuf;
1.1 cgd 597:
1.9 cgd 598: p->p_traceflag |= KTRFAC_ACTIVE;
1.74.2.8 skrll 599: kte = pool_get(&kte_pool, PR_WAITOK);
600: kth = &kte->kte_kth;
601: ktrinitheader(kth, l, KTR_PSIG);
602:
603: kbuf = malloc(sizeof(*kbuf), M_KTRACE, M_WAITOK);
604: kbuf->kp.signo = (char)sig;
605: kbuf->kp.action = action;
606: kbuf->kp.mask = *mask;
607: kte->kte_buf = kbuf;
1.74.2.3 skrll 608: if (ksi) {
1.74.2.8 skrll 609: kbuf->kp.code = KSI_TRAPCODE(ksi);
610: (void)memset(&kbuf->si, 0, sizeof(kbuf->si));
611: kbuf->si._info = ksi->ksi_info;
1.74.2.11 skrll 612: kth->ktr_len = sizeof(*kbuf);
1.74.2.3 skrll 613: } else {
1.74.2.8 skrll 614: kbuf->kp.code = 0;
615: kth->ktr_len = sizeof(struct ktr_psig);
1.74.2.3 skrll 616: }
1.74.2.8 skrll 617:
618: ktraddentry(l, kte, KTA_WAITOK);
1.9 cgd 619: p->p_traceflag &= ~KTRFAC_ACTIVE;
620: }
621:
1.74.2.8 skrll 622: void
1.74.2.7 skrll 623: ktrcsw(struct lwp *l, int out, int user)
1.9 cgd 624: {
1.74.2.7 skrll 625: struct proc *p = l->l_proc;
1.74.2.8 skrll 626: struct ktrace_entry *kte;
627: struct ktr_header *kth;
628: struct ktr_csw *kc;
1.9 cgd 629:
630: p->p_traceflag |= KTRFAC_ACTIVE;
631:
1.74.2.8 skrll 632: /*
633: * We can't sleep if we're already going to sleep (if original
634: * condition is met during sleep, we hang up).
635: */
636: kte = pool_get(&kte_pool, out ? PR_NOWAIT : PR_WAITOK);
637: if (kte == NULL) {
638: ktd_logerr(p, KTDE_ENOMEM);
639: goto out;
640: }
641: kth = &kte->kte_kth;
642: ktrinitheader(kth, l, KTR_CSW);
643:
644: kc = malloc(sizeof(struct ktr_csw), M_KTRACE,
645: out ? M_NOWAIT : M_WAITOK);
646: if (kc == NULL) {
647: ktd_logerr(p, KTDE_ENOMEM);
648: goto free_kte;
649: }
650: kc->out = out;
651: kc->user = user;
652: kth->ktr_len = sizeof(struct ktr_csw);
653: kte->kte_buf = kc;
654:
655: ktraddentry(l, kte, out ? KTA_NOWAIT : KTA_WAITOK);
656: p->p_traceflag &= ~KTRFAC_ACTIVE;
657: return;
658:
659: free_kte:
660: pool_put(&kte_pool, kte);
661: out:
1.9 cgd 662: p->p_traceflag &= ~KTRFAC_ACTIVE;
1.1 cgd 663: }
664:
1.74.2.8 skrll 665: void
1.74.2.7 skrll 666: ktruser(struct lwp *l, const char *id, void *addr, size_t len, int ustr)
1.51 jdolecek 667: {
1.74.2.7 skrll 668: struct proc *p = l->l_proc;
1.74.2.8 skrll 669: struct ktrace_entry *kte;
670: struct ktr_header *kth;
1.51 jdolecek 671: struct ktr_user *ktp;
672: caddr_t user_dta;
673:
674: p->p_traceflag |= KTRFAC_ACTIVE;
1.74.2.8 skrll 675: kte = pool_get(&kte_pool, PR_WAITOK);
676: kth = &kte->kte_kth;
677: ktrinitheader(kth, l, KTR_USER);
678:
679: ktp = malloc(sizeof(struct ktr_user) + len, M_KTRACE, M_WAITOK);
1.51 jdolecek 680: if (ustr) {
681: if (copyinstr(id, ktp->ktr_id, KTR_USER_MAXIDLEN, NULL) != 0)
682: ktp->ktr_id[0] = '\0';
683: } else
684: strncpy(ktp->ktr_id, id, KTR_USER_MAXIDLEN);
685: ktp->ktr_id[KTR_USER_MAXIDLEN-1] = '\0';
686:
1.74.2.8 skrll 687: user_dta = (caddr_t)(ktp + 1);
688: if (copyin(addr, (void *)user_dta, len) != 0)
1.51 jdolecek 689: len = 0;
690:
1.74.2.8 skrll 691: kth->ktr_len = sizeof(struct ktr_user) + len;
692: kte->kte_buf = ktp;
1.51 jdolecek 693:
1.74.2.8 skrll 694: ktraddentry(l, kte, KTA_WAITOK);
1.51 jdolecek 695: p->p_traceflag &= ~KTRFAC_ACTIVE;
696: }
697:
1.74.2.8 skrll 698: void
1.74.2.7 skrll 699: ktrmmsg(struct lwp *l, const void *msgh, size_t size)
1.62 manu 700: {
1.74.2.8 skrll 701: ktrkmem(l, KTR_MMSG, msgh, size);
1.74.2.2 skrll 702: }
703:
1.74.2.8 skrll 704: void
1.74.2.7 skrll 705: ktrmool(struct lwp *l, const void *kaddr, size_t size, const void *uaddr)
1.74.2.4 skrll 706: {
1.74.2.7 skrll 707: struct proc *p = l->l_proc;
1.74.2.8 skrll 708: struct ktrace_entry *kte;
709: struct ktr_header *kth;
1.74.2.4 skrll 710: struct ktr_mool *kp;
711: struct ktr_mool *buf;
712:
713: p->p_traceflag |= KTRFAC_ACTIVE;
1.74.2.8 skrll 714: kte = pool_get(&kte_pool, PR_WAITOK);
715: kth = &kte->kte_kth;
716: ktrinitheader(kth, l, KTR_MOOL);
1.74.2.4 skrll 717:
1.74.2.8 skrll 718: kp = malloc(size + sizeof(*kp), M_KTRACE, M_WAITOK);
1.74.2.4 skrll 719: kp->uaddr = uaddr;
720: kp->size = size;
721: buf = kp + 1; /* Skip uaddr and size */
722: (void)memcpy(buf, kaddr, size);
723:
1.74.2.8 skrll 724: kth->ktr_len = size + sizeof(*kp);
725: kte->kte_buf = kp;
1.74.2.4 skrll 726:
1.74.2.8 skrll 727: ktraddentry(l, kte, KTA_WAITOK);
1.74.2.4 skrll 728: p->p_traceflag &= ~KTRFAC_ACTIVE;
729: }
730:
1.74.2.8 skrll 731: void
1.74.2.7 skrll 732: ktrsaupcall(struct lwp *l, int type, int nevent, int nint, void *sas,
733: void *ap)
734: {
735: struct proc *p = l->l_proc;
1.74.2.8 skrll 736: struct ktrace_entry *kte;
737: struct ktr_header *kth;
1.74.2.7 skrll 738: struct ktr_saupcall *ktp;
739: size_t len;
740: struct sa_t **sapp;
741: int i;
742:
743: p->p_traceflag |= KTRFAC_ACTIVE;
1.74.2.8 skrll 744: kte = pool_get(&kte_pool, PR_WAITOK);
745: kth = &kte->kte_kth;
746: ktrinitheader(kth, l, KTR_SAUPCALL);
1.74.2.7 skrll 747:
748: len = sizeof(struct ktr_saupcall);
1.74.2.8 skrll 749: ktp = malloc(len + sizeof(struct sa_t) * (nevent + nint + 1), M_KTRACE,
1.74.2.7 skrll 750: M_WAITOK);
751:
752: ktp->ktr_type = type;
753: ktp->ktr_nevent = nevent;
754: ktp->ktr_nint = nint;
755: ktp->ktr_sas = sas;
756: ktp->ktr_ap = ap;
757: /*
758: * Copy the sa_t's
759: */
760: sapp = (struct sa_t **) sas;
761:
762: for (i = nevent + nint; i >= 0; i--) {
763: if (copyin(*sapp, (char *)ktp + len, sizeof(struct sa_t)) == 0)
764: len += sizeof(struct sa_t);
765: sapp++;
766: }
767:
1.74.2.8 skrll 768: kth->ktr_len = len;
769: kte->kte_buf = ktp;
1.74.2.7 skrll 770:
1.74.2.8 skrll 771: ktraddentry(l, kte, KTA_WAITOK);
1.74.2.7 skrll 772: p->p_traceflag &= ~KTRFAC_ACTIVE;
773: }
1.62 manu 774:
1.1 cgd 775: /* Interface and common routines */
776:
1.17 cgd 777: int
1.74.2.8 skrll 778: ktrace_common(struct proc *curp, int ops, int facs, int pid, struct file *fp)
1.28 christos 779: {
1.74.2.7 skrll 780: struct proc *p;
1.74.2.8 skrll 781: struct pgrp *pg;
782: struct ktr_desc *ktd = NULL;
1.74.2.7 skrll 783: int ret = 0;
1.74.2.8 skrll 784: int error = 0;
1.42 sommerfe 785: int descend;
1.28 christos 786:
787: curp->p_traceflag |= KTRFAC_ACTIVE;
1.42 sommerfe 788: descend = ops & KTRFLAG_DESCEND;
789: facs = facs & ~((unsigned) KTRFAC_ROOT);
1.28 christos 790:
1.74.2.8 skrll 791: switch (KTROP(ops)) {
792:
793: case KTROP_CLEARFILE:
794: /*
795: * Clear all uses of the tracefile
796: */
797:
798: ktd = ktd_lookup(fp);
799: if (ktd == NULL)
800: goto done;
801:
1.37 thorpej 802: proclist_lock_read();
1.74.2.10 skrll 803: PROCLIST_FOREACH(p, &allproc) {
1.74.2.8 skrll 804: if (p->p_tracep == ktd) {
1.28 christos 805: if (ktrcanset(curp, p))
806: ktrderef(p);
807: else
808: error = EPERM;
809: }
810: }
1.36 thorpej 811: proclist_unlock_read();
1.28 christos 812: goto done;
1.42 sommerfe 813:
1.74.2.8 skrll 814: case KTROP_SET:
815: ktd = ktd_lookup(fp);
816: if (ktd == NULL) {
817: ktd = malloc(sizeof(struct ktr_desc),
818: M_KTRACE, M_WAITOK);
819: TAILQ_INIT(&ktd->ktd_queue);
820: simple_lock_init(&ktd->ktd_slock);
821: callout_init(&ktd->ktd_wakch);
822: ktd->ktd_flags = ktd->ktd_qcount =
823: ktd->ktd_error = ktd->ktd_errcnt = 0;
824: ktd->ktd_ref = 1;
825: ktd->ktd_delayqcnt = ktd_delayqcnt;
826: ktd->ktd_wakedelay = mstohz(ktd_wakedelay);
827: ktd->ktd_intrwakdl = mstohz(ktd_intrwakdl);
828: /*
829: * XXX: not correct. needs an way to detect
830: * whether ktruss or ktrace.
831: */
832: if (fp->f_type == DTYPE_PIPE)
833: ktd->ktd_flags |= KTDF_INTERACTIVE;
1.42 sommerfe 834:
1.74.2.8 skrll 835: error = kthread_create1(ktrace_thread, ktd,
836: &ktd->ktd_proc, "ktr %p", ktd);
837: if (error != 0) {
838: free(ktd, M_KTRACE);
839: goto done;
840: }
841:
842: simple_lock(&fp->f_slock);
843: fp->f_count++;
844: simple_unlock(&fp->f_slock);
845: ktd->ktd_fp = fp;
846:
847: simple_lock(&ktdq_slock);
848: TAILQ_INSERT_TAIL(&ktdq, ktd, ktd_list);
849: simple_unlock(&ktdq_slock);
850: }
851: break;
852:
853: case KTROP_CLEAR:
854: break;
1.43 sommerfe 855: }
1.74.2.3 skrll 856:
1.28 christos 857: /*
858: * need something to (un)trace (XXX - why is this here?)
859: */
860: if (!facs) {
861: error = EINVAL;
862: goto done;
863: }
1.74.2.8 skrll 864:
1.74.2.3 skrll 865: /*
1.28 christos 866: * do it
867: */
1.42 sommerfe 868: if (pid < 0) {
1.28 christos 869: /*
870: * by process group
871: */
1.74.2.3 skrll 872: pg = pg_find(-pid, PFIND_UNLOCK_FAIL);
1.28 christos 873: if (pg == NULL) {
874: error = ESRCH;
875: goto done;
876: }
1.74.2.3 skrll 877: LIST_FOREACH(p, &pg->pg_members, p_pglist) {
1.28 christos 878: if (descend)
1.74.2.8 skrll 879: ret |= ktrsetchildren(curp, p, ops, facs, ktd);
1.74.2.3 skrll 880: else
1.74.2.8 skrll 881: ret |= ktrops(curp, p, ops, facs, ktd);
1.39 thorpej 882: }
1.74.2.3 skrll 883:
1.28 christos 884: } else {
885: /*
886: * by pid
887: */
1.74.2.3 skrll 888: p = p_find(pid, PFIND_UNLOCK_FAIL);
1.28 christos 889: if (p == NULL) {
890: error = ESRCH;
891: goto done;
892: }
893: if (descend)
1.74.2.8 skrll 894: ret |= ktrsetchildren(curp, p, ops, facs, ktd);
1.28 christos 895: else
1.74.2.8 skrll 896: ret |= ktrops(curp, p, ops, facs, ktd);
1.28 christos 897: }
1.74.2.3 skrll 898: proclist_unlock_read(); /* taken by p{g}_find */
1.28 christos 899: if (!ret)
900: error = EPERM;
901: done:
1.74.2.13! skrll 902: if (ktd != NULL) {
! 903: if (error != 0) {
! 904: /*
! 905: * Wakeup the thread so that it can be die if we
! 906: * can't trace any process.
! 907: */
! 908: ktd_wakeup(ktd);
! 909: }
! 910: if (KTROP(ops) == KTROP_SET || KTROP(ops) == KTROP_CLEARFILE) {
! 911: simple_lock(&ktd->ktd_slock);
! 912: ktdrel(ktd);
! 913: }
1.74.2.8 skrll 914: }
1.28 christos 915: curp->p_traceflag &= ~KTRFAC_ACTIVE;
916: return (error);
917: }
918:
919: /*
1.74.2.8 skrll 920: * fktrace system call
1.28 christos 921: */
922: /* ARGSUSED */
923: int
1.74.2.3 skrll 924: sys_fktrace(struct lwp *l, void *v, register_t *retval)
1.42 sommerfe 925: {
926: struct sys_fktrace_args /* {
927: syscallarg(int) fd;
928: syscallarg(int) ops;
929: syscallarg(int) facs;
930: syscallarg(int) pid;
931: } */ *uap = v;
1.74.2.7 skrll 932: struct proc *curp;
1.42 sommerfe 933: struct file *fp = NULL;
1.74.2.7 skrll 934: struct filedesc *fdp = l->l_proc->p_fd;
1.70 yamt 935: int error;
1.42 sommerfe 936:
1.74.2.7 skrll 937: curp = l->l_proc;
938: fdp = curp->p_fd;
1.54 thorpej 939: if ((fp = fd_getfile(fdp, SCARG(uap, fd))) == NULL)
940: return (EBADF);
941:
1.70 yamt 942: FILE_USE(fp);
943:
1.54 thorpej 944: if ((fp->f_flag & FWRITE) == 0)
1.70 yamt 945: error = EBADF;
946: else
1.74.2.8 skrll 947: error = ktrace_common(curp, SCARG(uap, ops),
1.70 yamt 948: SCARG(uap, facs), SCARG(uap, pid), fp);
949:
1.74.2.7 skrll 950: FILE_UNUSE(fp, l);
1.42 sommerfe 951:
1.70 yamt 952: return error;
1.42 sommerfe 953: }
954:
955: /*
956: * ktrace system call
957: */
958: /* ARGSUSED */
959: int
1.74.2.3 skrll 960: sys_ktrace(struct lwp *l, void *v, register_t *retval)
1.19 thorpej 961: {
1.28 christos 962: struct sys_ktrace_args /* {
1.24 mycroft 963: syscallarg(const char *) fname;
1.13 cgd 964: syscallarg(int) ops;
965: syscallarg(int) facs;
966: syscallarg(int) pid;
1.19 thorpej 967: } */ *uap = v;
1.67 thorpej 968: struct proc *curp = l->l_proc;
1.28 christos 969: struct vnode *vp = NULL;
1.42 sommerfe 970: struct file *fp = NULL;
971: int ops = SCARG(uap, ops);
1.74.2.6 skrll 972: struct nameidata nd;
1.74.2.7 skrll 973: int error = 0;
974: int fd;
1.1 cgd 975:
1.42 sommerfe 976: ops = KTROP(ops) | (ops & KTRFLAG_DESCEND);
977:
1.9 cgd 978: curp->p_traceflag |= KTRFAC_ACTIVE;
1.69 christos 979: if ((ops & KTROP_CLEAR) == 0) {
1.1 cgd 980: /*
981: * an operation which requires a file argument.
982: */
1.13 cgd 983: NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, fname),
1.74.2.7 skrll 984: l);
1.22 christos 985: if ((error = vn_open(&nd, FREAD|FWRITE, 0)) != 0) {
1.9 cgd 986: curp->p_traceflag &= ~KTRFAC_ACTIVE;
1.1 cgd 987: return (error);
1.9 cgd 988: }
1.1 cgd 989: vp = nd.ni_vp;
1.25 fvdl 990: VOP_UNLOCK(vp, 0);
1.1 cgd 991: if (vp->v_type != VREG) {
1.74.2.7 skrll 992: (void) vn_close(vp, FREAD|FWRITE, curp->p_ucred, l);
1.9 cgd 993: curp->p_traceflag &= ~KTRFAC_ACTIVE;
1.1 cgd 994: return (EACCES);
995: }
996: /*
1.42 sommerfe 997: * XXX This uses up a file descriptor slot in the
998: * tracing process for the duration of this syscall.
999: * This is not expected to be a problem. If
1000: * falloc(NULL, ...) DTRT we could skip that part, but
1001: * that would require changing its interface to allow
1002: * the caller to pass in a ucred..
1003: *
1.74.2.3 skrll 1004: * This will FILE_USE the fp it returns, if any.
1.42 sommerfe 1005: * Keep it in use until we return.
1.1 cgd 1006: */
1.42 sommerfe 1007: if ((error = falloc(curp, &fp, &fd)) != 0)
1.1 cgd 1008: goto done;
1.74.2.3 skrll 1009:
1.74.2.8 skrll 1010: fp->f_flag = FWRITE;
1.42 sommerfe 1011: fp->f_type = DTYPE_VNODE;
1012: fp->f_ops = &vnops;
1013: fp->f_data = (caddr_t)vp;
1.54 thorpej 1014: FILE_SET_MATURE(fp);
1.42 sommerfe 1015: vp = NULL;
1016: }
1.74.2.8 skrll 1017: error = ktrace_common(curp, SCARG(uap, ops), SCARG(uap, facs),
1.42 sommerfe 1018: SCARG(uap, pid), fp);
1.74.2.3 skrll 1019: done:
1.1 cgd 1020: if (vp != NULL)
1.74.2.7 skrll 1021: (void) vn_close(vp, FWRITE, curp->p_ucred, l);
1.42 sommerfe 1022: if (fp != NULL) {
1.74.2.7 skrll 1023: FILE_UNUSE(fp, l); /* release file */
1024: fdrelease(l, fd); /* release fd table slot */
1.42 sommerfe 1025: }
1.1 cgd 1026: return (error);
1027: }
1028:
1.4 andrew 1029: int
1.74.2.5 skrll 1030: ktrops(struct proc *curp, struct proc *p, int ops, int facs,
1.74.2.8 skrll 1031: struct ktr_desc *ktd)
1.1 cgd 1032: {
1033:
1034: if (!ktrcanset(curp, p))
1035: return (0);
1.28 christos 1036: if (KTROP(ops) == KTROP_SET) {
1.74.2.8 skrll 1037: if (p->p_tracep != ktd) {
1.1 cgd 1038: /*
1039: * if trace file already in use, relinquish
1040: */
1.28 christos 1041: ktrderef(p);
1.74.2.8 skrll 1042: p->p_tracep = ktd;
1.28 christos 1043: ktradref(p);
1.1 cgd 1044: }
1045: p->p_traceflag |= facs;
1046: if (curp->p_ucred->cr_uid == 0)
1047: p->p_traceflag |= KTRFAC_ROOT;
1.74.2.3 skrll 1048: } else {
1.1 cgd 1049: /* KTROP_CLEAR */
1050: if (((p->p_traceflag &= ~facs) & KTRFAC_MASK) == 0) {
1051: /* no more tracing */
1.28 christos 1052: ktrderef(p);
1.1 cgd 1053: }
1054: }
1.21 christos 1055:
1056: /*
1057: * Emit an emulation record, every time there is a ktrace
1.74.2.3 skrll 1058: * change/attach request.
1.21 christos 1059: */
1060: if (KTRPOINT(p, KTR_EMUL))
1.74.2.3 skrll 1061: p->p_traceflag |= KTRFAC_TRC_EMUL;
1.49 martin 1062: #ifdef __HAVE_SYSCALL_INTERN
1.48 mycroft 1063: (*p->p_emul->e_syscall_intern)(p);
1.49 martin 1064: #endif
1.1 cgd 1065:
1066: return (1);
1067: }
1068:
1.22 christos 1069: int
1.74.2.5 skrll 1070: ktrsetchildren(struct proc *curp, struct proc *top, int ops, int facs,
1.74.2.8 skrll 1071: struct ktr_desc *ktd)
1.1 cgd 1072: {
1.74.2.5 skrll 1073: struct proc *p;
1.28 christos 1074: int ret = 0;
1.1 cgd 1075:
1076: p = top;
1077: for (;;) {
1.74.2.8 skrll 1078: ret |= ktrops(curp, p, ops, facs, ktd);
1.1 cgd 1079: /*
1080: * If this process has children, descend to them next,
1081: * otherwise do any siblings, and if done with this level,
1082: * follow back up the tree (but not past top).
1083: */
1.74.2.3 skrll 1084: if (LIST_FIRST(&p->p_children) != NULL) {
1.39 thorpej 1085: p = LIST_FIRST(&p->p_children);
1.74.2.3 skrll 1086: continue;
1087: }
1088: for (;;) {
1.1 cgd 1089: if (p == top)
1090: return (ret);
1.39 thorpej 1091: if (LIST_NEXT(p, p_sibling) != NULL) {
1092: p = LIST_NEXT(p, p_sibling);
1.1 cgd 1093: break;
1094: }
1.12 mycroft 1095: p = p->p_pptr;
1.1 cgd 1096: }
1097: }
1098: /*NOTREACHED*/
1099: }
1100:
1.74.2.8 skrll 1101: void
1102: ktrwrite(struct ktr_desc *ktd, struct ktrace_entry *kte)
1.1 cgd 1103: {
1.74.2.7 skrll 1104: struct uio auio;
1.74.2.8 skrll 1105: struct iovec aiov[64], *iov;
1106: struct ktrace_entry *top = kte;
1107: struct ktr_header *kth;
1108: struct file *fp = ktd->ktd_fp;
1.74.2.7 skrll 1109: struct proc *p;
1.74.2.9 skrll 1110: int rl, hl;
1.74.2.8 skrll 1111: int error;
1112: next:
1113: auio.uio_iov = iov = &aiov[0];
1114: auio.uio_offset = 0;
1115: auio.uio_segflg = UIO_SYSSPACE;
1116: auio.uio_rw = UIO_WRITE;
1117: auio.uio_resid = 0;
1118: auio.uio_iovcnt = 0;
1119: auio.uio_lwp = NULL;
1120: do {
1121: kth = &kte->kte_kth;
1.74.2.9 skrll 1122:
1123: rl = kth->ktr_len;
1124: hl = KTRv0_LEN;
1125:
1.74.2.12 skrll 1126: switch (kth->ktr_version) {
1.74.2.9 skrll 1127: case 0:
1128: /*
1.74.2.12 skrll 1129: * Convert back to the old format fields
1.74.2.9 skrll 1130: */
1.74.2.12 skrll 1131: TIMESPEC_TO_TIMEVAL(&kth->ktr_tv, &kth->ktr_time);
1132: kth->ktr_unused = NULL;
1.74.2.9 skrll 1133: hl = KTRv0_LEN;
1134: break;
1135: /*
1136: * Add in the incremental header size for later versions of
1137: * header records so that old kdump(1) binaries get the right
1138: * total record lenth.
1139: */
1140: case 1:
1141: kth->ktr_len += KTRv1_LEN - KTRv0_LEN;
1142:
1143: hl = KTRv1_LEN;
1144: break;
1145: }
1.74.2.8 skrll 1146: iov->iov_base = (caddr_t)kth;
1.74.2.9 skrll 1147: iov++->iov_len = hl;
1148: auio.uio_resid += hl;
1.74.2.8 skrll 1149: auio.uio_iovcnt++;
1.74.2.9 skrll 1150: if (rl > 0) {
1.74.2.8 skrll 1151: iov->iov_base = kte->kte_buf;
1.74.2.9 skrll 1152: iov++->iov_len = rl;
1153: auio.uio_resid += rl;
1.74.2.8 skrll 1154: auio.uio_iovcnt++;
1155: }
1156: } while ((kte = TAILQ_NEXT(kte, kte_list)) != NULL &&
1157: auio.uio_iovcnt < sizeof(aiov) / sizeof(aiov[0]) - 1);
1.74.2.7 skrll 1158:
1.74.2.8 skrll 1159: again:
1160: simple_lock(&fp->f_slock);
1161: FILE_USE(fp);
1162: error = (*fp->f_ops->fo_write)(fp, &fp->f_offset, &auio,
1163: fp->f_cred, FOF_UPDATE_OFFSET);
1164: FILE_UNUSE(fp, NULL);
1165: switch (error) {
1.1 cgd 1166:
1.74.2.8 skrll 1167: case 0:
1168: if (auio.uio_resid > 0)
1169: goto again;
1170: if (kte != NULL)
1171: goto next;
1172: break;
1173:
1174: case EWOULDBLOCK:
1175: preempt(1);
1176: goto again;
1.74.2.3 skrll 1177:
1.74.2.8 skrll 1178: default:
1179: /*
1180: * If error encountered, give up tracing on this
1181: * vnode. Don't report EPIPE as this can easily
1182: * happen with fktrace()/ktruss.
1183: */
1184: #ifndef DEBUG
1185: if (error != EPIPE)
1186: #endif
1187: log(LOG_NOTICE,
1188: "ktrace write failed, errno %d, tracing stopped\n",
1189: error);
1190: proclist_lock_read();
1.74.2.10 skrll 1191: PROCLIST_FOREACH(p, &allproc) {
1.74.2.8 skrll 1192: if (p->p_tracep == ktd)
1193: ktrderef(p);
1194: }
1195: proclist_unlock_read();
1.74.2.3 skrll 1196: }
1197:
1.74.2.8 skrll 1198: while ((kte = top) != NULL) {
1199: top = TAILQ_NEXT(top, kte_list);
1200: ktefree(kte);
1201: }
1202: }
1203:
1204: void
1205: ktrace_thread(void *arg)
1206: {
1207: struct ktr_desc *ktd = arg;
1208: struct file *fp = ktd->ktd_fp;
1209: struct ktrace_entry *kte;
1210: int ktrerr, errcnt;
1211:
1212: for (;;) {
1213: simple_lock(&ktd->ktd_slock);
1214: kte = TAILQ_FIRST(&ktd->ktd_queue);
1215: if (kte == NULL) {
1216: if (ktd->ktd_flags & KTDF_WAIT) {
1217: ktd->ktd_flags &= ~(KTDF_WAIT | KTDF_BLOCKING);
1218: wakeup(&ktd->ktd_flags);
1219: }
1220: if (ktd->ktd_ref == 0)
1221: break;
1222: ltsleep(ktd, PWAIT | PNORELOCK, "ktrwait", 0,
1223: &ktd->ktd_slock);
1224: continue;
1225: }
1226: TAILQ_INIT(&ktd->ktd_queue);
1227: ktd->ktd_qcount = 0;
1228: ktrerr = ktd->ktd_error;
1229: errcnt = ktd->ktd_errcnt;
1230: ktd->ktd_error = ktd->ktd_errcnt = 0;
1231: simple_unlock(&ktd->ktd_slock);
1232:
1233: if (ktrerr) {
1234: log(LOG_NOTICE,
1235: "ktrace failed, fp %p, error 0x%x, total %d\n",
1236: fp, ktrerr, errcnt);
1237: }
1238: ktrwrite(ktd, kte);
1.1 cgd 1239: }
1.74.2.8 skrll 1240: simple_unlock(&ktd->ktd_slock);
1241:
1242: simple_lock(&ktdq_slock);
1243: TAILQ_REMOVE(&ktdq, ktd, ktd_list);
1244: simple_unlock(&ktdq_slock);
1.28 christos 1245:
1.68 pk 1246: simple_lock(&fp->f_slock);
1.42 sommerfe 1247: FILE_USE(fp);
1248:
1.1 cgd 1249: /*
1.74.2.8 skrll 1250: * ktrace file descriptor can't be watched (are not visible to
1251: * userspace), so no kqueue stuff here
1252: * XXX: The above comment is wrong, because the fktrace file
1253: * descriptor is available in userland.
1.1 cgd 1254: */
1.74.2.8 skrll 1255: closef(fp, NULL);
1.39 thorpej 1256:
1.74.2.8 skrll 1257: callout_stop(&ktd->ktd_wakch);
1258: free(ktd, M_KTRACE);
1259:
1260: kthread_exit(0);
1.1 cgd 1261: }
1262:
1263: /*
1264: * Return true if caller has permission to set the ktracing state
1265: * of target. Essentially, the target can't possess any
1266: * more permissions than the caller. KTRFAC_ROOT signifies that
1.74.2.3 skrll 1267: * root previously set the tracing status on the target process, and
1.1 cgd 1268: * so, only root may further change it.
1269: *
1270: * TODO: check groups. use caller effective gid.
1271: */
1.22 christos 1272: int
1.74.2.3 skrll 1273: ktrcanset(struct proc *callp, struct proc *targetp)
1.1 cgd 1274: {
1.28 christos 1275: struct pcred *caller = callp->p_cred;
1276: struct pcred *target = targetp->p_cred;
1.1 cgd 1277:
1278: if ((caller->pc_ucred->cr_uid == target->p_ruid &&
1.74.2.3 skrll 1279: target->p_ruid == target->p_svuid &&
1280: caller->p_rgid == target->p_rgid && /* XXX */
1281: target->p_rgid == target->p_svgid &&
1282: (targetp->p_traceflag & KTRFAC_ROOT) == 0 &&
1283: (targetp->p_flag & P_SUGID) == 0) ||
1284: caller->pc_ucred->cr_uid == 0)
1.1 cgd 1285: return (1);
1286:
1287: return (0);
1288: }
1.47 thorpej 1289: #endif /* KTRACE */
1.51 jdolecek 1290:
1291: /*
1292: * Put user defined entry to ktrace records.
1293: */
1294: int
1.74.2.3 skrll 1295: sys_utrace(struct lwp *l, void *v, register_t *retval)
1.51 jdolecek 1296: {
1297: #ifdef KTRACE
1298: struct sys_utrace_args /* {
1.52 jdolecek 1299: syscallarg(const char *) label;
1.51 jdolecek 1300: syscallarg(void *) addr;
1301: syscallarg(size_t) len;
1302: } */ *uap = v;
1.67 thorpej 1303: struct proc *p = l->l_proc;
1.74.2.3 skrll 1304:
1.51 jdolecek 1305: if (!KTRPOINT(p, KTR_USER))
1306: return (0);
1.53 jdolecek 1307:
1308: if (SCARG(uap, len) > KTR_USER_MAXLEN)
1309: return (EINVAL);
1.51 jdolecek 1310:
1.74.2.7 skrll 1311: ktruser(l, SCARG(uap, label), SCARG(uap, addr), SCARG(uap, len), 1);
1.51 jdolecek 1312:
1313: return (0);
1314: #else /* !KTRACE */
1315: return ENOSYS;
1316: #endif /* KTRACE */
1317: }
CVSweb <webmaster@jp.NetBSD.org>