kern_ktrace.c revision 83366
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: head/sys/kern/kern_ktrace.c 83366 2001-09-12 08:38:13Z julian $ 35 */ 36 37#include "opt_ktrace.h" 38 39#include <sys/param.h> 40#include <sys/systm.h> 41#include <sys/lock.h> 42#include <sys/mutex.h> 43#include <sys/sysproto.h> 44#include <sys/kernel.h> 45#include <sys/proc.h> 46#include <sys/fcntl.h> 47#include <sys/namei.h> 48#include <sys/vnode.h> 49#include <sys/ktrace.h> 50#include <sys/malloc.h> 51#include <sys/sx.h> 52#include <sys/syslog.h> 53#include <sys/jail.h> 54 55static MALLOC_DEFINE(M_KTRACE, "KTRACE", "KTRACE"); 56 57#ifdef KTRACE 58static struct ktr_header *ktrgetheader __P((int type)); 59static void ktrwrite __P((struct vnode *, struct ktr_header *, struct uio *)); 60static int ktrcanset __P((struct proc *,struct proc *)); 61static int ktrsetchildren __P((struct proc *,struct proc *,int,int,struct vnode *)); 62static int ktrops __P((struct proc *,struct proc *,int,int,struct vnode *)); 63 64 65static struct ktr_header * 66ktrgetheader(type) 67 int type; 68{ 69 register struct ktr_header *kth; 70 struct proc *p = curproc; /* XXX */ 71 72 MALLOC(kth, struct ktr_header *, sizeof (struct ktr_header), 73 M_KTRACE, M_WAITOK); 74 kth->ktr_type = type; 75 microtime(&kth->ktr_time); 76 kth->ktr_pid = p->p_pid; 77 bcopy(p->p_comm, kth->ktr_comm, MAXCOMLEN + 1); 78 return (kth); 79} 80 81/* 82 * MPSAFE 83 */ 84void 85ktrsyscall(vp, code, narg, args) 86 struct vnode *vp; 87 int code, narg; 88 register_t args[]; 89{ 90 struct ktr_header *kth; 91 struct ktr_syscall *ktp; 92 register int len = offsetof(struct ktr_syscall, ktr_args) + 93 (narg * sizeof(register_t)); 94 struct proc *p = curproc; /* XXX */ 95 register_t *argp; 96 int i; 97 98 mtx_lock(&Giant); 99 p->p_traceflag |= KTRFAC_ACTIVE; 100 kth = ktrgetheader(KTR_SYSCALL); 101 MALLOC(ktp, struct ktr_syscall *, len, M_KTRACE, M_WAITOK); 102 ktp->ktr_code = code; 103 ktp->ktr_narg = narg; 104 argp = &ktp->ktr_args[0]; 105 for (i = 0; i < narg; i++) 106 *argp++ = args[i]; 107 kth->ktr_buffer = (caddr_t)ktp; 108 kth->ktr_len = len; 109 ktrwrite(vp, kth, NULL); 110 FREE(ktp, M_KTRACE); 111 FREE(kth, M_KTRACE); 112 p->p_traceflag &= ~KTRFAC_ACTIVE; 113 mtx_unlock(&Giant); 114} 115 116/* 117 * MPSAFE 118 */ 119void 120ktrsysret(vp, code, error, retval) 121 struct vnode *vp; 122 int code, error; 123 register_t retval; 124{ 125 struct ktr_header *kth; 126 struct ktr_sysret ktp; 127 struct proc *p = curproc; /* XXX */ 128 129 mtx_lock(&Giant); 130 p->p_traceflag |= KTRFAC_ACTIVE; 131 kth = ktrgetheader(KTR_SYSRET); 132 ktp.ktr_code = code; 133 ktp.ktr_error = error; 134 ktp.ktr_retval = retval; /* what about val2 ? */ 135 136 kth->ktr_buffer = (caddr_t)&ktp; 137 kth->ktr_len = sizeof(struct ktr_sysret); 138 139 ktrwrite(vp, kth, NULL); 140 FREE(kth, M_KTRACE); 141 p->p_traceflag &= ~KTRFAC_ACTIVE; 142 mtx_unlock(&Giant); 143} 144 145void 146ktrnamei(vp, path) 147 struct vnode *vp; 148 char *path; 149{ 150 struct ktr_header *kth; 151 struct proc *p = curproc; /* XXX */ 152 153 p->p_traceflag |= KTRFAC_ACTIVE; 154 kth = ktrgetheader(KTR_NAMEI); 155 kth->ktr_len = strlen(path); 156 kth->ktr_buffer = path; 157 158 ktrwrite(vp, kth, NULL); 159 FREE(kth, M_KTRACE); 160 p->p_traceflag &= ~KTRFAC_ACTIVE; 161} 162 163void 164ktrgenio(vp, fd, rw, uio, error) 165 struct vnode *vp; 166 int fd; 167 enum uio_rw rw; 168 struct uio *uio; 169 int error; 170{ 171 struct ktr_header *kth; 172 struct ktr_genio ktg; 173 struct proc *p = curproc; /* XXX */ 174 175 if (error) 176 return; 177 p->p_traceflag |= KTRFAC_ACTIVE; 178 kth = ktrgetheader(KTR_GENIO); 179 ktg.ktr_fd = fd; 180 ktg.ktr_rw = rw; 181 kth->ktr_buffer = (caddr_t)&ktg; 182 kth->ktr_len = sizeof(struct ktr_genio); 183 uio->uio_offset = 0; 184 uio->uio_rw = UIO_WRITE; 185 186 ktrwrite(vp, kth, uio); 187 FREE(kth, M_KTRACE); 188 p->p_traceflag &= ~KTRFAC_ACTIVE; 189} 190 191void 192ktrpsig(vp, sig, action, mask, code) 193 struct vnode *vp; 194 int sig; 195 sig_t action; 196 sigset_t *mask; 197 int code; 198{ 199 struct ktr_header *kth; 200 struct ktr_psig kp; 201 struct proc *p = curproc; /* XXX */ 202 203 p->p_traceflag |= KTRFAC_ACTIVE; 204 kth = ktrgetheader(KTR_PSIG); 205 kp.signo = (char)sig; 206 kp.action = action; 207 kp.mask = *mask; 208 kp.code = code; 209 kth->ktr_buffer = (caddr_t)&kp; 210 kth->ktr_len = sizeof (struct ktr_psig); 211 212 ktrwrite(vp, kth, NULL); 213 FREE(kth, M_KTRACE); 214 p->p_traceflag &= ~KTRFAC_ACTIVE; 215} 216 217void 218ktrcsw(vp, out, user) 219 struct vnode *vp; 220 int out, user; 221{ 222 struct ktr_header *kth; 223 struct ktr_csw kc; 224 struct proc *p = curproc; /* XXX */ 225 226 p->p_traceflag |= KTRFAC_ACTIVE; 227 kth = ktrgetheader(KTR_CSW); 228 kc.out = out; 229 kc.user = user; 230 kth->ktr_buffer = (caddr_t)&kc; 231 kth->ktr_len = sizeof (struct ktr_csw); 232 233 ktrwrite(vp, kth, NULL); 234 FREE(kth, M_KTRACE); 235 p->p_traceflag &= ~KTRFAC_ACTIVE; 236} 237#endif 238 239/* Interface and common routines */ 240 241/* 242 * ktrace system call 243 */ 244#ifndef _SYS_SYSPROTO_H_ 245struct ktrace_args { 246 char *fname; 247 int ops; 248 int facs; 249 int pid; 250}; 251#endif 252/* ARGSUSED */ 253int 254ktrace(td, uap) 255 struct thread *td; 256 register struct ktrace_args *uap; 257{ 258#ifdef KTRACE 259 struct proc *curp = td->td_proc; 260 register struct vnode *vp = NULL; 261 register struct proc *p; 262 struct pgrp *pg; 263 int facs = uap->facs & ~KTRFAC_ROOT; 264 int ops = KTROP(uap->ops); 265 int descend = uap->ops & KTRFLAG_DESCEND; 266 int ret = 0; 267 int flags, error = 0; 268 struct nameidata nd; 269 270 curp->p_traceflag |= KTRFAC_ACTIVE; 271 if (ops != KTROP_CLEAR) { 272 /* 273 * an operation which requires a file argument. 274 */ 275 NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, uap->fname, td); 276 flags = FREAD | FWRITE | O_NOFOLLOW; 277 error = vn_open(&nd, &flags, 0); 278 if (error) { 279 curp->p_traceflag &= ~KTRFAC_ACTIVE; 280 return (error); 281 } 282 NDFREE(&nd, NDF_ONLY_PNBUF); 283 vp = nd.ni_vp; 284 VOP_UNLOCK(vp, 0, td); 285 if (vp->v_type != VREG) { 286 (void) vn_close(vp, FREAD|FWRITE, curp->p_ucred, td); 287 curp->p_traceflag &= ~KTRFAC_ACTIVE; 288 return (EACCES); 289 } 290 } 291 /* 292 * Clear all uses of the tracefile 293 */ 294 if (ops == KTROP_CLEARFILE) { 295 sx_slock(&allproc_lock); 296 LIST_FOREACH(p, &allproc, p_list) { 297 if (p->p_tracep == vp) { 298 if (ktrcanset(curp, p)) { 299 p->p_tracep = NULL; 300 p->p_traceflag = 0; 301 (void) vn_close(vp, FREAD|FWRITE, 302 p->p_ucred, td); 303 } else 304 error = EPERM; 305 } 306 } 307 sx_sunlock(&allproc_lock); 308 goto done; 309 } 310 /* 311 * need something to (un)trace (XXX - why is this here?) 312 */ 313 if (!facs) { 314 error = EINVAL; 315 goto done; 316 } 317 /* 318 * do it 319 */ 320 if (uap->pid < 0) { 321 /* 322 * by process group 323 */ 324 pg = pgfind(-uap->pid); 325 if (pg == NULL) { 326 error = ESRCH; 327 goto done; 328 } 329 LIST_FOREACH(p, &pg->pg_members, p_pglist) 330 if (descend) 331 ret |= ktrsetchildren(curp, p, ops, facs, vp); 332 else 333 ret |= ktrops(curp, p, ops, facs, vp); 334 } else { 335 /* 336 * by pid 337 */ 338 p = pfind(uap->pid); 339 if (p == NULL) { 340 error = ESRCH; 341 goto done; 342 } 343 PROC_UNLOCK(p); 344 if (descend) 345 ret |= ktrsetchildren(curp, p, ops, facs, vp); 346 else 347 ret |= ktrops(curp, p, ops, facs, vp); 348 } 349 if (!ret) 350 error = EPERM; 351done: 352 if (vp != NULL) 353 (void) vn_close(vp, FWRITE, curp->p_ucred, td); 354 curp->p_traceflag &= ~KTRFAC_ACTIVE; 355 return (error); 356#else 357 return ENOSYS; 358#endif 359} 360 361/* 362 * utrace system call 363 */ 364/* ARGSUSED */ 365int 366utrace(td, uap) 367 struct thread *td; 368 register struct utrace_args *uap; 369{ 370 371#ifdef KTRACE 372 struct ktr_header *kth; 373 struct proc *p = curproc; /* XXX */ 374 register caddr_t cp; 375 376 if (!KTRPOINT(p, KTR_USER)) 377 return (0); 378 if (uap->len > KTR_USER_MAXLEN) 379 return (EINVAL); 380 p->p_traceflag |= KTRFAC_ACTIVE; 381 kth = ktrgetheader(KTR_USER); 382 MALLOC(cp, caddr_t, uap->len, M_KTRACE, M_WAITOK); 383 if (!copyin(uap->addr, cp, uap->len)) { 384 kth->ktr_buffer = cp; 385 kth->ktr_len = uap->len; 386 ktrwrite(p->p_tracep, kth, NULL); 387 } 388 FREE(kth, M_KTRACE); 389 FREE(cp, M_KTRACE); 390 p->p_traceflag &= ~KTRFAC_ACTIVE; 391 392 return (0); 393#else 394 return (ENOSYS); 395#endif 396} 397 398#ifdef KTRACE 399static int 400ktrops(curp, p, ops, facs, vp) 401 struct proc *p, *curp; 402 int ops, facs; 403 struct vnode *vp; 404{ 405 406 if (!ktrcanset(curp, p)) 407 return (0); 408 if (ops == KTROP_SET) { 409 if (p->p_tracep != vp) { 410 /* 411 * if trace file already in use, relinquish 412 */ 413 if (p->p_tracep != NULL) 414 vrele(p->p_tracep); 415 VREF(vp); 416 p->p_tracep = vp; 417 } 418 p->p_traceflag |= facs; 419 if (curp->p_ucred->cr_uid == 0) 420 p->p_traceflag |= KTRFAC_ROOT; 421 } else { 422 /* KTROP_CLEAR */ 423 if (((p->p_traceflag &= ~facs) & KTRFAC_MASK) == 0) { 424 /* no more tracing */ 425 p->p_traceflag = 0; 426 if (p->p_tracep != NULL) { 427 vrele(p->p_tracep); 428 p->p_tracep = NULL; 429 } 430 } 431 } 432 433 return (1); 434} 435 436static int 437ktrsetchildren(curp, top, ops, facs, vp) 438 struct proc *curp, *top; 439 int ops, facs; 440 struct vnode *vp; 441{ 442 register struct proc *p; 443 register int ret = 0; 444 445 p = top; 446 sx_slock(&proctree_lock); 447 for (;;) { 448 ret |= ktrops(curp, p, ops, facs, vp); 449 /* 450 * If this process has children, descend to them next, 451 * otherwise do any siblings, and if done with this level, 452 * follow back up the tree (but not past top). 453 */ 454 if (!LIST_EMPTY(&p->p_children)) 455 p = LIST_FIRST(&p->p_children); 456 else for (;;) { 457 if (p == top) { 458 sx_sunlock(&proctree_lock); 459 return (ret); 460 } 461 if (LIST_NEXT(p, p_sibling)) { 462 p = LIST_NEXT(p, p_sibling); 463 break; 464 } 465 p = p->p_pptr; 466 } 467 } 468 /*NOTREACHED*/ 469} 470 471static void 472ktrwrite(vp, kth, uio) 473 struct vnode *vp; 474 register struct ktr_header *kth; 475 struct uio *uio; 476{ 477 struct uio auio; 478 struct iovec aiov[2]; 479 struct thread *td = curthread; /* XXX */ 480 struct proc *p = td->td_proc; /* XXX */ 481 struct mount *mp; 482 int error; 483 484 if (vp == NULL) 485 return; 486 auio.uio_iov = &aiov[0]; 487 auio.uio_offset = 0; 488 auio.uio_segflg = UIO_SYSSPACE; 489 auio.uio_rw = UIO_WRITE; 490 aiov[0].iov_base = (caddr_t)kth; 491 aiov[0].iov_len = sizeof(struct ktr_header); 492 auio.uio_resid = sizeof(struct ktr_header); 493 auio.uio_iovcnt = 1; 494 auio.uio_td = curthread; 495 if (kth->ktr_len > 0) { 496 auio.uio_iovcnt++; 497 aiov[1].iov_base = kth->ktr_buffer; 498 aiov[1].iov_len = kth->ktr_len; 499 auio.uio_resid += kth->ktr_len; 500 if (uio != NULL) 501 kth->ktr_len += uio->uio_resid; 502 } 503 vn_start_write(vp, &mp, V_WAIT); 504 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 505 (void)VOP_LEASE(vp, td, p->p_ucred, LEASE_WRITE); 506 error = VOP_WRITE(vp, &auio, IO_UNIT | IO_APPEND, p->p_ucred); 507 if (error == 0 && uio != NULL) { 508 (void)VOP_LEASE(vp, td, p->p_ucred, LEASE_WRITE); 509 error = VOP_WRITE(vp, uio, IO_UNIT | IO_APPEND, p->p_ucred); 510 } 511 VOP_UNLOCK(vp, 0, td); 512 vn_finished_write(mp); 513 if (!error) 514 return; 515 /* 516 * If error encountered, give up tracing on this vnode. 517 */ 518 log(LOG_NOTICE, "ktrace write failed, errno %d, tracing stopped\n", 519 error); 520 sx_slock(&allproc_lock); 521 LIST_FOREACH(p, &allproc, p_list) { 522 if (p->p_tracep == vp) { 523 p->p_tracep = NULL; 524 p->p_traceflag = 0; 525 vrele(vp); 526 } 527 } 528 sx_sunlock(&allproc_lock); 529} 530 531/* 532 * Return true if caller has permission to set the ktracing state 533 * of target. Essentially, the target can't possess any 534 * more permissions than the caller. KTRFAC_ROOT signifies that 535 * root previously set the tracing status on the target process, and 536 * so, only root may further change it. 537 */ 538static int 539ktrcanset(callp, targetp) 540 struct proc *callp, *targetp; 541{ 542 543 if (targetp->p_traceflag & KTRFAC_ROOT && 544 suser_xxx(NULL, callp, PRISON_ROOT)) 545 return (0); 546 547 if (p_candebug(callp, targetp) != 0) 548 return (0); 549 550 return (1); 551} 552 553#endif /* KTRACE */ 554