mirror_zfs/module/os/linux/zfs
Christian Schwarz df000276b8 zfs_domount: fix double-disown of dataset / double-free of zfsvfs_t
Before this patch, in zfs_domount, if zfs_root or d_make_root fails, we
leave zfsvfs != NULL. This will lead to execution of the error handling
`if` statement at the `out` label, and hence to a call to
dmu_objset_disown and zfsvfs_free.

However, zfs_umount, which we call upon failure of zfs_root and
d_make_root already does dmu_objset_disown and zfsvfs_free.

I suppose this patch rather adds to the brittleness of this part of the
code base, but I don't want to invest more time in this right now.
To add a regression test, we'd need some kind of fault injection
facility for zfs_root or d_make_root, which doesn't exist right now.
And even then, I think that regression test would be too closely tied
to the implementation.

To repro the double-disown / double-free, do the following:
1. patch zfs_root to always return an error
2. mount a ZFS filesystem

Here's the stack trace you would see then:

  VERIFY3(ds->ds_owner == tag) failed (0000000000000000 == ffff9142361e8000)
  PANIC at dsl_dataset.c:1003:dsl_dataset_disown()
  Showing stack for process 28332
  CPU: 2 PID: 28332 Comm: zpool Tainted: G           O      5.10.103-1.nutanix.el7.x86_64 #1
  Call Trace:
   dump_stack+0x74/0x92
   spl_dumpstack+0x29/0x2b [spl]
   spl_panic+0xd4/0xfc [spl]
   dsl_dataset_disown+0xe9/0x150 [zfs]
   dmu_objset_disown+0xd6/0x150 [zfs]
   zfs_domount+0x17b/0x4b0 [zfs]
   zpl_mount+0x174/0x220 [zfs]
   legacy_get_tree+0x2b/0x50
   vfs_get_tree+0x2a/0xc0
   path_mount+0x2fa/0xa70
   do_mount+0x7c/0xa0
   __x64_sys_mount+0x8b/0xe0
   do_syscall_64+0x38/0x50
   entry_SYSCALL_64_after_hwframe+0x44/0xa9

Reviewed-by: Richard Yao <richard.yao@alumni.stonybrook.edu>
Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Reviewed-by: Ryan Moeller <ryan@iXsystems.com>
Co-authored-by: Christian Schwarz <christian.schwarz@nutanix.com>
Signed-off-by: Christian Schwarz <christian.schwarz@nutanix.com>
Closes #14025
2022-11-01 12:42:32 -07:00
..
abd_os.c Avoid small buffer copying on write 2022-07-26 10:10:37 -07:00
arc_os.c Remove b_pabd/b_rabd allocation from arc_hdr_alloc() 2021-09-14 14:31:50 -07:00
Makefile.in Restore FreeBSD resource usage accounting 2021-02-19 22:34:33 -08:00
mmp_os.c Add zfs_multihost_interval tunable handler for FreeBSD 2020-06-23 13:32:42 -07:00
policy.c Fix ACL checks for NFS kernel server 2022-03-20 21:21:18 -07:00
qat_compress.c Modify checksum obtain method of QAT 2021-09-14 14:29:46 -07:00
qat_crypt.c QAT related bug fixes 2019-09-12 13:33:44 -07:00
qat.c QAT related bug fixes 2019-09-12 13:33:44 -07:00
spa_misc_os.c Make spa_history_zone platform-dependent in kernel 2020-03-02 09:43:30 -08:00
trace.c Enable use of DTRACE_PROBE* macros in "spl" module 2019-11-01 13:13:43 -07:00
vdev_disk.c Linux 5.20 compat: bdevname() 2022-08-09 09:41:06 -07:00
vdev_file.c module: zfs: fix unused, remove argsused 2022-02-16 17:58:56 -08:00
zfs_acl.c Use fallthrough macro 2021-11-02 09:50:30 -07:00
zfs_ctldir.c Linux: always check or verify return of igrab() 2021-03-16 16:33:34 -07:00
zfs_debug.c Annotated dprintf as printf-like 2021-06-24 13:12:36 -07:00
zfs_dir.c Clean up use of zfs_log_create in zfs_dir 2021-05-10 12:16:32 -07:00
zfs_file_os.c file reference counts can get corrupted 2021-09-14 12:37:38 -07:00
zfs_ioctl_os.c libzfs: On FreeBSD, use MNT_NOWAIT with getfsstat 2021-06-09 13:05:34 -07:00
zfs_racct.c module: zfs: fix unused, remove argsused 2022-02-16 17:58:56 -08:00
zfs_sysfs.c Linux 5.18 compat: kobj_type.default_attrs replaced with default_groups 2022-04-25 10:00:09 -07:00
zfs_uio.c autoconf: Fail when __copy_from_user_inatomic is a non-GPL symbol 2022-05-20 10:33:24 -07:00
zfs_vfsops.c zfs_domount: fix double-disown of dataset / double-free of zfsvfs_t 2022-11-01 12:42:32 -07:00
zfs_vnops_os.c Linux 5.18 compat: replace __set_page_dirty_nobuffers 2022-04-28 15:17:38 -07:00
zfs_znode.c Use fallthrough macro 2021-11-02 09:50:30 -07:00
zio_crypt.c Linux: Fix uninitialized variable usage in zio_do_crypt_data() 2022-09-27 15:43:26 -07:00
zpl_ctldir.c Linux 5.12 compat: idmapped mounts 2021-03-19 21:00:59 -07:00
zpl_export.c Return required size when encode_fh size too small 2021-05-10 12:13:45 -07:00
zpl_file.c Linux 5.19 compat: aops->read_folio() 2022-06-01 14:24:49 -07:00
zpl_inode.c Fix ACL checks for NFS kernel server 2022-03-20 21:21:18 -07:00
zpl_super.c Linux: Fix ZFS_ENTER/ZFS_EXIT/ZFS_VERFY_ZP usage 2020-11-14 10:19:00 -08:00
zpl_xattr.c Fix ACL checks for NFS kernel server 2022-03-20 21:21:18 -07:00
zvol_os.c Linux 5.20 compat: blk_cleanup_disk() 2022-08-09 09:41:06 -07:00