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