Module Name:    src
Committed By:   pooka
Date:           Thu Apr  8 15:56:26 UTC 2010

Modified Files:
        src/sys/miscfs/genfs: genfs_vnops.c

Log Message:
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


To generate a diff of this commit:
cvs rdiff -u -r1.176 -r1.177 src/sys/miscfs/genfs/genfs_vnops.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/miscfs/genfs/genfs_vnops.c
diff -u src/sys/miscfs/genfs/genfs_vnops.c:1.176 src/sys/miscfs/genfs/genfs_vnops.c:1.177
--- src/sys/miscfs/genfs/genfs_vnops.c:1.176	Wed Jan 27 15:52:31 2010
+++ src/sys/miscfs/genfs/genfs_vnops.c	Thu Apr  8 15:56:26 2010
@@ -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)

Reply via email to