Date: Sat, 10 Jan 2015 01:01:13 +0000 (UTC) From: Xin LI <delphij@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-10@freebsd.org Subject: svn commit: r276899 - stable/10/sys/cddl/contrib/opensolaris/uts/common/fs/zfs Message-ID: <201501100101.t0A11Drf096490@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: delphij Date: Sat Jan 10 01:01:12 2015 New Revision: 276899 URL: https://svnweb.freebsd.org/changeset/base/276899 Log: MFC r264392 (davide): Fix a panic in zfs_rename(). this is due to a wrong dereference of a vnode when it's not locked and can be (potentially) recycled. 'sdvp' cannot be locked on zfs_rename() entry point because the VFS can't be sure that this scenario is LOR-free (it might violate the parent->child lock acquisition rule). Dereference 'tdvp' instead, which is already locked on entry, and access 'sdvp' fields only when it's safe, i.e. under ZFS_ENTER scope. While at it, remove the usage of VOP_REALVP, as long as this is a NOP on FreeBSD. Modified: stable/10/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c Directory Properties: stable/10/ (props changed) Modified: stable/10/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c ============================================================================== --- stable/10/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c Sat Jan 10 00:11:10 2015 (r276898) +++ stable/10/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c Sat Jan 10 01:01:12 2015 (r276899) @@ -3730,9 +3730,8 @@ static int zfs_rename(vnode_t *sdvp, char *snm, vnode_t *tdvp, char *tnm, cred_t *cr, caller_context_t *ct, int flags) { - znode_t *tdzp, *szp, *tzp; - znode_t *sdzp = VTOZ(sdvp); - zfsvfs_t *zfsvfs = sdzp->z_zfsvfs; + znode_t *tdzp, *sdzp, *szp, *tzp; + zfsvfs_t *zfsvfs; zilog_t *zilog; vnode_t *realvp; zfs_dirlock_t *sdl, *tdl; @@ -3743,24 +3742,27 @@ zfs_rename(vnode_t *sdvp, char *snm, vno int zflg = 0; boolean_t waited = B_FALSE; + tdzp = VTOZ(tdvp); + ZFS_VERIFY_ZP(tdzp); + zfsvfs = tdzp->z_zfsvfs; ZFS_ENTER(zfsvfs); - ZFS_VERIFY_ZP(sdzp); zilog = zfsvfs->z_log; + sdzp = VTOZ(sdvp); /* - * Make sure we have the real vp for the target directory. + * In case sdzp is not valid, let's be sure to exit from the right + * zfsvfs_t. */ - if (VOP_REALVP(tdvp, &realvp, ct) == 0) - tdvp = realvp; - - tdzp = VTOZ(tdvp); - ZFS_VERIFY_ZP(tdzp); + if (sdzp->z_sa_hdl == NULL) { + ZFS_EXIT(zfsvfs); + return (SET_ERROR(EIO)); + } /* * We check z_zfsvfs rather than v_vfsp here, because snapshots and the * ctldir appear to have the same v_vfsp. */ - if (tdzp->z_zfsvfs != zfsvfs || zfsctl_is_node(tdvp)) { + if (sdzp->z_zfsvfs != zfsvfs || zfsctl_is_node(tdvp)) { ZFS_EXIT(zfsvfs); return (SET_ERROR(EXDEV)); }
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201501100101.t0A11Drf096490>