1 /* $NetBSD: kern_ktrace.c,v 1.51 2000/12/28 11:10:15 jdolecek 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 (((u_int)SCARG(uap, fd)) >= fdp->fd_nfiles || 422 (fp = fdp->fd_ofiles[SCARG(uap, fd)]) == NULL || 423 (fp->f_flag & FWRITE) == 0) 424 return (EBADF); 425 426 return ktrace_common(curp, SCARG(uap, ops), 427 SCARG(uap, facs), SCARG(uap, pid), fp); 428 } 429 430 /* 431 * ktrace system call 432 */ 433 /* ARGSUSED */ 434 int 435 sys_ktrace(struct proc *curp, void *v, register_t *retval) 436 { 437 struct sys_ktrace_args /* { 438 syscallarg(const char *) fname; 439 syscallarg(int) ops; 440 syscallarg(int) facs; 441 syscallarg(int) pid; 442 } */ *uap = v; 443 struct vnode *vp = NULL; 444 struct file *fp = NULL; 445 int fd; 446 int ops = SCARG(uap, ops); 447 int error = 0; 448 struct nameidata nd; 449 450 ops = KTROP(ops) | (ops & KTRFLAG_DESCEND); 451 452 curp->p_traceflag |= KTRFAC_ACTIVE; 453 if (ops != KTROP_CLEAR) { 454 /* 455 * an operation which requires a file argument. 456 */ 457 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, fname), 458 curp); 459 if ((error = vn_open(&nd, FREAD|FWRITE, 0)) != 0) { 460 curp->p_traceflag &= ~KTRFAC_ACTIVE; 461 return (error); 462 } 463 vp = nd.ni_vp; 464 VOP_UNLOCK(vp, 0); 465 if (vp->v_type != VREG) { 466 (void) vn_close(vp, FREAD|FWRITE, curp->p_ucred, curp); 467 curp->p_traceflag &= ~KTRFAC_ACTIVE; 468 return (EACCES); 469 } 470 /* 471 * XXX This uses up a file descriptor slot in the 472 * tracing process for the duration of this syscall. 473 * This is not expected to be a problem. If 474 * falloc(NULL, ...) DTRT we could skip that part, but 475 * that would require changing its interface to allow 476 * the caller to pass in a ucred.. 477 * 478 * This will FILE_USE the fp it returns, if any. 479 * Keep it in use until we return. 480 */ 481 if ((error = falloc(curp, &fp, &fd)) != 0) 482 goto done; 483 484 fp->f_flag = FWRITE|FAPPEND; 485 fp->f_type = DTYPE_VNODE; 486 fp->f_ops = &vnops; 487 fp->f_data = (caddr_t)vp; 488 vp = NULL; 489 } 490 error = ktrace_common(curp, SCARG(uap, ops), SCARG(uap, facs), 491 SCARG(uap, pid), fp); 492 done: 493 if (vp != NULL) 494 (void) vn_close(vp, FWRITE, curp->p_ucred, curp); 495 if (fp != NULL) { 496 FILE_UNUSE(fp, curp); /* release file */ 497 fdrelease(curp, fd); /* release fd table slot */ 498 } 499 return (error); 500 } 501 502 int 503 ktrops(struct proc *curp, struct proc *p, int ops, int facs, struct file *fp) 504 { 505 506 if (!ktrcanset(curp, p)) 507 return (0); 508 if (KTROP(ops) == KTROP_SET) { 509 if (p->p_tracep != fp) { 510 /* 511 * if trace file already in use, relinquish 512 */ 513 ktrderef(p); 514 p->p_tracep = fp; 515 ktradref(p); 516 } 517 p->p_traceflag |= facs; 518 if (curp->p_ucred->cr_uid == 0) 519 p->p_traceflag |= KTRFAC_ROOT; 520 } else { 521 /* KTROP_CLEAR */ 522 if (((p->p_traceflag &= ~facs) & KTRFAC_MASK) == 0) { 523 /* no more tracing */ 524 ktrderef(p); 525 } 526 } 527 528 /* 529 * Emit an emulation record, every time there is a ktrace 530 * change/attach request. 531 */ 532 if (KTRPOINT(p, KTR_EMUL)) 533 ktremul(p); 534 #ifdef __HAVE_SYSCALL_INTERN 535 (*p->p_emul->e_syscall_intern)(p); 536 #endif 537 538 return (1); 539 } 540 541 int 542 ktrsetchildren(struct proc *curp, struct proc *top, int ops, int facs, 543 struct file *fp) 544 { 545 struct proc *p; 546 int ret = 0; 547 548 p = top; 549 for (;;) { 550 ret |= ktrops(curp, p, ops, facs, fp); 551 /* 552 * If this process has children, descend to them next, 553 * otherwise do any siblings, and if done with this level, 554 * follow back up the tree (but not past top). 555 */ 556 if (LIST_FIRST(&p->p_children) != NULL) 557 p = LIST_FIRST(&p->p_children); 558 else for (;;) { 559 if (p == top) 560 return (ret); 561 if (LIST_NEXT(p, p_sibling) != NULL) { 562 p = LIST_NEXT(p, p_sibling); 563 break; 564 } 565 p = p->p_pptr; 566 } 567 } 568 /*NOTREACHED*/ 569 } 570 571 int 572 ktrwrite(struct proc *p, struct ktr_header *kth) 573 { 574 struct uio auio; 575 struct iovec aiov[2]; 576 int error, tries; 577 struct file *fp = p->p_tracep; 578 579 if (fp == NULL) 580 return 0; 581 582 auio.uio_iov = &aiov[0]; 583 auio.uio_offset = 0; 584 auio.uio_segflg = UIO_SYSSPACE; 585 auio.uio_rw = UIO_WRITE; 586 aiov[0].iov_base = (caddr_t)kth; 587 aiov[0].iov_len = sizeof(struct ktr_header); 588 auio.uio_resid = sizeof(struct ktr_header); 589 auio.uio_iovcnt = 1; 590 auio.uio_procp = (struct proc *)0; 591 if (kth->ktr_len > 0) { 592 auio.uio_iovcnt++; 593 aiov[1].iov_base = kth->ktr_buf; 594 aiov[1].iov_len = kth->ktr_len; 595 auio.uio_resid += kth->ktr_len; 596 } 597 598 FILE_USE(fp); 599 600 tries = 0; 601 do { 602 error = (*fp->f_ops->fo_write)(fp, &fp->f_offset, &auio, 603 fp->f_cred, FOF_UPDATE_OFFSET); 604 tries++; 605 if (error == EWOULDBLOCK) 606 yield(); 607 } while ((error == EWOULDBLOCK) && (tries < 3)); 608 FILE_UNUSE(fp, NULL); 609 610 if (__predict_true(error == 0)) 611 return (0); 612 /* 613 * If error encountered, give up tracing on this vnode. Don't report 614 * EPIPE as this can easily happen with fktrace()/ktruss. 615 */ 616 if (error != EPIPE) 617 log(LOG_NOTICE, 618 "ktrace write failed, errno %d, tracing stopped\n", 619 error); 620 proclist_lock_read(); 621 for (p = LIST_FIRST(&allproc); p != NULL; p = LIST_NEXT(p, p_list)) { 622 if (ktrsamefile(p->p_tracep, fp)) 623 ktrderef(p); 624 } 625 proclist_unlock_read(); 626 627 return (error); 628 } 629 630 /* 631 * Return true if caller has permission to set the ktracing state 632 * of target. Essentially, the target can't possess any 633 * more permissions than the caller. KTRFAC_ROOT signifies that 634 * root previously set the tracing status on the target process, and 635 * so, only root may further change it. 636 * 637 * TODO: check groups. use caller effective gid. 638 */ 639 int 640 ktrcanset(struct proc *callp, struct proc *targetp) 641 { 642 struct pcred *caller = callp->p_cred; 643 struct pcred *target = targetp->p_cred; 644 645 if ((caller->pc_ucred->cr_uid == target->p_ruid && 646 target->p_ruid == target->p_svuid && 647 caller->p_rgid == target->p_rgid && /* XXX */ 648 target->p_rgid == target->p_svgid && 649 (targetp->p_traceflag & KTRFAC_ROOT) == 0) || 650 caller->pc_ucred->cr_uid == 0) 651 return (1); 652 653 return (0); 654 } 655 #endif /* KTRACE */ 656 657 /* 658 * Put user defined entry to ktrace records. 659 */ 660 int 661 sys_utrace(p, v, retval) 662 struct proc *p; 663 void *v; 664 register_t *retval; 665 { 666 #ifdef KTRACE 667 struct sys_utrace_args /* { 668 syscallarg(const char *) id; 669 syscallarg(void *) addr; 670 syscallarg(size_t) len; 671 } */ *uap = v; 672 673 if (!KTRPOINT(p, KTR_USER)) 674 return (0); 675 676 ktruser(p, SCARG(uap, id), SCARG(uap, addr), SCARG(uap, len), 1); 677 678 return (0); 679 #else /* !KTRACE */ 680 return ENOSYS; 681 #endif /* KTRACE */ 682 } 683