diff options
| author | Eric Badger <badger@FreeBSD.org> | 2017-03-05 03:05:24 +0000 |
|---|---|---|
| committer | Eric Badger <badger@FreeBSD.org> | 2017-03-05 03:05:24 +0000 |
| commit | 99b14d9f1bdd6a455774a41e28a6c8e81e82c94b (patch) | |
| tree | a92b989200d42247be5447cd7c77b64d95a155a7 /sys/fs/procfs | |
| parent | 6977499ccff09ba45843d232fec5d4e26b1f01b0 (diff) | |
Notes
Diffstat (limited to 'sys/fs/procfs')
| -rw-r--r-- | sys/fs/procfs/README | 113 | ||||
| -rw-r--r-- | sys/fs/procfs/procfs.c | 5 | ||||
| -rw-r--r-- | sys/fs/procfs/procfs.h | 1 | ||||
| -rw-r--r-- | sys/fs/procfs/procfs_ctl.c | 359 |
4 files changed, 1 insertions, 477 deletions
diff --git a/sys/fs/procfs/README b/sys/fs/procfs/README deleted file mode 100644 index f816b321b432c..0000000000000 --- a/sys/fs/procfs/README +++ /dev/null @@ -1,113 +0,0 @@ -saute procfs lyonnais - -procfs supports two levels of directory. the filesystem root -directory contains a representation of the system process table. -this consists of an entry for each active and zombie process, and -an additional entry "curproc" which always represents the process -making the lookup request. - -each of the sub-directories contains several files. these files -are used to control and interrogate processes. the files implemented -are: - - file - xxx. the exec'ed file. - - status - r/o. returns process status. - - ctl - w/o. sends a control message to the process. - for example: - echo hup > /proc/curproc/note - will send a SIGHUP to the shell. - whereas - echo attach > /proc/1293/ctl - would set up process 1293 for debugging. - see below for more details. - - mem - r/w. virtual memory image of the process. - parts of the address space are readable - only if they exist in the target process. - a more reasonable alternative might be - to return zero pages instead of an error. - comments? - - note - w/o. writing a string here sends the - equivalent note to the process. - [ not implemented. ] - - notepg - w/o. the same as note, but sends to all - members of the process group. - [ not implemented. ] - - regs - r/w. process register set. this can be read - or written any time even if the process - is not stopped. since the bsd kernel - is single-processor, this implementation - will get the "right" register values. - a multi-proc kernel would need to do some - synchronisation. - -this then looks like: - -% ls -li /proc -total 0 - 9 dr-xr-xr-x 2 root wheel 0 Sep 21 15:06 0 - 17 dr-xr-xr-x 2 root wheel 0 Sep 21 15:06 1 - 89 dr-xr-xr-x 2 root wheel 0 Sep 21 15:06 10 - 25 dr-xr-xr-x 2 root wheel 0 Sep 21 15:06 2 -2065 dr-xr-xr-x 2 root wheel 0 Sep 21 15:06 257 -2481 dr-xr-xr-x 2 jsp staff 0 Sep 21 15:06 309 - 265 dr-xr-xr-x 2 root wheel 0 Sep 21 15:06 32 -3129 dr-xr-xr-x 2 jsp staff 0 Sep 21 15:06 390 -3209 dr-xr-xr-x 2 jsp staff 0 Sep 21 15:06 400 -3217 dr-xr-xr-x 2 jsp staff 0 Sep 21 15:06 401 -3273 dr-xr-xr-x 2 jsp staff 0 Sep 21 15:06 408 - 393 dr-xr-xr-x 2 root wheel 0 Sep 21 15:06 48 - 409 dr-xr-xr-x 2 root wheel 0 Sep 21 15:06 50 - 465 dr-xr-xr-x 2 root wheel 0 Sep 21 15:06 57 - 481 dr-xr-xr-x 2 root wheel 0 Sep 21 15:06 59 - 537 dr-xr-xr-x 2 root kmem 0 Sep 21 15:06 66 - 545 dr-xr-xr-x 2 root wheel 0 Sep 21 15:06 67 - 657 dr-xr-xr-x 2 jsp staff 0 Sep 21 15:06 81 - 665 dr-xr-xr-x 2 jsp staff 0 Sep 21 15:06 82 - 673 dr-xr-xr-x 2 jsp staff 0 Sep 21 15:06 83 - 681 dr-xr-xr-x 2 root wheel 0 Sep 21 15:06 84 -3273 dr-xr-xr-x 2 jsp staff 0 Sep 21 15:06 curproc -% ls -li /proc/curproc -total 408 -3341 --w------- 1 jsp staff 0 Sep 21 15:06 ctl -1554 -r-xr-xr-x 1 bin bin 90112 Mar 29 04:52 file -3339 -rw------- 1 jsp staff 118784 Sep 21 15:06 mem -3343 --w------- 1 jsp staff 0 Sep 21 15:06 note -3344 --w------- 1 jsp staff 0 Sep 21 15:06 notepg -3340 -rw------- 1 jsp staff 0 Sep 21 15:06 regs -3342 -r--r--r-- 1 jsp staff 0 Sep 21 15:06 status -% df /proc/curproc /proc/curproc/file -Filesystem 512-blocks Used Avail Capacity Mounted on -proc 2 2 0 100% /proc -/dev/wd0a 16186 13548 1018 93% / -% cat /proc/curproc/status -cat 446 439 400 81 12,0 ctty 748620684 270000 0 0 0 20000 nochan 11 20 20 20 0 21 117 - - - -the basic sequence of commands written to "ctl" would be - - attach - this stops the target process and - arranges for the sending process - to become the debug control process - wait - wait for the target process to come to - a steady state ready for debugging. - step - single step, with no signal delivery. - run - continue running, with no signal delivery, - until next trap or breakpoint. - <signame> - deliver signal <signame> and continue running. - detach - continue execution of the target process - and remove it from control by the debug process - -in a normal debugging environment, where the target is fork/exec'd by -the debugger, the debugger should fork and the child should stop itself -(with a self-inflicted SIGSTOP). the parent should do a "wait" then an -"attach". as before, the child will hit a breakpoint on the first -instruction in any newly exec'd image. - -$FreeBSD$ diff --git a/sys/fs/procfs/procfs.c b/sys/fs/procfs/procfs.c index a41e7d1ba1b81..91ef0d83efd27 100644 --- a/sys/fs/procfs/procfs.c +++ b/sys/fs/procfs/procfs.c @@ -104,8 +104,7 @@ procfs_attr(PFS_ATTR_ARGS) { /* XXX inefficient, split into separate functions */ - if (strcmp(pn->pn_name, "ctl") == 0 || - strcmp(pn->pn_name, "note") == 0 || + if (strcmp(pn->pn_name, "note") == 0 || strcmp(pn->pn_name, "notepg") == 0) vap->va_mode = 0200; else if (strcmp(pn->pn_name, "mem") == 0 || @@ -166,8 +165,6 @@ procfs_init(PFS_INIT_ARGS) procfs_attr, NULL, NULL, PFS_PROCDEP); pfs_create_file(dir, "cmdline", procfs_doproccmdline, NULL, NULL, NULL, PFS_RD); - pfs_create_file(dir, "ctl", procfs_doprocctl, - procfs_attr, NULL, NULL, PFS_WR); pfs_create_file(dir, "dbregs", procfs_doprocdbregs, procfs_attr, procfs_candebug, NULL, PFS_RDWR|PFS_RAW); pfs_create_file(dir, "etype", procfs_doproctype, diff --git a/sys/fs/procfs/procfs.h b/sys/fs/procfs/procfs.h index c88d57605f829..d9ca44613f980 100644 --- a/sys/fs/procfs/procfs.h +++ b/sys/fs/procfs/procfs.h @@ -41,7 +41,6 @@ int procfs_docurproc(PFS_FILL_ARGS); int procfs_doosrel(PFS_FILL_ARGS); int procfs_doproccmdline(PFS_FILL_ARGS); -int procfs_doprocctl(PFS_FILL_ARGS); int procfs_doprocdbregs(PFS_FILL_ARGS); int procfs_doprocfile(PFS_FILL_ARGS); int procfs_doprocfpregs(PFS_FILL_ARGS); diff --git a/sys/fs/procfs/procfs_ctl.c b/sys/fs/procfs/procfs_ctl.c deleted file mode 100644 index b1f1cc863eefb..0000000000000 --- a/sys/fs/procfs/procfs_ctl.c +++ /dev/null @@ -1,359 +0,0 @@ -/*- - * Copyright (c) 1993 Jan-Simon Pendry - * Copyright (c) 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Jan-Simon Pendry. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)procfs_ctl.c 8.4 (Berkeley) 6/15/94 - * - * From: - * $Id: procfs_ctl.c,v 1.51 2003/12/07 17:40:00 des Exp $ - * $FreeBSD$ - */ - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/lock.h> -#include <sys/mutex.h> -#include <sys/proc.h> -#include <sys/ptrace.h> -#include <sys/sbuf.h> -#include <sys/signalvar.h> -#include <sys/sx.h> -#include <sys/uio.h> - -#include <fs/pseudofs/pseudofs.h> -#include <fs/procfs/procfs.h> - -#include <vm/vm.h> - -/* - * True iff process (p) is in trace wait state - * relative to process (curp) - */ -#define TRACE_WAIT_P(curp, p) \ - (P_SHOULDSTOP(p) && \ - (p)->p_pptr == (curp) && \ - ((p)->p_flag & P_TRACED)) - -#define PROCFS_CTL_ATTACH 1 -#define PROCFS_CTL_DETACH 2 -#define PROCFS_CTL_STEP 3 -#define PROCFS_CTL_RUN 4 -#define PROCFS_CTL_WAIT 5 - -struct namemap { - const char *nm_name; - int nm_val; -}; - -static struct namemap ctlnames[] = { - /* special /proc commands */ - { "attach", PROCFS_CTL_ATTACH }, - { "detach", PROCFS_CTL_DETACH }, - { "step", PROCFS_CTL_STEP }, - { "run", PROCFS_CTL_RUN }, - { "wait", PROCFS_CTL_WAIT }, - { 0 }, -}; - -static struct namemap signames[] = { - /* regular signal names */ - { "hup", SIGHUP }, { "int", SIGINT }, - { "quit", SIGQUIT }, { "ill", SIGILL }, - { "trap", SIGTRAP }, { "abrt", SIGABRT }, - { "iot", SIGIOT }, { "emt", SIGEMT }, - { "fpe", SIGFPE }, { "kill", SIGKILL }, - { "bus", SIGBUS }, { "segv", SIGSEGV }, - { "sys", SIGSYS }, { "pipe", SIGPIPE }, - { "alrm", SIGALRM }, { "term", SIGTERM }, - { "urg", SIGURG }, { "stop", SIGSTOP }, - { "tstp", SIGTSTP }, { "cont", SIGCONT }, - { "chld", SIGCHLD }, { "ttin", SIGTTIN }, - { "ttou", SIGTTOU }, { "io", SIGIO }, - { "xcpu", SIGXCPU }, { "xfsz", SIGXFSZ }, - { "vtalrm", SIGVTALRM }, { "prof", SIGPROF }, - { "winch", SIGWINCH }, { "info", SIGINFO }, - { "usr1", SIGUSR1 }, { "usr2", SIGUSR2 }, - { 0 }, -}; - -static int procfs_control(struct thread *td, struct proc *p, int op); - -static int -procfs_control(struct thread *td, struct proc *p, int op) -{ - int error = 0; - struct thread *temp; - - /* - * Attach - attaches the target process for debugging - * by the calling process. - */ - if (op == PROCFS_CTL_ATTACH) { - sx_xlock(&proctree_lock); - PROC_LOCK(p); - if ((error = p_candebug(td, p)) != 0) - goto out; - if (p->p_flag & P_TRACED) { - error = EBUSY; - goto out; - } - - /* Can't trace yourself! */ - if (p->p_pid == td->td_proc->p_pid) { - error = EINVAL; - goto out; - } - - /* - * Go ahead and set the trace flag. - * Save the old parent (it's reset in - * _DETACH, and also in kern_exit.c:wait4() - * Reparent the process so that the tracing - * proc gets to see all the action. - * Stop the target. - */ - p->p_flag |= P_TRACED; - faultin(p); - p->p_xsig = 0; /* XXX ? */ - p->p_oppid = p->p_pptr->p_pid; - if (p->p_pptr != td->td_proc) { - proc_reparent(p, td->td_proc); - } - kern_psignal(p, SIGSTOP); -out: - PROC_UNLOCK(p); - sx_xunlock(&proctree_lock); - return (error); - } - - /* - * Authorization check: rely on normal debugging protection, except - * allow processes to disengage debugging on a process onto which - * they have previously attached, but no longer have permission to - * debug. - */ - PROC_LOCK(p); - if (op != PROCFS_CTL_DETACH && - ((error = p_candebug(td, p)))) { - PROC_UNLOCK(p); - return (error); - } - - /* - * Target process must be stopped, owned by (td) and - * be set up for tracing (P_TRACED flag set). - * Allow DETACH to take place at any time for sanity. - * Allow WAIT any time, of course. - */ - switch (op) { - case PROCFS_CTL_DETACH: - case PROCFS_CTL_WAIT: - break; - - default: - if (!TRACE_WAIT_P(td->td_proc, p)) { - PROC_UNLOCK(p); - return (EBUSY); - } - } - - -#ifdef FIX_SSTEP - /* - * do single-step fixup if needed - */ - FIX_SSTEP(FIRST_THREAD_IN_PROC(p)); -#endif - - /* - * Don't deliver any signal by default. - * To continue with a signal, just send - * the signal name to the ctl file - */ - p->p_xsig = 0; - - switch (op) { - /* - * Detach. Cleans up the target process, reparent it if possible - * and set it running once more. - */ - case PROCFS_CTL_DETACH: - /* if not being traced, then this is a painless no-op */ - if ((p->p_flag & P_TRACED) == 0) { - PROC_UNLOCK(p); - return (0); - } - - /* not being traced any more */ - p->p_flag &= ~(P_TRACED | P_STOPPED_TRACE); - - /* remove pending SIGTRAP, else the process will die */ - sigqueue_delete_proc(p, SIGTRAP); - FOREACH_THREAD_IN_PROC(p, temp) - temp->td_dbgflags &= ~TDB_SUSPEND; - PROC_UNLOCK(p); - - /* give process back to original parent */ - sx_xlock(&proctree_lock); - if (p->p_oppid != p->p_pptr->p_pid) { - struct proc *pp; - - pp = pfind(p->p_oppid); - PROC_LOCK(p); - if (pp) { - PROC_UNLOCK(pp); - proc_reparent(p, pp); - } - } else - PROC_LOCK(p); - p->p_oppid = 0; - p->p_stops = 0; - p->p_flag &= ~P_WAITED; /* XXX ? */ - sx_xunlock(&proctree_lock); - - wakeup(td->td_proc); /* XXX for CTL_WAIT below ? */ - - break; - - /* - * Step. Let the target process execute a single instruction. - * What does it mean to single step a threaded program? - */ - case PROCFS_CTL_STEP: - error = proc_sstep(FIRST_THREAD_IN_PROC(p)); - if (error) { - PROC_UNLOCK(p); - return (error); - } - break; - - /* - * Run. Let the target process continue running until a breakpoint - * or some other trap. - */ - case PROCFS_CTL_RUN: - p->p_flag &= ~P_STOPPED_SIG; /* this uses SIGSTOP */ - break; - - /* - * Wait for the target process to stop. - * If the target is not being traced then just wait - * to enter - */ - case PROCFS_CTL_WAIT: - if (p->p_flag & P_TRACED) { - while (error == 0 && - (P_SHOULDSTOP(p)) && - (p->p_flag & P_TRACED) && - (p->p_pptr == td->td_proc)) - error = msleep(p, &p->p_mtx, - PWAIT|PCATCH, "procfsx", 0); - if (error == 0 && !TRACE_WAIT_P(td->td_proc, p)) - error = EBUSY; - } else { - while (error == 0 && P_SHOULDSTOP(p)) - error = msleep(p, &p->p_mtx, - PWAIT|PCATCH, "procfs", 0); - } - PROC_UNLOCK(p); - return (error); - default: - panic("procfs_control"); - } - - PROC_SLOCK(p); - thread_unsuspend(p); /* If it can run, let it do so. */ - PROC_SUNLOCK(p); - PROC_UNLOCK(p); - return (0); -} - -static struct namemap * -findname(struct namemap *nm, char *buf, int buflen) -{ - - for (; nm->nm_name; nm++) - if (bcmp(buf, nm->nm_name, buflen+1) == 0) - return (nm); - - return (0); -} - -int -procfs_doprocctl(PFS_FILL_ARGS) -{ - int error; - struct namemap *nm; - - if (uio == NULL || uio->uio_rw != UIO_WRITE) - return (EOPNOTSUPP); - - /* - * Map signal names into signal generation - * or debug control. Unknown commands and/or signals - * return EOPNOTSUPP. - * - * Sending a signal while the process is being debugged - * also has the side effect of letting the target continue - * to run. There is no way to single-step a signal delivery. - */ - error = EOPNOTSUPP; - - sbuf_trim(sb); - sbuf_finish(sb); - nm = findname(ctlnames, sbuf_data(sb), sbuf_len(sb)); - if (nm) { - printf("procfs: got a %s command\n", sbuf_data(sb)); - error = procfs_control(td, p, nm->nm_val); - } else { - nm = findname(signames, sbuf_data(sb), sbuf_len(sb)); - if (nm) { - printf("procfs: got a sig%s\n", sbuf_data(sb)); - PROC_LOCK(p); - - if (TRACE_WAIT_P(td->td_proc, p)) { - p->p_xsig = nm->nm_val; -#ifdef FIX_SSTEP - FIX_SSTEP(FIRST_THREAD_IN_PROC(p)); -#endif - p->p_flag &= ~P_STOPPED_SIG; - PROC_SLOCK(p); - thread_unsuspend(p); - PROC_SUNLOCK(p); - } else - kern_psignal(p, nm->nm_val); - PROC_UNLOCK(p); - error = 0; - } - } - - return (error); -} |
