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