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