|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1989 The Regents of the University of California. ! 3: * 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 7.15 (Berkeley) 6/21/91 ! 34: */ ! 35: ! 36: #ifdef KTRACE ! 37: ! 38: #include "param.h" ! 39: #include "proc.h" ! 40: #include "file.h" ! 41: #include "namei.h" ! 42: #include "vnode.h" ! 43: #include "ktrace.h" ! 44: #include "malloc.h" ! 45: #include "syslog.h" ! 46: ! 47: struct ktr_header * ! 48: ktrgetheader(type) ! 49: { ! 50: register struct ktr_header *kth; ! 51: struct proc *p = curproc; /* XXX */ ! 52: ! 53: MALLOC(kth, struct ktr_header *, sizeof (struct ktr_header), ! 54: M_TEMP, M_WAITOK); ! 55: kth->ktr_type = type; ! 56: microtime(&kth->ktr_time); ! 57: kth->ktr_pid = p->p_pid; ! 58: bcopy(p->p_comm, kth->ktr_comm, MAXCOMLEN); ! 59: return (kth); ! 60: } ! 61: ! 62: ktrsyscall(vp, code, narg, args) ! 63: struct vnode *vp; ! 64: int code, narg, args[]; ! 65: { ! 66: struct ktr_header *kth = ktrgetheader(KTR_SYSCALL); ! 67: struct ktr_syscall *ktp; ! 68: register len = sizeof(struct ktr_syscall) + (narg * sizeof(int)); ! 69: int *argp, i; ! 70: ! 71: MALLOC(ktp, struct ktr_syscall *, len, M_TEMP, M_WAITOK); ! 72: ktp->ktr_code = code; ! 73: ktp->ktr_narg = narg; ! 74: argp = (int *)((char *)ktp + sizeof(struct ktr_syscall)); ! 75: for (i = 0; i < narg; i++) ! 76: *argp++ = args[i]; ! 77: kth->ktr_buf = (caddr_t)ktp; ! 78: kth->ktr_len = len; ! 79: ktrwrite(vp, kth); ! 80: FREE(ktp, M_TEMP); ! 81: FREE(kth, M_TEMP); ! 82: } ! 83: ! 84: ktrsysret(vp, code, error, retval) ! 85: struct vnode *vp; ! 86: int code, error, retval; ! 87: { ! 88: struct ktr_header *kth = ktrgetheader(KTR_SYSRET); ! 89: struct ktr_sysret ktp; ! 90: ! 91: ktp.ktr_code = code; ! 92: ktp.ktr_error = error; ! 93: ktp.ktr_retval = retval; /* what about val2 ? */ ! 94: ! 95: kth->ktr_buf = (caddr_t)&ktp; ! 96: kth->ktr_len = sizeof(struct ktr_sysret); ! 97: ! 98: ktrwrite(vp, kth); ! 99: FREE(kth, M_TEMP); ! 100: } ! 101: ! 102: ktrnamei(vp, path) ! 103: struct vnode *vp; ! 104: char *path; ! 105: { ! 106: struct ktr_header *kth = ktrgetheader(KTR_NAMEI); ! 107: ! 108: kth->ktr_len = strlen(path); ! 109: kth->ktr_buf = path; ! 110: ! 111: ktrwrite(vp, kth); ! 112: FREE(kth, M_TEMP); ! 113: } ! 114: ! 115: ktrgenio(vp, fd, rw, iov, len, error) ! 116: struct vnode *vp; ! 117: int fd; ! 118: enum uio_rw rw; ! 119: register struct iovec *iov; ! 120: { ! 121: struct ktr_header *kth = ktrgetheader(KTR_GENIO); ! 122: register struct ktr_genio *ktp; ! 123: register caddr_t cp; ! 124: register int resid = len, cnt; ! 125: ! 126: if (error) ! 127: return; ! 128: MALLOC(ktp, struct ktr_genio *, sizeof(struct ktr_genio) + len, ! 129: M_TEMP, M_WAITOK); ! 130: ktp->ktr_fd = fd; ! 131: ktp->ktr_rw = rw; ! 132: cp = (caddr_t)((char *)ktp + sizeof (struct ktr_genio)); ! 133: while (resid > 0) { ! 134: if ((cnt = iov->iov_len) > resid) ! 135: cnt = resid; ! 136: if (copyin(iov->iov_base, cp, (unsigned)cnt)) ! 137: goto done; ! 138: cp += cnt; ! 139: resid -= cnt; ! 140: iov++; ! 141: } ! 142: kth->ktr_buf = (caddr_t)ktp; ! 143: kth->ktr_len = sizeof (struct ktr_genio) + len; ! 144: ! 145: ktrwrite(vp, kth); ! 146: done: ! 147: FREE(kth, M_TEMP); ! 148: FREE(ktp, M_TEMP); ! 149: } ! 150: ! 151: ktrpsig(vp, sig, action, mask, code) ! 152: struct vnode *vp; ! 153: sig_t action; ! 154: { ! 155: struct ktr_header *kth = ktrgetheader(KTR_PSIG); ! 156: struct ktr_psig kp; ! 157: ! 158: kp.signo = (char)sig; ! 159: kp.action = action; ! 160: kp.mask = mask; ! 161: kp.code = code; ! 162: kth->ktr_buf = (caddr_t)&kp; ! 163: kth->ktr_len = sizeof (struct ktr_psig); ! 164: ! 165: ktrwrite(vp, kth); ! 166: FREE(kth, M_TEMP); ! 167: } ! 168: ! 169: /* Interface and common routines */ ! 170: ! 171: /* ! 172: * ktrace system call ! 173: */ ! 174: /* ARGSUSED */ ! 175: ktrace(curp, uap, retval) ! 176: struct proc *curp; ! 177: register struct args { ! 178: char *fname; ! 179: int ops; ! 180: int facs; ! 181: int pid; ! 182: } *uap; ! 183: int *retval; ! 184: { ! 185: register struct vnode *vp = NULL; ! 186: register struct proc *p; ! 187: struct pgrp *pg; ! 188: int facs = uap->facs & ~KTRFAC_ROOT; ! 189: int ops = KTROP(uap->ops); ! 190: int descend = uap->ops & KTRFLAG_DESCEND; ! 191: int ret = 0; ! 192: int error = 0; ! 193: struct nameidata nd; ! 194: ! 195: if (ops != KTROP_CLEAR) { ! 196: /* ! 197: * an operation which requires a file argument. ! 198: */ ! 199: nd.ni_segflg = UIO_USERSPACE; ! 200: nd.ni_dirp = uap->fname; ! 201: if (error = vn_open(&nd, curp, FREAD|FWRITE, 0)) ! 202: return (error); ! 203: vp = nd.ni_vp; ! 204: VOP_UNLOCK(vp); ! 205: if (vp->v_type != VREG) { ! 206: (void) vn_close(vp, FREAD|FWRITE, curp->p_ucred, curp); ! 207: return (EACCES); ! 208: } ! 209: } ! 210: /* ! 211: * Clear all uses of the tracefile ! 212: */ ! 213: if (ops == KTROP_CLEARFILE) { ! 214: for (p = allproc; p != NULL; p = p->p_nxt) { ! 215: if (p->p_tracep == vp) { ! 216: if (ktrcanset(curp, p)) { ! 217: p->p_tracep = NULL; ! 218: p->p_traceflag = 0; ! 219: (void) vn_close(vp, FREAD|FWRITE, ! 220: p->p_ucred, p); ! 221: } else ! 222: error = EPERM; ! 223: } ! 224: } ! 225: goto done; ! 226: } ! 227: /* ! 228: * need something to (un)trace (XXX - why is this here?) ! 229: */ ! 230: if (!facs) { ! 231: error = EINVAL; ! 232: goto done; ! 233: } ! 234: /* ! 235: * do it ! 236: */ ! 237: if (uap->pid < 0) { ! 238: /* ! 239: * by process group ! 240: */ ! 241: pg = pgfind(-uap->pid); ! 242: if (pg == NULL) { ! 243: error = ESRCH; ! 244: goto done; ! 245: } ! 246: for (p = pg->pg_mem; p != NULL; p = p->p_pgrpnxt) ! 247: if (descend) ! 248: ret |= ktrsetchildren(curp, p, ops, facs, vp); ! 249: else ! 250: ret |= ktrops(curp, p, ops, facs, vp); ! 251: ! 252: } else { ! 253: /* ! 254: * by pid ! 255: */ ! 256: p = pfind(uap->pid); ! 257: if (p == NULL) { ! 258: error = ESRCH; ! 259: goto done; ! 260: } ! 261: if (descend) ! 262: ret |= ktrsetchildren(curp, p, ops, facs, vp); ! 263: else ! 264: ret |= ktrops(curp, p, ops, facs, vp); ! 265: } ! 266: if (!ret) ! 267: error = EPERM; ! 268: done: ! 269: if (vp != NULL) ! 270: (void) vn_close(vp, FWRITE, curp->p_ucred, curp); ! 271: return (error); ! 272: } ! 273: ! 274: ktrops(curp, p, ops, facs, vp) ! 275: struct proc *curp, *p; ! 276: struct vnode *vp; ! 277: { ! 278: ! 279: if (!ktrcanset(curp, p)) ! 280: return (0); ! 281: if (ops == KTROP_SET) { ! 282: if (p->p_tracep != vp) { ! 283: /* ! 284: * if trace file already in use, relinquish ! 285: */ ! 286: if (p->p_tracep != NULL) ! 287: vrele(p->p_tracep); ! 288: VREF(vp); ! 289: p->p_tracep = vp; ! 290: } ! 291: p->p_traceflag |= facs; ! 292: if (curp->p_ucred->cr_uid == 0) ! 293: p->p_traceflag |= KTRFAC_ROOT; ! 294: } else { ! 295: /* KTROP_CLEAR */ ! 296: if (((p->p_traceflag &= ~facs) & KTRFAC_MASK) == 0) { ! 297: /* no more tracing */ ! 298: p->p_traceflag = 0; ! 299: if (p->p_tracep != NULL) { ! 300: vrele(p->p_tracep); ! 301: p->p_tracep = NULL; ! 302: } ! 303: } ! 304: } ! 305: ! 306: return (1); ! 307: } ! 308: ! 309: ktrsetchildren(curp, top, ops, facs, vp) ! 310: struct proc *curp, *top; ! 311: struct vnode *vp; ! 312: { ! 313: register struct proc *p; ! 314: register int ret = 0; ! 315: ! 316: p = top; ! 317: for (;;) { ! 318: ret |= ktrops(curp, p, ops, facs, vp); ! 319: /* ! 320: * If this process has children, descend to them next, ! 321: * otherwise do any siblings, and if done with this level, ! 322: * follow back up the tree (but not past top). ! 323: */ ! 324: if (p->p_cptr) ! 325: p = p->p_cptr; ! 326: else if (p == top) ! 327: return (ret); ! 328: else if (p->p_osptr) ! 329: p = p->p_osptr; ! 330: else for (;;) { ! 331: p = p->p_pptr; ! 332: if (p == top) ! 333: return (ret); ! 334: if (p->p_osptr) { ! 335: p = p->p_osptr; ! 336: break; ! 337: } ! 338: } ! 339: } ! 340: /*NOTREACHED*/ ! 341: } ! 342: ! 343: ktrwrite(vp, kth) ! 344: struct vnode *vp; ! 345: register struct ktr_header *kth; ! 346: { ! 347: struct uio auio; ! 348: struct iovec aiov[2]; ! 349: register struct proc *p = curproc; /* XXX */ ! 350: int error; ! 351: ! 352: if (vp == NULL) ! 353: return; ! 354: auio.uio_iov = &aiov[0]; ! 355: auio.uio_offset = 0; ! 356: auio.uio_segflg = UIO_SYSSPACE; ! 357: auio.uio_rw = UIO_WRITE; ! 358: aiov[0].iov_base = (caddr_t)kth; ! 359: aiov[0].iov_len = sizeof(struct ktr_header); ! 360: auio.uio_resid = sizeof(struct ktr_header); ! 361: auio.uio_iovcnt = 1; ! 362: auio.uio_procp = (struct proc *)0; ! 363: if (kth->ktr_len > 0) { ! 364: auio.uio_iovcnt++; ! 365: aiov[1].iov_base = kth->ktr_buf; ! 366: aiov[1].iov_len = kth->ktr_len; ! 367: auio.uio_resid += kth->ktr_len; ! 368: } ! 369: VOP_LOCK(vp); ! 370: error = VOP_WRITE(vp, &auio, IO_UNIT|IO_APPEND, p->p_ucred); ! 371: VOP_UNLOCK(vp); ! 372: if (!error) ! 373: return; ! 374: /* ! 375: * If error encountered, give up tracing on this vnode. ! 376: */ ! 377: log(LOG_NOTICE, "ktrace write failed, errno %d, tracing stopped\n", ! 378: error); ! 379: for (p = allproc; p != NULL; p = p->p_nxt) { ! 380: if (p->p_tracep == vp) { ! 381: p->p_tracep = NULL; ! 382: p->p_traceflag = 0; ! 383: vrele(vp); ! 384: } ! 385: } ! 386: } ! 387: ! 388: /* ! 389: * Return true if caller has permission to set the ktracing state ! 390: * of target. Essentially, the target can't possess any ! 391: * more permissions than the caller. KTRFAC_ROOT signifies that ! 392: * root previously set the tracing status on the target process, and ! 393: * so, only root may further change it. ! 394: * ! 395: * TODO: check groups. use caller effective gid. ! 396: */ ! 397: ktrcanset(callp, targetp) ! 398: struct proc *callp, *targetp; ! 399: { ! 400: register struct pcred *caller = callp->p_cred; ! 401: register struct pcred *target = targetp->p_cred; ! 402: ! 403: if ((caller->pc_ucred->cr_uid == target->p_ruid && ! 404: target->p_ruid == target->p_svuid && ! 405: caller->p_rgid == target->p_rgid && /* XXX */ ! 406: target->p_rgid == target->p_svgid && ! 407: (targetp->p_traceflag & KTRFAC_ROOT) == 0) || ! 408: caller->pc_ucred->cr_uid == 0) ! 409: return (1); ! 410: ! 411: return (0); ! 412: } ! 413: ! 414: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.