Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files. =================================================================== RCS file: /ftp/cvs/cvsroot/src/sys/ufs/ufs/ufs_lookup.c,v rcsdiff: /ftp/cvs/cvsroot/src/sys/ufs/ufs/ufs_lookup.c,v: warning: Unknown phrases like `commitid ...;' are present. retrieving revision 1.111 retrieving revision 1.111.2.1 diff -u -p -r1.111 -r1.111.2.1 --- src/sys/ufs/ufs/ufs_lookup.c 2011/07/17 22:07:59 1.111 +++ src/sys/ufs/ufs/ufs_lookup.c 2012/04/17 00:08:57 1.111.2.1 @@ -1,4 +1,4 @@ -/* $NetBSD: ufs_lookup.c,v 1.111 2011/07/17 22:07:59 dholland Exp $ */ +/* $NetBSD: ufs_lookup.c,v 1.111.2.1 2012/04/17 00:08:57 yamt Exp $ */ /* * Copyright (c) 1989, 1993 @@ -37,7 +37,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: ufs_lookup.c,v 1.111 2011/07/17 22:07:59 dholland Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ufs_lookup.c,v 1.111.2.1 2012/04/17 00:08:57 yamt Exp $"); #ifdef _KERNEL_OPT #include "opt_ffs.h" @@ -68,6 +68,8 @@ __KERNEL_RCSID(0, "$NetBSD: ufs_lookup.c #include #include +#include + #ifdef DIAGNOSTIC int dirchk = 1; #else @@ -521,12 +523,6 @@ found: */ if (nameiop == DELETE && (flags & ISLASTCN)) { /* - * Write access to directory required to delete files. - */ - error = VOP_ACCESS(vdp, VWRITE, cred); - if (error) - goto out; - /* * Return pointer to current entry in results->ulr_offset, * and distance past previous entry (if there * is a previous entry in this block) in results->ulr_count. @@ -538,31 +534,45 @@ found: results->ulr_count = results->ulr_offset - prevoff; if (dp->i_number == foundino) { vref(vdp); - *vpp = vdp; - error = 0; - goto out; + tdp = vdp; + } else { + if (flags & ISDOTDOT) + VOP_UNLOCK(vdp); /* race to get the inode */ + error = VFS_VGET(vdp->v_mount, foundino, &tdp); + if (flags & ISDOTDOT) + vn_lock(vdp, LK_EXCLUSIVE | LK_RETRY); + if (error) + goto out; } - if (flags & ISDOTDOT) - VOP_UNLOCK(vdp); /* race to get the inode */ - error = VFS_VGET(vdp->v_mount, foundino, &tdp); - if (flags & ISDOTDOT) - vn_lock(vdp, LK_EXCLUSIVE | LK_RETRY); - if (error) + /* + * Write access to directory required to delete files. + */ + error = VOP_ACCESS(vdp, VWRITE, cred); + if (error) { + if (dp->i_number == foundino) + vrele(tdp); + else + vput(tdp); goto out; + } /* * If directory is "sticky", then user must own * the directory, or the file in it, else she * may not delete it (unless she's root). This * implements append-only directories. */ - if ((dp->i_mode & ISVTX) && - kauth_authorize_generic(cred, KAUTH_GENERIC_ISSUSER, - NULL) != 0 && - kauth_cred_geteuid(cred) != dp->i_uid && - VTOI(tdp)->i_uid != kauth_cred_geteuid(cred)) { - vput(tdp); - error = EPERM; - goto out; + if (dp->i_mode & ISVTX) { + error = kauth_authorize_vnode(cred, KAUTH_VNODE_DELETE, + tdp, vdp, genfs_can_sticky(cred, dp->i_uid, + VTOI(tdp)->i_uid)); + if (error) { + if (dp->i_number == foundino) + vrele(tdp); + else + vput(tdp); + error = EPERM; + goto out; + } } *vpp = tdp; error = 0;