|
|
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: /* $NetBSD: procfs_ctl.c,v 1.12 1994/06/29 06:34:46 cgd Exp $ */ ! 26: ! 27: /* ! 28: * Copyright (c) 1993 Jan-Simon Pendry ! 29: * Copyright (c) 1993 ! 30: * The Regents of the University of California. All rights reserved. ! 31: * ! 32: * This code is derived from software contributed to Berkeley by ! 33: * Jan-Simon Pendry. ! 34: * ! 35: * Redistribution and use in source and binary forms, with or without ! 36: * modification, are permitted provided that the following conditions ! 37: * are met: ! 38: * 1. Redistributions of source code must retain the above copyright ! 39: * notice, this list of conditions and the following disclaimer. ! 40: * 2. Redistributions in binary form must reproduce the above copyright ! 41: * notice, this list of conditions and the following disclaimer in the ! 42: * documentation and/or other materials provided with the distribution. ! 43: * 3. All advertising materials mentioning features or use of this software ! 44: * must display the following acknowledgement: ! 45: * This product includes software developed by the University of ! 46: * California, Berkeley and its contributors. ! 47: * 4. Neither the name of the University nor the names of its contributors ! 48: * may be used to endorse or promote products derived from this software ! 49: * without specific prior written permission. ! 50: * ! 51: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ! 52: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ! 53: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ! 54: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE ! 55: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ! 56: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ! 57: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ! 58: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ! 59: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ! 60: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ! 61: * SUCH DAMAGE. ! 62: * ! 63: * @(#)procfs_ctl.c 8.4 (Berkeley) 6/15/94 ! 64: */ ! 65: ! 66: #include <sys/param.h> ! 67: #include <sys/systm.h> ! 68: #include <sys/time.h> ! 69: #include <sys/kernel.h> ! 70: #include <sys/proc.h> ! 71: #include <sys/vnode.h> ! 72: #include <sys/ioctl.h> ! 73: #include <sys/tty.h> ! 74: #include <sys/resource.h> ! 75: #include <sys/resourcevar.h> ! 76: #include <sys/ptrace.h> ! 77: #include <miscfs/procfs/procfs.h> ! 78: ! 79: /* ! 80: * True iff process (p) is in trace wait state ! 81: * relative to process (curp) ! 82: */ ! 83: #define TRACE_WAIT_P(curp, p) \ ! 84: ((p)->p_stat == SSTOP && \ ! 85: (p)->p_pptr == (curp) && \ ! 86: ((p)->p_flag & P_TRACED)) ! 87: ! 88: #define PROCFS_CTL_ATTACH 1 ! 89: #define PROCFS_CTL_DETACH 2 ! 90: #define PROCFS_CTL_STEP 3 ! 91: #define PROCFS_CTL_RUN 4 ! 92: #define PROCFS_CTL_WAIT 5 ! 93: ! 94: static vfs_namemap_t ctlnames[] = { ! 95: /* special /proc commands */ ! 96: { "attach", PROCFS_CTL_ATTACH }, ! 97: { "detach", PROCFS_CTL_DETACH }, ! 98: { "step", PROCFS_CTL_STEP }, ! 99: { "run", PROCFS_CTL_RUN }, ! 100: { "wait", PROCFS_CTL_WAIT }, ! 101: { 0 }, ! 102: }; ! 103: ! 104: static vfs_namemap_t signames[] = { ! 105: /* regular signal names */ ! 106: { "hup", SIGHUP }, { "int", SIGINT }, ! 107: { "quit", SIGQUIT }, { "ill", SIGILL }, ! 108: { "trap", SIGTRAP }, { "abrt", SIGABRT }, ! 109: { "iot", SIGIOT }, { "emt", SIGEMT }, ! 110: { "fpe", SIGFPE }, { "kill", SIGKILL }, ! 111: { "bus", SIGBUS }, { "segv", SIGSEGV }, ! 112: { "sys", SIGSYS }, { "pipe", SIGPIPE }, ! 113: { "alrm", SIGALRM }, { "term", SIGTERM }, ! 114: { "urg", SIGURG }, { "stop", SIGSTOP }, ! 115: { "tstp", SIGTSTP }, { "cont", SIGCONT }, ! 116: { "chld", SIGCHLD }, { "ttin", SIGTTIN }, ! 117: { "ttou", SIGTTOU }, { "io", SIGIO }, ! 118: { "xcpu", SIGXCPU }, { "xfsz", SIGXFSZ }, ! 119: { "vtalrm", SIGVTALRM }, { "prof", SIGPROF }, ! 120: { "winch", SIGWINCH }, { "info", SIGINFO }, ! 121: { "usr1", SIGUSR1 }, { "usr2", SIGUSR2 }, ! 122: { 0 }, ! 123: }; ! 124: ! 125: static int ! 126: procfs_control(curp, p, op) ! 127: struct proc *curp; ! 128: struct proc *p; ! 129: int op; ! 130: { ! 131: int error; ! 132: ! 133: /* ! 134: * Attach - attaches the target process for debugging ! 135: * by the calling process. ! 136: */ ! 137: if (op == PROCFS_CTL_ATTACH) { ! 138: /* check whether already being traced */ ! 139: if (p->p_flag & P_TRACED) ! 140: return (EBUSY); ! 141: ! 142: /* can't trace yourself! */ ! 143: if (p->p_pid == curp->p_pid) ! 144: return (EINVAL); ! 145: ! 146: /* ! 147: * Go ahead and set the trace flag. ! 148: * Save the old parent (it's reset in ! 149: * _DETACH, and also in kern_exit.c:wait4() ! 150: * Reparent the process so that the tracing ! 151: * proc gets to see all the action. ! 152: * Stop the target. ! 153: */ ! 154: p->p_flag |= P_TRACED; ! 155: p->p_xstat = 0; /* XXX ? */ ! 156: if (p->p_pptr != curp) { ! 157: p->p_oppid = p->p_pptr->p_pid; ! 158: proc_reparent(p, curp); ! 159: } ! 160: psignal(p, SIGSTOP); ! 161: return (0); ! 162: } ! 163: ! 164: /* ! 165: * Target process must be stopped, owned by (curp) and ! 166: * be set up for tracing (P_TRACED flag set). ! 167: * Allow DETACH to take place at any time for sanity. ! 168: * Allow WAIT any time, of course. ! 169: */ ! 170: switch (op) { ! 171: case PROCFS_CTL_DETACH: ! 172: case PROCFS_CTL_WAIT: ! 173: break; ! 174: ! 175: default: ! 176: if (!TRACE_WAIT_P(curp, p)) ! 177: return (EBUSY); ! 178: } ! 179: ! 180: /* ! 181: * do single-step fixup if needed ! 182: */ ! 183: FIX_SSTEP(p); ! 184: ! 185: /* ! 186: * Don't deliver any signal by default. ! 187: * To continue with a signal, just send ! 188: * the signal name to the ctl file ! 189: */ ! 190: p->p_xstat = 0; ! 191: ! 192: switch (op) { ! 193: /* ! 194: * Detach. Cleans up the target process, reparent it if possible ! 195: * and set it running once more. ! 196: */ ! 197: case PROCFS_CTL_DETACH: ! 198: /* if not being traced, then this is a painless no-op */ ! 199: if ((p->p_flag & P_TRACED) == 0) ! 200: return (0); ! 201: ! 202: /* not being traced any more */ ! 203: p->p_flag &= ~P_TRACED; ! 204: ! 205: /* give process back to original parent */ ! 206: if (p->p_oppid != p->p_pptr->p_pid) { ! 207: struct proc *pp; ! 208: ! 209: pp = pfind(p->p_oppid); ! 210: if (pp) ! 211: proc_reparent(p, pp); ! 212: } ! 213: ! 214: p->p_oppid = 0; ! 215: p->p_flag &= ~P_WAITED; /* XXX ? */ ! 216: wakeup((caddr_t) curp); /* XXX for CTL_WAIT below ? */ ! 217: ! 218: break; ! 219: ! 220: /* ! 221: * Step. Let the target process execute a single instruction. ! 222: */ ! 223: case PROCFS_CTL_STEP: ! 224: if (error = process_sstep(p, 1)) ! 225: return (error); ! 226: break; ! 227: ! 228: /* ! 229: * Run. Let the target process continue running until a breakpoint ! 230: * or some other trap. ! 231: */ ! 232: case PROCFS_CTL_RUN: ! 233: break; ! 234: ! 235: /* ! 236: * Wait for the target process to stop. ! 237: * If the target is not being traced then just wait ! 238: * to enter ! 239: */ ! 240: case PROCFS_CTL_WAIT: ! 241: error = 0; ! 242: if (p->p_flag & P_TRACED) { ! 243: while (error == 0 && ! 244: (p->p_stat != SSTOP) && ! 245: (p->p_flag & P_TRACED) && ! 246: (p->p_pptr == curp)) { ! 247: error = tsleep((caddr_t) p, ! 248: PWAIT|PCATCH, "procfsx", 0); ! 249: } ! 250: if (error == 0 && !TRACE_WAIT_P(curp, p)) ! 251: error = EBUSY; ! 252: } else { ! 253: while (error == 0 && p->p_stat != SSTOP) { ! 254: error = tsleep((caddr_t) p, ! 255: PWAIT|PCATCH, "procfs", 0); ! 256: } ! 257: } ! 258: return (error); ! 259: ! 260: default: ! 261: panic("procfs_control"); ! 262: } ! 263: ! 264: if (p->p_stat == SSTOP) ! 265: setrunnable(p); ! 266: return (0); ! 267: } ! 268: ! 269: int ! 270: procfs_doctl(curp, p, pfs, uio) ! 271: struct proc *curp; ! 272: struct pfsnode *pfs; ! 273: struct uio *uio; ! 274: struct proc *p; ! 275: { ! 276: int xlen; ! 277: int error; ! 278: char msg[PROCFS_CTLLEN+1]; ! 279: vfs_namemap_t *nm; ! 280: ! 281: if (uio->uio_rw != UIO_WRITE) ! 282: return (EOPNOTSUPP); ! 283: ! 284: xlen = PROCFS_CTLLEN; ! 285: error = vfs_getuserstr(uio, msg, &xlen); ! 286: if (error) ! 287: return (error); ! 288: ! 289: /* ! 290: * Map signal names into signal generation ! 291: * or debug control. Unknown commands and/or signals ! 292: * return EOPNOTSUPP. ! 293: * ! 294: * Sending a signal while the process is being debugged ! 295: * also has the side effect of letting the target continue ! 296: * to run. There is no way to single-step a signal delivery. ! 297: */ ! 298: error = EOPNOTSUPP; ! 299: ! 300: nm = vfs_findname(ctlnames, msg, xlen); ! 301: if (nm) { ! 302: error = procfs_control(curp, p, nm->nm_val); ! 303: } else { ! 304: nm = vfs_findname(signames, msg, xlen); ! 305: if (nm) { ! 306: if (TRACE_WAIT_P(curp, p)) { ! 307: p->p_xstat = nm->nm_val; ! 308: FIX_SSTEP(p); ! 309: setrunnable(p); ! 310: } else { ! 311: psignal(p, nm->nm_val); ! 312: } ! 313: error = 0; ! 314: } ! 315: } ! 316: ! 317: return (error); ! 318: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.