[BACK]Return to procfs_subr.c CVS log [TXT][DIR] Up to [local] / sys / miscfs / procfs

Annotation of sys/miscfs/procfs/procfs_subr.c, Revision 1.1

1.1     ! nbrk        1: /*     $OpenBSD: procfs_subr.c,v 1.27 2007/06/22 09:38:53 jasper Exp $ */
        !             2: /*     $NetBSD: procfs_subr.c,v 1.15 1996/02/12 15:01:42 christos Exp $        */
        !             3:
        !             4: /*
        !             5:  * Copyright (c) 1993 Jan-Simon Pendry
        !             6:  * Copyright (c) 1993
        !             7:  *     The Regents of the University of California.  All rights reserved.
        !             8:  *
        !             9:  * This code is derived from software contributed to Berkeley by
        !            10:  * Jan-Simon Pendry.
        !            11:  *
        !            12:  * Redistribution and use in source and binary forms, with or without
        !            13:  * modification, are permitted provided that the following conditions
        !            14:  * are met:
        !            15:  * 1. Redistributions of source code must retain the above copyright
        !            16:  *    notice, this list of conditions and the following disclaimer.
        !            17:  * 2. Redistributions in binary form must reproduce the above copyright
        !            18:  *    notice, this list of conditions and the following disclaimer in the
        !            19:  *    documentation and/or other materials provided with the distribution.
        !            20:  * 3. Neither the name of the University nor the names of its contributors
        !            21:  *    may be used to endorse or promote products derived from this software
        !            22:  *    without specific prior written permission.
        !            23:  *
        !            24:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
        !            25:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
        !            26:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
        !            27:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
        !            28:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
        !            29:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
        !            30:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
        !            31:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
        !            32:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
        !            33:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
        !            34:  * SUCH DAMAGE.
        !            35:  *
        !            36:  *     @(#)procfs_subr.c       8.5 (Berkeley) 6/15/94
        !            37:  */
        !            38:
        !            39: #include <sys/param.h>
        !            40: #include <sys/systm.h>
        !            41: #include <sys/time.h>
        !            42: #include <sys/kernel.h>
        !            43: #include <sys/proc.h>
        !            44: #include <sys/vnode.h>
        !            45: #include <sys/malloc.h>
        !            46: #include <sys/stat.h>
        !            47: #include <sys/ptrace.h>
        !            48:
        !            49: #include <miscfs/procfs/procfs.h>
        !            50:
        !            51: static TAILQ_HEAD(, pfsnode)   pfshead;
        !            52: struct lock pfs_vlock;
        !            53:
        !            54: /*ARGSUSED*/
        !            55: int
        !            56: procfs_init(struct vfsconf *vfsp)
        !            57: {
        !            58:        lockinit(&pfs_vlock, PVFS, "procfsl", 0, 0);
        !            59:        TAILQ_INIT(&pfshead);
        !            60:        return (0);
        !            61: }
        !            62:
        !            63: /*
        !            64:  * allocate a pfsnode/vnode pair.  the vnode is
        !            65:  * referenced, but not locked.
        !            66:  *
        !            67:  * the pid, pfs_type, and mount point uniquely
        !            68:  * identify a pfsnode.  the mount point is needed
        !            69:  * because someone might mount this filesystem
        !            70:  * twice.
        !            71:  *
        !            72:  * all pfsnodes are maintained on a singly-linked
        !            73:  * list.  new nodes are only allocated when they cannot
        !            74:  * be found on this list.  entries on the list are
        !            75:  * removed when the vfs reclaim entry is called.
        !            76:  *
        !            77:  * a single lock is kept for the entire list.  this is
        !            78:  * needed because the getnewvnode() function can block
        !            79:  * waiting for a vnode to become free, in which case there
        !            80:  * may be more than one process trying to get the same
        !            81:  * vnode.  this lock is only taken if we are going to
        !            82:  * call getnewvnode, since the kernel itself is single-threaded.
        !            83:  *
        !            84:  * if an entry is found on the list, then call vget() to
        !            85:  * take a reference.  this is done because there may be
        !            86:  * zero references to it and so it needs to removed from
        !            87:  * the vnode free list.
        !            88:  */
        !            89: int
        !            90: procfs_allocvp(struct mount *mp, struct vnode **vpp, pid_t pid, pfstype pfs_type)
        !            91: {
        !            92:        struct proc *p = curproc;
        !            93:        struct pfsnode *pfs;
        !            94:        struct vnode *vp;
        !            95:        int error;
        !            96:
        !            97:        /*
        !            98:         * Lock the vp list, getnewvnode can sleep.
        !            99:         */
        !           100:        error = lockmgr(&pfs_vlock, LK_EXCLUSIVE, NULL);
        !           101:        if (error)
        !           102:                return (error);
        !           103: loop:
        !           104:        TAILQ_FOREACH(pfs, &pfshead, list) {
        !           105:                vp = PFSTOV(pfs);
        !           106:                if (pfs->pfs_pid == pid &&
        !           107:                    pfs->pfs_type == pfs_type &&
        !           108:                    vp->v_mount == mp) {
        !           109:                        if (vget(vp, 0, p))
        !           110:                                goto loop;
        !           111:                        *vpp = vp;
        !           112:                        goto out;
        !           113:                }
        !           114:        }
        !           115:
        !           116:        if ((error = getnewvnode(VT_PROCFS, mp, procfs_vnodeop_p, vpp)) != 0)
        !           117:                goto out;
        !           118:        vp = *vpp;
        !           119:
        !           120:        MALLOC(pfs, void *, sizeof(struct pfsnode), M_TEMP, M_WAITOK);
        !           121:        vp->v_data = pfs;
        !           122:
        !           123:        pfs->pfs_pid = pid;
        !           124:        pfs->pfs_type = pfs_type;
        !           125:        pfs->pfs_vnode = vp;
        !           126:        pfs->pfs_flags = 0;
        !           127:        pfs->pfs_fileno = PROCFS_FILENO(pid, pfs_type);
        !           128:
        !           129:        switch (pfs_type) {
        !           130:        case Proot:     /* /proc = dr-xr-xr-x */
        !           131:                pfs->pfs_mode = S_IRUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH;
        !           132:                vp->v_type = VDIR;
        !           133:                vp->v_flag = VROOT;
        !           134:                break;
        !           135:
        !           136:        case Pcurproc:  /* /proc/curproc = lr--r--r-- */
        !           137:        case Pself:     /* /proc/self = lr--r--r-- */
        !           138:                pfs->pfs_mode = S_IRUSR|S_IRGRP|S_IROTH;
        !           139:                vp->v_type = VLNK;
        !           140:                break;
        !           141:
        !           142:        case Pproc:     /* /proc/N = dr-xr-xr-x */
        !           143:                pfs->pfs_mode = S_IRUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH;
        !           144:                vp->v_type = VDIR;
        !           145:                break;
        !           146:
        !           147:        case Pfile:     /* /proc/N/file = -rw------- */
        !           148:        case Pmem:      /* /proc/N/mem = -rw------- */
        !           149:        case Pregs:     /* /proc/N/regs = -rw------- */
        !           150:        case Pfpregs:   /* /proc/N/fpregs = -rw------- */
        !           151:                pfs->pfs_mode = S_IRUSR|S_IWUSR;
        !           152:                vp->v_type = VREG;
        !           153:                break;
        !           154:
        !           155:        case Pctl:      /* /proc/N/ctl = --w------ */
        !           156:        case Pnote:     /* /proc/N/note = --w------ */
        !           157:        case Pnotepg:   /* /proc/N/notepg = --w------ */
        !           158:                pfs->pfs_mode = S_IWUSR;
        !           159:                vp->v_type = VREG;
        !           160:                break;
        !           161:
        !           162:        case Pstatus:   /* /proc/N/status = -r--r--r-- */
        !           163:        case Pcmdline:  /* /proc/N/cmdline = -r--r--r-- */
        !           164:        case Pmeminfo:  /* /proc/meminfo = -r--r--r-- */
        !           165:        case Pcpuinfo:  /* /proc/cpuinfo = -r--r--r-- */
        !           166:                pfs->pfs_mode = S_IRUSR|S_IRGRP|S_IROTH;
        !           167:                vp->v_type = VREG;
        !           168:                break;
        !           169:
        !           170:        default:
        !           171:                panic("procfs_allocvp");
        !           172:        }
        !           173:
        !           174:        /* add to procfs vnode list */
        !           175:        TAILQ_INSERT_TAIL(&pfshead, pfs, list);
        !           176:        uvm_vnp_setsize(vp, 0);
        !           177: out:
        !           178:        lockmgr(&pfs_vlock, LK_RELEASE, NULL);
        !           179:
        !           180:        return (error);
        !           181: }
        !           182:
        !           183: int
        !           184: procfs_freevp(struct vnode *vp)
        !           185: {
        !           186:        struct pfsnode *pfs = VTOPFS(vp);
        !           187:
        !           188:        TAILQ_REMOVE(&pfshead, pfs, list);
        !           189:        FREE(vp->v_data, M_TEMP);
        !           190:        vp->v_data = 0;
        !           191:        return (0);
        !           192: }
        !           193:
        !           194: int
        !           195: procfs_rw(void *v)
        !           196: {
        !           197:        struct vop_read_args *ap = v;
        !           198:        struct vnode *vp = ap->a_vp;
        !           199:        struct uio *uio = ap->a_uio;
        !           200:        struct proc *curp = uio->uio_procp;
        !           201:        struct pfsnode *pfs = VTOPFS(vp);
        !           202:        struct proc *p;
        !           203:
        !           204:        p = pfind(pfs->pfs_pid);
        !           205:        if (p == 0)
        !           206:                return (EINVAL);
        !           207:        /* Do not permit games to be played with init(8) */
        !           208:        if (p->p_pid == 1 && securelevel > 0 && uio->uio_rw == UIO_WRITE)
        !           209:                return (EPERM);
        !           210:        if (uio->uio_offset < 0)
        !           211:                return (EINVAL);
        !           212:
        !           213:        switch (pfs->pfs_type) {
        !           214:        case Pnote:
        !           215:        case Pnotepg:
        !           216:                return (procfs_donote(curp, p, pfs, uio));
        !           217:
        !           218:        case Pctl:
        !           219:                return (procfs_doctl(curp, p, pfs, uio));
        !           220:
        !           221:        case Pstatus:
        !           222:                return (procfs_dostatus(curp, p, pfs, uio));
        !           223:
        !           224:        case Pmem:
        !           225:                return (process_domem(curp, p, uio, PT_WRITE_I));
        !           226:
        !           227:        case Pcmdline:
        !           228:                return (procfs_docmdline(curp, p, pfs, uio));
        !           229:
        !           230:        case Pmeminfo:
        !           231:                return (procfs_domeminfo(curp, p, pfs, uio));
        !           232:
        !           233:        case Pcpuinfo:
        !           234:                return (procfs_docpuinfo(curp, p, pfs, uio));
        !           235:
        !           236:        default:
        !           237:                return (EOPNOTSUPP);
        !           238:        }
        !           239: }
        !           240:
        !           241: /*
        !           242:  * Get a string from userland into (buf).  Strip a trailing
        !           243:  * nl character (to allow easy access from the shell).
        !           244:  * The buffer should be *buflenp + 1 chars long.  vfs_getuserstr
        !           245:  * will automatically add a nul char at the end.
        !           246:  *
        !           247:  * Returns 0 on success or the following errors
        !           248:  *
        !           249:  * EINVAL:    file offset is non-zero.
        !           250:  * EMSGSIZE:  message is longer than kernel buffer
        !           251:  * EFAULT:    user i/o buffer is not addressable
        !           252:  */
        !           253: int
        !           254: vfs_getuserstr(struct uio *uio, char *buf, int *buflenp)
        !           255: {
        !           256:        int xlen;
        !           257:        int error;
        !           258:
        !           259:        if (uio->uio_offset != 0)
        !           260:                return (EINVAL);
        !           261:
        !           262:        xlen = *buflenp;
        !           263:
        !           264:        /* must be able to read the whole string in one go */
        !           265:        if (xlen < uio->uio_resid)
        !           266:                return (EMSGSIZE);
        !           267:        xlen = uio->uio_resid;
        !           268:
        !           269:        if ((error = uiomove(buf, xlen, uio)) != 0)
        !           270:                return (error);
        !           271:
        !           272:        /* allow multiple writes without seeks */
        !           273:        uio->uio_offset = 0;
        !           274:
        !           275:        /* cleanup string and remove trailing newline */
        !           276:        buf[xlen] = '\0';
        !           277:        xlen = strlen(buf);
        !           278:        if (xlen > 0 && buf[xlen-1] == '\n')
        !           279:                buf[--xlen] = '\0';
        !           280:        *buflenp = xlen;
        !           281:
        !           282:        return (0);
        !           283: }
        !           284:
        !           285: const vfs_namemap_t *
        !           286: vfs_findname(const vfs_namemap_t *nm, char *buf, int buflen)
        !           287: {
        !           288:        for (; nm->nm_name; nm++)
        !           289:                if (bcmp(buf, nm->nm_name, buflen + 1) == 0)
        !           290:                        return (nm);
        !           291:
        !           292:        return (0);
        !           293: }

CVSweb