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