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