From owner-svn-src-all@FreeBSD.ORG Sat Jan 10 01:01:14 2015 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id 0CBD332B; Sat, 10 Jan 2015 01:01:14 +0000 (UTC) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id D167491F; Sat, 10 Jan 2015 01:01:13 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.9/8.14.9) with ESMTP id t0A11DSf096491; Sat, 10 Jan 2015 01:01:13 GMT (envelope-from delphij@FreeBSD.org) Received: (from delphij@localhost) by svn.freebsd.org (8.14.9/8.14.9/Submit) id t0A11Drf096490; Sat, 10 Jan 2015 01:01:13 GMT (envelope-from delphij@FreeBSD.org) Message-Id: <201501100101.t0A11Drf096490@svn.freebsd.org> X-Authentication-Warning: svn.freebsd.org: delphij set sender to delphij@FreeBSD.org using -f From: Xin LI Date: Sat, 10 Jan 2015 01:01:13 +0000 (UTC) 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 X-SVN-Group: stable-10 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.18-1 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 10 Jan 2015 01:01:14 -0000 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)); }