From 891ac937beb959cad94a2ba267e4b56dee930a5e Mon Sep 17 00:00:00 2001 From: Richard Yao Date: Mon, 19 Sep 2022 20:30:58 -0400 Subject: [PATCH] Linux: Fix use-after-free in zfsvfs_create() Coverity reported that we pass a pointer to zfsvfs to `dmu_objset_disown()` after freeing zfsvfs in zfsvfs_create_impl() after a failure in zfsvfs_init(). We have nearly identical duplicate versions of this code for FreeBSD and Linux, but interestingly, the FreeBSD version of this code differs in such a way that it does not suffer from this bug. We remove the difference from the FreeBSD version to fix this bug. Reviewed-by: Brian Behlendorf Signed-off-by: Richard Yao Closes #13883 --- module/os/linux/zfs/zfs_vfsops.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/module/os/linux/zfs/zfs_vfsops.c b/module/os/linux/zfs/zfs_vfsops.c index 251d9e9a4..64d6b4616 100644 --- a/module/os/linux/zfs/zfs_vfsops.c +++ b/module/os/linux/zfs/zfs_vfsops.c @@ -784,9 +784,7 @@ zfsvfs_create(const char *osname, boolean_t readonly, zfsvfs_t **zfvp) } error = zfsvfs_create_impl(zfvp, zfsvfs, os); - if (error != 0) { - dmu_objset_disown(os, B_TRUE, zfsvfs); - } + return (error); } @@ -826,6 +824,7 @@ zfsvfs_create_impl(zfsvfs_t **zfvp, zfsvfs_t *zfsvfs, objset_t *os) error = zfsvfs_init(zfsvfs, os); if (error != 0) { + dmu_objset_disown(os, B_TRUE, zfsvfs); *zfvp = NULL; zfsvfs_free(zfsvfs); return (error);