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)