|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1989 The Regents of the University of California. ! 3: * All rights reserved. ! 4: * ! 5: * Redistribution is only permitted until one year after the first shipment ! 6: * of 4.4BSD by the Regents. Otherwise, redistribution and use in source and ! 7: * binary forms are permitted provided that: (1) source distributions retain ! 8: * this entire copyright notice and comment, and (2) distributions including ! 9: * binaries display the following acknowledgement: This product includes ! 10: * software developed by the University of California, Berkeley and its ! 11: * contributors'' in the documentation or other materials provided with the ! 12: * distribution and in all advertising materials mentioning features or use ! 13: * of this software. Neither the name of the University nor the names of ! 14: * its contributors may be used to endorse or promote products derived from ! 15: * this software without specific prior written permission. ! 16: * THIS SOFTWARE IS PROVIDED AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED ! 17: * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF ! 18: * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ! 19: * ! 20: * @(#)kern_ktrace.c 7.9 (Berkeley) 6/28/90 ! 21: */ ! 22: ! 23: #ifdef KTRACE ! 24: ! 25: #include "param.h" ! 26: #include "user.h" ! 27: #include "proc.h" ! 28: #include "file.h" ! 29: #include "vnode.h" ! 30: #include "ktrace.h" ! 31: #include "malloc.h" ! 32: ! 33: #include "syscalls.c" ! 34: ! 35: extern int nsysent; ! 36: extern char *syscallnames[]; ! 37: ! 38: int ktrace_nocheck = 0; /* set to 1 when security checks in place */ ! 39: ! 40: struct ktr_header * ! 41: ktrgetheader(type) ! 42: { ! 43: register struct ktr_header *kth; ! 44: ! 45: MALLOC(kth, struct ktr_header *, sizeof (struct ktr_header), ! 46: M_TEMP, M_WAITOK); ! 47: kth->ktr_type = type; ! 48: microtime(&kth->ktr_time); ! 49: kth->ktr_pid = u.u_procp->p_pid; ! 50: bcopy(u.u_procp->p_comm, kth->ktr_comm, MAXCOMLEN); ! 51: return (kth); ! 52: } ! 53: ! 54: ktrsyscall(vp, code, narg, args) ! 55: struct vnode *vp; ! 56: int code, narg, args[]; ! 57: { ! 58: struct ktr_header *kth = ktrgetheader(KTR_SYSCALL); ! 59: struct ktr_syscall *ktp; ! 60: register len = sizeof(struct ktr_syscall) + (narg * sizeof(int)); ! 61: int *argp, i; ! 62: ! 63: if (kth == NULL) ! 64: return; ! 65: MALLOC(ktp, struct ktr_syscall *, len, M_TEMP, M_WAITOK); ! 66: ktp->ktr_code = code; ! 67: ktp->ktr_narg = narg; ! 68: argp = (int *)((char *)ktp + sizeof(struct ktr_syscall)); ! 69: for (i = 0; i < narg; i++) ! 70: *argp++ = args[i]; ! 71: kth->ktr_buf = (caddr_t)ktp; ! 72: kth->ktr_len = len; ! 73: ktrwrite(vp, kth); ! 74: FREE(ktp, M_TEMP); ! 75: FREE(kth, M_TEMP); ! 76: } ! 77: ! 78: ktrsysret(vp, code, error, retval) ! 79: struct vnode *vp; ! 80: int code, error, retval; ! 81: { ! 82: struct ktr_header *kth = ktrgetheader(KTR_SYSRET); ! 83: struct ktr_sysret ktp; ! 84: ! 85: if (kth == NULL) ! 86: return; ! 87: ktp.ktr_code = code; ! 88: ktp.ktr_error = error; ! 89: ktp.ktr_retval = retval; /* what about val2 ? */ ! 90: ! 91: kth->ktr_buf = (caddr_t)&ktp; ! 92: kth->ktr_len = sizeof(struct ktr_sysret); ! 93: ! 94: ktrwrite(vp, kth); ! 95: FREE(kth, M_TEMP); ! 96: } ! 97: ! 98: ktrnamei(vp, path) ! 99: struct vnode *vp; ! 100: char *path; ! 101: { ! 102: struct ktr_header *kth = ktrgetheader(KTR_NAMEI); ! 103: ! 104: if (kth == NULL) ! 105: return; ! 106: kth->ktr_len = strlen(path); ! 107: kth->ktr_buf = path; ! 108: ! 109: ktrwrite(vp, kth); ! 110: FREE(kth, M_TEMP); ! 111: } ! 112: ! 113: ktrgenio(vp, fd, rw, iov, len, error) ! 114: struct vnode *vp; ! 115: int fd; ! 116: enum uio_rw rw; ! 117: register struct iovec *iov; ! 118: { ! 119: struct ktr_header *kth = ktrgetheader(KTR_GENIO); ! 120: register struct ktr_genio *ktp; ! 121: register caddr_t cp; ! 122: register int resid = len, cnt; ! 123: ! 124: if (kth == NULL || error) ! 125: return; ! 126: MALLOC(ktp, struct ktr_genio *, sizeof(struct ktr_genio) + len, ! 127: M_TEMP, M_WAITOK); ! 128: ktp->ktr_fd = fd; ! 129: ktp->ktr_rw = rw; ! 130: cp = (caddr_t)((char *)ktp + sizeof (struct ktr_genio)); ! 131: while (resid > 0) { ! 132: if ((cnt = iov->iov_len) > resid) ! 133: cnt = resid; ! 134: if (copyin(iov->iov_base, cp, (unsigned)cnt)) ! 135: goto done; ! 136: cp += cnt; ! 137: resid -= cnt; ! 138: iov++; ! 139: } ! 140: kth->ktr_buf = (caddr_t)ktp; ! 141: kth->ktr_len = sizeof (struct ktr_genio) + len; ! 142: ! 143: ktrwrite(vp, kth); ! 144: done: ! 145: FREE(kth, M_TEMP); ! 146: FREE(ktp, M_TEMP); ! 147: } ! 148: ! 149: ktrpsig(vp, sig, action, mask, code) ! 150: struct vnode *vp; ! 151: sig_t action; ! 152: { ! 153: struct ktr_header *kth = ktrgetheader(KTR_PSIG); ! 154: struct ktr_psig kp; ! 155: ! 156: if (kth == NULL) ! 157: return; ! 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 nameidata *ndp = &u.u_nd; ! 187: register struct proc *p; ! 188: register ops = KTROP(uap->ops); ! 189: struct pgrp *pg; ! 190: register int facs = uap->facs; ! 191: register int ret = 0; ! 192: int error = 0; ! 193: ! 194: /* ! 195: * Until security implications are thought through, ! 196: * limit tracing to root (unless ktrace_nocheck is set). ! 197: */ ! 198: if (!ktrace_nocheck && (error = suser(u.u_cred, &u.u_acflag))) ! 199: return (error); ! 200: if (ops != KTROP_CLEAR) { ! 201: /* ! 202: * an operation which requires a file argument. ! 203: */ ! 204: ndp->ni_segflg = UIO_USERSPACE; ! 205: ndp->ni_dirp = uap->fname; ! 206: if (error = vn_open(ndp, FREAD|FWRITE, 0)) ! 207: return (error); ! 208: vp = ndp->ni_vp; ! 209: if (vp->v_type != VREG) { ! 210: vrele(vp); ! 211: return (EACCES); ! 212: } ! 213: } ! 214: /* ! 215: * Clear all uses of the tracefile ! 216: */ ! 217: if (ops == KTROP_CLEARFILE) { ! 218: for (p = allproc; p != NULL; p = p->p_nxt) { ! 219: if (p->p_tracep == vp) { ! 220: p->p_tracep = NULL; ! 221: p->p_traceflag = 0; ! 222: vrele(vp); ! 223: } ! 224: } ! 225: goto done; ! 226: } ! 227: /* ! 228: * need something to (un)trace ! 229: */ ! 230: if (!facs) { ! 231: error = EINVAL; ! 232: goto done; ! 233: } ! 234: /* ! 235: * doit ! 236: */ ! 237: if (uap->pid < 0) { ! 238: pg = pgfind(-uap->pid); ! 239: if (pg == NULL) { ! 240: error = ESRCH; ! 241: goto done; ! 242: } ! 243: for (p = pg->pg_mem; p != NULL; p = p->p_pgrpnxt) ! 244: if (uap->ops&KTRFLAG_DESCEND) ! 245: ret |= ktrsetchildren(p, ops, facs, vp); ! 246: else ! 247: ret |= ktrops(p, ops, facs, vp); ! 248: ! 249: } else { ! 250: p = pfind(uap->pid); ! 251: if (p == NULL) { ! 252: error = ESRCH; ! 253: goto done; ! 254: } ! 255: if (ops&KTRFLAG_DESCEND) ! 256: ret |= ktrsetchildren(p, ops, facs, vp); ! 257: else ! 258: ret |= ktrops(p, ops, facs, vp); ! 259: } ! 260: if (!ret) ! 261: error = EPERM; ! 262: done: ! 263: if (vp != NULL) ! 264: vrele(vp); ! 265: return (error); ! 266: } ! 267: ! 268: ktrops(p, ops, facs, vp) ! 269: struct proc *p; ! 270: struct vnode *vp; ! 271: { ! 272: ! 273: if (u.u_uid && u.u_uid != p->p_uid) ! 274: return (0); ! 275: if (ops == KTROP_SET) { ! 276: if (p->p_tracep != vp) { ! 277: /* ! 278: * if trace file already in use, relinquish ! 279: */ ! 280: if (p->p_tracep != NULL) ! 281: vrele(p->p_tracep); ! 282: VREF(vp); ! 283: p->p_tracep = vp; ! 284: } ! 285: p->p_traceflag |= facs; ! 286: } else { ! 287: /* KTROP_CLEAR */ ! 288: if (((p->p_traceflag &= ~facs) & ~KTRFAC_INHERIT) == 0) { ! 289: /* no more tracing */ ! 290: p->p_traceflag = 0; ! 291: if (p->p_tracep != NULL) { ! 292: vrele(p->p_tracep); ! 293: p->p_tracep = NULL; ! 294: } ! 295: } ! 296: } ! 297: ! 298: return 1; ! 299: } ! 300: ! 301: ktrsetchildren(top, ops, facs, vp) ! 302: struct proc *top; ! 303: struct vnode *vp; ! 304: { ! 305: register struct proc *p; ! 306: register int ret = 0; ! 307: ! 308: p = top; ! 309: for (;;) { ! 310: ret |= ktrops(p, ops, facs, vp); ! 311: /* ! 312: * If this process has children, descend to them next, ! 313: * otherwise do any siblings, and if done with this level, ! 314: * follow back up the tree (but not past top). ! 315: */ ! 316: if (p->p_cptr) ! 317: p = p->p_cptr; ! 318: else if (p == top) ! 319: return ret; ! 320: else if (p->p_osptr) ! 321: p = p->p_osptr; ! 322: else for (;;) { ! 323: p = p->p_pptr; ! 324: if (p == top) ! 325: return ret; ! 326: if (p->p_osptr) { ! 327: p = p->p_osptr; ! 328: break; ! 329: } ! 330: } ! 331: } ! 332: /*NOTREACHED*/ ! 333: } ! 334: ! 335: ktrwrite(vp, kth) ! 336: struct vnode *vp; ! 337: register struct ktr_header *kth; ! 338: { ! 339: struct uio auio; ! 340: struct iovec aiov[2]; ! 341: struct proc *p; ! 342: int error; ! 343: ! 344: if (vp == NULL) ! 345: return; ! 346: auio.uio_iov = &aiov[0]; ! 347: auio.uio_offset = 0; ! 348: auio.uio_segflg = UIO_SYSSPACE; ! 349: auio.uio_rw = UIO_WRITE; ! 350: aiov[0].iov_base = (caddr_t)kth; ! 351: aiov[0].iov_len = sizeof(struct ktr_header); ! 352: auio.uio_resid = sizeof(struct ktr_header); ! 353: auio.uio_iovcnt = 1; ! 354: if (kth->ktr_len > 0) { ! 355: auio.uio_iovcnt++; ! 356: aiov[1].iov_base = kth->ktr_buf; ! 357: aiov[1].iov_len = kth->ktr_len; ! 358: auio.uio_resid += kth->ktr_len; ! 359: } ! 360: VOP_LOCK(vp); ! 361: error = VOP_WRITE(vp, &auio, IO_UNIT|IO_APPEND, u.u_cred); ! 362: VOP_UNLOCK(vp); ! 363: if (!error) ! 364: return; ! 365: /* ! 366: * If error encountered, give up tracing on this vnode. ! 367: */ ! 368: uprintf("\ntrace write failed with errno %d, tracing stopped\n", error); ! 369: for (p = allproc; p != NULL; p = p->p_nxt) { ! 370: if (p->p_tracep == vp) { ! 371: p->p_tracep = NULL; ! 372: p->p_traceflag = 0; ! 373: vrele(vp); ! 374: } ! 375: } ! 376: } ! 377: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.