]> git.proxmox.com Git - mirror_zfs.git/commitdiff
Fix potential use-after-frees in FreeBSD getpages and setattr VOPs
authorMark Johnston <markj@FreeBSD.org>
Thu, 28 Oct 2021 15:58:57 +0000 (11:58 -0400)
committerBrian Behlendorf <behlendorf1@llnl.gov>
Fri, 29 Oct 2021 23:39:47 +0000 (16:39 -0700)
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

module/os/freebsd/zfs/zfs_vnops_os.c

index e4a15e6d9ea3f7c914dd2a643de1fa57392106db..322d64f01f167dc0b20de1062a1fdddf040a7b03 100644 (file)
@@ -2208,7 +2208,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;
@@ -2243,6 +2243,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;
 
        /*
@@ -4046,7 +4047,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;
@@ -4116,8 +4116,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);