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