1 /* $NetBSD: kern_ktrace.c,v 1.49 2000/12/11 19:53:06 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 "opt_ktrace.h" 39 40 #ifdef KTRACE 41 42 #include <sys/param.h> 43 #include <sys/systm.h> 44 #include <sys/proc.h> 45 #include <sys/file.h> 46 #include <sys/namei.h> 47 #include <sys/vnode.h> 48 #include <sys/ktrace.h> 49 #include <sys/malloc.h> 50 #include <sys/syslog.h> 51 #include <sys/filedesc.h> 52 #include <sys/ioctl.h> 53 54 #include <sys/mount.h> 55 #include <sys/syscallargs.h> 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 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 = 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 /* Interface and common routines */ 280 281 int 282 ktrace_common(struct proc *curp, int ops, int facs, int pid, struct file *fp) 283 { 284 int ret = 0; 285 int error = 0; 286 int one = 1; 287 int descend; 288 struct proc *p; 289 struct pgrp *pg; 290 291 curp->p_traceflag |= KTRFAC_ACTIVE; 292 descend = ops & KTRFLAG_DESCEND; 293 facs = facs & ~((unsigned) KTRFAC_ROOT); 294 295 /* 296 * Clear all uses of the tracefile 297 */ 298 if (KTROP(ops) == KTROP_CLEARFILE) { 299 proclist_lock_read(); 300 for (p = LIST_FIRST(&allproc); p != NULL; 301 p = LIST_NEXT(p, p_list)) { 302 if (ktrsamefile(p->p_tracep, fp)) { 303 if (ktrcanset(curp, p)) 304 ktrderef(p); 305 else 306 error = EPERM; 307 } 308 } 309 proclist_unlock_read(); 310 goto done; 311 } 312 313 /* 314 * Mark fp non-blocking, to avoid problems from possible deadlocks. 315 */ 316 317 if (fp != NULL) { 318 fp->f_flag |= FNONBLOCK; 319 (*fp->f_ops->fo_ioctl)(fp, FIONBIO, (caddr_t)&one, curp); 320 } 321 322 /* 323 * need something to (un)trace (XXX - why is this here?) 324 */ 325 if (!facs) { 326 error = EINVAL; 327 goto done; 328 } 329 /* 330 * do it 331 */ 332 if (pid < 0) { 333 /* 334 * by process group 335 */ 336 pg = pgfind(-pid); 337 if (pg == NULL) { 338 error = ESRCH; 339 goto done; 340 } 341 for (p = LIST_FIRST(&pg->pg_members); p != NULL; 342 p = LIST_NEXT(p, p_pglist)) { 343 if (descend) 344 ret |= ktrsetchildren(curp, p, ops, facs, fp); 345 else 346 ret |= ktrops(curp, p, ops, facs, fp); 347 } 348 349 } else { 350 /* 351 * by pid 352 */ 353 p = pfind(pid); 354 if (p == NULL) { 355 error = ESRCH; 356 goto done; 357 } 358 if (descend) 359 ret |= ktrsetchildren(curp, p, ops, facs, fp); 360 else 361 ret |= ktrops(curp, p, ops, facs, fp); 362 } 363 if (!ret) 364 error = EPERM; 365 done: 366 curp->p_traceflag &= ~KTRFAC_ACTIVE; 367 return (error); 368 } 369 370 /* 371 * ktrace system call 372 */ 373 /* ARGSUSED */ 374 int 375 sys_fktrace(struct proc *curp, void *v, register_t *retval) 376 { 377 struct sys_fktrace_args /* { 378 syscallarg(int) fd; 379 syscallarg(int) ops; 380 syscallarg(int) facs; 381 syscallarg(int) pid; 382 } */ *uap = v; 383 struct file *fp = NULL; 384 struct filedesc *fdp = curp->p_fd; 385 386 if (((u_int)SCARG(uap, fd)) >= fdp->fd_nfiles || 387 (fp = fdp->fd_ofiles[SCARG(uap, fd)]) == NULL || 388 (fp->f_flag & FWRITE) == 0) 389 return (EBADF); 390 391 return ktrace_common(curp, SCARG(uap, ops), 392 SCARG(uap, facs), SCARG(uap, pid), fp); 393 } 394 395 /* 396 * ktrace system call 397 */ 398 /* ARGSUSED */ 399 int 400 sys_ktrace(struct proc *curp, void *v, register_t *retval) 401 { 402 struct sys_ktrace_args /* { 403 syscallarg(const char *) fname; 404 syscallarg(int) ops; 405 syscallarg(int) facs; 406 syscallarg(int) pid; 407 } */ *uap = v; 408 struct vnode *vp = NULL; 409 struct file *fp = NULL; 410 int fd; 411 int ops = SCARG(uap, ops); 412 int error = 0; 413 struct nameidata nd; 414 415 ops = KTROP(ops) | (ops & KTRFLAG_DESCEND); 416 417 curp->p_traceflag |= KTRFAC_ACTIVE; 418 if (ops != KTROP_CLEAR) { 419 /* 420 * an operation which requires a file argument. 421 */ 422 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, fname), 423 curp); 424 if ((error = vn_open(&nd, FREAD|FWRITE, 0)) != 0) { 425 curp->p_traceflag &= ~KTRFAC_ACTIVE; 426 return (error); 427 } 428 vp = nd.ni_vp; 429 VOP_UNLOCK(vp, 0); 430 if (vp->v_type != VREG) { 431 (void) vn_close(vp, FREAD|FWRITE, curp->p_ucred, curp); 432 curp->p_traceflag &= ~KTRFAC_ACTIVE; 433 return (EACCES); 434 } 435 /* 436 * XXX This uses up a file descriptor slot in the 437 * tracing process for the duration of this syscall. 438 * This is not expected to be a problem. If 439 * falloc(NULL, ...) DTRT we could skip that part, but 440 * that would require changing its interface to allow 441 * the caller to pass in a ucred.. 442 * 443 * This will FILE_USE the fp it returns, if any. 444 * Keep it in use until we return. 445 */ 446 if ((error = falloc(curp, &fp, &fd)) != 0) 447 goto done; 448 449 fp->f_flag = FWRITE|FAPPEND; 450 fp->f_type = DTYPE_VNODE; 451 fp->f_ops = &vnops; 452 fp->f_data = (caddr_t)vp; 453 vp = NULL; 454 } 455 error = ktrace_common(curp, SCARG(uap, ops), SCARG(uap, facs), 456 SCARG(uap, pid), fp); 457 done: 458 if (vp != NULL) 459 (void) vn_close(vp, FWRITE, curp->p_ucred, curp); 460 if (fp != NULL) { 461 FILE_UNUSE(fp, curp); /* release file */ 462 fdrelease(curp, fd); /* release fd table slot */ 463 } 464 return (error); 465 } 466 467 int 468 ktrops(struct proc *curp, struct proc *p, int ops, int facs, struct file *fp) 469 { 470 471 if (!ktrcanset(curp, p)) 472 return (0); 473 if (KTROP(ops) == KTROP_SET) { 474 if (p->p_tracep != fp) { 475 /* 476 * if trace file already in use, relinquish 477 */ 478 ktrderef(p); 479 p->p_tracep = fp; 480 ktradref(p); 481 } 482 p->p_traceflag |= facs; 483 if (curp->p_ucred->cr_uid == 0) 484 p->p_traceflag |= KTRFAC_ROOT; 485 } else { 486 /* KTROP_CLEAR */ 487 if (((p->p_traceflag &= ~facs) & KTRFAC_MASK) == 0) { 488 /* no more tracing */ 489 ktrderef(p); 490 } 491 } 492 493 /* 494 * Emit an emulation record, every time there is a ktrace 495 * change/attach request. 496 */ 497 if (KTRPOINT(p, KTR_EMUL)) 498 ktremul(p); 499 #ifdef __HAVE_SYSCALL_INTERN 500 (*p->p_emul->e_syscall_intern)(p); 501 #endif 502 503 return (1); 504 } 505 506 int 507 ktrsetchildren(struct proc *curp, struct proc *top, int ops, int facs, 508 struct file *fp) 509 { 510 struct proc *p; 511 int ret = 0; 512 513 p = top; 514 for (;;) { 515 ret |= ktrops(curp, p, ops, facs, fp); 516 /* 517 * If this process has children, descend to them next, 518 * otherwise do any siblings, and if done with this level, 519 * follow back up the tree (but not past top). 520 */ 521 if (LIST_FIRST(&p->p_children) != NULL) 522 p = LIST_FIRST(&p->p_children); 523 else for (;;) { 524 if (p == top) 525 return (ret); 526 if (LIST_NEXT(p, p_sibling) != NULL) { 527 p = LIST_NEXT(p, p_sibling); 528 break; 529 } 530 p = p->p_pptr; 531 } 532 } 533 /*NOTREACHED*/ 534 } 535 536 int 537 ktrwrite(struct proc *p, struct ktr_header *kth) 538 { 539 struct uio auio; 540 struct iovec aiov[2]; 541 int error, tries; 542 struct file *fp = p->p_tracep; 543 544 if (fp == NULL) 545 return 0; 546 547 auio.uio_iov = &aiov[0]; 548 auio.uio_offset = 0; 549 auio.uio_segflg = UIO_SYSSPACE; 550 auio.uio_rw = UIO_WRITE; 551 aiov[0].iov_base = (caddr_t)kth; 552 aiov[0].iov_len = sizeof(struct ktr_header); 553 auio.uio_resid = sizeof(struct ktr_header); 554 auio.uio_iovcnt = 1; 555 auio.uio_procp = (struct proc *)0; 556 if (kth->ktr_len > 0) { 557 auio.uio_iovcnt++; 558 aiov[1].iov_base = kth->ktr_buf; 559 aiov[1].iov_len = kth->ktr_len; 560 auio.uio_resid += kth->ktr_len; 561 } 562 563 FILE_USE(fp); 564 565 tries = 0; 566 do { 567 error = (*fp->f_ops->fo_write)(fp, &fp->f_offset, &auio, 568 fp->f_cred, FOF_UPDATE_OFFSET); 569 tries++; 570 if (error == EWOULDBLOCK) 571 yield(); 572 } while ((error == EWOULDBLOCK) && (tries < 3)); 573 FILE_UNUSE(fp, NULL); 574 575 if (__predict_true(error == 0)) 576 return (0); 577 /* 578 * If error encountered, give up tracing on this vnode. Don't report 579 * EPIPE as this can easily happen with fktrace()/ktruss. 580 */ 581 if (error != EPIPE) 582 log(LOG_NOTICE, 583 "ktrace write failed, errno %d, tracing stopped\n", 584 error); 585 proclist_lock_read(); 586 for (p = LIST_FIRST(&allproc); p != NULL; p = LIST_NEXT(p, p_list)) { 587 if (ktrsamefile(p->p_tracep, fp)) 588 ktrderef(p); 589 } 590 proclist_unlock_read(); 591 592 return (error); 593 } 594 595 /* 596 * Return true if caller has permission to set the ktracing state 597 * of target. Essentially, the target can't possess any 598 * more permissions than the caller. KTRFAC_ROOT signifies that 599 * root previously set the tracing status on the target process, and 600 * so, only root may further change it. 601 * 602 * TODO: check groups. use caller effective gid. 603 */ 604 int 605 ktrcanset(struct proc *callp, struct proc *targetp) 606 { 607 struct pcred *caller = callp->p_cred; 608 struct pcred *target = targetp->p_cred; 609 610 if ((caller->pc_ucred->cr_uid == target->p_ruid && 611 target->p_ruid == target->p_svuid && 612 caller->p_rgid == target->p_rgid && /* XXX */ 613 target->p_rgid == target->p_svgid && 614 (targetp->p_traceflag & KTRFAC_ROOT) == 0) || 615 caller->pc_ucred->cr_uid == 0) 616 return (1); 617 618 return (0); 619 } 620 #endif /* KTRACE */ 621