mirror of
https://git.proxmox.com/git/mirror_zfs.git
synced 2026-05-22 02:27:36 +03:00
Fix unprotected zfs_znode_dmu_fini
In original code, zfs_znode_dmu_fini is called in zfs_rmnode without zfs_znode_hold_enter. It seems to assume it's ok to do so when the znode is unlinked. However this assumption is not correct, as zfs_zget can be called by NFS through zpl_fh_to_dentry as pointed out by Christian in https://github.com/openzfs/zfs/pull/12767, which could result in a use-after-free bug. Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov> Co-authored-by: Ryan Moeller <ryan@iXsystems.com> Signed-off-by: Chunwei Chen <david.chen@nutanix.com> Signed-off-by: Ryan Moeller <ryan@iXsystems.com> Closes #12767 Closes #14364
This commit is contained in:
@@ -426,6 +426,7 @@ zfs_rmnode(znode_t *zp)
|
||||
zfsvfs_t *zfsvfs = zp->z_zfsvfs;
|
||||
objset_t *os = zfsvfs->z_os;
|
||||
dmu_tx_t *tx;
|
||||
uint64_t z_id = zp->z_id;
|
||||
uint64_t acl_obj;
|
||||
uint64_t xattr_obj;
|
||||
uint64_t count;
|
||||
@@ -445,8 +446,10 @@ zfs_rmnode(znode_t *zp)
|
||||
* Not enough space to delete some xattrs.
|
||||
* Leave it in the unlinked set.
|
||||
*/
|
||||
ZFS_OBJ_HOLD_ENTER(zfsvfs, z_id);
|
||||
zfs_znode_dmu_fini(zp);
|
||||
zfs_znode_free(zp);
|
||||
ZFS_OBJ_HOLD_EXIT(zfsvfs, z_id);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
@@ -464,8 +467,10 @@ zfs_rmnode(znode_t *zp)
|
||||
* Not enough space or we were interrupted by unmount.
|
||||
* Leave the file in the unlinked set.
|
||||
*/
|
||||
ZFS_OBJ_HOLD_ENTER(zfsvfs, z_id);
|
||||
zfs_znode_dmu_fini(zp);
|
||||
zfs_znode_free(zp);
|
||||
ZFS_OBJ_HOLD_EXIT(zfsvfs, z_id);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -501,8 +506,10 @@ zfs_rmnode(znode_t *zp)
|
||||
* which point we'll call zfs_unlinked_drain() to process it).
|
||||
*/
|
||||
dmu_tx_abort(tx);
|
||||
ZFS_OBJ_HOLD_ENTER(zfsvfs, z_id);
|
||||
zfs_znode_dmu_fini(zp);
|
||||
zfs_znode_free(zp);
|
||||
ZFS_OBJ_HOLD_EXIT(zfsvfs, z_id);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -386,7 +386,6 @@ void
|
||||
zfs_znode_dmu_fini(znode_t *zp)
|
||||
{
|
||||
ASSERT(MUTEX_HELD(ZFS_OBJ_MUTEX(zp->z_zfsvfs, zp->z_id)) ||
|
||||
zp->z_unlinked ||
|
||||
ZFS_TEARDOWN_INACTIVE_WRITE_HELD(zp->z_zfsvfs));
|
||||
|
||||
sa_handle_destroy(zp->z_sa_hdl);
|
||||
|
||||
Reference in New Issue
Block a user