xref: /netbsd-src/sys/kern/kern_ktrace.c (revision da5f4674a3fc214be3572d358b66af40ab9401e7)
1 /*	$NetBSD: kern_ktrace.c,v 1.77 2003/08/07 16:31:45 agc Exp $	*/
2 
3 /*
4  * Copyright (c) 1989, 1993
5  *	The Regents of the University of California.  All rights reserved.
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.
15  * 3. Neither the name of the University nor the names of its contributors
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  *
31  *	@(#)kern_ktrace.c	8.5 (Berkeley) 5/14/95
32  */
33 
34 #include <sys/cdefs.h>
35 __KERNEL_RCSID(0, "$NetBSD: kern_ktrace.c,v 1.77 2003/08/07 16:31:45 agc Exp $");
36 
37 #include "opt_ktrace.h"
38 #include "opt_compat_mach.h"
39 
40 #include <sys/param.h>
41 #include <sys/systm.h>
42 #include <sys/proc.h>
43 #include <sys/file.h>
44 #include <sys/namei.h>
45 #include <sys/vnode.h>
46 #include <sys/ktrace.h>
47 #include <sys/malloc.h>
48 #include <sys/syslog.h>
49 #include <sys/filedesc.h>
50 #include <sys/ioctl.h>
51 
52 #include <sys/mount.h>
53 #include <sys/sa.h>
54 #include <sys/syscallargs.h>
55 
56 #ifdef KTRACE
57 
58 int	ktrace_common(struct proc *, int, int, int, struct file *);
59 void	ktrinitheader(struct ktr_header *, struct proc *, int);
60 int	ktrops(struct proc *, struct proc *, int, int, struct file *);
61 int	ktrsetchildren(struct proc *, struct proc *, int, int,
62 	    struct file *);
63 int	ktrwrite(struct proc *, struct ktr_header *);
64 int	ktrcanset(struct proc *, struct proc *);
65 int	ktrsamefile(struct file *, struct file *);
66 
67 /*
68  * "deep" compare of two files for the purposes of clearing a trace.
69  * Returns true if they're the same open file, or if they point at the
70  * same underlying vnode/socket.
71  */
72 
73 int
74 ktrsamefile(f1, f2)
75 	struct file *f1;
76 	struct file *f2;
77 {
78 	return ((f1 == f2) ||
79 	    ((f1 != NULL) && (f2 != NULL) &&
80 		(f1->f_type == f2->f_type) &&
81 		(f1->f_data == f2->f_data)));
82 }
83 
84 void
85 ktrderef(p)
86 	struct proc *p;
87 {
88 	struct file *fp = p->p_tracep;
89 	p->p_traceflag = 0;
90 	if (fp == NULL)
91 		return;
92 	simple_lock(&fp->f_slock);
93 	FILE_USE(fp);
94 
95 	/*
96 	 * ktrace file descriptor can't be watched (are not visible to
97 	 * userspace), so no kqueue stuff here
98 	 */
99 	closef(fp, NULL);
100 
101 	p->p_tracep = NULL;
102 }
103 
104 void
105 ktradref(p)
106 	struct proc *p;
107 {
108 	struct file *fp = p->p_tracep;
109 
110 	fp->f_count++;
111 }
112 
113 void
114 ktrinitheader(kth, p, type)
115 	struct ktr_header *kth;
116 	struct proc *p;
117 	int type;
118 {
119 
120 	memset(kth, 0, sizeof(*kth));
121 	kth->ktr_type = type;
122 	microtime(&kth->ktr_time);
123 	kth->ktr_pid = p->p_pid;
124 	memcpy(kth->ktr_comm, p->p_comm, MAXCOMLEN);
125 }
126 
127 void
128 ktrsyscall(p, code, realcode, callp, args)
129 	struct proc *p;
130 	register_t code;
131 	register_t realcode;
132 	const struct sysent *callp;
133 	register_t args[];
134 {
135 	struct ktr_header kth;
136 	struct ktr_syscall *ktp;
137 	register_t *argp;
138 	int argsize;
139 	size_t len;
140 	u_int i;
141 
142 	if (callp == NULL)
143 		callp = p->p_emul->e_sysent;
144 
145 	argsize = callp[code].sy_argsize;
146 	len = sizeof(struct ktr_syscall) + argsize;
147 
148 	p->p_traceflag |= KTRFAC_ACTIVE;
149 	ktrinitheader(&kth, p, KTR_SYSCALL);
150 	ktp = malloc(len, M_TEMP, M_WAITOK);
151 	ktp->ktr_code = realcode;
152 	ktp->ktr_argsize = argsize;
153 	argp = (register_t *)((char *)ktp + sizeof(struct ktr_syscall));
154 	for (i = 0; i < (argsize / sizeof(*argp)); i++)
155 		*argp++ = args[i];
156 	kth.ktr_buf = (caddr_t)ktp;
157 	kth.ktr_len = len;
158 	(void) ktrwrite(p, &kth);
159 	free(ktp, M_TEMP);
160 	p->p_traceflag &= ~KTRFAC_ACTIVE;
161 }
162 
163 void
164 ktrsysret(p, code, error, retval)
165 	struct proc *p;
166 	register_t code;
167 	int error;
168 	register_t *retval;
169 {
170 	struct ktr_header kth;
171 	struct ktr_sysret ktp;
172 
173 	p->p_traceflag |= KTRFAC_ACTIVE;
174 	ktrinitheader(&kth, p, KTR_SYSRET);
175 	ktp.ktr_code = code;
176 	ktp.ktr_eosys = 0;			/* XXX unused */
177 	ktp.ktr_error = error;
178 	ktp.ktr_retval = retval ? retval[0] : 0;
179 	ktp.ktr_retval_1 = retval ? retval[1] : 0;
180 
181 	kth.ktr_buf = (caddr_t)&ktp;
182 	kth.ktr_len = sizeof(struct ktr_sysret);
183 
184 	(void) ktrwrite(p, &kth);
185 	p->p_traceflag &= ~KTRFAC_ACTIVE;
186 }
187 
188 void
189 ktrnamei(p, path)
190 	struct proc *p;
191 	char *path;
192 {
193 	struct ktr_header kth;
194 
195 	p->p_traceflag |= KTRFAC_ACTIVE;
196 	ktrinitheader(&kth, p, KTR_NAMEI);
197 	kth.ktr_len = strlen(path);
198 	kth.ktr_buf = path;
199 
200 	(void) ktrwrite(p, &kth);
201 	p->p_traceflag &= ~KTRFAC_ACTIVE;
202 }
203 
204 void
205 ktremul(p)
206 	struct proc *p;
207 {
208 	struct ktr_header kth;
209 	const char *emul = p->p_emul->e_name;
210 
211 	p->p_traceflag |= KTRFAC_ACTIVE;
212 	ktrinitheader(&kth, p, KTR_EMUL);
213 	kth.ktr_len = strlen(emul);
214 	kth.ktr_buf = (caddr_t)emul;
215 
216 	(void) ktrwrite(p, &kth);
217 	p->p_traceflag &= ~KTRFAC_ACTIVE;
218 }
219 
220 void
221 ktrkmem(struct proc *p, int ktr, const void *buf, size_t len)
222 {
223 	struct ktr_header kth;
224 
225 	p->p_traceflag |= KTRFAC_ACTIVE;
226 	ktrinitheader(&kth, p, ktr);
227 	kth.ktr_len = len;
228 	kth.ktr_buf = buf;
229 
230 	(void)ktrwrite(p, &kth);
231 	p->p_traceflag &= ~KTRFAC_ACTIVE;
232 }
233 
234 void
235 ktrgenio(p, fd, rw, iov, len, error)
236 	struct proc *p;
237 	int fd;
238 	enum uio_rw rw;
239 	struct iovec *iov;
240 	int len;
241 	int error;
242 {
243 	struct ktr_header kth;
244 	struct ktr_genio *ktp;
245 	caddr_t cp;
246 	int resid = len, cnt;
247 	int buflen;
248 
249 	if (error)
250 		return;
251 
252 	p->p_traceflag |= KTRFAC_ACTIVE;
253 
254 	buflen = min(PAGE_SIZE, len + sizeof(struct ktr_genio));
255 
256 	ktrinitheader(&kth, p, KTR_GENIO);
257 	ktp = malloc(buflen, M_TEMP, M_WAITOK);
258 	ktp->ktr_fd = fd;
259 	ktp->ktr_rw = rw;
260 
261 	kth.ktr_buf = (caddr_t)ktp;
262 
263 	cp = (caddr_t)((char *)ktp + sizeof(struct ktr_genio));
264 	buflen -= sizeof(struct ktr_genio);
265 
266 	while (resid > 0) {
267 #if 0 /* XXX NJWLWP */
268 		KDASSERT(p->p_cpu != NULL);
269 		KDASSERT(p->p_cpu == curcpu());
270 #endif
271 		/* XXX NJWLWP */
272 		if (curcpu()->ci_schedstate.spc_flags & SPCF_SHOULDYIELD)
273 			preempt(1);
274 
275 		cnt = min(iov->iov_len, buflen);
276 		if (cnt > resid)
277 			cnt = resid;
278 		if (copyin(iov->iov_base, cp, cnt))
279 			break;
280 
281 		kth.ktr_len = cnt + sizeof(struct ktr_genio);
282 
283 		if (__predict_false(ktrwrite(p, &kth) != 0))
284 			break;
285 
286 		iov->iov_base = (caddr_t)iov->iov_base + cnt;
287 		iov->iov_len -= cnt;
288 
289 		if (iov->iov_len == 0)
290 			iov++;
291 
292 		resid -= cnt;
293 	}
294 
295 	free(ktp, M_TEMP);
296 	p->p_traceflag &= ~KTRFAC_ACTIVE;
297 }
298 
299 void
300 ktrpsig(p, sig, action, mask, code)
301 	struct proc *p;
302 	int sig;
303 	sig_t action;
304 	sigset_t *mask;
305 	int code;
306 {
307 	struct ktr_header kth;
308 	struct ktr_psig	kp;
309 
310 	p->p_traceflag |= KTRFAC_ACTIVE;
311 	ktrinitheader(&kth, p, KTR_PSIG);
312 	kp.signo = (char)sig;
313 	kp.action = action;
314 	kp.mask = *mask;
315 	kp.code = code;
316 	kth.ktr_buf = (caddr_t)&kp;
317 	kth.ktr_len = sizeof(struct ktr_psig);
318 
319 	(void) ktrwrite(p, &kth);
320 	p->p_traceflag &= ~KTRFAC_ACTIVE;
321 }
322 
323 void
324 ktrcsw(p, out, user)
325 	struct proc *p;
326 	int out;
327 	int user;
328 {
329 	struct ktr_header kth;
330 	struct ktr_csw kc;
331 
332 	p->p_traceflag |= KTRFAC_ACTIVE;
333 	ktrinitheader(&kth, p, KTR_CSW);
334 	kc.out = out;
335 	kc.user = user;
336 	kth.ktr_buf = (caddr_t)&kc;
337 	kth.ktr_len = sizeof(struct ktr_csw);
338 
339 	(void) ktrwrite(p, &kth);
340 	p->p_traceflag &= ~KTRFAC_ACTIVE;
341 }
342 
343 void
344 ktruser(p, id, addr, len, ustr)
345 	struct proc *p;
346 	const char *id;
347 	void *addr;
348 	size_t len;
349 	int ustr;
350 {
351 	struct ktr_header kth;
352 	struct ktr_user *ktp;
353 	caddr_t user_dta;
354 
355 	p->p_traceflag |= KTRFAC_ACTIVE;
356 	ktrinitheader(&kth, p, KTR_USER);
357 	ktp = malloc(sizeof(struct ktr_user) + len, M_TEMP, M_WAITOK);
358 	if (ustr) {
359 		if (copyinstr(id, ktp->ktr_id, KTR_USER_MAXIDLEN, NULL) != 0)
360 			ktp->ktr_id[0] = '\0';
361 	} else
362 		strncpy(ktp->ktr_id, id, KTR_USER_MAXIDLEN);
363 	ktp->ktr_id[KTR_USER_MAXIDLEN-1] = '\0';
364 
365 	user_dta = (caddr_t) ((char *)ktp + sizeof(struct ktr_user));
366 	if (copyin(addr, (void *) user_dta, len) != 0)
367 		len = 0;
368 
369 	kth.ktr_buf = (void *)ktp;
370 	kth.ktr_len = sizeof(struct ktr_user) + len;
371 	(void) ktrwrite(p, &kth);
372 
373 	free(ktp, M_TEMP);
374 	p->p_traceflag &= ~KTRFAC_ACTIVE;
375 
376 }
377 
378 void
379 ktrmmsg(p, msgh, size)
380 	struct proc *p;
381 	const void *msgh;
382 	size_t size;
383 {
384 	struct ktr_header kth;
385 	struct ktr_mmsg	*kp;
386 
387 	p->p_traceflag |= KTRFAC_ACTIVE;
388 	ktrinitheader(&kth, p, KTR_MMSG);
389 
390 	kp = (struct ktr_mmsg *)msgh;
391 	kth.ktr_buf = (caddr_t)kp;
392 	kth.ktr_len = size;
393 	(void) ktrwrite(p, &kth);
394 	p->p_traceflag &= ~KTRFAC_ACTIVE;
395 }
396 
397 /* Interface and common routines */
398 
399 int
400 ktrace_common(curp, ops, facs, pid, fp)
401 	struct proc *curp;
402 	int ops;
403 	int facs;
404 	int pid;
405 	struct file *fp;
406 {
407 	int ret = 0;
408 	int error = 0;
409 	int one = 1;
410 	int descend;
411 	struct proc *p;
412 	struct pgrp *pg;
413 
414 	curp->p_traceflag |= KTRFAC_ACTIVE;
415 	descend = ops & KTRFLAG_DESCEND;
416 	facs = facs & ~((unsigned) KTRFAC_ROOT);
417 
418 	/*
419 	 * Clear all uses of the tracefile
420 	 */
421 	if (KTROP(ops) == KTROP_CLEARFILE) {
422 		proclist_lock_read();
423 		for (p = LIST_FIRST(&allproc); p != NULL;
424 		     p = LIST_NEXT(p, p_list)) {
425 			if (ktrsamefile(p->p_tracep, fp)) {
426 				if (ktrcanset(curp, p))
427 					ktrderef(p);
428 				else
429 					error = EPERM;
430 			}
431 		}
432 		proclist_unlock_read();
433 		goto done;
434 	}
435 
436 	/*
437 	 * Mark fp non-blocking, to avoid problems from possible deadlocks.
438 	 */
439 
440 	if (fp != NULL) {
441 		fp->f_flag |= FNONBLOCK;
442 		(*fp->f_ops->fo_ioctl)(fp, FIONBIO, (caddr_t)&one, curp);
443 	}
444 
445 	/*
446 	 * need something to (un)trace (XXX - why is this here?)
447 	 */
448 	if (!facs) {
449 		error = EINVAL;
450 		goto done;
451 	}
452 	/*
453 	 * do it
454 	 */
455 	if (pid < 0) {
456 		/*
457 		 * by process group
458 		 */
459 		pg = pgfind(-pid);
460 		if (pg == NULL) {
461 			error = ESRCH;
462 			goto done;
463 		}
464 		for (p = LIST_FIRST(&pg->pg_members); p != NULL;
465 		     p = LIST_NEXT(p, p_pglist)) {
466 			if (descend)
467 				ret |= ktrsetchildren(curp, p, ops, facs, fp);
468 			else
469 				ret |= ktrops(curp, p, ops, facs, fp);
470 		}
471 
472 	} else {
473 		/*
474 		 * by pid
475 		 */
476 		p = pfind(pid);
477 		if (p == NULL) {
478 			error = ESRCH;
479 			goto done;
480 		}
481 		if (descend)
482 			ret |= ktrsetchildren(curp, p, ops, facs, fp);
483 		else
484 			ret |= ktrops(curp, p, ops, facs, fp);
485 	}
486 	if (!ret)
487 		error = EPERM;
488 done:
489 	curp->p_traceflag &= ~KTRFAC_ACTIVE;
490 	return (error);
491 }
492 
493 /*
494  * ktrace system call
495  */
496 /* ARGSUSED */
497 int
498 sys_fktrace(l, v, retval)
499 	struct lwp *l;
500 	void *v;
501 	register_t *retval;
502 {
503 	struct sys_fktrace_args /* {
504 		syscallarg(int) fd;
505 		syscallarg(int) ops;
506 		syscallarg(int) facs;
507 		syscallarg(int) pid;
508 	} */ *uap = v;
509 	struct proc *curp = l->l_proc;
510 	struct file *fp = NULL;
511 	struct filedesc *fdp = curp->p_fd;
512 	int error;
513 
514 	if ((fp = fd_getfile(fdp, SCARG(uap, fd))) == NULL)
515 		return (EBADF);
516 
517 	FILE_USE(fp);
518 
519 	if ((fp->f_flag & FWRITE) == 0)
520 		error = EBADF;
521 	else
522 		error = ktrace_common(curp, SCARG(uap, ops),
523 		    SCARG(uap, facs), SCARG(uap, pid), fp);
524 
525 	FILE_UNUSE(fp, curp);
526 
527 	return error;
528 }
529 
530 /*
531  * ktrace system call
532  */
533 /* ARGSUSED */
534 int
535 sys_ktrace(l, v, retval)
536 	struct lwp *l;
537 	void *v;
538 	register_t *retval;
539 {
540 	struct sys_ktrace_args /* {
541 		syscallarg(const char *) fname;
542 		syscallarg(int) ops;
543 		syscallarg(int) facs;
544 		syscallarg(int) pid;
545 	} */ *uap = v;
546 	struct proc *curp = l->l_proc;
547 	struct vnode *vp = NULL;
548 	struct file *fp = NULL;
549 	int fd;
550 	int ops = SCARG(uap, ops);
551 	int error = 0;
552 	struct nameidata nd;
553 
554 	ops = KTROP(ops) | (ops & KTRFLAG_DESCEND);
555 
556 	curp->p_traceflag |= KTRFAC_ACTIVE;
557 	if ((ops & KTROP_CLEAR) == 0) {
558 		/*
559 		 * an operation which requires a file argument.
560 		 */
561 		NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, fname),
562 		    curp);
563 		if ((error = vn_open(&nd, FREAD|FWRITE, 0)) != 0) {
564 			curp->p_traceflag &= ~KTRFAC_ACTIVE;
565 			return (error);
566 		}
567 		vp = nd.ni_vp;
568 		VOP_UNLOCK(vp, 0);
569 		if (vp->v_type != VREG) {
570 			(void) vn_close(vp, FREAD|FWRITE, curp->p_ucred, curp);
571 			curp->p_traceflag &= ~KTRFAC_ACTIVE;
572 			return (EACCES);
573 		}
574 		/*
575 		 * XXX This uses up a file descriptor slot in the
576 		 * tracing process for the duration of this syscall.
577 		 * This is not expected to be a problem.  If
578 		 * falloc(NULL, ...) DTRT we could skip that part, but
579 		 * that would require changing its interface to allow
580 		 * the caller to pass in a ucred..
581 		 *
582 		 * This will FILE_USE the fp it returns, if any.
583 		 * Keep it in use until we return.
584 		 */
585 		if ((error = falloc(curp, &fp, &fd)) != 0)
586 			goto done;
587 
588 		fp->f_flag = FWRITE|FAPPEND;
589 		fp->f_type = DTYPE_VNODE;
590 		fp->f_ops = &vnops;
591 		fp->f_data = (caddr_t)vp;
592 		FILE_SET_MATURE(fp);
593 		vp = NULL;
594 	}
595 	error = ktrace_common(curp, SCARG(uap, ops), SCARG(uap, facs),
596 	    SCARG(uap, pid), fp);
597 done:
598 	if (vp != NULL)
599 		(void) vn_close(vp, FWRITE, curp->p_ucred, curp);
600 	if (fp != NULL) {
601 		FILE_UNUSE(fp, curp);	/* release file */
602 		fdrelease(curp, fd); 	/* release fd table slot */
603 	}
604 	return (error);
605 }
606 
607 int
608 ktrops(curp, p, ops, facs, fp)
609 	struct proc *curp;
610 	struct proc *p;
611 	int ops;
612 	int facs;
613 	struct file *fp;
614 {
615 
616 	if (!ktrcanset(curp, p))
617 		return (0);
618 	if (KTROP(ops) == KTROP_SET) {
619 		if (p->p_tracep != fp) {
620 			/*
621 			 * if trace file already in use, relinquish
622 			 */
623 			ktrderef(p);
624 			p->p_tracep = fp;
625 			ktradref(p);
626 		}
627 		p->p_traceflag |= facs;
628 		if (curp->p_ucred->cr_uid == 0)
629 			p->p_traceflag |= KTRFAC_ROOT;
630 	} else {
631 		/* KTROP_CLEAR */
632 		if (((p->p_traceflag &= ~facs) & KTRFAC_MASK) == 0) {
633 			/* no more tracing */
634 			ktrderef(p);
635 		}
636 	}
637 
638 	/*
639 	 * Emit an emulation record, every time there is a ktrace
640 	 * change/attach request.
641 	 */
642 	if (KTRPOINT(p, KTR_EMUL))
643 		ktremul(p);
644 #ifdef __HAVE_SYSCALL_INTERN
645 	(*p->p_emul->e_syscall_intern)(p);
646 #endif
647 
648 	return (1);
649 }
650 
651 int
652 ktrsetchildren(curp, top, ops, facs, fp)
653 	struct proc *curp;
654 	struct proc *top;
655 	int ops;
656 	int facs;
657 	struct file *fp;
658 {
659 	struct proc *p;
660 	int ret = 0;
661 
662 	p = top;
663 	for (;;) {
664 		ret |= ktrops(curp, p, ops, facs, fp);
665 		/*
666 		 * If this process has children, descend to them next,
667 		 * otherwise do any siblings, and if done with this level,
668 		 * follow back up the tree (but not past top).
669 		 */
670 		if (LIST_FIRST(&p->p_children) != NULL)
671 			p = LIST_FIRST(&p->p_children);
672 		else for (;;) {
673 			if (p == top)
674 				return (ret);
675 			if (LIST_NEXT(p, p_sibling) != NULL) {
676 				p = LIST_NEXT(p, p_sibling);
677 				break;
678 			}
679 			p = p->p_pptr;
680 		}
681 	}
682 	/*NOTREACHED*/
683 }
684 
685 int
686 ktrwrite(p, kth)
687 	struct proc *p;
688 	struct ktr_header *kth;
689 {
690 	struct uio auio;
691 	struct iovec aiov[2];
692 	int error, tries;
693 	struct file *fp = p->p_tracep;
694 
695 	if (fp == NULL)
696 		return 0;
697 
698 	auio.uio_iov = &aiov[0];
699 	auio.uio_offset = 0;
700 	auio.uio_segflg = UIO_SYSSPACE;
701 	auio.uio_rw = UIO_WRITE;
702 	aiov[0].iov_base = (caddr_t)kth;
703 	aiov[0].iov_len = sizeof(struct ktr_header);
704 	auio.uio_resid = sizeof(struct ktr_header);
705 	auio.uio_iovcnt = 1;
706 	auio.uio_procp = (struct proc *)0;
707 	if (kth->ktr_len > 0) {
708 		auio.uio_iovcnt++;
709 		aiov[1].iov_base = (void *)kth->ktr_buf;
710 		aiov[1].iov_len = kth->ktr_len;
711 		auio.uio_resid += kth->ktr_len;
712 	}
713 
714 	simple_lock(&fp->f_slock);
715 	FILE_USE(fp);
716 
717 	tries = 0;
718 	do {
719 		error = (*fp->f_ops->fo_write)(fp, &fp->f_offset, &auio,
720 		    fp->f_cred, FOF_UPDATE_OFFSET);
721 		tries++;
722 		if (error == EWOULDBLOCK)
723 		  	preempt(1);
724 	} while ((error == EWOULDBLOCK) && (tries < 3));
725 	FILE_UNUSE(fp, NULL);
726 
727 	if (__predict_true(error == 0))
728 		return (0);
729 	/*
730 	 * If error encountered, give up tracing on this vnode.  Don't report
731 	 * EPIPE as this can easily happen with fktrace()/ktruss.
732 	 */
733 	if (error != EPIPE)
734 		log(LOG_NOTICE,
735 		    "ktrace write failed, errno %d, tracing stopped\n",
736 		    error);
737 	proclist_lock_read();
738 	for (p = LIST_FIRST(&allproc); p != NULL; p = LIST_NEXT(p, p_list)) {
739 		if (ktrsamefile(p->p_tracep, fp))
740 			ktrderef(p);
741 	}
742 	proclist_unlock_read();
743 
744 	return (error);
745 }
746 
747 /*
748  * Return true if caller has permission to set the ktracing state
749  * of target.  Essentially, the target can't possess any
750  * more permissions than the caller.  KTRFAC_ROOT signifies that
751  * root previously set the tracing status on the target process, and
752  * so, only root may further change it.
753  *
754  * TODO: check groups.  use caller effective gid.
755  */
756 int
757 ktrcanset(callp, targetp)
758 	struct proc *callp;
759 	struct proc *targetp;
760 {
761 	struct pcred *caller = callp->p_cred;
762 	struct pcred *target = targetp->p_cred;
763 
764 	if ((caller->pc_ucred->cr_uid == target->p_ruid &&
765 	     target->p_ruid == target->p_svuid &&
766 	     caller->p_rgid == target->p_rgid &&	/* XXX */
767 	     target->p_rgid == target->p_svgid &&
768 	     (targetp->p_traceflag & KTRFAC_ROOT) == 0 &&
769 	     (targetp->p_flag & P_SUGID) == 0) ||
770 	     caller->pc_ucred->cr_uid == 0)
771 		return (1);
772 
773 	return (0);
774 }
775 #endif /* KTRACE */
776 
777 /*
778  * Put user defined entry to ktrace records.
779  */
780 int
781 sys_utrace(l, v, retval)
782 	struct lwp *l;
783 	void *v;
784 	register_t *retval;
785 {
786 #ifdef KTRACE
787 	struct sys_utrace_args /* {
788 		syscallarg(const char *) label;
789 		syscallarg(void *) addr;
790 		syscallarg(size_t) len;
791 	} */ *uap = v;
792 	struct proc *p = l->l_proc;
793 	if (!KTRPOINT(p, KTR_USER))
794 		return (0);
795 
796 	if (SCARG(uap, len) > KTR_USER_MAXLEN)
797 		return (EINVAL);
798 
799 	ktruser(p, SCARG(uap, label), SCARG(uap, addr), SCARG(uap, len), 1);
800 
801 	return (0);
802 #else /* !KTRACE */
803 	return ENOSYS;
804 #endif /* KTRACE */
805 }
806