diff options
author | msmith <msmith@FreeBSD.org> | 2000-04-20 03:56:10 +0000 |
---|---|---|
committer | msmith <msmith@FreeBSD.org> | 2000-04-20 03:56:10 +0000 |
commit | 7424a3b87e9b1e63f9137e3501edec1ac4eb30a3 (patch) | |
tree | 0fc9e71c720764ccf3d3693113e553e85d73c234 /sys/miscfs | |
parent | 7c8ba198e8d40701fb8c437dfb2e351cd3541298 (diff) | |
download | FreeBSD-src-7424a3b87e9b1e63f9137e3501edec1ac4eb30a3.zip FreeBSD-src-7424a3b87e9b1e63f9137e3501edec1ac4eb30a3.tar.gz |
Remove the linprocfs bits from their old location, as they've moved now.
Diffstat (limited to 'sys/miscfs')
-rw-r--r-- | sys/miscfs/linprocfs/linprocfs.h | 135 | ||||
-rw-r--r-- | sys/miscfs/linprocfs/linprocfs_misc.c | 202 | ||||
-rw-r--r-- | sys/miscfs/linprocfs/linprocfs_subr.c | 353 | ||||
-rw-r--r-- | sys/miscfs/linprocfs/linprocfs_vfsops.c | 178 | ||||
-rw-r--r-- | sys/miscfs/linprocfs/linprocfs_vnops.c | 994 |
5 files changed, 0 insertions, 1862 deletions
diff --git a/sys/miscfs/linprocfs/linprocfs.h b/sys/miscfs/linprocfs/linprocfs.h deleted file mode 100644 index e7f70bc..0000000 --- a/sys/miscfs/linprocfs/linprocfs.h +++ /dev/null @@ -1,135 +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.h 8.9 (Berkeley) 5/14/95 - * - * $FreeBSD$ - */ - -/* - * The different types of node in a procfs filesystem - */ -typedef enum { - Proot, /* the filesystem root */ - Pself, /* symbolic link for curproc */ - Pproc, /* a process-specific sub-directory */ - Pexe, /* the executable file */ - Pmem, /* the process's memory image */ - Pmeminfo, - Pcpuinfo -} 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_NAMELEN 8 /* max length of a filename component */ - -/* - * Kernel stuff follows - */ -#ifdef _KERNEL -#define CNEQ(cnp, s, len) \ - ((cnp)->cn_namelen == (len) && \ - (bcmp((s), (cnp)->cn_nameptr, (len)) == 0)) - -#define KMEM_GROUP 2 - -#define PROCFS_FILENO(pid, type) \ - (((type) < Pproc) ? \ - ((type) + 2) : \ - ((((pid)+1) << 4) + ((int) (type)))) - -/* - * Convert between pfsnode vnode - */ -#define VTOPFS(vp) ((struct pfsnode *)(vp)->v_data) -#define PFSTOV(pfs) ((pfs)->pfs_vnode) - -typedef struct vfs_namemap vfs_namemap_t; -struct vfs_namemap { - const char *nm_name; - int nm_val; -}; - -int vfs_getuserstr __P((struct uio *, char *, int *)); -vfs_namemap_t *vfs_findname __P((vfs_namemap_t *, char *, int)); - -/* <machine/reg.h> */ -struct reg; -struct fpreg; -struct dbreg; - -#define PFIND(pid) ((pid) ? pfind(pid) : &proc0) - -void linprocfs_exit __P((struct proc *)); -int linprocfs_freevp __P((struct vnode *)); -int linprocfs_allocvp __P((struct mount *, struct vnode **, long, pfstype)); -struct vnode *linprocfs_findtextvp __P((struct proc *)); -int linprocfs_sstep __P((struct proc *)); -void linprocfs_fix_sstep __P((struct proc *)); -#if 0 -int linprocfs_read_regs __P((struct proc *, struct reg *)); -int linprocfs_write_regs __P((struct proc *, struct reg *)); -int linprocfs_read_fpregs __P((struct proc *, struct fpreg *)); -int linprocfs_write_fpregs __P((struct proc *, struct fpreg *)); -int linprocfs_read_dbregs __P((struct proc *, struct dbreg *)); -int linprocfs_write_dbregs __P((struct proc *, struct dbreg *)); -#endif -int linprocfs_domeminfo __P((struct proc *, struct proc *, struct pfsnode *pfsp, struct uio *uio)); -int linprocfs_docpuinfo __P((struct proc *, struct proc *, struct pfsnode *pfsp, struct uio *uio)); - -/* functions to check whether or not files should be displayed */ -int linprocfs_validfile __P((struct proc *)); - -#define PROCFS_LOCKED 0x01 -#define PROCFS_WANT 0x02 - -extern vop_t **linprocfs_vnodeop_p; - -int linprocfs_root __P((struct mount *, struct vnode **)); -int linprocfs_rw __P((struct vop_read_args *)); -#endif /* _KERNEL */ diff --git a/sys/miscfs/linprocfs/linprocfs_misc.c b/sys/miscfs/linprocfs/linprocfs_misc.c deleted file mode 100644 index ab94415..0000000 --- a/sys/miscfs/linprocfs/linprocfs_misc.c +++ /dev/null @@ -1,202 +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_status.c 8.4 (Berkeley) 6/15/94 - * - * $FreeBSD$ - */ - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/proc.h> -#include <sys/jail.h> -#include <sys/vnode.h> -#include <sys/blist.h> -#include <sys/tty.h> -#include <sys/resourcevar.h> -#include <miscfs/linprocfs/linprocfs.h> - -#include <vm/vm.h> -#include <vm/pmap.h> -#include <vm/vm_param.h> -#include <vm/swap_pager.h> -#include <sys/vmmeter.h> -#include <sys/exec.h> - -#include <machine/md_var.h> -#include <machine/cputypes.h> - -struct proc; - -int -linprocfs_domeminfo(curp, p, pfs, uio) - struct proc *curp; - struct proc *p; - struct pfsnode *pfs; - struct uio *uio; -{ - char *ps; - int xlen; - int error; - char psbuf[512]; /* XXX - conservative */ - unsigned long memtotal; /* total memory in bytes */ - unsigned long memused; /* used memory in bytes */ - unsigned long memfree; /* free memory in bytes */ - unsigned long memshared; /* shared memory ??? */ - unsigned long buffers, cached; /* buffer / cache memory ??? */ - unsigned long swaptotal; /* total swap space in bytes */ - unsigned long swapused; /* used swap space in bytes */ - unsigned long swapfree; /* free swap space in bytes */ - - if (uio->uio_rw != UIO_READ) - return (EOPNOTSUPP); - - memtotal = physmem * PAGE_SIZE; - /* - * The correct thing here would be: - * - memfree = cnt.v_free_count * PAGE_SIZE; - memused = memtotal - memfree; - * - * but it might mislead linux binaries into thinking there - * is very little memory left, so we cheat and tell them that - * all memory that isn't wired down is free. - */ - memused = cnt.v_wire_count * PAGE_SIZE; - memfree = memtotal - memused; - swaptotal = swapblist->bl_blocks * 1024; /* XXX why 1024? */ - swapfree = swapblist->bl_root->u.bmu_avail * PAGE_SIZE; - swapused = swaptotal - swapfree; - memshared = 0; /* XXX what's this supposed to be? */ - /* - * We'd love to be able to write: - * - buffers = bufspace; - * - * but bufspace is internal to vfs_bio.c and we don't feel - * like unstaticizing it just for linprocfs's sake. - */ - buffers = 0; - cached = cnt.v_cache_count * PAGE_SIZE; - - ps = psbuf; - ps += sprintf(ps, - " total: used: free: shared: buffers: cached:\n" - "Mem: %lu %lu %lu %lu %lu %lu\n" - "Swap: %lu %lu %lu\n" - "MemTotal: %9lu kB\n" - "MemFree: %9lu kB\n" - "MemShared:%9lu kB\n" - "Buffers: %9lu kB\n" - "Cached: %9lu kB\n" - "SwapTotal:%9lu kB\n" - "SwapFree: %9lu kB\n", - memtotal, memused, memfree, memshared, buffers, cached, - swaptotal, swapused, swapfree, - memtotal >> 10, memfree >> 10, - memshared >> 10, buffers >> 10, cached >> 10, - swaptotal >> 10, swapfree >> 10); - - 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); -} - -int -linprocfs_docpuinfo(curp, p, pfs, uio) - struct proc *curp; - struct proc *p; - struct pfsnode *pfs; - struct uio *uio; -{ - char *ps; - int xlen; - int error; - char psbuf[512]; /* XXX - conservative */ - char *class; -#if 0 - extern char *cpu_model; /* Yuck */ -#endif - - if (uio->uio_rw != UIO_READ) - return (EOPNOTSUPP); - - switch (cpu_class) { - case CPUCLASS_286: - class = "286"; - break; - case CPUCLASS_386: - class = "386"; - break; - case CPUCLASS_486: - class = "486"; - break; - case CPUCLASS_586: - class = "586"; - break; - case CPUCLASS_686: - class = "686"; - break; - default: - class = "unknown"; - break; - } - - ps = psbuf; - ps += sprintf(ps, - "processor : %d\n" - "cpu : %.3s\n" - "model : %.20s\n" - "vendor_id : %.20s\n" - "stepping : %d\n", - 0, class, "unknown", cpu_vendor, cpu_id); - - 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); -} diff --git a/sys/miscfs/linprocfs/linprocfs_subr.c b/sys/miscfs/linprocfs/linprocfs_subr.c deleted file mode 100644 index 7944eeb..0000000 --- a/sys/miscfs/linprocfs/linprocfs_subr.c +++ /dev/null @@ -1,353 +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/proc.h> -#include <sys/vnode.h> -#include <sys/malloc.h> -#include <miscfs/linprocfs/linprocfs.h> - -static struct pfsnode *pfshead; -static int pfsvplock; - -extern int procfs_domem __P((struct proc *, struct proc *, struct pfsnode *pfsp, struct uio *uio)); - -/* - * 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 -linprocfs_allocvp(mp, vpp, pid, pfs_type) - struct mount *mp; - struct vnode **vpp; - long pid; - pfstype pfs_type; -{ - struct proc *p = curproc; /* 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, p)) - 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, linprocfs_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 Pself: /* /proc/self = 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 Pexe: - case Pmem: - pfs->pfs_mode = (VREAD|VWRITE) | - (VREAD) >> 3;; - vp->v_type = VREG; - break; - - case Pmeminfo: - case Pcpuinfo: - pfs->pfs_mode = (VREAD) | - (VREAD >> 3) | - (VREAD >> 6); - vp->v_type = VREG; - break; - - default: - panic("linprocfs_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 -linprocfs_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 -linprocfs_rw(ap) - struct vop_read_args *ap; -{ - struct vnode *vp = ap->a_vp; - struct uio *uio = ap->a_uio; - struct proc *curp = uio->uio_procp; - struct pfsnode *pfs = VTOPFS(vp); - struct proc *p; - int rtval; - - p = PFIND(pfs->pfs_pid); - if (p == 0) - return (EINVAL); - if (p->p_pid == 1 && securelevel > 0 && uio->uio_rw == UIO_WRITE) - return (EACCES); - - while (pfs->pfs_lockowner) { - tsleep(&pfs->pfs_lockowner, PRIBIO, "pfslck", 0); - } - pfs->pfs_lockowner = curproc->p_pid; - - switch (pfs->pfs_type) { - case Pmem: - rtval = procfs_domem(curp, p, pfs, uio); - break; - case Pmeminfo: - rtval = linprocfs_domeminfo(curp, p, pfs, uio); - break; - case Pcpuinfo: - rtval = linprocfs_docpuinfo(curp, p, pfs, uio); - break; - default: - rtval = EOPNOTSUPP; - break; - } - pfs->pfs_lockowner = 0; - wakeup(&pfs->pfs_lockowner); - return rtval; -} - -#if 0 -/* - * 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); -} -#endif - -void -linprocfs_exit(struct proc *p) -{ - struct pfsnode *pfs; - pid_t pid = p->p_pid; - - /* - * The reason for this loop is not obvious -- basicly, - * linprocfs_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; - } -} diff --git a/sys/miscfs/linprocfs/linprocfs_vfsops.c b/sys/miscfs/linprocfs/linprocfs_vfsops.c deleted file mode 100644 index 1132194..0000000 --- a/sys/miscfs/linprocfs/linprocfs_vfsops.c +++ /dev/null @@ -1,178 +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/syslog.h> -#include <sys/mount.h> -#include <sys/vnode.h> -#include <miscfs/linprocfs/linprocfs.h> - -static int linprocfs_mount __P((struct mount *mp, char *path, caddr_t data, - struct nameidata *ndp, struct proc *p)); -static int linprocfs_statfs __P((struct mount *mp, struct statfs *sbp, - struct proc *p)); -static int linprocfs_unmount __P((struct mount *mp, int mntflags, - struct proc *p)); - -/* - * VFS Operations. - * - * mount system call - */ -/* ARGSUSED */ -static int -linprocfs_mount(mp, path, data, ndp, p) - struct mount *mp; - char *path; - caddr_t data; - struct nameidata *ndp; - struct proc *p; -{ - size_t size; - int error; - - if (mp->mnt_flag & MNT_UPDATE) - return (EOPNOTSUPP); - - if (mp->mnt_vfc->vfc_refcount == 1 && (error = at_exit(linprocfs_exit))) { - printf("linprocfs: cannot register linprocfs_exit with at_exit\n"); - return(error); - } - - mp->mnt_flag |= MNT_LOCAL; - mp->mnt_data = 0; - vfs_getnewfsid(mp); - - (void) copyinstr(path, (caddr_t)mp->mnt_stat.f_mntonname, MNAMELEN, &size); - bzero(mp->mnt_stat.f_mntonname + size, MNAMELEN - size); - - size = sizeof("linprocfs") - 1; - bcopy("linprocfs", mp->mnt_stat.f_mntfromname, size); - bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size); - (void)linprocfs_statfs(mp, &mp->mnt_stat, p); - - return (0); -} - -/* - * unmount system call - */ -static int -linprocfs_unmount(mp, mntflags, p) - struct mount *mp; - int mntflags; - struct proc *p; -{ - 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(linprocfs_exit); - - return (0); -} - -int -linprocfs_root(mp, vpp) - struct mount *mp; - struct vnode **vpp; -{ - - return (linprocfs_allocvp(mp, vpp, 0, Proot)); -} - -/* - * Get file system statistics. - */ -static int -linprocfs_statfs(mp, sbp, p) - struct mount *mp; - struct statfs *sbp; - struct proc *p; -{ - 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 linprocfs_vfsops = { - linprocfs_mount, - vfs_stdstart, - linprocfs_unmount, - linprocfs_root, - vfs_stdquotactl, - linprocfs_statfs, - vfs_stdsync, - vfs_stdvget, - vfs_stdfhtovp, - vfs_stdcheckexp, - vfs_stdvptofh, - vfs_stdinit, -}; - -VFS_SET(linprocfs_vfsops, linprocfs, VFCF_SYNTHETIC); diff --git a/sys/miscfs/linprocfs/linprocfs_vnops.c b/sys/miscfs/linprocfs/linprocfs_vnops.c deleted file mode 100644 index 5e9e98a..0000000 --- a/sys/miscfs/linprocfs/linprocfs_vnops.c +++ /dev/null @@ -1,994 +0,0 @@ -/* - * Copyright (c) 1993, 1995 Jan-Simon Pendry - * Copyright (c) 1993, 1995 - * 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_vnops.c 8.18 (Berkeley) 5/21/95 - * - * $FreeBSD$ - */ - -/* - * procfs vnode interface - */ - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/time.h> -#include <sys/kernel.h> -#include <sys/lock.h> -#include <sys/fcntl.h> -#include <sys/proc.h> -#include <sys/signalvar.h> -#include <sys/vnode.h> -#include <sys/mount.h> -#include <sys/namei.h> -#include <sys/dirent.h> -#include <machine/reg.h> -#include <vm/vm_zone.h> -#include <miscfs/linprocfs/linprocfs.h> -#include <sys/pioctl.h> - -extern struct vnode *procfs_findtextvp __P((struct proc *)); -extern int procfs_kmemaccess __P((struct proc *)); - -static int linprocfs_access __P((struct vop_access_args *)); -static int linprocfs_badop __P((void)); -static int linprocfs_bmap __P((struct vop_bmap_args *)); -static int linprocfs_close __P((struct vop_close_args *)); -static int linprocfs_getattr __P((struct vop_getattr_args *)); -static int linprocfs_inactive __P((struct vop_inactive_args *)); -static int linprocfs_ioctl __P((struct vop_ioctl_args *)); -static int linprocfs_lookup __P((struct vop_lookup_args *)); -static int linprocfs_open __P((struct vop_open_args *)); -static int linprocfs_print __P((struct vop_print_args *)); -static int linprocfs_readdir __P((struct vop_readdir_args *)); -static int linprocfs_readlink __P((struct vop_readlink_args *)); -static int linprocfs_reclaim __P((struct vop_reclaim_args *)); -static int linprocfs_setattr __P((struct vop_setattr_args *)); - -/* - * This is a list of the valid names in the - * process-specific sub-directories. It is - * used in linprocfs_lookup and linprocfs_readdir - */ -static struct proc_target { - u_char pt_type; - u_char pt_namlen; - char *pt_name; - pfstype pt_pfstype; - int (*pt_valid) __P((struct proc *p)); -} proc_targets[] = { -#define N(s) sizeof(s)-1, s - /* name type validp */ - { DT_DIR, N("."), Pproc, NULL }, - { DT_DIR, N(".."), Proot, NULL }, - { DT_REG, N("exe"), Pexe, linprocfs_validfile }, - { DT_REG, N("mem"), Pmem, NULL }, -#undef N -}; -static const int nproc_targets = sizeof(proc_targets) / sizeof(proc_targets[0]); - -static pid_t atopid __P((const char *, u_int)); - -/* - * set things up for doing i/o on - * the pfsnode (vp). (vp) is locked - * on entry, and should be left locked - * on exit. - * - * for procfs we don't need to do anything - * in particular for i/o. all that is done - * is to support exclusive open on process - * memory images. - */ -static int -linprocfs_open(ap) - struct vop_open_args /* { - struct vnode *a_vp; - int a_mode; - struct ucred *a_cred; - struct proc *a_p; - } */ *ap; -{ - struct pfsnode *pfs = VTOPFS(ap->a_vp); - struct proc *p1, *p2; - - p2 = PFIND(pfs->pfs_pid); - if (p2 == NULL) - return (ENOENT); - if (pfs->pfs_pid && !PRISON_CHECK(ap->a_p, p2)) - return (ENOENT); - - switch (pfs->pfs_type) { - case Pmem: - if (((pfs->pfs_flags & FWRITE) && (ap->a_mode & O_EXCL)) || - ((pfs->pfs_flags & O_EXCL) && (ap->a_mode & FWRITE))) - return (EBUSY); - - p1 = ap->a_p; - if (p_trespass(p1, p2) && - !procfs_kmemaccess(p1)) - return (EPERM); - - if (ap->a_mode & FWRITE) - pfs->pfs_flags = ap->a_mode & (FWRITE|O_EXCL); - - return (0); - - default: - break; - } - - return (0); -} - -/* - * close the pfsnode (vp) after doing i/o. - * (vp) is not locked on entry or exit. - * - * nothing to do for procfs other than undo - * any exclusive open flag (see _open above). - */ -static int -linprocfs_close(ap) - struct vop_close_args /* { - struct vnode *a_vp; - int a_fflag; - struct ucred *a_cred; - struct proc *a_p; - } */ *ap; -{ - struct pfsnode *pfs = VTOPFS(ap->a_vp); - struct proc *p; - - switch (pfs->pfs_type) { - case Pmem: - if ((ap->a_fflag & FWRITE) && (pfs->pfs_flags & O_EXCL)) - pfs->pfs_flags &= ~(FWRITE|O_EXCL); - /* - * This rather complicated-looking code is trying to - * determine if this was the last close on this particular - * vnode. While one would expect v_usecount to be 1 at - * that point, it seems that (according to John Dyson) - * the VM system will bump up the usecount. So: if the - * usecount is 2, and VOBJBUF is set, then this is really - * the last close. Otherwise, if the usecount is < 2 - * then it is definitely the last close. - * If this is the last close, then it checks to see if - * the target process has PF_LINGER set in p_pfsflags, - * if this is *not* the case, then the process' stop flags - * are cleared, and the process is woken up. This is - * to help prevent the case where a process has been - * told to stop on an event, but then the requesting process - * has gone away or forgotten about it. - */ - if ((ap->a_vp->v_usecount < 2) - && (p = pfind(pfs->pfs_pid)) - && !(p->p_pfsflags & PF_LINGER)) { - p->p_stops = 0; - p->p_step = 0; - wakeup(&p->p_step); - } - break; - default: - break; - } - - return (0); -} - -/* - * do an ioctl operation on a pfsnode (vp). - * (vp) is not locked on entry or exit. - */ -static int -linprocfs_ioctl(ap) - struct vop_ioctl_args *ap; -{ - struct pfsnode *pfs = VTOPFS(ap->a_vp); - struct proc *procp, *p; - int error; - int signo; - struct procfs_status *psp; - unsigned char flags; - - p = ap->a_p; - procp = pfind(pfs->pfs_pid); - if (procp == NULL) { - return ENOTTY; - } - - if (p_trespass(p, procp)) - return EPERM; - - switch (ap->a_command) { - case PIOCBIS: - procp->p_stops |= *(unsigned int*)ap->a_data; - break; - case PIOCBIC: - procp->p_stops &= ~*(unsigned int*)ap->a_data; - break; - case PIOCSFL: - /* - * NFLAGS is "non-suser_xxx flags" -- currently, only - * PFS_ISUGID ("ignore set u/g id"); - */ -#define NFLAGS (PF_ISUGID) - flags = (unsigned char)*(unsigned int*)ap->a_data; - if (flags & NFLAGS && (error = suser(p))) - return error; - procp->p_pfsflags = flags; - break; - case PIOCGFL: - *(unsigned int*)ap->a_data = (unsigned int)procp->p_pfsflags; - case PIOCSTATUS: - psp = (struct procfs_status *)ap->a_data; - psp->state = (procp->p_step == 0); - psp->flags = procp->p_pfsflags; - psp->events = procp->p_stops; - if (procp->p_step) { - psp->why = procp->p_stype; - psp->val = procp->p_xstat; - } else { - psp->why = psp->val = 0; /* Not defined values */ - } - break; - case PIOCWAIT: - psp = (struct procfs_status *)ap->a_data; - if (procp->p_step == 0) { - error = tsleep(&procp->p_stype, PWAIT | PCATCH, "piocwait", 0); - if (error) - return error; - } - psp->state = 1; /* It stopped */ - psp->flags = procp->p_pfsflags; - psp->events = procp->p_stops; - psp->why = procp->p_stype; /* why it stopped */ - psp->val = procp->p_xstat; /* any extra info */ - break; - case PIOCCONT: /* Restart a proc */ - if (procp->p_step == 0) - return EINVAL; /* Can only start a stopped process */ - if ((signo = *(int*)ap->a_data) != 0) { - if (signo >= NSIG || signo <= 0) - return EINVAL; - psignal(procp, signo); - } - procp->p_step = 0; - wakeup(&procp->p_step); - break; - default: - return (ENOTTY); - } - return 0; -} - -/* - * do block mapping for pfsnode (vp). - * since we don't use the buffer cache - * for procfs this function should never - * be called. in any case, it's not clear - * what part of the kernel ever makes use - * of this function. for sanity, this is the - * usual no-op bmap, although returning - * (EIO) would be a reasonable alternative. - */ -static int -linprocfs_bmap(ap) - struct vop_bmap_args /* { - struct vnode *a_vp; - daddr_t a_bn; - struct vnode **a_vpp; - daddr_t *a_bnp; - int *a_runp; - } */ *ap; -{ - - if (ap->a_vpp != NULL) - *ap->a_vpp = ap->a_vp; - if (ap->a_bnp != NULL) - *ap->a_bnp = ap->a_bn; - if (ap->a_runp != NULL) - *ap->a_runp = 0; - return (0); -} - -/* - * linprocfs_inactive is called when the pfsnode - * is vrele'd and the reference count goes - * to zero. (vp) will be on the vnode free - * list, so to get it back vget() must be - * used. - * - * (vp) is locked on entry, but must be unlocked on exit. - */ -static int -linprocfs_inactive(ap) - struct vop_inactive_args /* { - struct vnode *a_vp; - } */ *ap; -{ - struct vnode *vp = ap->a_vp; - - VOP_UNLOCK(vp, 0, ap->a_p); - - return (0); -} - -/* - * _reclaim is called when getnewvnode() - * wants to make use of an entry on the vnode - * free list. at this time the filesystem needs - * to free any private data and remove the node - * from any private lists. - */ -static int -linprocfs_reclaim(ap) - struct vop_reclaim_args /* { - struct vnode *a_vp; - } */ *ap; -{ - - return (linprocfs_freevp(ap->a_vp)); -} - -/* - * _print is used for debugging. - * just print a readable description - * of (vp). - */ -static int -linprocfs_print(ap) - struct vop_print_args /* { - struct vnode *a_vp; - } */ *ap; -{ - struct pfsnode *pfs = VTOPFS(ap->a_vp); - - printf("tag VT_PROCFS, type %d, pid %ld, mode %x, flags %lx\n", - pfs->pfs_type, (long)pfs->pfs_pid, pfs->pfs_mode, pfs->pfs_flags); - return (0); -} - -/* - * generic entry point for unsupported operations - */ -static int -linprocfs_badop() -{ - - return (EIO); -} - -/* - * Invent attributes for pfsnode (vp) and store - * them in (vap). - * Directories lengths are returned as zero since - * any real length would require the genuine size - * to be computed, and nothing cares anyway. - * - * this is relatively minimal for procfs. - */ -static int -linprocfs_getattr(ap) - struct vop_getattr_args /* { - struct vnode *a_vp; - struct vattr *a_vap; - struct ucred *a_cred; - struct proc *a_p; - } */ *ap; -{ - struct pfsnode *pfs = VTOPFS(ap->a_vp); - struct vattr *vap = ap->a_vap; - struct proc *procp; - int error; - - /* - * First make sure that the process and its credentials - * still exist. - */ - switch (pfs->pfs_type) { - case Proot: - case Pself: - procp = 0; - break; - - default: - procp = PFIND(pfs->pfs_pid); - if (procp == 0 || procp->p_cred == NULL || - procp->p_ucred == NULL) - return (ENOENT); - } - - error = 0; - - /* start by zeroing out the attributes */ - VATTR_NULL(vap); - - /* next do all the common fields */ - vap->va_type = ap->a_vp->v_type; - vap->va_mode = pfs->pfs_mode; - vap->va_fileid = pfs->pfs_fileno; - vap->va_flags = 0; - vap->va_blocksize = PAGE_SIZE; - vap->va_bytes = vap->va_size = 0; - vap->va_fsid = ap->a_vp->v_mount->mnt_stat.f_fsid.val[0]; - - /* - * Make all times be current TOD. - * It would be possible to get the process start - * time from the p_stat structure, but there's - * no "file creation" time stamp anyway, and the - * p_stat structure is not addressible if u. gets - * swapped out for that process. - */ - nanotime(&vap->va_ctime); - vap->va_atime = vap->va_mtime = vap->va_ctime; - - /* - * If the process has exercised some setuid or setgid - * privilege, then rip away read/write permission so - * that only root can gain access. - */ - switch (pfs->pfs_type) { - case Pmem: - /* Retain group kmem readablity. */ - if (procp->p_flag & P_SUGID) - vap->va_mode &= ~(VREAD|VWRITE); - break; - default: - break; - } - - /* - * now do the object specific fields - * - * The size could be set from struct reg, but it's hardly - * worth the trouble, and it puts some (potentially) machine - * dependent data into this machine-independent code. If it - * becomes important then this function should break out into - * a per-file stat function in the corresponding .c file. - */ - - vap->va_nlink = 1; - if (procp) { - vap->va_uid = procp->p_ucred->cr_uid; - vap->va_gid = procp->p_ucred->cr_gid; - } - - switch (pfs->pfs_type) { - case Proot: - /* - * Set nlink to 1 to tell fts(3) we don't actually know. - */ - vap->va_nlink = 1; - vap->va_uid = 0; - vap->va_gid = 0; - vap->va_size = vap->va_bytes = DEV_BSIZE; - break; - - case Pself: { - char buf[16]; /* should be enough */ - vap->va_uid = 0; - vap->va_gid = 0; - vap->va_size = vap->va_bytes = - snprintf(buf, sizeof(buf), "%ld", (long)curproc->p_pid); - break; - } - - case Pproc: - vap->va_nlink = nproc_targets; - vap->va_size = vap->va_bytes = DEV_BSIZE; - break; - - case Pexe: - error = EOPNOTSUPP; - break; - - case Pmeminfo: - case Pcpuinfo: - break; - - case Pmem: - /* - * If we denied owner access earlier, then we have to - * change the owner to root - otherwise 'ps' and friends - * will break even though they are setgid kmem. *SIGH* - */ - if (procp->p_flag & P_SUGID) - vap->va_uid = 0; - else - vap->va_uid = procp->p_ucred->cr_uid; - vap->va_gid = KMEM_GROUP; - break; - - default: - panic("linprocfs_getattr"); - } - - return (error); -} - -static int -linprocfs_setattr(ap) - struct vop_setattr_args /* { - struct vnode *a_vp; - struct vattr *a_vap; - struct ucred *a_cred; - struct proc *a_p; - } */ *ap; -{ - - if (ap->a_vap->va_flags != VNOVAL) - return (EOPNOTSUPP); - - /* - * just fake out attribute setting - * it's not good to generate an error - * return, otherwise things like creat() - * will fail when they try to set the - * file length to 0. worse, this means - * that echo $note > /proc/$pid/note will fail. - */ - - return (0); -} - -/* - * implement access checking. - * - * something very similar to this code is duplicated - * throughout the 4bsd kernel and should be moved - * into kern/vfs_subr.c sometime. - * - * actually, the check for super-user is slightly - * broken since it will allow read access to write-only - * objects. this doesn't cause any particular trouble - * but does mean that the i/o entry points need to check - * that the operation really does make sense. - */ -static int -linprocfs_access(ap) - struct vop_access_args /* { - struct vnode *a_vp; - int a_mode; - struct ucred *a_cred; - struct proc *a_p; - } */ *ap; -{ - struct vattr *vap; - struct vattr vattr; - int error; - - /* - * If you're the super-user, - * you always get access. - */ - if (ap->a_cred->cr_uid == 0) - return (0); - - vap = &vattr; - error = VOP_GETATTR(ap->a_vp, vap, ap->a_cred, ap->a_p); - if (error) - return (error); - - /* - * Access check is based on only one of owner, group, public. - * If not owner, then check group. If not a member of the - * group, then check public access. - */ - if (ap->a_cred->cr_uid != vap->va_uid) { - gid_t *gp; - int i; - - ap->a_mode >>= 3; - gp = ap->a_cred->cr_groups; - for (i = 0; i < ap->a_cred->cr_ngroups; i++, gp++) - if (vap->va_gid == *gp) - goto found; - ap->a_mode >>= 3; -found: - ; - } - - if ((vap->va_mode & ap->a_mode) == ap->a_mode) - return (0); - - return (EACCES); -} - -/* - * lookup. this is incredibly complicated in the - * general case, however for most pseudo-filesystems - * very little needs to be done. - * - * unless you want to get a migraine, just make sure your - * filesystem doesn't do any locking of its own. otherwise - * read and inwardly digest ufs_lookup(). - */ -static int -linprocfs_lookup(ap) - struct vop_lookup_args /* { - struct vnode * a_dvp; - struct vnode ** a_vpp; - struct componentname * a_cnp; - } */ *ap; -{ - struct componentname *cnp = ap->a_cnp; - struct vnode **vpp = ap->a_vpp; - struct vnode *dvp = ap->a_dvp; - char *pname = cnp->cn_nameptr; - struct proc *curp = cnp->cn_proc; - struct proc_target *pt; - struct vnode *fvp; - pid_t pid; - struct pfsnode *pfs; - struct proc *p; - int i; - - *vpp = NULL; - - if (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME) - return (EROFS); - - if (cnp->cn_namelen == 1 && *pname == '.') { - *vpp = dvp; - VREF(dvp); - /* vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY, curp); */ - return (0); - } - - pfs = VTOPFS(dvp); - switch (pfs->pfs_type) { - case Proot: - if (cnp->cn_flags & ISDOTDOT) - return (EIO); - - if (CNEQ(cnp, "self", 4)) - return (linprocfs_allocvp(dvp->v_mount, vpp, 0, Pself)); - if (CNEQ(cnp, "meminfo", 7)) - return (linprocfs_allocvp(dvp->v_mount, vpp, 0, Pmeminfo)); - if (CNEQ(cnp, "cpuinfo", 7)) - return (linprocfs_allocvp(dvp->v_mount, vpp, 0, Pcpuinfo)); - - pid = atopid(pname, cnp->cn_namelen); - if (pid == NO_PID) - break; - - p = PFIND(pid); - if (p == 0) - break; - - return (linprocfs_allocvp(dvp->v_mount, vpp, pid, Pproc)); - - case Pproc: - if (cnp->cn_flags & ISDOTDOT) - return (linprocfs_root(dvp->v_mount, vpp)); - - p = PFIND(pfs->pfs_pid); - if (p == 0) - break; - - for (pt = proc_targets, i = 0; i < nproc_targets; pt++, i++) { - if (cnp->cn_namelen == pt->pt_namlen && - bcmp(pt->pt_name, pname, cnp->cn_namelen) == 0 && - (pt->pt_valid == NULL || (*pt->pt_valid)(p))) - goto found; - } - break; - - found: - if (pt->pt_pfstype == Pexe) { - fvp = procfs_findtextvp(p); - /* We already checked that it exists. */ - VREF(fvp); - vn_lock(fvp, LK_EXCLUSIVE | LK_RETRY, curp); - *vpp = fvp; - return (0); - } - - return (linprocfs_allocvp(dvp->v_mount, vpp, pfs->pfs_pid, - pt->pt_pfstype)); - - default: - return (ENOTDIR); - } - - return (cnp->cn_nameiop == LOOKUP ? ENOENT : EROFS); -} - -/* - * Does this process have a text file? - */ -int -linprocfs_validfile(p) - struct proc *p; -{ - - return (procfs_findtextvp(p) != NULLVP); -} - -/* - * readdir() returns directory entries from pfsnode (vp). - * - * We generate just one directory entry at a time, as it would probably - * not pay off to buffer several entries locally to save uiomove calls. - */ -static int -linprocfs_readdir(ap) - struct vop_readdir_args /* { - struct vnode *a_vp; - struct uio *a_uio; - struct ucred *a_cred; - int *a_eofflag; - int *a_ncookies; - u_long **a_cookies; - } */ *ap; -{ - struct uio *uio = ap->a_uio; - struct dirent d; - struct dirent *dp = &d; - struct pfsnode *pfs; - int count, error, i, off; - static u_int delen; - - if (!delen) { - - d.d_namlen = PROCFS_NAMELEN; - delen = GENERIC_DIRSIZ(&d); - } - - pfs = VTOPFS(ap->a_vp); - - off = (int)uio->uio_offset; - if (off != uio->uio_offset || off < 0 || - off % delen != 0 || uio->uio_resid < delen) - return (EINVAL); - - error = 0; - count = 0; - i = off / delen; - - switch (pfs->pfs_type) { - /* - * this is for the process-specific sub-directories. - * all that is needed to is copy out all the entries - * from the procent[] table (top of this file). - */ - case Pproc: { - struct proc *p; - struct proc_target *pt; - - p = PFIND(pfs->pfs_pid); - if (p == NULL) - break; - if (!PRISON_CHECK(curproc, p)) - break; - - for (pt = &proc_targets[i]; - uio->uio_resid >= delen && i < nproc_targets; pt++, i++) { - if (pt->pt_valid && (*pt->pt_valid)(p) == 0) - continue; - - dp->d_reclen = delen; - dp->d_fileno = PROCFS_FILENO(pfs->pfs_pid, pt->pt_pfstype); - dp->d_namlen = pt->pt_namlen; - bcopy(pt->pt_name, dp->d_name, pt->pt_namlen + 1); - dp->d_type = pt->pt_type; - - if ((error = uiomove((caddr_t)dp, delen, uio)) != 0) - break; - } - - break; - } - - /* - * this is for the root of the procfs filesystem - * what is needed is a special entry for "self" - * followed by an entry for each process on allproc -#ifdef PROCFS_ZOMBIE - * and zombproc. -#endif - */ - - case Proot: { -#ifdef PROCFS_ZOMBIE - int doingzomb = 0; -#endif - int pcnt = 0; - volatile struct proc *p = allproc.lh_first; - - for (; p && uio->uio_resid >= delen; i++, pcnt++) { - bzero((char *) dp, delen); - dp->d_reclen = delen; - - switch (i) { - case 0: /* `.' */ - case 1: /* `..' */ - dp->d_fileno = PROCFS_FILENO(0, Proot); - dp->d_namlen = i + 1; - bcopy("..", dp->d_name, dp->d_namlen); - dp->d_name[i + 1] = '\0'; - dp->d_type = DT_DIR; - break; - - case 2: - dp->d_fileno = PROCFS_FILENO(0, Pself); - dp->d_namlen = 4; - bcopy("self", dp->d_name, 5); - dp->d_type = DT_LNK; - break; - - case 3: - dp->d_fileno = PROCFS_FILENO(0, Pmeminfo); - dp->d_namlen = 7; - bcopy("meminfo", dp->d_name, 8); - dp->d_type = DT_REG; - break; - - case 4: - dp->d_fileno = PROCFS_FILENO(0, Pcpuinfo); - dp->d_namlen = 7; - bcopy("cpuinfo", dp->d_name, 8); - dp->d_type = DT_REG; - break; - - default: - while (pcnt < i) { - p = p->p_list.le_next; - if (!p) - goto done; - if (!PRISON_CHECK(curproc, p)) - continue; - pcnt++; - } - while (!PRISON_CHECK(curproc, p)) { - p = p->p_list.le_next; - if (!p) - goto done; - } - dp->d_fileno = PROCFS_FILENO(p->p_pid, Pproc); - dp->d_namlen = sprintf(dp->d_name, "%ld", - (long)p->p_pid); - dp->d_type = DT_REG; - p = p->p_list.le_next; - break; - } - - if ((error = uiomove((caddr_t)dp, delen, uio)) != 0) - break; - } - done: - -#ifdef PROCFS_ZOMBIE - if (p == 0 && doingzomb == 0) { - doingzomb = 1; - p = zombproc.lh_first; - goto again; - } -#endif - - break; - - } - - default: - error = ENOTDIR; - break; - } - - uio->uio_offset = i * delen; - - return (error); -} - -/* - * readlink reads the link of `self' - */ -static int -linprocfs_readlink(ap) - struct vop_readlink_args *ap; -{ - char buf[16]; /* should be enough */ - int len; - - if (VTOPFS(ap->a_vp)->pfs_fileno != PROCFS_FILENO(0, Pself)) - return (EINVAL); - - len = snprintf(buf, sizeof(buf), "%ld", (long)curproc->p_pid); - - return (uiomove((caddr_t)buf, len, ap->a_uio)); -} - -/* - * convert decimal ascii to pid_t - */ -static pid_t -atopid(b, len) - const char *b; - u_int len; -{ - pid_t p = 0; - - while (len--) { - char c = *b++; - if (c < '0' || c > '9') - return (NO_PID); - p = 10 * p + (c - '0'); - if (p > PID_MAX) - return (NO_PID); - } - - return (p); -} - -/* - * procfs vnode operations. - */ -vop_t **linprocfs_vnodeop_p; -static struct vnodeopv_entry_desc linprocfs_vnodeop_entries[] = { - { &vop_default_desc, (vop_t *) vop_defaultop }, - { &vop_access_desc, (vop_t *) linprocfs_access }, - { &vop_advlock_desc, (vop_t *) linprocfs_badop }, - { &vop_bmap_desc, (vop_t *) linprocfs_bmap }, - { &vop_close_desc, (vop_t *) linprocfs_close }, - { &vop_create_desc, (vop_t *) linprocfs_badop }, - { &vop_getattr_desc, (vop_t *) linprocfs_getattr }, - { &vop_inactive_desc, (vop_t *) linprocfs_inactive }, - { &vop_link_desc, (vop_t *) linprocfs_badop }, - { &vop_lookup_desc, (vop_t *) linprocfs_lookup }, - { &vop_mkdir_desc, (vop_t *) linprocfs_badop }, - { &vop_mknod_desc, (vop_t *) linprocfs_badop }, - { &vop_open_desc, (vop_t *) linprocfs_open }, - { &vop_pathconf_desc, (vop_t *) vop_stdpathconf }, - { &vop_print_desc, (vop_t *) linprocfs_print }, - { &vop_read_desc, (vop_t *) linprocfs_rw }, - { &vop_readdir_desc, (vop_t *) linprocfs_readdir }, - { &vop_readlink_desc, (vop_t *) linprocfs_readlink }, - { &vop_reclaim_desc, (vop_t *) linprocfs_reclaim }, - { &vop_remove_desc, (vop_t *) linprocfs_badop }, - { &vop_rename_desc, (vop_t *) linprocfs_badop }, - { &vop_rmdir_desc, (vop_t *) linprocfs_badop }, - { &vop_setattr_desc, (vop_t *) linprocfs_setattr }, - { &vop_symlink_desc, (vop_t *) linprocfs_badop }, - { &vop_write_desc, (vop_t *) linprocfs_rw }, - { &vop_ioctl_desc, (vop_t *) linprocfs_ioctl }, - { NULL, NULL } -}; -static struct vnodeopv_desc linprocfs_vnodeop_opv_desc = - { &linprocfs_vnodeop_p, linprocfs_vnodeop_entries }; - -VNODEOP_SET(linprocfs_vnodeop_opv_desc); |