|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. ! 3: * ! 4: * @APPLE_LICENSE_HEADER_START@ ! 5: * ! 6: * The contents of this file constitute Original Code as defined in and ! 7: * are subject to the Apple Public Source License Version 1.1 (the ! 8: * "License"). You may not use this file except in compliance with the ! 9: * License. Please obtain a copy of the License at ! 10: * http://www.apple.com/publicsource and read it before using this file. ! 11: * ! 12: * This Original Code and all software distributed under the License are ! 13: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER ! 14: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, ! 15: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, ! 16: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the ! 17: * License for the specific language governing rights and limitations ! 18: * under the License. ! 19: * ! 20: * @APPLE_LICENSE_HEADER_END@ ! 21: */ ! 22: /* Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved */ ! 23: /* ! 24: * Copyright (c) 1989, 1993 ! 25: * The Regents of the University of California. All rights reserved. ! 26: * ! 27: * Redistribution and use in source and binary forms, with or without ! 28: * modification, are permitted provided that the following conditions ! 29: * are met: ! 30: * 1. Redistributions of source code must retain the above copyright ! 31: * notice, this list of conditions and the following disclaimer. ! 32: * 2. Redistributions in binary form must reproduce the above copyright ! 33: * notice, this list of conditions and the following disclaimer in the ! 34: * documentation and/or other materials provided with the distribution. ! 35: * 3. All advertising materials mentioning features or use of this software ! 36: * must display the following acknowledgement: ! 37: * This product includes software developed by the University of ! 38: * California, Berkeley and its contributors. ! 39: * 4. Neither the name of the University nor the names of its contributors ! 40: * may be used to endorse or promote products derived from this software ! 41: * without specific prior written permission. ! 42: * ! 43: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ! 44: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ! 45: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ! 46: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE ! 47: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ! 48: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ! 49: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ! 50: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ! 51: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ! 52: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ! 53: * SUCH DAMAGE. ! 54: * ! 55: * @(#)kern_ktrace.c 8.2 (Berkeley) 9/23/93 ! 56: */ ! 57: ! 58: ! 59: #include <sys/param.h> ! 60: #include <sys/systm.h> ! 61: #include <sys/proc.h> ! 62: #include <sys/file.h> ! 63: #include <sys/namei.h> ! 64: #include <sys/vnode.h> ! 65: #include <sys/ktrace.h> ! 66: #include <sys/malloc.h> ! 67: #include <sys/syslog.h> ! 68: ! 69: #include <sys/mount.h> ! 70: ! 71: #if KTRACE ! 72: ! 73: struct ktr_header * ! 74: ktrgetheader(type) ! 75: int type; ! 76: { ! 77: register struct ktr_header *kth; ! 78: struct proc *p = current_proc(); /* XXX */ ! 79: ! 80: MALLOC(kth, struct ktr_header *, sizeof (struct ktr_header), ! 81: M_TEMP, M_WAITOK); ! 82: kth->ktr_type = type; ! 83: microtime(&kth->ktr_time); ! 84: kth->ktr_pid = p->p_pid; ! 85: bcopy(p->p_comm, kth->ktr_comm, MAXCOMLEN); ! 86: return (kth); ! 87: } ! 88: ! 89: void ! 90: ktrsyscall(vp, code, argsize, args) ! 91: struct vnode *vp; ! 92: register_t code; ! 93: size_t argsize; ! 94: register_t args[]; ! 95: { ! 96: struct ktr_header *kth; ! 97: struct ktr_syscall *ktp; ! 98: register len = sizeof(struct ktr_syscall) + argsize; ! 99: struct proc *p = current_proc(); /* XXX */ ! 100: register_t *argp; ! 101: int i; ! 102: ! 103: p->p_traceflag |= KTRFAC_ACTIVE; ! 104: kth = ktrgetheader(KTR_SYSCALL); ! 105: MALLOC(ktp, struct ktr_syscall *, len, M_TEMP, M_WAITOK); ! 106: ktp->ktr_code = code; ! 107: ktp->ktr_argsize = argsize; ! 108: argp = (register_t *)((char *)ktp + sizeof(struct ktr_syscall)); ! 109: for (i = 0; i < (argsize / sizeof *argp); i++) ! 110: *argp++ = args[i]; ! 111: kth->ktr_buf = (caddr_t)ktp; ! 112: kth->ktr_len = len; ! 113: ktrwrite(vp, kth); ! 114: FREE(ktp, M_TEMP); ! 115: FREE(kth, M_TEMP); ! 116: p->p_traceflag &= ~KTRFAC_ACTIVE; ! 117: } ! 118: ! 119: void ! 120: ktrsysret(vp, code, error, retval) ! 121: struct vnode *vp; ! 122: register_t code; ! 123: int error; ! 124: register_t retval; ! 125: { ! 126: struct ktr_header *kth; ! 127: struct ktr_sysret ktp; ! 128: struct proc *p = current_proc(); /* XXX */ ! 129: ! 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_buf = (caddr_t)&ktp; ! 137: kth->ktr_len = sizeof(struct ktr_sysret); ! 138: ! 139: ktrwrite(vp, kth); ! 140: FREE(kth, M_TEMP); ! 141: p->p_traceflag &= ~KTRFAC_ACTIVE; ! 142: } ! 143: ! 144: void ! 145: ktrnamei(vp, path) ! 146: struct vnode *vp; ! 147: char *path; ! 148: { ! 149: struct ktr_header *kth; ! 150: struct proc *p = current_proc(); /* XXX */ ! 151: ! 152: p->p_traceflag |= KTRFAC_ACTIVE; ! 153: kth = ktrgetheader(KTR_NAMEI); ! 154: kth->ktr_len = strlen(path); ! 155: kth->ktr_buf = path; ! 156: ! 157: ktrwrite(vp, kth); ! 158: FREE(kth, M_TEMP); ! 159: p->p_traceflag &= ~KTRFAC_ACTIVE; ! 160: } ! 161: ! 162: void ! 163: ktrgenio(vp, fd, rw, iov, len, error) ! 164: struct vnode *vp; ! 165: int fd; ! 166: enum uio_rw rw; ! 167: register struct iovec *iov; ! 168: int len, error; ! 169: { ! 170: struct ktr_header *kth; ! 171: register struct ktr_genio *ktp; ! 172: register caddr_t cp; ! 173: register int resid = len, cnt; ! 174: struct proc *p = current_proc(); /* XXX */ ! 175: ! 176: if (error) ! 177: return; ! 178: p->p_traceflag |= KTRFAC_ACTIVE; ! 179: kth = ktrgetheader(KTR_GENIO); ! 180: MALLOC(ktp, struct ktr_genio *, sizeof(struct ktr_genio) + len, ! 181: M_TEMP, M_WAITOK); ! 182: ktp->ktr_fd = fd; ! 183: ktp->ktr_rw = rw; ! 184: cp = (caddr_t)((char *)ktp + sizeof (struct ktr_genio)); ! 185: while (resid > 0) { ! 186: if ((cnt = iov->iov_len) > resid) ! 187: cnt = resid; ! 188: if (copyin(iov->iov_base, cp, (unsigned)cnt)) ! 189: goto done; ! 190: cp += cnt; ! 191: resid -= cnt; ! 192: iov++; ! 193: } ! 194: kth->ktr_buf = (caddr_t)ktp; ! 195: kth->ktr_len = sizeof (struct ktr_genio) + len; ! 196: ! 197: ktrwrite(vp, kth); ! 198: done: ! 199: FREE(kth, M_TEMP); ! 200: FREE(ktp, M_TEMP); ! 201: p->p_traceflag &= ~KTRFAC_ACTIVE; ! 202: } ! 203: ! 204: void ! 205: ktrpsig(vp, sig, action, mask, code) ! 206: struct vnode *vp; ! 207: int sig; ! 208: sig_t action; ! 209: int mask, code; ! 210: { ! 211: struct ktr_header *kth; ! 212: struct ktr_psig kp; ! 213: struct proc *p = current_proc(); /* XXX */ ! 214: ! 215: p->p_traceflag |= KTRFAC_ACTIVE; ! 216: kth = ktrgetheader(KTR_PSIG); ! 217: kp.signo = (char)sig; ! 218: kp.action = action; ! 219: kp.mask = mask; ! 220: kp.code = code; ! 221: kth->ktr_buf = (caddr_t)&kp; ! 222: kth->ktr_len = sizeof (struct ktr_psig); ! 223: ! 224: ktrwrite(vp, kth); ! 225: FREE(kth, M_TEMP); ! 226: p->p_traceflag &= ~KTRFAC_ACTIVE; ! 227: } ! 228: ! 229: void ! 230: ktrcsw(vp, out, user) ! 231: struct vnode *vp; ! 232: int out, user; ! 233: { ! 234: struct ktr_header *kth; ! 235: struct ktr_csw kc; ! 236: struct proc *p = current_proc(); /* XXX */ ! 237: ! 238: p->p_traceflag |= KTRFAC_ACTIVE; ! 239: kth = ktrgetheader(KTR_CSW); ! 240: kc.out = out; ! 241: kc.user = user; ! 242: kth->ktr_buf = (caddr_t)&kc; ! 243: kth->ktr_len = sizeof (struct ktr_csw); ! 244: ! 245: ktrwrite(vp, kth); ! 246: FREE(kth, M_TEMP); ! 247: p->p_traceflag &= ~KTRFAC_ACTIVE; ! 248: } ! 249: ! 250: /* Interface and common routines */ ! 251: ! 252: /* ! 253: * ktrace system call ! 254: */ ! 255: struct ktrace_args { ! 256: char * fname; ! 257: int ops; ! 258: int facs; ! 259: int pid; ! 260: }; ! 261: /* ARGSUSED */ ! 262: int ! 263: ktrace(curp, uap, retval) ! 264: struct proc *curp; ! 265: register struct ktrace_args *uap; ! 266: register_t *retval; ! 267: { ! 268: register struct vnode *vp = NULL; ! 269: register struct proc *p; ! 270: struct pgrp *pg; ! 271: int facs = SCARG(uap, facs) & ~KTRFAC_ROOT; ! 272: int ops = KTROP(SCARG(uap, ops)); ! 273: int descend = SCARG(uap, ops) & KTRFLAG_DESCEND; ! 274: int ret = 0; ! 275: int error = 0; ! 276: struct nameidata nd; ! 277: ! 278: curp->p_traceflag |= KTRFAC_ACTIVE; ! 279: if (ops != KTROP_CLEAR) { ! 280: /* ! 281: * an operation which requires a file argument. ! 282: */ ! 283: NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, fname), ! 284: curp); ! 285: if (error = vn_open(&nd, FREAD|FWRITE, 0)) { ! 286: curp->p_traceflag &= ~KTRFAC_ACTIVE; ! 287: return (error); ! 288: } ! 289: vp = nd.ni_vp; ! 290: VOP_UNLOCK(vp, 0, p); ! 291: if (vp->v_type != VREG) { ! 292: (void) vn_close(vp, FREAD|FWRITE, curp->p_ucred, curp); ! 293: curp->p_traceflag &= ~KTRFAC_ACTIVE; ! 294: return (EACCES); ! 295: } ! 296: } ! 297: /* ! 298: * Clear all uses of the tracefile ! 299: */ ! 300: if (ops == KTROP_CLEARFILE) { ! 301: for (p = allproc.lh_first; p != 0; p = p->p_list.le_next) { ! 302: if (p->p_tracep == vp) { ! 303: if (ktrcanset(curp, p)) { ! 304: p->p_tracep = NULL; ! 305: p->p_traceflag = 0; ! 306: (void) vn_close(vp, FREAD|FWRITE, ! 307: p->p_ucred, p); ! 308: } else ! 309: error = EPERM; ! 310: } ! 311: } ! 312: goto done; ! 313: } ! 314: /* ! 315: * need something to (un)trace (XXX - why is this here?) ! 316: */ ! 317: if (!facs) { ! 318: error = EINVAL; ! 319: goto done; ! 320: } ! 321: /* ! 322: * do it ! 323: */ ! 324: if (SCARG(uap, pid) < 0) { ! 325: /* ! 326: * by process group ! 327: */ ! 328: pg = pgfind(-SCARG(uap, pid)); ! 329: if (pg == NULL) { ! 330: error = ESRCH; ! 331: goto done; ! 332: } ! 333: for (p = pg->pg_members.lh_first; p != 0; p = p->p_pglist.le_next) ! 334: if (descend) ! 335: ret |= ktrsetchildren(curp, p, ops, facs, vp); ! 336: else ! 337: ret |= ktrops(curp, p, ops, facs, vp); ! 338: ! 339: } else { ! 340: /* ! 341: * by pid ! 342: */ ! 343: p = pfind(SCARG(uap, pid)); ! 344: if (p == NULL) { ! 345: error = ESRCH; ! 346: goto done; ! 347: } ! 348: if (descend) ! 349: ret |= ktrsetchildren(curp, p, ops, facs, vp); ! 350: else ! 351: ret |= ktrops(curp, p, ops, facs, vp); ! 352: } ! 353: if (!ret) ! 354: error = EPERM; ! 355: done: ! 356: if (vp != NULL) ! 357: (void) vn_close(vp, FWRITE, curp->p_ucred, curp); ! 358: curp->p_traceflag &= ~KTRFAC_ACTIVE; ! 359: return (error); ! 360: } ! 361: ! 362: int ! 363: ktrops(curp, p, ops, facs, vp) ! 364: struct proc *p, *curp; ! 365: int ops, facs; ! 366: struct vnode *vp; ! 367: { ! 368: ! 369: if (!ktrcanset(curp, p)) ! 370: return (0); ! 371: if (ops == KTROP_SET) { ! 372: if (p->p_tracep != vp) { ! 373: /* ! 374: * if trace file already in use, relinquish ! 375: */ ! 376: if (p->p_tracep != NULL) ! 377: vrele(p->p_tracep); ! 378: VREF(vp); ! 379: p->p_tracep = vp; ! 380: } ! 381: p->p_traceflag |= facs; ! 382: if (curp->p_ucred->cr_uid == 0) ! 383: p->p_traceflag |= KTRFAC_ROOT; ! 384: } else { ! 385: /* KTROP_CLEAR */ ! 386: if (((p->p_traceflag &= ~facs) & KTRFAC_MASK) == 0) { ! 387: /* no more tracing */ ! 388: p->p_traceflag = 0; ! 389: if (p->p_tracep != NULL) { ! 390: vrele(p->p_tracep); ! 391: p->p_tracep = NULL; ! 392: } ! 393: } ! 394: } ! 395: ! 396: return (1); ! 397: } ! 398: ! 399: ktrsetchildren(curp, top, ops, facs, vp) ! 400: struct proc *curp, *top; ! 401: int ops, facs; ! 402: struct vnode *vp; ! 403: { ! 404: register struct proc *p; ! 405: register int ret = 0; ! 406: ! 407: p = top; ! 408: for (;;) { ! 409: ret |= ktrops(curp, p, ops, facs, vp); ! 410: /* ! 411: * If this process has children, descend to them next, ! 412: * otherwise do any siblings, and if done with this level, ! 413: * follow back up the tree (but not past top). ! 414: */ ! 415: if (p->p_children.lh_first) ! 416: p = p->p_children.lh_first; ! 417: else for (;;) { ! 418: if (p == top) ! 419: return (ret); ! 420: if (p->p_sibling.le_next) { ! 421: p = p->p_sibling.le_next; ! 422: break; ! 423: } ! 424: p = p->p_pptr; ! 425: } ! 426: } ! 427: /*NOTREACHED*/ ! 428: } ! 429: ! 430: ktrwrite(vp, kth) ! 431: struct vnode *vp; ! 432: register struct ktr_header *kth; ! 433: { ! 434: struct uio auio; ! 435: struct iovec aiov[2]; ! 436: register struct proc *p = current_proc(); /* XXX */ ! 437: int error; ! 438: ! 439: if (vp == NULL) ! 440: return; ! 441: auio.uio_iov = &aiov[0]; ! 442: auio.uio_offset = 0; ! 443: auio.uio_segflg = UIO_SYSSPACE; ! 444: auio.uio_rw = UIO_WRITE; ! 445: aiov[0].iov_base = (caddr_t)kth; ! 446: aiov[0].iov_len = sizeof(struct ktr_header); ! 447: auio.uio_resid = sizeof(struct ktr_header); ! 448: auio.uio_iovcnt = 1; ! 449: auio.uio_procp = (struct proc *)0; ! 450: if (kth->ktr_len > 0) { ! 451: auio.uio_iovcnt++; ! 452: aiov[1].iov_base = kth->ktr_buf; ! 453: aiov[1].iov_len = kth->ktr_len; ! 454: auio.uio_resid += kth->ktr_len; ! 455: } ! 456: vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); ! 457: error = VOP_WRITE(vp, &auio, IO_UNIT|IO_APPEND, p->p_ucred); ! 458: VOP_UNLOCK(vp, 0, p); ! 459: if (!error) ! 460: return; ! 461: /* ! 462: * If error encountered, give up tracing on this vnode. ! 463: */ ! 464: log(LOG_NOTICE, "ktrace write failed, errno %d, tracing stopped\n", ! 465: error); ! 466: for (p = allproc.lh_first; p != 0; p = p->p_list.le_next) { ! 467: if (p->p_tracep == vp) { ! 468: p->p_tracep = NULL; ! 469: p->p_traceflag = 0; ! 470: vrele(vp); ! 471: } ! 472: } ! 473: } ! 474: ! 475: /* ! 476: * Return true if caller has permission to set the ktracing state ! 477: * of target. Essentially, the target can't possess any ! 478: * more permissions than the caller. KTRFAC_ROOT signifies that ! 479: * root previously set the tracing status on the target process, and ! 480: * so, only root may further change it. ! 481: * ! 482: * TODO: check groups. use caller effective gid. ! 483: */ ! 484: ktrcanset(callp, targetp) ! 485: struct proc *callp, *targetp; ! 486: { ! 487: register struct pcred *caller = callp->p_cred; ! 488: register struct pcred *target = targetp->p_cred; ! 489: ! 490: if ((caller->pc_ucred->cr_uid == target->p_ruid && ! 491: target->p_ruid == target->p_svuid && ! 492: caller->p_rgid == target->p_rgid && /* XXX */ ! 493: target->p_rgid == target->p_svgid && ! 494: (targetp->p_traceflag & KTRFAC_ROOT) == 0) || ! 495: caller->pc_ucred->cr_uid == 0) ! 496: return (1); ! 497: ! 498: return (0); ! 499: } ! 500: ! 501: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.