Pseudofsize procfs(5).

This commit is contained in:
Dag-Erling Smørgrav 2001-12-04 01:35:06 +00:00
parent 3bff55e81b
commit 3a669c52a8
20 changed files with 484 additions and 2045 deletions

View File

@ -644,19 +644,18 @@ fs/nwfs/nwfs_vfsops.c optional nwfs
fs/nwfs/nwfs_vnops.c optional nwfs fs/nwfs/nwfs_vnops.c optional nwfs
fs/portalfs/portal_vfsops.c optional portalfs fs/portalfs/portal_vfsops.c optional portalfs
fs/portalfs/portal_vnops.c optional portalfs fs/portalfs/portal_vnops.c optional portalfs
fs/procfs/procfs.c optional procfs
fs/procfs/procfs_ctl.c optional procfs fs/procfs/procfs_ctl.c optional procfs
fs/procfs/procfs_dbregs.c optional procfs fs/procfs/procfs_dbregs.c optional procfs
fs/procfs/procfs_fpregs.c optional procfs fs/procfs/procfs_fpregs.c optional procfs
fs/procfs/procfs_ioctl.c optional procfs
fs/procfs/procfs_map.c optional procfs fs/procfs/procfs_map.c optional procfs
fs/procfs/procfs_mem.c optional procfs fs/procfs/procfs_mem.c optional procfs
fs/procfs/procfs_note.c optional procfs fs/procfs/procfs_note.c optional procfs
fs/procfs/procfs_regs.c optional procfs fs/procfs/procfs_regs.c optional procfs
fs/procfs/procfs_rlimit.c optional procfs fs/procfs/procfs_rlimit.c optional procfs
fs/procfs/procfs_status.c optional procfs fs/procfs/procfs_status.c optional procfs
fs/procfs/procfs_subr.c optional procfs
fs/procfs/procfs_type.c optional procfs fs/procfs/procfs_type.c optional procfs
fs/procfs/procfs_vfsops.c optional procfs
fs/procfs/procfs_vnops.c optional procfs
fs/pseudofs/pseudofs.c optional pseudofs fs/pseudofs/pseudofs.c optional pseudofs
fs/pseudofs/pseudofs_fileno.c optional pseudofs fs/pseudofs/pseudofs_fileno.c optional pseudofs
fs/pseudofs/pseudofs_vncache.c optional pseudofs fs/pseudofs/pseudofs_vncache.c optional pseudofs

198
sys/fs/procfs/procfs.c Normal file
View File

@ -0,0 +1,198 @@
/*
* Copyright (c) 2001 Dag-Erling Smørgrav
* 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.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 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_vfsops.c 8.7 (Berkeley) 5/10/95
*
* $FreeBSD$
*/
#include <sys/param.h>
#include <sys/queue.h>
#include <sys/exec.h>
#include <sys/lock.h>
#include <sys/kernel.h>
#include <sys/malloc.h>
#include <sys/mount.h>
#include <sys/mutex.h>
#include <sys/proc.h>
#include <sys/sbuf.h>
#include <sys/sysproto.h>
#include <sys/systm.h>
#include <sys/vnode.h>
#include <vm/vm.h>
#include <vm/pmap.h>
#include <vm/vm_param.h>
#include <fs/pseudofs/pseudofs.h>
#include <fs/procfs/procfs.h>
/*
* Filler function for proc/pid/self
*/
static int
procfs_doprocfile(PFS_FILL_ARGS)
{
char *fullpath = "unknown";
char *freepath = NULL;
vn_fullpath(td, td->td_proc->p_textvp, &fullpath, &freepath);
sbuf_printf(sb, "%s", fullpath);
if (freepath)
free(freepath, M_TEMP);
return (0);
}
/*
* Filler function for proc/curproc
*/
static int
procfs_docurproc(PFS_FILL_ARGS)
{
sbuf_printf(sb, "%ld", (long)td->td_proc->p_pid);
return (0);
}
/*
* Adjust mode for some nodes that need it
*/
int
procfs_attr(PFS_ATTR_ARGS)
{
/* XXX inefficient, split into separate functions */
if (strcmp(pn->pn_name, "ctl") == 0 ||
strcmp(pn->pn_name, "note") == 0 ||
strcmp(pn->pn_name, "notepg") == 0)
vap->va_mode = 0200;
else if (strcmp(pn->pn_name, "mem") == 0 ||
strcmp(pn->pn_name, "regs") == 0 ||
strcmp(pn->pn_name, "dbregs") == 0 ||
strcmp(pn->pn_name, "fpregs") == 0)
vap->va_mode = 0600;
/* p is locked by caller */
vap->va_uid = p->p_ucred->cr_uid;
vap->va_gid = p->p_ucred->cr_gid;
return (0);
}
/*
* Visibility: some files only exist for non-system processes
* Non-static because linprocfs uses it.
*/
int
procfs_notsystem(PFS_VIS_ARGS)
{
return ((p->p_flag & P_SYSTEM) == 0);
}
/*
* Visibility: some files are only visible to process that can debug
* the target process.
*/
int
procfs_candebug(PFS_VIS_ARGS)
{
return ((p->p_flag & P_SYSTEM) == 0 &&
p_candebug(td->td_proc, p) == 0);
}
/*
* Constructor
*/
static int
procfs_init(PFS_INIT_ARGS)
{
struct pfs_node *root;
struct pfs_node *dir;
struct pfs_node *node;
root = pi->pi_root;
pfs_create_link(root, "curproc", &procfs_docurproc,
NULL, NULL, 0);
dir = pfs_create_dir(root, "pid",
&procfs_attr, NULL, PFS_PROCDEP);
pfs_create_file(dir, "cmdline", &procfs_doproccmdline,
NULL, NULL, PFS_RD);
pfs_create_file(dir, "ctl", &procfs_doprocctl,
&procfs_attr, NULL, PFS_WR);
pfs_create_file(dir, "dbregs", &procfs_doprocdbregs,
&procfs_attr, &procfs_candebug, PFS_RDWR|PFS_RAW);
pfs_create_file(dir, "etype", &procfs_doproctype,
NULL, NULL, PFS_RD);
pfs_create_file(dir, "fpregs", &procfs_doprocfpregs,
&procfs_attr, &procfs_candebug, PFS_RDWR|PFS_RAW);
pfs_create_file(dir, "map", &procfs_doprocmap,
NULL, &procfs_notsystem, PFS_RD);
node = pfs_create_file(dir, "mem", &procfs_doprocmem,
&procfs_attr, &procfs_candebug, PFS_RDWR|PFS_RAW);
#ifdef PROCFS_DEBUG
node->pn_ioctl = &procfs_ioctl;
node->pn_close = &procfs_close;
#endif
pfs_create_file(dir, "note", &procfs_doprocnote,
&procfs_attr, &procfs_candebug, PFS_WR);
pfs_create_file(dir, "notepg", &procfs_doprocnote,
&procfs_attr, &procfs_candebug, PFS_WR);
pfs_create_file(dir, "regs", &procfs_doprocregs,
&procfs_attr, &procfs_candebug, PFS_RDWR|PFS_RAW);
pfs_create_file(dir, "rlimit", &procfs_doprocrlimit,
NULL, NULL, PFS_RD);
pfs_create_file(dir, "status", &procfs_doprocstatus,
NULL, NULL, PFS_RD);
pfs_create_link(dir, "file", &procfs_doprocfile,
NULL, procfs_notsystem, 0);
return (0);
}
/*
* Destructor
*/
static int
procfs_uninit(PFS_INIT_ARGS)
{
/* nothing to do, pseudofs will GC */
return (0);
}
PSEUDOFS(procfs, 1);

View File

@ -40,109 +40,30 @@
* $FreeBSD$ * $FreeBSD$
*/ */
/*
* The different types of node in a procfs filesystem
*/
typedef enum {
Proot, /* the filesystem root */
Pcurproc, /* symbolic link for curproc */
Pproc, /* a process-specific sub-directory */
Pfile, /* the executable file */
Pmem, /* the process's memory image */
Pregs, /* the process's register set */
Pfpregs, /* the process's FP register set */
Pdbregs, /* the process's debug register set */
Pctl, /* process control */
Pstatus, /* process status */
Pnote, /* process notifier */
Pnotepg, /* process group notifier */
Pmap, /* memory map */
Ptype, /* executable type */
Pcmdline, /* command line */
Prlimit /* resource limits */
} pfstype;
/*
* control data for the proc file system.
*/
struct pfsnode {
struct pfsnode *pfs_next; /* next on list */
struct vnode *pfs_vnode; /* vnode associated with this pfsnode */
pfstype pfs_type; /* type of procfs node */
pid_t pfs_pid; /* associated process */
u_short pfs_mode; /* mode bits for stat() */
u_long pfs_flags; /* open flags */
u_long pfs_fileno; /* unique file id */
pid_t pfs_lockowner; /* pfs lock owner */
};
#define PROCFS_NOTELEN 64 /* max length of a note (/proc/$pid/note) */
#define PROCFS_CTLLEN 8 /* max length of a ctl msg (/proc/$pid/ctl */
#define PROCFS_NAMELEN 8 /* max length of a filename component */
/*
* Kernel stuff follows
*/
#ifdef _KERNEL #ifdef _KERNEL
#define CNEQ(cnp, s, len) \
((cnp)->cn_namelen == (len) && \
(bcmp((s), (cnp)->cn_nameptr, (len)) == 0))
#define PROCFS_FILENO(pid, type) \ int procfs_doproccmdline(PFS_FILL_ARGS);
(((type) < Pproc) ? \ int procfs_doprocctl(PFS_FILL_ARGS);
((type) + 2) : \ int procfs_doprocdbregs(PFS_FILL_ARGS);
((((pid)+1) << 4) + ((int) (type)))) int procfs_doprocfpregs(PFS_FILL_ARGS);
int procfs_doprocmap(PFS_FILL_ARGS);
int procfs_doprocmem(PFS_FILL_ARGS);
int procfs_doprocnote(PFS_FILL_ARGS);
int procfs_doprocregs(PFS_FILL_ARGS);
int procfs_doprocrlimit(PFS_FILL_ARGS);
int procfs_doprocstatus(PFS_FILL_ARGS);
int procfs_doproctype(PFS_FILL_ARGS);
int procfs_ioctl(PFS_IOCTL_ARGS);
int procfs_close(PFS_CLOSE_ARGS);
/* /* Return 1 if process has special kernel digging privileges */
* Convert between pfsnode vnode int procfs_kmemaccess(struct proc *);
*/
#define VTOPFS(vp) ((struct pfsnode *)(vp)->v_data)
#define PFSTOV(pfs) ((pfs)->pfs_vnode)
typedef struct vfs_namemap vfs_namemap_t; /* Attributes */
struct vfs_namemap { int procfs_attr(PFS_ATTR_ARGS);
const char *nm_name;
int nm_val;
};
int vfs_getuserstr __P((struct uio *, char *, int *)); /* Visbility */
vfs_namemap_t *vfs_findname __P((vfs_namemap_t *, char *, int)); int procfs_notsystem(PFS_VIS_ARGS);
int procfs_candebug(PFS_VIS_ARGS);
/* <machine/reg.h> */
struct reg;
struct fpreg;
struct dbreg;
#define PFIND(pid) (pfind(pid))
void procfs_exit __P((struct proc *));
int procfs_freevp __P((struct vnode *));
int procfs_allocvp __P((struct mount *, struct vnode **, long, pfstype));
int procfs_donote __P((struct proc *, struct proc *, struct pfsnode *pfsp, struct uio *uio));
int procfs_doregs __P((struct proc *, struct proc *, struct pfsnode *pfsp, struct uio *uio));
int procfs_dofpregs __P((struct proc *, struct proc *, struct pfsnode *pfsp, struct uio *uio));
int procfs_dodbregs __P((struct proc *, struct proc *, struct pfsnode *pfsp, struct uio *uio));
int procfs_domem __P((struct proc *, struct proc *, struct pfsnode *pfsp, struct uio *uio));
int procfs_doctl __P((struct proc *, struct proc *, struct pfsnode *pfsp, struct uio *uio));
int procfs_dostatus __P((struct proc *, struct proc *, struct pfsnode *pfsp, struct uio *uio));
int procfs_domap __P((struct proc *, struct proc *, struct pfsnode *pfsp, struct uio *uio));
int procfs_dotype __P((struct proc *, struct proc *, struct pfsnode *pfsp, struct uio *uio));
int procfs_docmdline __P((struct proc *, struct proc *, struct pfsnode *pfsp, struct uio *uio));
int procfs_dorlimit __P((struct proc *, struct proc *, struct pfsnode *pfsp, struct uio *uio));
/* functions to check whether or not files should be displayed */
int procfs_validfile __P((struct thread *));
int procfs_validfpregs __P((struct thread *));
int procfs_validregs __P((struct thread *));
int procfs_validdbregs __P((struct thread *));
int procfs_validmap __P((struct thread *));
int procfs_validtype __P((struct thread *));
#define PROCFS_LOCKED 0x01
#define PROCFS_WANT 0x02
extern vop_t **procfs_vnodeop_p;
int procfs_root __P((struct mount *, struct vnode **));
int procfs_rw __P((struct vop_read_args *));
#endif /* _KERNEL */ #endif /* _KERNEL */

View File

@ -44,10 +44,12 @@
#include <sys/mutex.h> #include <sys/mutex.h>
#include <sys/proc.h> #include <sys/proc.h>
#include <sys/ptrace.h> #include <sys/ptrace.h>
#include <sys/sbuf.h>
#include <sys/signalvar.h> #include <sys/signalvar.h>
#include <sys/sx.h> #include <sys/sx.h>
#include <sys/vnode.h> #include <sys/uio.h>
#include <fs/pseudofs/pseudofs.h>
#include <fs/procfs/procfs.h> #include <fs/procfs/procfs.h>
#include <vm/vm.h> #include <vm/vm.h>
@ -67,7 +69,12 @@
#define PROCFS_CTL_RUN 4 #define PROCFS_CTL_RUN 4
#define PROCFS_CTL_WAIT 5 #define PROCFS_CTL_WAIT 5
static vfs_namemap_t ctlnames[] = { struct namemap {
const char *nm_name;
int nm_val;
};
static struct namemap ctlnames[] = {
/* special /proc commands */ /* special /proc commands */
{ "attach", PROCFS_CTL_ATTACH }, { "attach", PROCFS_CTL_ATTACH },
{ "detach", PROCFS_CTL_DETACH }, { "detach", PROCFS_CTL_DETACH },
@ -77,7 +84,7 @@ static vfs_namemap_t ctlnames[] = {
{ 0 }, { 0 },
}; };
static vfs_namemap_t signames[] = { static struct namemap signames[] = {
/* regular signal names */ /* regular signal names */
{ "hup", SIGHUP }, { "int", SIGINT }, { "hup", SIGHUP }, { "int", SIGINT },
{ "quit", SIGQUIT }, { "ill", SIGILL }, { "quit", SIGQUIT }, { "ill", SIGILL },
@ -101,10 +108,7 @@ static vfs_namemap_t signames[] = {
static int procfs_control __P((struct proc *curp, struct proc *p, int op)); static int procfs_control __P((struct proc *curp, struct proc *p, int op));
static int static int
procfs_control(curp, p, op) procfs_control(struct proc *curp, struct proc *p, int op)
struct proc *curp;
struct proc *p;
int op;
{ {
int error = 0; int error = 0;
@ -240,7 +244,6 @@ procfs_control(curp, p, op)
* Step. Let the target process execute a single instruction. * Step. Let the target process execute a single instruction.
*/ */
case PROCFS_CTL_STEP: case PROCFS_CTL_STEP:
_PHOLD(p);
PROC_UNLOCK(p); PROC_UNLOCK(p);
error = proc_sstep(&p->p_thread); /* XXXKSE */ error = proc_sstep(&p->p_thread); /* XXXKSE */
PRELE(p); PRELE(p);
@ -301,26 +304,26 @@ procfs_control(curp, p, op)
return (0); return (0);
} }
int static struct namemap *
procfs_doctl(curp, p, pfs, uio) findname(struct namemap *nm, char *buf, int buflen)
struct proc *curp; {
struct pfsnode *pfs;
struct uio *uio; for (; nm->nm_name; nm++)
struct proc *p; if (bcmp(buf, nm->nm_name, buflen+1) == 0)
return (nm);
return (0);
}
int
procfs_doprocctl(PFS_FILL_ARGS)
{ {
int xlen;
int error; int error;
char msg[PROCFS_CTLLEN+1]; struct namemap *nm;
vfs_namemap_t *nm;
if (uio->uio_rw != UIO_WRITE) if (uio == NULL || uio->uio_rw != UIO_WRITE)
return (EOPNOTSUPP); return (EOPNOTSUPP);
xlen = PROCFS_CTLLEN;
error = vfs_getuserstr(uio, msg, &xlen);
if (error)
return (error);
/* /*
* Map signal names into signal generation * Map signal names into signal generation
* or debug control. Unknown commands and/or signals * or debug control. Unknown commands and/or signals
@ -332,15 +335,19 @@ procfs_doctl(curp, p, pfs, uio)
*/ */
error = EOPNOTSUPP; error = EOPNOTSUPP;
nm = vfs_findname(ctlnames, msg, xlen); sbuf_trim(sb);
sbuf_finish(sb);
nm = findname(ctlnames, sbuf_data(sb), sbuf_len(sb));
if (nm) { if (nm) {
error = procfs_control(curp, p, nm->nm_val); printf("procfs: got a %s command\n", sbuf_data(sb));
error = procfs_control(td->td_proc, p, nm->nm_val);
} else { } else {
nm = vfs_findname(signames, msg, xlen); nm = findname(signames, sbuf_data(sb), sbuf_len(sb));
if (nm) { if (nm) {
printf("procfs: got a sig%s\n", sbuf_data(sb));
PROC_LOCK(p); PROC_LOCK(p);
mtx_lock_spin(&sched_lock); mtx_lock_spin(&sched_lock);
if (TRACE_WAIT_P(curp, p)) { if (TRACE_WAIT_P(td->td_proc, p)) {
p->p_xstat = nm->nm_val; p->p_xstat = nm->nm_val;
#ifdef FIX_SSTEP #ifdef FIX_SSTEP
FIX_SSTEP(&p->p_thread); /* XXXKSE */ FIX_SSTEP(&p->p_thread); /* XXXKSE */

View File

@ -49,27 +49,22 @@
#include <sys/mutex.h> #include <sys/mutex.h>
#include <sys/proc.h> #include <sys/proc.h>
#include <sys/ptrace.h> #include <sys/ptrace.h>
#include <sys/vnode.h> #include <sys/uio.h>
#include <machine/reg.h> #include <machine/reg.h>
#include <fs/pseudofs/pseudofs.h>
#include <fs/procfs/procfs.h> #include <fs/procfs/procfs.h>
#include <vm/vm.h>
int int
procfs_dodbregs(curp, p, pfs, uio) procfs_doprocdbregs(PFS_FILL_ARGS)
struct proc *curp;
struct proc *p;
struct pfsnode *pfs;
struct uio *uio;
{ {
int error; int error;
struct dbreg r; struct dbreg r;
char *kv; char *kv;
int kl; int kl;
if (p_candebug(curp, p)) if (p_candebug(td->td_proc, p) != 0)
return (EPERM); return (EPERM);
kl = sizeof(r); kl = sizeof(r);
kv = (char *) &r; kv = (char *) &r;
@ -79,8 +74,6 @@ procfs_dodbregs(curp, p, pfs, uio)
if (kl > uio->uio_resid) if (kl > uio->uio_resid)
kl = uio->uio_resid; kl = uio->uio_resid;
PHOLD(p);
if (kl < 0) if (kl < 0)
error = EINVAL; error = EINVAL;
else else
@ -93,15 +86,7 @@ procfs_dodbregs(curp, p, pfs, uio)
else else
error = proc_write_dbregs(&p->p_thread, &r); /* XXXKSE */ error = proc_write_dbregs(&p->p_thread, &r); /* XXXKSE */
} }
PRELE(p);
uio->uio_offset = 0; uio->uio_offset = 0;
return (error); return (error);
} }
int
procfs_validdbregs(struct thread *td)
{
return ((td->td_proc->p_flag & P_SYSTEM) == 0);
}

View File

@ -46,27 +46,22 @@
#include <sys/mutex.h> #include <sys/mutex.h>
#include <sys/proc.h> #include <sys/proc.h>
#include <sys/ptrace.h> #include <sys/ptrace.h>
#include <sys/vnode.h> #include <sys/uio.h>
#include <machine/reg.h> #include <machine/reg.h>
#include <fs/pseudofs/pseudofs.h>
#include <fs/procfs/procfs.h> #include <fs/procfs/procfs.h>
#include <vm/vm.h>
int int
procfs_dofpregs(curp, p, pfs, uio) procfs_doprocfpregs(PFS_FILL_ARGS)
struct proc *curp;
struct proc *p;
struct pfsnode *pfs;
struct uio *uio;
{ {
int error; int error;
struct fpreg r; struct fpreg r;
char *kv; char *kv;
int kl; int kl;
if (p_candebug(curp, p)) if (p_candebug(td->td_proc, p))
return EPERM; return EPERM;
kl = sizeof(r); kl = sizeof(r);
kv = (char *) &r; kv = (char *) &r;
@ -95,10 +90,3 @@ procfs_dofpregs(curp, p, pfs, uio)
uio->uio_offset = 0; uio->uio_offset = 0;
return (error); return (error);
} }
int
procfs_validfpregs(struct thread *td)
{
return (( td->td_proc->p_flag & P_SYSTEM) == 0);
}

View File

@ -0,0 +1,132 @@
/*-
* Copyright (c) 2001 Dag-Erling Coïdan Smørgrav
* All rights reserved.
*
* 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
* in this position and unchanged.
* 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.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
*
* $FreeBSD$
*/
#include <sys/param.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/pioctl.h>
#include <sys/proc.h>
#include <sys/signalvar.h>
#include <sys/systm.h>
#include <fs/pseudofs/pseudofs.h>
#include <fs/procfs/procfs.h>
#ifdef PROCFS_DEBUG
/*
* Process ioctls
*/
int
procfs_ioctl(PFS_IOCTL_ARGS)
{
struct procfs_status *ps;
int error, sig;
PROC_LOCK(p);
error = 0;
switch (cmd) {
case PIOCBIS:
p->p_stops |= *(unsigned int *)data;
break;
case PIOCBIC:
p->p_stops &= ~*(unsigned int *)data;
break;
case PIOCSFL:
/* ignore */
break;
case PIOCGFL:
*(unsigned int *)data = 0; /* nope */
break;
case PIOCWAIT:
while (p->p_step == 0) {
/* sleep until p stops */
error = msleep(&p->p_stype, &p->p_mtx,
PWAIT|PCATCH, "pioctl", 0);
if (error != 0)
break;
}
/* fall through to PIOCSTATUS */
case PIOCSTATUS:
ps = (struct procfs_status *)data;
ps->state = (p->p_step == 0);
ps->flags = 0; /* nope */
ps->events = p->p_stops;
ps->why = p->p_step ? p->p_stype : 0;
ps->val = p->p_step ? p->p_xstat : 0;
break;
case PIOCCONT:
if (p->p_step)
break;
sig = *(int *)data;
if (!_SIG_VALID(sig)) {
error = EINVAL;
break;
}
#if 0
mtx_lock_spin(&sched_lock);
p->p_step = 0;
if (p->p_stat == SSTOP) {
p->p_xstat = sig;
setrunnable(&p->p_thread);
mtx_unlock_spin(&sched_lock);
} else {
mtx_unlock_spin(&sched_lock);
if (sig)
psignal(p, sig);
}
#else
if (sig)
psignal(p, sig);
wakeup(&p->p_step);
#endif
break;
default:
error = (ENOTTY);
}
PROC_UNLOCK(p);
return (error);
}
/*
* Clean up on last close
*/
int
procfs_close(PFS_CLOSE_ARGS)
{
if (p != NULL && (p->p_pfsflags & PF_LINGER) == 0) {
p->p_pfsflags = 0;
p->p_stops = 0;
p->p_step = 0;
wakeup(&p->p_step);
}
return (0);
}
#endif

View File

@ -44,8 +44,9 @@
#include <sys/lock.h> #include <sys/lock.h>
#include <sys/mutex.h> #include <sys/mutex.h>
#include <sys/proc.h> #include <sys/proc.h>
#include <sys/vnode.h> #include <sys/uio.h>
#include <fs/pseudofs/pseudofs.h>
#include <fs/procfs/procfs.h> #include <fs/procfs/procfs.h>
#include <vm/vm.h> #include <vm/vm.h>
@ -68,11 +69,7 @@
* can try a bigger buffer. * can try a bigger buffer.
*/ */
int int
procfs_domap(curp, p, pfs, uio) procfs_doprocmap(PFS_FILL_ARGS)
struct proc *curp;
struct proc *p;
struct pfsnode *pfs;
struct uio *uio;
{ {
int len; int len;
int error; int error;
@ -90,7 +87,7 @@ procfs_domap(curp, p, pfs, uio)
return (0); return (0);
error = 0; error = 0;
if (map != &curproc->p_vmspace->vm_map) if (map != &curthread->td_proc->p_vmspace->vm_map)
vm_map_lock_read(map); vm_map_lock_read(map);
for (entry = map->header.next; for (entry = map->header.next;
((uio->uio_resid > 0) && (entry != &map->header)); ((uio->uio_resid > 0) && (entry != &map->header));
@ -118,23 +115,22 @@ procfs_domap(curp, p, pfs, uio)
addr += PAGE_SIZE; addr += PAGE_SIZE;
} }
for( lobj = tobj = obj; tobj; tobj = tobj->backing_object) for (lobj = tobj = obj; tobj; tobj = tobj->backing_object)
lobj = tobj; lobj = tobj;
if (lobj) { if (lobj) {
switch(lobj->type) { switch(lobj->type) {
default:
default: case OBJT_DEFAULT:
case OBJT_DEFAULT:
type = "default"; type = "default";
break; break;
case OBJT_VNODE: case OBJT_VNODE:
type = "vnode"; type = "vnode";
break; break;
case OBJT_SWAP: case OBJT_SWAP:
type = "swap"; type = "swap";
break; break;
case OBJT_DEVICE: case OBJT_DEVICE:
type = "device"; type = "device";
break; break;
} }
@ -148,13 +144,12 @@ case OBJT_DEVICE:
ref_count = 0; ref_count = 0;
shadow_count = 0; shadow_count = 0;
} }
/* /*
* format: * format:
* start, end, resident, private resident, cow, access, type. * start, end, resident, private resident, cow, access, type.
*/ */
snprintf(mebuffer, sizeof(mebuffer), snprintf(mebuffer, sizeof mebuffer,
"0x%lx 0x%lx %d %d %p %s%s%s %d %d 0x%x %s %s %s\n", "0x%lx 0x%lx %d %d %p %s%s%s %d %d 0x%x %s %s %s\n",
(u_long)entry->start, (u_long)entry->end, (u_long)entry->start, (u_long)entry->end,
resident, privateresident, obj, resident, privateresident, obj,
@ -175,14 +170,8 @@ case OBJT_DEVICE:
if (error) if (error)
break; break;
} }
if (map != &curproc->p_vmspace->vm_map) if (map != &curthread->td_proc->p_vmspace->vm_map)
vm_map_unlock_read(map); vm_map_unlock_read(map);
return error; return (error);
}
int
procfs_validmap(struct thread *td)
{
return ((td->td_proc->p_flag & P_SYSTEM) == 0);
} }

View File

@ -41,14 +41,13 @@
*/ */
#include <sys/param.h> #include <sys/param.h>
#include <sys/systm.h>
#include <sys/lock.h> #include <sys/lock.h>
#include <sys/mutex.h> #include <sys/mutex.h>
#include <sys/proc.h> #include <sys/proc.h>
#include <sys/ptrace.h> #include <sys/ptrace.h>
#include <sys/user.h> #include <sys/uio.h>
#include <sys/vnode.h>
#include <fs/pseudofs/pseudofs.h>
#include <fs/procfs/procfs.h> #include <fs/procfs/procfs.h>
/* /*
@ -58,20 +57,17 @@
* from the kernel address space. * from the kernel address space.
*/ */
int int
procfs_domem(curp, p, pfs, uio) procfs_doprocmem(PFS_FILL_ARGS)
struct proc *curp;
struct proc *p;
struct pfsnode *pfs;
struct uio *uio;
{ {
int error; int error;
if (uio->uio_resid == 0) if (uio->uio_resid == 0)
return (0); return (0);
error = p_candebug(curp, p); error = p_candebug(td->td_proc, p);
if (error) if (error)
return (error); return (error);
error = proc_rwmem(p, uio);
return (proc_rwmem(p, uio)); return (error);
} }

View File

@ -40,28 +40,18 @@
*/ */
#include <sys/param.h> #include <sys/param.h>
#include <sys/vnode.h> #include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/sbuf.h>
#include <fs/pseudofs/pseudofs.h>
#include <fs/procfs/procfs.h> #include <fs/procfs/procfs.h>
int int
procfs_donote(curp, p, pfs, uio) procfs_doprocnote(PFS_FILL_ARGS)
struct proc *curp;
struct proc *p;
struct pfsnode *pfs;
struct uio *uio;
{ {
int xlen; sbuf_trim(sb);
int error; sbuf_finish(sb);
char note[PROCFS_NOTELEN+1];
if (uio->uio_rw != UIO_WRITE)
return (EINVAL);
xlen = PROCFS_NOTELEN;
error = vfs_getuserstr(uio, note, &xlen);
if (error)
return (error);
/* send to process's notify function */ /* send to process's notify function */
return (EOPNOTSUPP); return (EOPNOTSUPP);
} }

View File

@ -46,28 +46,22 @@
#include <sys/mutex.h> #include <sys/mutex.h>
#include <sys/proc.h> #include <sys/proc.h>
#include <sys/ptrace.h> #include <sys/ptrace.h>
#include <sys/vnode.h> #include <sys/uio.h>
#include <machine/reg.h> #include <machine/reg.h>
#include <vm/vm.h> #include <fs/pseudofs/pseudofs.h>
#include <vm/vm_extern.h>
#include <fs/procfs/procfs.h> #include <fs/procfs/procfs.h>
int int
procfs_doregs(curp, p, pfs, uio) procfs_doprocregs(PFS_FILL_ARGS)
struct proc *curp;
struct proc *p;
struct pfsnode *pfs;
struct uio *uio;
{ {
int error; int error;
struct reg r; struct reg r;
char *kv; char *kv;
int kl; int kl;
if (p_candebug(curp, p)) if (p_candebug(td->td_proc, p))
return EPERM; return EPERM;
kl = sizeof(r); kl = sizeof(r);
kv = (char *) &r; kv = (char *) &r;
@ -96,10 +90,3 @@ procfs_doregs(curp, p, pfs, uio)
uio->uio_offset = 0; uio->uio_offset = 0;
return (error); return (error);
} }
int
procfs_validregs(struct thread *td)
{
return ((td->td_proc->p_flag & P_SYSTEM) == 0);
}

View File

@ -48,31 +48,18 @@
#include <sys/param.h> #include <sys/param.h>
#include <sys/systm.h> #include <sys/systm.h>
#include <sys/proc.h> #include <sys/proc.h>
#include <sys/vnode.h>
#include <sys/resourcevar.h> #include <sys/resourcevar.h>
#include <sys/resource.h> #include <sys/resource.h>
#include <sys/types.h> #include <sys/sbuf.h>
#include <fs/pseudofs/pseudofs.h>
#include <fs/procfs/procfs.h> #include <fs/procfs/procfs.h>
int int
procfs_dorlimit(curp, p, pfs, uio) procfs_doprocrlimit(PFS_FILL_ARGS)
struct proc *curp;
struct proc *p;
struct pfsnode *pfs;
struct uio *uio;
{ {
char *ps;
int i; int i;
int xlen;
int error;
char psbuf[512]; /* XXX - conservative */
if (uio->uio_rw != UIO_READ)
return (EOPNOTSUPP);
ps = psbuf;
for (i = 0; i < RLIM_NLIMITS; i++) { for (i = 0; i < RLIM_NLIMITS; i++) {
@ -80,7 +67,7 @@ procfs_dorlimit(curp, p, pfs, uio)
* Add the rlimit ident * Add the rlimit ident
*/ */
ps += sprintf(ps, "%s ", rlimit_ident[i]); sbuf_printf(sb, "%s ", rlimit_ident[i]);
/* /*
* Replace RLIM_INFINITY with -1 in the string * Replace RLIM_INFINITY with -1 in the string
@ -91,9 +78,9 @@ procfs_dorlimit(curp, p, pfs, uio)
*/ */
if (p->p_rlimit[i].rlim_cur == RLIM_INFINITY) { if (p->p_rlimit[i].rlim_cur == RLIM_INFINITY) {
ps += sprintf(ps, "-1 "); sbuf_printf(sb, "-1 ");
} else { } else {
ps += sprintf(ps, "%llu ", sbuf_printf(sb, "%llu ",
(unsigned long long)p->p_rlimit[i].rlim_cur); (unsigned long long)p->p_rlimit[i].rlim_cur);
} }
@ -102,27 +89,13 @@ procfs_dorlimit(curp, p, pfs, uio)
*/ */
if (p->p_rlimit[i].rlim_max == RLIM_INFINITY) { if (p->p_rlimit[i].rlim_max == RLIM_INFINITY) {
ps += sprintf(ps, "-1\n"); sbuf_printf(sb, "-1\n");
} else { } else {
ps += sprintf(ps, "%llu\n", sbuf_printf(sb, "%llu\n",
(unsigned long long)p->p_rlimit[i].rlim_max); (unsigned long long)p->p_rlimit[i].rlim_max);
} }
} }
/* return (0);
* This logic is rather tasty - but its from procfs_status.c, so
* I guess I'll use it here.
*/
xlen = ps - psbuf;
xlen -= uio->uio_offset;
ps = psbuf + uio->uio_offset;
xlen = imin(xlen, uio->uio_resid);
if (xlen <= 0)
error = 0;
else
error = uiomove(ps, xlen, uio);
return (error);
} }

View File

@ -49,36 +49,26 @@
#include <sys/malloc.h> #include <sys/malloc.h>
#include <sys/proc.h> #include <sys/proc.h>
#include <sys/resourcevar.h> #include <sys/resourcevar.h>
#include <sys/sbuf.h>
#include <sys/tty.h> #include <sys/tty.h>
#include <sys/vnode.h>
#include <vm/vm.h> #include <vm/vm.h>
#include <vm/pmap.h> #include <vm/pmap.h>
#include <vm/vm_param.h> #include <vm/vm_param.h>
#include <fs/pseudofs/pseudofs.h>
#include <fs/procfs/procfs.h> #include <fs/procfs/procfs.h>
#define DOCHECK() do { if (ps >= psbuf+sizeof(psbuf)) goto bailout; } while (0)
int int
procfs_dostatus(curp, p, pfs, uio) procfs_doprocstatus(PFS_FILL_ARGS)
struct proc *curp;
struct proc *p;
struct pfsnode *pfs;
struct uio *uio;
{ {
struct session *sess; struct session *sess;
struct tty *tp; struct tty *tp;
struct ucred *cr; struct ucred *cr;
char *ps, *pc; char *pc;
char *sep; char *sep;
int pid, ppid, pgid, sid; int pid, ppid, pgid, sid;
int i; int i;
int xlen;
int error;
char psbuf[256]; /* XXX - conservative */
if (uio->uio_rw != UIO_READ)
return (EOPNOTSUPP);
pid = p->p_pid; pid = p->p_pid;
PROC_LOCK(p); PROC_LOCK(p);
@ -91,45 +81,31 @@ procfs_dostatus(curp, p, pfs, uio)
/* comm pid ppid pgid sid maj,min ctty,sldr start ut st wmsg /* comm pid ppid pgid sid maj,min ctty,sldr start ut st wmsg
euid ruid rgid,egid,groups[1 .. NGROUPS] euid ruid rgid,egid,groups[1 .. NGROUPS]
*/ */
KASSERT(sizeof(psbuf) > MAXCOMLEN,
("Too short buffer for new MAXCOMLEN"));
ps = psbuf;
pc = p->p_comm; pc = p->p_comm;
xlen = strlen(p->p_comm);
do { do {
if (*pc < 33 || *pc > 126 || *pc == '\\') if (*pc < 33 || *pc > 126 || *pc == '\\')
ps += snprintf(ps, psbuf + sizeof(psbuf) - ps, "\\%03o", sbuf_printf(sb, "\\%03o", *pc);
*pc);
else else
*ps++ = *pc; sbuf_putc(sb, *pc);
DOCHECK(); } while (*++pc);
} while (++pc < p->p_comm + xlen); sbuf_printf(sb, " %d %d %d %d ", pid, ppid, pgid, sid);
ps += snprintf(ps, psbuf + sizeof(psbuf) - ps,
" %d %d %d %d ", pid, ppid, pgid, sid);
DOCHECK();
if ((p->p_flag&P_CONTROLT) && (tp = sess->s_ttyp)) if ((p->p_flag&P_CONTROLT) && (tp = sess->s_ttyp))
ps += snprintf(ps, psbuf + sizeof(psbuf) - ps, sbuf_printf(sb, "%d,%d ", major(tp->t_dev), minor(tp->t_dev));
"%d,%d ", major(tp->t_dev), minor(tp->t_dev));
else else
ps += snprintf(ps, psbuf + sizeof(psbuf) - ps, sbuf_printf(sb, "%d,%d ", -1, -1);
"%d,%d ", -1, -1);
DOCHECK();
sep = ""; sep = "";
if (sess->s_ttyvp) { if (sess->s_ttyvp) {
ps += snprintf(ps, psbuf + sizeof(psbuf) - ps, "%sctty", sep); sbuf_printf(sb, "%sctty", sep);
sep = ","; sep = ",";
DOCHECK();
} }
if (SESS_LEADER(p)) { if (SESS_LEADER(p)) {
ps += snprintf(ps, psbuf + sizeof(psbuf) - ps, "%ssldr", sep); sbuf_printf(sb, "%ssldr", sep);
sep = ","; sep = ",";
DOCHECK();
} }
if (*sep != ',') { if (*sep != ',') {
ps += snprintf(ps, psbuf + sizeof(psbuf) - ps, "noflags"); sbuf_printf(sb, "noflags");
DOCHECK();
} }
mtx_lock_spin(&sched_lock); mtx_lock_spin(&sched_lock);
@ -138,92 +114,56 @@ procfs_dostatus(curp, p, pfs, uio)
calcru(p, &ut, &st, (struct timeval *) NULL); calcru(p, &ut, &st, (struct timeval *) NULL);
mtx_unlock_spin(&sched_lock); mtx_unlock_spin(&sched_lock);
ps += snprintf(ps, psbuf + sizeof(psbuf) - ps, sbuf_printf(sb, " %lld,%ld %ld,%ld %ld,%ld",
" %lld,%ld %ld,%ld %ld,%ld",
(long long)p->p_stats->p_start.tv_sec, (long long)p->p_stats->p_start.tv_sec,
p->p_stats->p_start.tv_usec, p->p_stats->p_start.tv_usec,
(long)ut.tv_sec, ut.tv_usec, ut.tv_sec, ut.tv_usec,
(long)st.tv_sec, st.tv_usec); st.tv_sec, st.tv_usec);
} else { } else {
mtx_unlock_spin(&sched_lock); mtx_unlock_spin(&sched_lock);
ps += snprintf(ps, psbuf + sizeof(psbuf) - ps, sbuf_printf(sb, " -1,-1 -1,-1 -1,-1");
" -1,-1 -1,-1 -1,-1");
} }
DOCHECK();
if (p->p_flag & P_KSES) { if (p->p_flag & P_KSES) {
ps += snprintf(ps, psbuf + sizeof(psbuf) - ps, " %s", sbuf_printf(sb, " %s", "-kse- ");
"-kse- ");
} else { } else {
ps += snprintf(ps, psbuf + sizeof(psbuf) - ps, " %s", sbuf_printf(sb, " %s",
(p->p_thread.td_wchan && p->p_thread.td_wmesg) ? (p->p_thread.td_wchan && p->p_thread.td_wmesg) ?
p->p_thread.td_wmesg : "nochan"); p->p_thread.td_wmesg : "nochan");
} }
DOCHECK();
cr = p->p_ucred; cr = p->p_ucred;
ps += snprintf(ps, psbuf + sizeof(psbuf) - ps, " %lu %lu %lu", sbuf_printf(sb, " %lu %lu %lu",
(u_long)cr->cr_uid, (u_long)cr->cr_uid,
(u_long)cr->cr_ruid, (u_long)cr->cr_ruid,
(u_long)cr->cr_rgid); (u_long)cr->cr_rgid);
DOCHECK();
/* egid (cr->cr_svgid) is equal to cr_ngroups[0] /* egid (cr->cr_svgid) is equal to cr_ngroups[0]
see also getegid(2) in /sys/kern/kern_prot.c */ see also getegid(2) in /sys/kern/kern_prot.c */
for (i = 0; i < cr->cr_ngroups; i++) { for (i = 0; i < cr->cr_ngroups; i++) {
ps += snprintf(ps, psbuf + sizeof(psbuf) - ps, sbuf_printf(sb, ",%lu", (u_long)cr->cr_groups[i]);
",%lu", (u_long)cr->cr_groups[i]);
DOCHECK();
} }
if (jailed(p->p_ucred)) { if (jailed(p->p_ucred)) {
mtx_lock(&p->p_ucred->cr_prison->pr_mtx); mtx_lock(&p->p_ucred->cr_prison->pr_mtx);
ps += snprintf(ps, psbuf + sizeof(psbuf) - ps, sbuf_printf(sb, " %s", p->p_ucred->cr_prison->pr_host);
" %s", p->p_ucred->cr_prison->pr_host);
mtx_unlock(&p->p_ucred->cr_prison->pr_mtx); mtx_unlock(&p->p_ucred->cr_prison->pr_mtx);
} else { } else {
ps += snprintf(ps, psbuf + sizeof(psbuf) - ps, " -"); sbuf_printf(sb, " -");
} }
DOCHECK(); sbuf_printf(sb, "\n");
ps += snprintf(ps, psbuf + sizeof(psbuf) - ps, "\n");
DOCHECK();
xlen = ps - psbuf; return (0);
xlen -= uio->uio_offset;
ps = psbuf + uio->uio_offset;
xlen = imin(xlen, uio->uio_resid);
if (xlen <= 0)
error = 0;
else
error = uiomove(ps, xlen, uio);
return (error);
bailout:
return (ENOMEM);
} }
int int
procfs_docmdline(curp, p, pfs, uio) procfs_doproccmdline(PFS_FILL_ARGS)
struct proc *curp;
struct proc *p;
struct pfsnode *pfs;
struct uio *uio;
{ {
char *ps;
int xlen;
int error;
char *buf, *bp;
int buflen;
struct ps_strings pstr; struct ps_strings pstr;
int i; int error, i;
size_t bytes_left, done;
if (uio->uio_rw != UIO_READ)
return (EOPNOTSUPP);
/* /*
* If we are using the ps/cmdline caching, use that. Otherwise * If we are using the ps/cmdline caching, use that. Otherwise
* revert back to the old way which only implements full cmdline * revert back to the old way which only implements full cmdline
@ -234,47 +174,19 @@ procfs_docmdline(curp, p, pfs, uio)
* Linux behaviour is to return zero-length in this case. * Linux behaviour is to return zero-length in this case.
*/ */
if (p->p_args && (ps_argsopen || !p_cansee(curp, p))) { if (p->p_args && (ps_argsopen || !p_cansee(td->td_proc, p))) {
bp = p->p_args->ar_args; sbuf_bcpy(sb, p->p_args->ar_args, p->p_args->ar_length);
buflen = p->p_args->ar_length; } else if (p != td->td_proc) {
buf = 0; sbuf_printf(sb, "%.*s", MAXCOMLEN, p->p_comm);
} else if (p != curp) {
bp = p->p_comm;
buflen = MAXCOMLEN;
buf = 0;
} else { } else {
buflen = 256;
MALLOC(buf, char *, buflen + 1, M_TEMP, M_WAITOK);
bp = buf;
ps = buf;
error = copyin((void*)PS_STRINGS, &pstr, sizeof(pstr)); error = copyin((void*)PS_STRINGS, &pstr, sizeof(pstr));
if (error) { if (error)
FREE(buf, M_TEMP);
return (error); return (error);
for (i = 0; i < pstr.ps_nargvstr; i++) {
sbuf_copyin(sb, pstr.ps_argvstr[i], 0);
sbuf_printf(sb, "%c", '\0');
} }
bytes_left = buflen;
for (i = 0; bytes_left && (i < pstr.ps_nargvstr); i++) {
error = copyinstr(pstr.ps_argvstr[i], ps,
bytes_left, &done);
/* If too long or malformed, just truncate */
if (error) {
error = 0;
break;
}
ps += done;
bytes_left -= done;
}
buflen = ps - buf;
} }
buflen -= uio->uio_offset; return (0);
ps = bp + uio->uio_offset;
xlen = min(buflen, uio->uio_resid);
if (xlen <= 0)
error = 0;
else
error = uiomove(ps, xlen, uio);
if (buf)
FREE(buf, M_TEMP);
return (error);
} }

View File

@ -1,413 +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.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 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_subr.c 8.6 (Berkeley) 5/14/95
*
* $FreeBSD$
*/
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/lock.h>
#include <sys/malloc.h>
#include <sys/mount.h>
#include <sys/mutex.h>
#include <sys/proc.h>
#include <sys/socket.h>
#include <sys/sysctl.h>
#include <sys/vnode.h>
#include <fs/procfs/procfs.h>
static struct pfsnode *pfshead;
static int pfsvplock;
/*
* allocate a pfsnode/vnode pair. the vnode is
* referenced, but not locked.
*
* the pid, pfs_type, and mount point uniquely
* identify a pfsnode. the mount point is needed
* because someone might mount this filesystem
* twice.
*
* all pfsnodes are maintained on a singly-linked
* list. new nodes are only allocated when they cannot
* be found on this list. entries on the list are
* removed when the vfs reclaim entry is called.
*
* a single lock is kept for the entire list. this is
* needed because the getnewvnode() function can block
* waiting for a vnode to become free, in which case there
* may be more than one process trying to get the same
* vnode. this lock is only taken if we are going to
* call getnewvnode, since the kernel itself is single-threaded.
*
* if an entry is found on the list, then call vget() to
* take a reference. this is done because there may be
* zero references to it and so it needs to removed from
* the vnode free list.
*/
int
procfs_allocvp(mp, vpp, pid, pfs_type)
struct mount *mp;
struct vnode **vpp;
long pid;
pfstype pfs_type;
{
struct thread *td = curthread; /* XXX */
struct pfsnode *pfs;
struct vnode *vp;
struct pfsnode **pp;
int error;
loop:
for (pfs = pfshead; pfs != 0; pfs = pfs->pfs_next) {
vp = PFSTOV(pfs);
if (pfs->pfs_pid == pid &&
pfs->pfs_type == pfs_type &&
vp->v_mount == mp) {
if (vget(vp, 0, td))
goto loop;
*vpp = vp;
return (0);
}
}
/*
* otherwise lock the vp list while we call getnewvnode
* since that can block.
*/
if (pfsvplock & PROCFS_LOCKED) {
pfsvplock |= PROCFS_WANT;
(void) tsleep((caddr_t) &pfsvplock, PINOD, "pfsavp", 0);
goto loop;
}
pfsvplock |= PROCFS_LOCKED;
/*
* Do the MALLOC before the getnewvnode since doing so afterward
* might cause a bogus v_data pointer to get dereferenced
* elsewhere if MALLOC should block.
*/
MALLOC(pfs, struct pfsnode *, sizeof(struct pfsnode), M_TEMP, M_WAITOK);
if ((error = getnewvnode(VT_PROCFS, mp, procfs_vnodeop_p, vpp)) != 0) {
FREE(pfs, M_TEMP);
goto out;
}
vp = *vpp;
vp->v_data = pfs;
pfs->pfs_next = 0;
pfs->pfs_pid = (pid_t) pid;
pfs->pfs_type = pfs_type;
pfs->pfs_vnode = vp;
pfs->pfs_flags = 0;
pfs->pfs_lockowner = 0;
pfs->pfs_fileno = PROCFS_FILENO(pid, pfs_type);
switch (pfs_type) {
case Proot: /* /proc = dr-xr-xr-x */
pfs->pfs_mode = (VREAD|VEXEC) |
(VREAD|VEXEC) >> 3 |
(VREAD|VEXEC) >> 6;
vp->v_type = VDIR;
vp->v_flag = VROOT;
break;
case Pcurproc: /* /proc/curproc = lr--r--r-- */
pfs->pfs_mode = (VREAD) |
(VREAD >> 3) |
(VREAD >> 6);
vp->v_type = VLNK;
break;
case Pproc:
pfs->pfs_mode = (VREAD|VEXEC) |
(VREAD|VEXEC) >> 3 |
(VREAD|VEXEC) >> 6;
vp->v_type = VDIR;
break;
case Pfile:
pfs->pfs_mode = (VREAD|VEXEC) |
(VREAD|VEXEC) >> 3 |
(VREAD|VEXEC) >> 6;
vp->v_type = VLNK;
break;
case Pmem:
pfs->pfs_mode = (VREAD|VWRITE);
vp->v_type = VREG;
break;
case Pregs:
case Pfpregs:
case Pdbregs:
pfs->pfs_mode = (VREAD|VWRITE);
vp->v_type = VREG;
break;
case Pctl:
case Pnote:
case Pnotepg:
pfs->pfs_mode = (VWRITE);
vp->v_type = VREG;
break;
case Ptype:
case Pmap:
case Pstatus:
case Pcmdline:
case Prlimit:
pfs->pfs_mode = (VREAD) |
(VREAD >> 3) |
(VREAD >> 6);
vp->v_type = VREG;
break;
default:
panic("procfs_allocvp");
}
/* add to procfs vnode list */
for (pp = &pfshead; *pp; pp = &(*pp)->pfs_next)
continue;
*pp = pfs;
out:
pfsvplock &= ~PROCFS_LOCKED;
if (pfsvplock & PROCFS_WANT) {
pfsvplock &= ~PROCFS_WANT;
wakeup((caddr_t) &pfsvplock);
}
return (error);
}
int
procfs_freevp(vp)
struct vnode *vp;
{
struct pfsnode **pfspp;
struct pfsnode *pfs = VTOPFS(vp);
for (pfspp = &pfshead; *pfspp != 0; pfspp = &(*pfspp)->pfs_next) {
if (*pfspp == pfs) {
*pfspp = pfs->pfs_next;
break;
}
}
FREE(vp->v_data, M_TEMP);
vp->v_data = 0;
return (0);
}
int
procfs_rw(ap)
struct vop_read_args *ap;
{
struct vnode *vp = ap->a_vp;
struct uio *uio = ap->a_uio;
struct proc *curp = uio->uio_td->td_proc;
struct pfsnode *pfs = VTOPFS(vp);
struct proc *p;
int rtval;
p = PFIND(pfs->pfs_pid);
if (p == NULL)
return (EINVAL);
PROC_UNLOCK(p);
mp_fixme("pfs_lockowner needs a lock");
while (pfs->pfs_lockowner) {
tsleep(&pfs->pfs_lockowner, PRIBIO, "pfslck", 0);
}
pfs->pfs_lockowner = curproc->p_pid;
switch (pfs->pfs_type) {
case Pnote:
case Pnotepg:
rtval = procfs_donote(curp, p, pfs, uio);
break;
case Pregs:
rtval = procfs_doregs(curp, p, pfs, uio);
break;
case Pfpregs:
rtval = procfs_dofpregs(curp, p, pfs, uio);
break;
case Pdbregs:
rtval = procfs_dodbregs(curp, p, pfs, uio);
break;
case Pctl:
rtval = procfs_doctl(curp, p, pfs, uio);
break;
case Pstatus:
rtval = procfs_dostatus(curp, p, pfs, uio);
break;
case Pmap:
rtval = procfs_domap(curp, p, pfs, uio);
break;
case Pmem:
rtval = procfs_domem(curp, p, pfs, uio);
break;
case Ptype:
rtval = procfs_dotype(curp, p, pfs, uio);
break;
case Pcmdline:
rtval = procfs_docmdline(curp, p, pfs, uio);
break;
case Prlimit:
rtval = procfs_dorlimit(curp, p, pfs, uio);
break;
default:
rtval = EOPNOTSUPP;
break;
}
pfs->pfs_lockowner = 0;
wakeup(&pfs->pfs_lockowner);
return rtval;
}
/*
* Get a string from userland into (buf). Strip a trailing
* nl character (to allow easy access from the shell).
* The buffer should be *buflenp + 1 chars long. vfs_getuserstr
* will automatically add a nul char at the end.
*
* Returns 0 on success or the following errors
*
* EINVAL: file offset is non-zero.
* EMSGSIZE: message is longer than kernel buffer
* EFAULT: user i/o buffer is not addressable
*/
int
vfs_getuserstr(uio, buf, buflenp)
struct uio *uio;
char *buf;
int *buflenp;
{
int xlen;
int error;
if (uio->uio_offset != 0)
return (EINVAL);
xlen = *buflenp;
/* must be able to read the whole string in one go */
if (xlen < uio->uio_resid)
return (EMSGSIZE);
xlen = uio->uio_resid;
if ((error = uiomove(buf, xlen, uio)) != 0)
return (error);
/* allow multiple writes without seeks */
uio->uio_offset = 0;
/* cleanup string and remove trailing newline */
buf[xlen] = '\0';
xlen = strlen(buf);
if (xlen > 0 && buf[xlen-1] == '\n')
buf[--xlen] = '\0';
*buflenp = xlen;
return (0);
}
vfs_namemap_t *
vfs_findname(nm, buf, buflen)
vfs_namemap_t *nm;
char *buf;
int buflen;
{
for (; nm->nm_name; nm++)
if (bcmp(buf, nm->nm_name, buflen+1) == 0)
return (nm);
return (0);
}
void
procfs_exit(struct proc *p)
{
struct pfsnode *pfs;
pid_t pid = p->p_pid;
/*
* The reason for this loop is not obvious -- basicly,
* procfs_freevp(), which is called via vgone() (eventually),
* removes the specified procfs node from the pfshead list.
* It does this by *pfsp = pfs->pfs_next, meaning that it
* overwrites the node. So when we do pfs = pfs->next, we
* end up skipping the node that replaces the one that was
* vgone'd. Since it may have been the last one on the list,
* it may also have been set to null -- but *our* pfs pointer,
* here, doesn't see this. So the loop starts from the beginning
* again.
*
* This is not a for() loop because the final event
* would be "pfs = pfs->pfs_next"; in the case where
* pfs is set to pfshead again, that would mean that
* pfshead is skipped over.
*
*/
pfs = pfshead;
while (pfs) {
if (pfs->pfs_pid == pid) {
vgone(PFSTOV(pfs));
pfs = pfshead;
} else
pfs = pfs->pfs_next;
}
}

View File

@ -40,45 +40,22 @@
#include <sys/param.h> #include <sys/param.h>
#include <sys/systm.h> #include <sys/systm.h>
#include <sys/proc.h> #include <sys/proc.h>
#include <sys/sbuf.h>
#include <sys/sysent.h> #include <sys/sysent.h>
#include <sys/vnode.h>
#include <fs/pseudofs/pseudofs.h>
#include <fs/procfs/procfs.h> #include <fs/procfs/procfs.h>
int int
procfs_dotype(curp, p, pfs, uio) procfs_doproctype(PFS_FILL_ARGS)
struct proc *curp;
struct proc *p;
struct pfsnode *pfs;
struct uio *uio;
{ {
int len; static const char *none = "Not Available";
int error;
/*
* buffer for emulation type
*/
char mebuffer[256];
char *none = "Not Available";
if (uio->uio_rw != UIO_READ)
return (EOPNOTSUPP);
if (uio->uio_offset != 0)
return (0);
if (p && p->p_sysent && p->p_sysent->sv_name) { if (p && p->p_sysent && p->p_sysent->sv_name) {
len = strlen(p->p_sysent->sv_name); sbuf_printf(sb, p->p_sysent->sv_name);
bcopy(p->p_sysent->sv_name, mebuffer, len);
} else { } else {
len = strlen(none); sbuf_printf(sb, none);
bcopy(none, mebuffer, len);
} }
mebuffer[len++] = '\n'; sbuf_putc(sb, '\n');
error = uiomove(mebuffer, len, uio); return (0);
return error;
}
int
procfs_validtype(struct thread *td)
{
return ((td->td_proc->p_flag & P_SYSTEM) == 0);
} }

View File

@ -1,177 +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.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 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_vfsops.c 8.7 (Berkeley) 5/10/95
*
* $FreeBSD$
*/
/*
* procfs VFS interface
*/
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/proc.h>
#include <sys/mount.h>
#include <sys/vnode.h>
#include <fs/procfs/procfs.h>
static int procfs_mount __P((struct mount *mp, char *path, caddr_t data,
struct nameidata *ndp, struct thread *td));
static int procfs_statfs __P((struct mount *mp, struct statfs *sbp,
struct thread *td));
static int procfs_unmount __P((struct mount *mp, int mntflags,
struct thread *td));
/*
* VFS Operations.
*
* mount system call
*/
/* ARGSUSED */
static int
procfs_mount(mp, path, data, ndp, td)
struct mount *mp;
char *path;
caddr_t data;
struct nameidata *ndp;
struct thread *td;
{
size_t size;
int error;
if (mp->mnt_flag & MNT_UPDATE)
return (EOPNOTSUPP);
if (mp->mnt_vfc->vfc_refcount == 1 && (error = at_exit(procfs_exit))) {
printf("procfs: cannot register procfs_exit with at_exit\n");
return(error);
}
mp->mnt_flag |= MNT_LOCAL;
mp->mnt_data = 0;
vfs_getnewfsid(mp);
size = sizeof("procfs") - 1;
bcopy("procfs", mp->mnt_stat.f_mntfromname, size);
bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size);
(void)procfs_statfs(mp, &mp->mnt_stat, td);
return (0);
}
/*
* unmount system call
*/
static int
procfs_unmount(mp, mntflags, td)
struct mount *mp;
int mntflags;
struct thread *td;
{
int error;
int flags = 0;
if (mntflags & MNT_FORCE)
flags |= FORCECLOSE;
error = vflush(mp, 0, flags);
if (error)
return (error);
if (mp->mnt_vfc->vfc_refcount == 1)
rm_at_exit(procfs_exit);
return (0);
}
int
procfs_root(mp, vpp)
struct mount *mp;
struct vnode **vpp;
{
return (procfs_allocvp(mp, vpp, 0, Proot));
}
/*
* Get file system statistics.
*/
static int
procfs_statfs(mp, sbp, td)
struct mount *mp;
struct statfs *sbp;
struct thread *td;
{
sbp->f_bsize = PAGE_SIZE;
sbp->f_iosize = PAGE_SIZE;
sbp->f_blocks = 1; /* avoid divide by zero in some df's */
sbp->f_bfree = 0;
sbp->f_bavail = 0;
sbp->f_files = maxproc; /* approx */
sbp->f_ffree = maxproc - nprocs; /* approx */
if (sbp != &mp->mnt_stat) {
sbp->f_type = mp->mnt_vfc->vfc_typenum;
bcopy(&mp->mnt_stat.f_fsid, &sbp->f_fsid, sizeof(sbp->f_fsid));
bcopy(mp->mnt_stat.f_mntonname, sbp->f_mntonname, MNAMELEN);
bcopy(mp->mnt_stat.f_mntfromname, sbp->f_mntfromname, MNAMELEN);
}
return (0);
}
static struct vfsops procfs_vfsops = {
procfs_mount,
vfs_stdstart,
procfs_unmount,
procfs_root,
vfs_stdquotactl,
procfs_statfs,
vfs_stdsync,
vfs_stdvget,
vfs_stdfhtovp,
vfs_stdcheckexp,
vfs_stdvptofh,
vfs_stdinit,
vfs_stduninit,
vfs_stdextattrctl,
};
VFS_SET(procfs_vfsops, procfs, VFCF_SYNTHETIC);
MODULE_VERSION(procfs, 1);

File diff suppressed because it is too large Load Diff

View File

@ -68,7 +68,6 @@ SUBDIR= 3dfx \
ppbus \ ppbus \
ppi \ ppi \
pps \ pps \
procfs \
${_random} \ ${_random} \
rl \ rl \
rp \ rp \

View File

@ -2,6 +2,7 @@
SUBDIR = SUBDIR =
SUBDIR += linprocfs SUBDIR += linprocfs
SUBDIR += procfs
SUBDIR += pseudofs SUBDIR += pseudofs
.include <bsd.subdir.mk> .include <bsd.subdir.mk>

View File

@ -1,22 +1,20 @@
# $FreeBSD$ # $FreeBSD$
.PATH: ${.CURDIR}/../../fs/procfs .PATH: ${.CURDIR}/../../../fs/procfs
KMOD= procfs KMOD= procfs
SRCS= vnode_if.h \ SRCS= vnode_if.h \
procfs_ctl.c \ procfs_ctl.c \
procfs_dbregs.c \ procfs_dbregs.c \
procfs_fpregs.c \ procfs_fpregs.c \
procfs_ioctl.c \
procfs_map.c \ procfs_map.c \
procfs_mem.c \ procfs_mem.c \
procfs_note.c \ procfs_note.c \
procfs_regs.c \ procfs_regs.c \
procfs_rlimit.c \ procfs_rlimit.c \
procfs_status.c \ procfs_status.c \
procfs_subr.c \
procfs_type.c \ procfs_type.c \
procfs_vfsops.c \ procfs.c
procfs_vnops.c
NOMAN=
.include <bsd.kmod.mk> .include <bsd.kmod.mk>