1 /* 2 * Copyright (c) 1989, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. All advertising materials mentioning features or use of this software 14 * must display the following acknowledgement: 15 * This product includes software developed by the University of 16 * California, Berkeley and its contributors. 17 * 4. Neither the name of the University nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 * 33 * @(#)kern_ktrace.c 8.2 (Berkeley) 9/23/93 34 * $FreeBSD: src/sys/kern/kern_ktrace.c,v 1.35.2.6 2002/07/05 22:36:38 darrenr Exp $ 35 * $DragonFly: src/sys/kern/kern_ktrace.c,v 1.30 2008/04/14 12:01:50 dillon Exp $ 36 */ 37 38 #include "opt_ktrace.h" 39 40 #include <sys/param.h> 41 #include <sys/systm.h> 42 #include <sys/sysproto.h> 43 #include <sys/kernel.h> 44 #include <sys/proc.h> 45 #include <sys/fcntl.h> 46 #include <sys/lock.h> 47 #include <sys/nlookup.h> 48 #include <sys/vnode.h> 49 #include <sys/ktrace.h> 50 #include <sys/malloc.h> 51 #include <sys/syslog.h> 52 #include <sys/sysent.h> 53 54 #include <vm/vm_zone.h> 55 56 #include <sys/mplock2.h> 57 58 static MALLOC_DEFINE(M_KTRACE, "KTRACE", "KTRACE"); 59 60 #ifdef KTRACE 61 static struct ktr_header *ktrgetheader (int type); 62 static void ktrwrite (struct lwp *, struct ktr_header *, struct uio *); 63 static int ktrcanset (struct thread *,struct proc *); 64 static int ktrsetchildren (struct thread *,struct proc *,int,int, ktrace_node_t); 65 static int ktrops (struct thread *,struct proc *,int,int, ktrace_node_t); 66 67 /* 68 * MPSAFE 69 */ 70 static struct ktr_header * 71 ktrgetheader(int type) 72 { 73 struct ktr_header *kth; 74 struct proc *p = curproc; /* XXX */ 75 struct lwp *lp = curthread->td_lwp; 76 77 MALLOC(kth, struct ktr_header *, sizeof (struct ktr_header), 78 M_KTRACE, M_WAITOK); 79 kth->ktr_type = type; 80 /* XXX threaded flag is a hack at the moment */ 81 kth->ktr_flags = (p->p_nthreads > 1) ? KTRH_THREADED : 0; 82 microtime(&kth->ktr_time); 83 kth->ktr_pid = p->p_pid; 84 kth->ktr_tid = lp->lwp_tid; 85 bcopy(p->p_comm, kth->ktr_comm, MAXCOMLEN + 1); 86 return (kth); 87 } 88 89 void 90 ktrsyscall(struct lwp *lp, int code, int narg, register_t args[]) 91 { 92 struct ktr_header *kth; 93 struct ktr_syscall *ktp; 94 int len; 95 register_t *argp; 96 int i; 97 98 len = offsetof(struct ktr_syscall, ktr_args) + 99 (narg * sizeof(register_t)); 100 101 /* 102 * Setting the active bit prevents a ktrace recursion from the 103 * ktracing op itself. 104 */ 105 lp->lwp_traceflag |= KTRFAC_ACTIVE; 106 kth = ktrgetheader(KTR_SYSCALL); 107 MALLOC(ktp, struct ktr_syscall *, len, M_KTRACE, M_WAITOK); 108 ktp->ktr_code = code; 109 ktp->ktr_narg = narg; 110 argp = &ktp->ktr_args[0]; 111 for (i = 0; i < narg; i++) 112 *argp++ = args[i]; 113 kth->ktr_buf = (caddr_t)ktp; 114 kth->ktr_len = len; 115 ktrwrite(lp, kth, NULL); 116 FREE(ktp, M_KTRACE); 117 FREE(kth, M_KTRACE); 118 lp->lwp_traceflag &= ~KTRFAC_ACTIVE; 119 } 120 121 void 122 ktrsysret(struct lwp *lp, int code, int error, register_t retval) 123 { 124 struct ktr_header *kth; 125 struct ktr_sysret ktp; 126 127 lp->lwp_traceflag |= KTRFAC_ACTIVE; 128 kth = ktrgetheader(KTR_SYSRET); 129 ktp.ktr_code = code; 130 ktp.ktr_error = error; 131 if (error == 0) 132 ktp.ktr_retval = retval; /* what about val2 ? */ 133 else 134 ktp.ktr_retval = 0; 135 136 kth->ktr_buf = (caddr_t)&ktp; 137 kth->ktr_len = sizeof(struct ktr_sysret); 138 139 ktrwrite(lp, kth, NULL); 140 FREE(kth, M_KTRACE); 141 lp->lwp_traceflag &= ~KTRFAC_ACTIVE; 142 } 143 144 void 145 ktrnamei(struct lwp *lp, char *path) 146 { 147 struct ktr_header *kth; 148 149 lp->lwp_traceflag |= KTRFAC_ACTIVE; 150 kth = ktrgetheader(KTR_NAMEI); 151 kth->ktr_len = strlen(path); 152 kth->ktr_buf = path; 153 154 ktrwrite(lp, kth, NULL); 155 FREE(kth, M_KTRACE); 156 lp->lwp_traceflag &= ~KTRFAC_ACTIVE; 157 } 158 159 void 160 ktrgenio(struct lwp *lp, int fd, enum uio_rw rw, struct uio *uio, int error) 161 { 162 struct ktr_header *kth; 163 struct ktr_genio ktg; 164 165 if (error) 166 return; 167 lp->lwp_traceflag |= KTRFAC_ACTIVE; 168 kth = ktrgetheader(KTR_GENIO); 169 ktg.ktr_fd = fd; 170 ktg.ktr_rw = rw; 171 kth->ktr_buf = (caddr_t)&ktg; 172 kth->ktr_len = sizeof(struct ktr_genio); 173 uio->uio_offset = 0; 174 uio->uio_rw = UIO_WRITE; 175 176 ktrwrite(lp, kth, uio); 177 FREE(kth, M_KTRACE); 178 lp->lwp_traceflag &= ~KTRFAC_ACTIVE; 179 } 180 181 void 182 ktrpsig(struct lwp *lp, int sig, sig_t action, sigset_t *mask, int code) 183 { 184 struct ktr_header *kth; 185 struct ktr_psig kp; 186 187 lp->lwp_traceflag |= KTRFAC_ACTIVE; 188 kth = ktrgetheader(KTR_PSIG); 189 kp.signo = (char)sig; 190 kp.action = action; 191 kp.mask = *mask; 192 kp.code = code; 193 kth->ktr_buf = (caddr_t)&kp; 194 kth->ktr_len = sizeof (struct ktr_psig); 195 196 ktrwrite(lp, kth, NULL); 197 FREE(kth, M_KTRACE); 198 lp->lwp_traceflag &= ~KTRFAC_ACTIVE; 199 } 200 201 void 202 ktrcsw(struct lwp *lp, int out, int user) 203 { 204 struct ktr_header *kth; 205 struct ktr_csw kc; 206 207 lp->lwp_traceflag |= KTRFAC_ACTIVE; 208 kth = ktrgetheader(KTR_CSW); 209 kc.out = out; 210 kc.user = user; 211 kth->ktr_buf = (caddr_t)&kc; 212 kth->ktr_len = sizeof (struct ktr_csw); 213 214 ktrwrite(lp, kth, NULL); 215 FREE(kth, M_KTRACE); 216 lp->lwp_traceflag &= ~KTRFAC_ACTIVE; 217 } 218 #endif 219 220 /* Interface and common routines */ 221 222 #ifdef KTRACE 223 /* 224 * ktrace system call 225 */ 226 struct ktrace_clear_info { 227 ktrace_node_t tracenode; 228 int rootclear; 229 int error; 230 }; 231 232 static int ktrace_clear_callback(struct proc *p, void *data); 233 234 #endif 235 236 /* 237 * MPALMOSTSAFE 238 */ 239 int 240 sys_ktrace(struct ktrace_args *uap) 241 { 242 #ifdef KTRACE 243 struct ktrace_clear_info info; 244 struct thread *td = curthread; 245 struct proc *curp = td->td_proc; 246 struct proc *p; 247 struct pgrp *pg; 248 int facs = uap->facs & ~KTRFAC_ROOT; 249 int ops = KTROP(uap->ops); 250 int descend = uap->ops & KTRFLAG_DESCEND; 251 int ret = 0; 252 int error = 0; 253 struct nlookupdata nd; 254 ktrace_node_t tracenode = NULL; 255 256 get_mplock(); 257 curp->p_traceflag |= KTRFAC_ACTIVE; 258 if (ops != KTROP_CLEAR) { 259 /* 260 * an operation which requires a file argument. 261 */ 262 error = nlookup_init(&nd, uap->fname, 263 UIO_USERSPACE, NLC_LOCKVP); 264 if (error == 0) 265 error = vn_open(&nd, NULL, FREAD|FWRITE|O_NOFOLLOW, 0); 266 if (error == 0 && nd.nl_open_vp->v_type != VREG) 267 error = EACCES; 268 if (error) { 269 curp->p_traceflag &= ~KTRFAC_ACTIVE; 270 nlookup_done(&nd); 271 goto done; 272 } 273 MALLOC(tracenode, ktrace_node_t, sizeof (struct ktrace_node), 274 M_KTRACE, M_WAITOK | M_ZERO); 275 tracenode->kn_vp = nd.nl_open_vp; 276 tracenode->kn_refs = 1; 277 nd.nl_open_vp = NULL; 278 nlookup_done(&nd); 279 vn_unlock(tracenode->kn_vp); 280 } 281 /* 282 * Clear all uses of the tracefile. Not the most efficient operation 283 * in the world. 284 */ 285 if (ops == KTROP_CLEARFILE) { 286 info.tracenode = tracenode; 287 info.error = 0; 288 info.rootclear = 0; 289 allproc_scan(ktrace_clear_callback, &info); 290 error = info.error; 291 goto done; 292 } 293 /* 294 * need something to (un)trace (XXX - why is this here?) 295 */ 296 if (!facs) { 297 error = EINVAL; 298 goto done; 299 } 300 /* 301 * do it 302 */ 303 if (uap->pid < 0) { 304 /* 305 * By process group. Process group is referenced, preventing 306 * disposal. 307 */ 308 pg = pgfind(-uap->pid); 309 if (pg == NULL) { 310 error = ESRCH; 311 goto done; 312 } 313 lwkt_gettoken(&pg->pg_token); 314 LIST_FOREACH(p, &pg->pg_members, p_pglist) { 315 PHOLD(p); 316 if (descend) 317 ret |= ktrsetchildren(td, p, ops, facs, tracenode); 318 else 319 ret |= ktrops(td, p, ops, facs, tracenode); 320 PRELE(p); 321 } 322 lwkt_reltoken(&pg->pg_token); 323 pgrel(pg); 324 } else { 325 /* 326 * by pid 327 */ 328 p = pfind(uap->pid); 329 if (p == NULL) { 330 error = ESRCH; 331 goto done; 332 } 333 if (descend) 334 ret |= ktrsetchildren(td, p, ops, facs, tracenode); 335 else 336 ret |= ktrops(td, p, ops, facs, tracenode); 337 PRELE(p); 338 } 339 if (!ret) 340 error = EPERM; 341 done: 342 if (tracenode) 343 ktrdestroy(&tracenode); 344 curp->p_traceflag &= ~KTRFAC_ACTIVE; 345 rel_mplock(); 346 return (error); 347 #else 348 return ENOSYS; 349 #endif 350 } 351 352 #ifdef KTRACE 353 354 /* 355 * NOTE: NOT MPSAFE (yet) 356 */ 357 static int 358 ktrace_clear_callback(struct proc *p, void *data) 359 { 360 struct ktrace_clear_info *info = data; 361 362 if (p->p_tracenode) { 363 if (info->rootclear) { 364 if (p->p_tracenode == info->tracenode) { 365 ktrdestroy(&p->p_tracenode); 366 p->p_traceflag = 0; 367 } 368 } else { 369 if (p->p_tracenode->kn_vp == info->tracenode->kn_vp) { 370 if (ktrcanset(curthread, p)) { 371 ktrdestroy(&p->p_tracenode); 372 p->p_traceflag = 0; 373 } else { 374 info->error = EPERM; 375 } 376 } 377 } 378 } 379 return(0); 380 } 381 382 #endif 383 384 /* 385 * utrace system call 386 * 387 * MPALMOSTSAFE 388 */ 389 int 390 sys_utrace(struct utrace_args *uap) 391 { 392 #ifdef KTRACE 393 struct ktr_header *kth; 394 struct thread *td = curthread; /* XXX */ 395 caddr_t cp; 396 397 if (!KTRPOINT(td, KTR_USER)) 398 return (0); 399 if (uap->len > KTR_USER_MAXLEN) 400 return (EINVAL); 401 td->td_lwp->lwp_traceflag |= KTRFAC_ACTIVE; 402 kth = ktrgetheader(KTR_USER); 403 MALLOC(cp, caddr_t, uap->len, M_KTRACE, M_WAITOK); 404 if (!copyin(uap->addr, cp, uap->len)) { 405 kth->ktr_buf = cp; 406 kth->ktr_len = uap->len; 407 ktrwrite(td->td_lwp, kth, NULL); 408 } 409 FREE(kth, M_KTRACE); 410 FREE(cp, M_KTRACE); 411 td->td_lwp->lwp_traceflag &= ~KTRFAC_ACTIVE; 412 413 return (0); 414 #else 415 return (ENOSYS); 416 #endif 417 } 418 419 void 420 ktrdestroy(struct ktrace_node **tracenodep) 421 { 422 ktrace_node_t tracenode; 423 424 if ((tracenode = *tracenodep) != NULL) { 425 *tracenodep = NULL; 426 KKASSERT(tracenode->kn_refs > 0); 427 if (atomic_fetchadd_int(&tracenode->kn_refs, -1) == 1) { 428 vn_close(tracenode->kn_vp, FREAD|FWRITE); 429 tracenode->kn_vp = NULL; 430 FREE(tracenode, M_KTRACE); 431 } 432 } 433 } 434 435 /* 436 * This allows a process to inherit a ref on a tracenode and is also used 437 * as a temporary ref to prevent a tracenode from being destroyed out from 438 * under an active operation. 439 */ 440 ktrace_node_t 441 ktrinherit(ktrace_node_t tracenode) 442 { 443 if (tracenode) { 444 KKASSERT(tracenode->kn_refs > 0); 445 atomic_add_int(&tracenode->kn_refs, 1); 446 } 447 return(tracenode); 448 } 449 450 #ifdef KTRACE 451 static int 452 ktrops(struct thread *td, struct proc *p, int ops, int facs, 453 ktrace_node_t tracenode) 454 { 455 ktrace_node_t oldnode; 456 457 if (!ktrcanset(td, p)) 458 return (0); 459 if (ops == KTROP_SET) { 460 if ((oldnode = p->p_tracenode) != tracenode) { 461 p->p_tracenode = ktrinherit(tracenode); 462 ktrdestroy(&oldnode); 463 } 464 p->p_traceflag |= facs; 465 if (td->td_ucred->cr_uid == 0) 466 p->p_traceflag |= KTRFAC_ROOT; 467 } else { 468 /* KTROP_CLEAR */ 469 if (((p->p_traceflag &= ~facs) & KTRFAC_MASK) == 0) { 470 /* no more tracing */ 471 p->p_traceflag = 0; 472 ktrdestroy(&p->p_tracenode); 473 } 474 } 475 476 return (1); 477 } 478 479 static int 480 ktrsetchildren(struct thread *td, struct proc *top, int ops, int facs, 481 ktrace_node_t tracenode) 482 { 483 struct proc *p; 484 struct proc *np; 485 int ret = 0; 486 487 p = top; 488 PHOLD(p); 489 lwkt_gettoken(&p->p_token); 490 491 for (;;) { 492 ret |= ktrops(td, p, ops, facs, tracenode); 493 494 /* 495 * If this process has children, descend to them next, 496 * otherwise do any siblings, and if done with this level, 497 * follow back up the tree (but not past top). 498 */ 499 if ((np = LIST_FIRST(&p->p_children)) != NULL) { 500 PHOLD(np); 501 } 502 while (np == NULL) { 503 if (p == top) 504 break; 505 if ((np = LIST_NEXT(p, p_sibling)) != NULL) { 506 PHOLD(np); 507 break; 508 } 509 510 /* 511 * recurse up to parent, set p in our inner 512 * loop when doing this. np can be NULL if 513 * we race a reparenting to init (thus 'top' 514 * is skipped past and never encountered). 515 */ 516 np = p->p_pptr; 517 if (np == NULL) 518 break; 519 PHOLD(np); 520 lwkt_reltoken(&p->p_token); 521 PRELE(p); 522 p = np; 523 lwkt_gettoken(&p->p_token); 524 np = NULL; 525 } 526 lwkt_reltoken(&p->p_token); 527 PRELE(p); 528 p = np; 529 if (p == NULL) 530 break; 531 /* Already held, but we need the token too */ 532 lwkt_gettoken(&p->p_token); 533 } 534 return (ret); 535 } 536 537 static void 538 ktrwrite(struct lwp *lp, struct ktr_header *kth, struct uio *uio) 539 { 540 struct ktrace_clear_info info; 541 struct uio auio; 542 struct iovec aiov[2]; 543 int error; 544 ktrace_node_t tracenode; 545 546 /* 547 * We have to ref our tracenode to prevent it from being ripped out 548 * from under us while we are trying to use it. p_tracenode can 549 * go away at any time if another process gets a write error. 550 * 551 * XXX not MP safe 552 */ 553 if (lp->lwp_proc->p_tracenode == NULL) 554 return; 555 tracenode = ktrinherit(lp->lwp_proc->p_tracenode); 556 auio.uio_iov = &aiov[0]; 557 auio.uio_offset = 0; 558 auio.uio_segflg = UIO_SYSSPACE; 559 auio.uio_rw = UIO_WRITE; 560 aiov[0].iov_base = (caddr_t)kth; 561 aiov[0].iov_len = sizeof(struct ktr_header); 562 auio.uio_resid = sizeof(struct ktr_header); 563 auio.uio_iovcnt = 1; 564 auio.uio_td = curthread; 565 if (kth->ktr_len > 0) { 566 auio.uio_iovcnt++; 567 aiov[1].iov_base = kth->ktr_buf; 568 aiov[1].iov_len = kth->ktr_len; 569 auio.uio_resid += kth->ktr_len; 570 if (uio != NULL) 571 kth->ktr_len += uio->uio_resid; 572 } 573 vn_lock(tracenode->kn_vp, LK_EXCLUSIVE | LK_RETRY); 574 error = VOP_WRITE(tracenode->kn_vp, &auio, 575 IO_UNIT | IO_APPEND, lp->lwp_thread->td_ucred); 576 if (error == 0 && uio != NULL) { 577 error = VOP_WRITE(tracenode->kn_vp, uio, 578 IO_UNIT | IO_APPEND, lp->lwp_thread->td_ucred); 579 } 580 vn_unlock(tracenode->kn_vp); 581 if (error) { 582 /* 583 * If an error occured, give up tracing on all processes 584 * using this tracenode. This is not MP safe but is 585 * blocking-safe. 586 */ 587 log(LOG_NOTICE, 588 "ktrace write failed, errno %d, tracing stopped\n", error); 589 info.tracenode = tracenode; 590 info.error = 0; 591 info.rootclear = 1; 592 allproc_scan(ktrace_clear_callback, &info); 593 } 594 ktrdestroy(&tracenode); 595 } 596 597 /* 598 * Return true if caller has permission to set the ktracing state 599 * of target. Essentially, the target can't possess any 600 * more permissions than the caller. KTRFAC_ROOT signifies that 601 * root previously set the tracing status on the target process, and 602 * so, only root may further change it. 603 * 604 * TODO: check groups. use caller effective gid. 605 */ 606 static int 607 ktrcanset(struct thread *calltd, struct proc *targetp) 608 { 609 struct ucred *caller = calltd->td_ucred; 610 struct ucred *target = targetp->p_ucred; 611 612 if (!PRISON_CHECK(caller, target)) 613 return (0); 614 if ((caller->cr_uid == target->cr_ruid && 615 target->cr_ruid == target->cr_svuid && 616 caller->cr_rgid == target->cr_rgid && /* XXX */ 617 target->cr_rgid == target->cr_svgid && 618 (targetp->p_traceflag & KTRFAC_ROOT) == 0 && 619 (targetp->p_flags & P_SUGID) == 0) || 620 caller->cr_uid == 0) 621 return (1); 622 623 return (0); 624 } 625 626 #endif /* KTRACE */ 627