Source-Changes-HG archive

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

[src/trunk]: src/sys/miscfs/genfs Call VOP_ABORTOP in genfs_eopnotsupp. This...



details:   https://anonhg.NetBSD.org/src/rev/32267e360c97
branches:  trunk
changeset: 753735:32267e360c97
user:      pooka <pooka%NetBSD.org@localhost>
date:      Thu Apr 08 15:56:26 2010 +0000

description:
Call VOP_ABORTOP in genfs_eopnotsupp.  This prevents file system
authors from having to get down on their knees and pray they won't
get POGA'd(*) again.

This plugs componentname leaks in at least smbfs and buggy puffs
servers (buggy servers shouldn't be able to leak kernel memory).

*) principle of greatest astonishment

diffstat:

 sys/miscfs/genfs/genfs_vnops.c |  34 ++++++++++++++++++++++++++++------
 1 files changed, 28 insertions(+), 6 deletions(-)

diffs (67 lines):

diff -r fc899b86c8e0 -r 32267e360c97 sys/miscfs/genfs/genfs_vnops.c
--- a/sys/miscfs/genfs/genfs_vnops.c    Thu Apr 08 15:03:33 2010 +0000
+++ b/sys/miscfs/genfs/genfs_vnops.c    Thu Apr 08 15:56:26 2010 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: genfs_vnops.c,v 1.176 2010/01/27 15:52:31 uebayasi Exp $       */
+/*     $NetBSD: genfs_vnops.c,v 1.177 2010/04/08 15:56:26 pooka Exp $  */
 
 /*-
  * Copyright (c) 2008 The NetBSD Foundation, Inc.
@@ -57,7 +57,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: genfs_vnops.c,v 1.176 2010/01/27 15:52:31 uebayasi Exp $");
+__KERNEL_RCSID(0, "$NetBSD: genfs_vnops.c,v 1.177 2010/04/08 15:56:26 pooka Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -170,7 +170,8 @@
 
 /*
  * Called when an fs doesn't support a particular vop.
- * This takes care to vrele, vput, or vunlock passed in vnodes.
+ * This takes care to vrele, vput, or vunlock passed in vnodes
+ * and calls VOP_ABORTOP for a componentname (in non-rename VOP).
  */
 int
 genfs_eopnotsupp(void *v)
@@ -181,14 +182,35 @@
        } */ *ap = v;
        struct vnodeop_desc *desc = ap->a_desc;
        struct vnode *vp, *vp_last = NULL;
-       int flags, i, j, offset;
+       int flags, i, j, offset_cnp, offset_vp;
+
+       KASSERT(desc->vdesc_offset != VOP_LOOKUP_DESCOFFSET);
+       KASSERT(desc->vdesc_offset != VOP_ABORTOP_DESCOFFSET);
+
+       /*
+        * Free componentname that lookup potentially SAVENAMEd.
+        *
+        * As is logical, componentnames for VOP_RENAME are handled by
+        * the caller of VOP_RENAME.  Yay, rename!
+        */
+       if (desc->vdesc_offset != VOP_RENAME_DESCOFFSET &&
+           (offset_vp = desc->vdesc_vp_offsets[0]) != VDESC_NO_OFFSET &&
+           (offset_cnp = desc->vdesc_componentname_offset) != VDESC_NO_OFFSET){
+               struct componentname *cnp;
+               struct vnode *dvp;
+
+               dvp = *VOPARG_OFFSETTO(struct vnode **, offset_vp, ap);
+               cnp = *VOPARG_OFFSETTO(struct componentname **, offset_cnp, ap);
+
+               VOP_ABORTOP(dvp, cnp);
+       }
 
        flags = desc->vdesc_flags;
        for (i = 0; i < VDESC_MAX_VPS; flags >>=1, i++) {
-               if ((offset = desc->vdesc_vp_offsets[i]) == VDESC_NO_OFFSET)
+               if ((offset_vp = desc->vdesc_vp_offsets[i]) == VDESC_NO_OFFSET)
                        break;  /* stop at end of list */
                if ((j = flags & VDESC_VP0_WILLPUT)) {
-                       vp = *VOPARG_OFFSETTO(struct vnode **, offset, ap);
+                       vp = *VOPARG_OFFSETTO(struct vnode **, offset_vp, ap);
 
                        /* Skip if NULL */
                        if (!vp)



Home | Main Index | Thread Index | Old Index