Source-Changes-HG archive

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

[src/trunk]: src/sys/miscfs/procfs At mount/unmount time, add an exec hook to...



details:   https://anonhg.NetBSD.org/src/rev/1295093fddba
branches:  trunk
changeset: 481301:1295093fddba
user:      fvdl <fvdl%NetBSD.org@localhost>
date:      Tue Jan 25 21:52:04 2000 +0000

description:
At mount/unmount time, add an exec hook to revoke all vnodes iff the
process is about to exec a sugid binary.

To speed up things, use hashing for vnode allocation, like other filesystems
do. This avoids walking the whole procfs node list in the revoke case too.

diffstat:

 sys/miscfs/procfs/procfs.h        |   14 ++-
 sys/miscfs/procfs/procfs_subr.c   |  158 ++++++++++++++++++++++++++-----------
 sys/miscfs/procfs/procfs_vfsops.c |   19 ++++-
 3 files changed, 138 insertions(+), 53 deletions(-)

diffs (truncated from 318 to 300 lines):

diff -r 054eae22f253 -r 1295093fddba sys/miscfs/procfs/procfs.h
--- a/sys/miscfs/procfs/procfs.h        Tue Jan 25 21:50:30 2000 +0000
+++ b/sys/miscfs/procfs/procfs.h        Tue Jan 25 21:52:04 2000 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: procfs.h,v 1.27 1999/09/02 23:33:45 thorpej Exp $      */
+/*     $NetBSD: procfs.h,v 1.28 2000/01/25 21:52:04 fvdl Exp $ */
 
 /*
  * Copyright (c) 1993 Jan-Simon Pendry
@@ -63,7 +63,7 @@
  * control data for the proc file system.
  */
 struct pfsnode {
-       struct pfsnode  *pfs_next;      /* next on list */
+       LIST_ENTRY(pfsnode) pfs_hash;   /* hash chain */
        struct vnode    *pfs_vnode;     /* vnode associated with this pfsnode */
        pfstype         pfs_type;       /* type of procfs node */
        pid_t           pfs_pid;        /* associated process */
@@ -90,6 +90,14 @@
                        ((type) + 2) : \
                        ((((pid)+1) << 4) + ((int) (type))))
 
+struct procfsmount {
+       void *pmnt_exechook;
+       struct mount *pmnt_mp;
+};
+
+#define VFSTOPROC(mp)  ((struct procfsmount *)(mp)->mnt_data)
+#define PROCTOVFS(pp)  ((pp)->pmnt_mp)
+
 /*
  * Convert between pfsnode vnode
  */
@@ -127,6 +135,8 @@
     struct uio *));
 
 int procfs_checkioperm __P((struct proc *, struct proc *));
+void procfs_revoke_vnodes __P((struct proc *, void *));
+void procfs_hashinit __P((void));
 
 /* functions to check whether or not files should be displayed */
 int procfs_validfile __P((struct proc *));
diff -r 054eae22f253 -r 1295093fddba sys/miscfs/procfs/procfs_subr.c
--- a/sys/miscfs/procfs/procfs_subr.c   Tue Jan 25 21:50:30 2000 +0000
+++ b/sys/miscfs/procfs/procfs_subr.c   Tue Jan 25 21:52:04 2000 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: procfs_subr.c,v 1.28 1999/09/02 23:33:45 thorpej Exp $ */
+/*     $NetBSD: procfs_subr.c,v 1.29 2000/01/25 21:52:04 fvdl 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, LK_EXCLUSIVE))
-                               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;
@@ -176,20 +166,8 @@
                panic("procfs_allocvp");
        }
 
-       VOP_LOCK(vp, LK_EXCLUSIVE);
-
-       /* 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);
 }
@@ -198,15 +176,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;
@@ -336,3 +308,91 @@
 
        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_lock(&vp->v_interlock);
+                       simple_unlock(&pfs_hash_slock);
+                       if (vget(vp, LK_EXCLUSIVE | LK_INTERLOCK))
+                               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;
+
+       /* lock the pfsnode, then put it on the appropriate hash list */
+       lockmgr(&pp->pfs_vnode->v_lock, LK_EXCLUSIVE, (struct simplelock *)0);
+
+       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);
+       }
+}
diff -r 054eae22f253 -r 1295093fddba sys/miscfs/procfs/procfs_vfsops.c
--- a/sys/miscfs/procfs/procfs_vfsops.c Tue Jan 25 21:50:30 2000 +0000
+++ b/sys/miscfs/procfs/procfs_vfsops.c Tue Jan 25 21:52:04 2000 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: procfs_vfsops.c,v 1.31 1999/02/26 23:44:46 wrstuden Exp $      */
+/*     $NetBSD: procfs_vfsops.c,v 1.32 2000/01/25 21:52:04 fvdl Exp $  */
 
 /*
  * Copyright (c) 1993 Jan-Simon Pendry
@@ -57,6 +57,7 @@
 #include <sys/mount.h>
 #include <sys/signalvar.h>
 #include <sys/vnode.h>
+#include <sys/malloc.h>
 #include <miscfs/procfs/procfs.h>
 #include <vm/vm.h>                     /* for PAGE_SIZE */
 
@@ -91,6 +92,7 @@
        struct proc *p;
 {
        size_t size;
+       struct procfsmount *pmnt;
 
        if (UIO_MX & (UIO_MX-1)) {
                log(LOG_ERR, "procfs: invalid directory entry size");
@@ -101,13 +103,20 @@
                return (EOPNOTSUPP);
 
        mp->mnt_flag |= MNT_LOCAL;
-       mp->mnt_data = 0;
+       pmnt = (struct procfsmount *) malloc(sizeof(struct procfsmount),
+           M_UFSMNT, M_WAITOK);   /* XXX need new malloc type */
+
+       mp->mnt_data = (qaddr_t)pmnt;
        vfs_getnewfsid(mp, MOUNT_PROCFS);
 
        (void) copyinstr(path, mp->mnt_stat.f_mntonname, MNAMELEN, &size);
        memset(mp->mnt_stat.f_mntonname + size, 0, MNAMELEN - size);
        memset(mp->mnt_stat.f_mntfromname, 0, MNAMELEN);
        memcpy(mp->mnt_stat.f_mntfromname, "procfs", sizeof("procfs"));
+
+       pmnt->pmnt_exechook = exechook_establish(procfs_revoke_vnodes, mp);
+       pmnt->pmnt_mp = mp;
+
        return (0);
 }
 
@@ -129,6 +138,11 @@
        if ((error = vflush(mp, 0, flags)) != 0)



Home | Main Index | Thread Index | Old Index