summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMark Johnston <markj@FreeBSD.org>2021-10-28 11:58:57 -0400
committerTony Hutter <hutter2@llnl.gov>2021-12-13 13:22:34 -0800
commit07165ce540323bc80b7e25372ca60ac21a16b7f1 (patch)
tree67fb5cb990690223c554a481526baa80c4f405a5
parent6ed7d77b44b643e0755828b86e48bd2826df620f (diff)
Fix potential use-after-frees in FreeBSD getpages and setattr VOPs
The objset object is reallocated during certain dataset operations, such as rollbacks, so the objset pointer must be loaded after acquiring the teardown lock. Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov> Reviewed-by: Ryan Moeller <ryan@ixsystems.com> Signed-off-by: Mark Johnston <markj@FreeBSD.org> Closes #12704
-rw-r--r--module/os/freebsd/zfs/zfs_vnops_os.c8
1 files changed, 4 insertions, 4 deletions
diff --git a/module/os/freebsd/zfs/zfs_vnops_os.c b/module/os/freebsd/zfs/zfs_vnops_os.c
index 7aeb6ca3f..2c225c453 100644
--- a/module/os/freebsd/zfs/zfs_vnops_os.c
+++ b/module/os/freebsd/zfs/zfs_vnops_os.c
@@ -2222,7 +2222,7 @@ zfs_setattr(znode_t *zp, vattr_t *vap, int flags, cred_t *cr)
{
vnode_t *vp = ZTOV(zp);
zfsvfs_t *zfsvfs = zp->z_zfsvfs;
- objset_t *os = zfsvfs->z_os;
+ objset_t *os;
zilog_t *zilog;
dmu_tx_t *tx;
vattr_t oldva;
@@ -2257,6 +2257,7 @@ zfs_setattr(znode_t *zp, vattr_t *vap, int flags, cred_t *cr)
ZFS_ENTER(zfsvfs);
ZFS_VERIFY_ZP(zp);
+ os = zfsvfs->z_os;
zilog = zfsvfs->z_log;
/*
@@ -4060,7 +4061,6 @@ zfs_getpages(struct vnode *vp, vm_page_t *ma, int count, int *rbehind,
{
znode_t *zp = VTOZ(vp);
zfsvfs_t *zfsvfs = zp->z_zfsvfs;
- objset_t *os = zp->z_zfsvfs->z_os;
zfs_locked_range_t *lr;
vm_object_t object;
off_t start, end, obj_size;
@@ -4130,8 +4130,8 @@ zfs_getpages(struct vnode *vp, vm_page_t *ma, int count, int *rbehind,
* ZFS will panic if we request DMU to read beyond the end of the last
* allocated block.
*/
- error = dmu_read_pages(os, zp->z_id, ma, count, &pgsin_b, &pgsin_a,
- MIN(end, obj_size) - (end - PAGE_SIZE));
+ error = dmu_read_pages(zfsvfs->z_os, zp->z_id, ma, count, &pgsin_b,
+ &pgsin_a, MIN(end, obj_size) - (end - PAGE_SIZE));
if (lr != NULL)
zfs_rangelock_exit(lr);