Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/netbsd-1-4]: src/sys/miscfs/procfs Pull up revision 1.29 (via patch, req...



details:   https://anonhg.NetBSD.org/src/rev/368cbb52f8be
branches:  netbsd-1-4
changeset: 470248:368cbb52f8be
user:      he <he%NetBSD.org@localhost>
date:      Tue Feb 01 22:56:44 2000 +0000

description:
Pull up revision 1.29 (via patch, requested by fvdl):
  Close procfs security hole.  Fixes SA#2000-001.

diffstat:

 sys/miscfs/procfs/procfs_subr.c |  152 +++++++++++++++++++++++++++------------
 1 files changed, 105 insertions(+), 47 deletions(-)

diffs (203 lines):

diff -r dc7f3db77380 -r 368cbb52f8be sys/miscfs/procfs/procfs_subr.c
--- a/sys/miscfs/procfs/procfs_subr.c   Tue Feb 01 22:56:20 2000 +0000
+++ b/sys/miscfs/procfs/procfs_subr.c   Tue Feb 01 22:56:44 2000 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: procfs_subr.c,v 1.26 1999/03/12 18:45:40 christos Exp $        */
+/*     $NetBSD: procfs_subr.c,v 1.26.2.1 2000/02/01 22:56:44 he Exp $  */
 
 /*
  * Copyright (c) 1994 Christopher G. Demetriou.  All rights reserved.
@@ -51,8 +51,16 @@
 
 #include <miscfs/procfs/procfs.h>
 
-static struct pfsnode *pfshead;
-static int pfsvplock;
+void procfs_hashins __P((struct pfsnode *));
+void procfs_hashrem __P((struct pfsnode *));
+struct vnode *procfs_hashget __P((pid_t, pfstype, struct mount *));
+
+LIST_HEAD(pfs_hashhead, pfsnode) *pfs_hashtbl;
+u_long ihash;          /* size of hash table - 1 */
+#define PFSPIDHASH(pid)        (&pfs_hashtbl[(pid) & ihash])
+
+struct lock pfs_hashlock;
+struct simplelock pfs_hash_slock;
 
 #define        ISSET(t, f)     ((t) & (f))
 
@@ -91,41 +99,23 @@
 {
        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))
-                               goto loop;
-                       *vpp = vp;
+       do {
+               if ((*vpp = procfs_hashget(pid, pfs_type, mp)) != NULL)
                        return (0);
-               }
-       }
+       } while (lockmgr(&pfs_hashlock, LK_EXCLUSIVE|LK_SLEEPFAIL, 0));
 
-       /*
-        * otherwise lock the vp list while we call getnewvnode
-        * since that can block.
-        */ 
-       if (pfsvplock & PROCFS_LOCKED) {
-               pfsvplock |= PROCFS_WANT;
-               sleep((caddr_t) &pfsvplock, PINOD);
-               goto loop;
+       if ((error = getnewvnode(VT_PROCFS, mp, procfs_vnodeop_p, vpp)) != 0) {
+               *vpp = NULL;
+               lockmgr(&pfs_hashlock, LK_RELEASE, 0);
+               return (error);
        }
-       pfsvplock |= PROCFS_LOCKED;
-
-       if ((error = getnewvnode(VT_PROCFS, mp, procfs_vnodeop_p, vpp)) != 0)
-               goto out;
        vp = *vpp;
 
        MALLOC(pfs, void *, sizeof(struct pfsnode), M_TEMP, M_WAITOK);
        vp->v_data = pfs;
 
-       pfs->pfs_next = 0;
        pfs->pfs_pid = (pid_t) pid;
        pfs->pfs_type = pfs_type;
        pfs->pfs_vnode = vp;
@@ -175,18 +165,8 @@
                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);
-       }
+       procfs_hashins(pfs);
+       lockmgr(&pfs_hashlock, LK_RELEASE, 0);
 
        return (error);
 }
@@ -195,15 +175,9 @@
 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;
-               }
-       }
+       procfs_hashrem(pfs);
 
        FREE(vp->v_data, M_TEMP);
        vp->v_data = 0;
@@ -333,3 +307,87 @@
 
        return (0);
 }
+
+/*
+ * Initialize pfsnode hash table.
+ */
+void
+procfs_hashinit()
+{
+       lockinit(&pfs_hashlock, PINOD, "pfs_hashlock", 0, 0);
+       pfs_hashtbl = hashinit(desiredvnodes / 4, M_UFSMNT, M_WAITOK, &ihash);
+       simple_lock_init(&pfs_hash_slock);
+}
+
+struct vnode *
+procfs_hashget(pid, type, mp)
+       pid_t pid;
+       pfstype type;
+       struct mount *mp;
+{
+       struct pfsnode *pp;
+       struct vnode *vp;
+
+loop:
+       simple_lock(&pfs_hash_slock);
+       for (pp = PFSPIDHASH(pid)->lh_first; pp; pp = pp->pfs_hash.le_next) {
+               vp = PFSTOV(pp);
+               if (pid == pp->pfs_pid && pp->pfs_type == type &&
+                   vp->v_mount == mp) {
+                       simple_unlock(&pfs_hash_slock);
+                       if (vget(vp, 0))
+                               goto loop;
+                       return (vp);
+               }
+       }
+       simple_unlock(&pfs_hash_slock);
+       return (NULL);
+}
+
+/*
+ * Insert the pfsnode into the hash table and lock it.
+ */
+void
+procfs_hashins(pp)
+       struct pfsnode *pp;
+{
+       struct pfs_hashhead *ppp;
+
+       simple_lock(&pfs_hash_slock);
+       ppp = PFSPIDHASH(pp->pfs_pid);
+       LIST_INSERT_HEAD(ppp, pp, pfs_hash);
+       simple_unlock(&pfs_hash_slock);
+}
+
+/*
+ * Remove the pfsnode from the hash table.
+ */
+void
+procfs_hashrem(pp)
+       struct pfsnode *pp;
+{
+       simple_lock(&pfs_hash_slock);
+       LIST_REMOVE(pp, pfs_hash);
+       simple_unlock(&pfs_hash_slock);
+}
+
+void
+procfs_revoke_vnodes(p, arg)
+       struct proc *p;
+       void *arg;
+{
+       struct pfsnode *pfs, *pnext;
+       struct vnode *vp;
+       struct mount *mp = (struct mount *)arg;
+
+       if (!(p->p_flag & P_SUGID))
+               return;
+
+       for (pfs = PFSPIDHASH(p->p_pid)->lh_first; pfs; pfs = pnext) {
+               vp = PFSTOV(pfs);
+               pnext = pfs->pfs_hash.le_next;
+               if (vp->v_usecount > 0 && pfs->pfs_pid == p->p_pid &&
+                   vp->v_mount == mp)
+                       VOP_REVOKE(vp, REVOKEALL);
+       }
+}



Home | Main Index | Thread Index | Old Index