]> granicus.if.org Git - zfs/commitdiff
Close possible zfs_znode_held() race
authorBrian Behlendorf <behlendorf1@llnl.gov>
Tue, 19 Jan 2016 18:41:21 +0000 (10:41 -0800)
committerBrian Behlendorf <behlendorf1@llnl.gov>
Wed, 20 Jan 2016 21:36:15 +0000 (13:36 -0800)
Check if the lock is held while holding the z_hold_locks() lock.
This prevents a possible use-after-free bug for callers which are
not holding the lock.  There currently are no such callers so this
can't cause a problem today but it has been fixed regardless.

Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov>
Signed-off-by: Chunwei Chen <tuxoko@gmail.com>
Closes #4244
Issue #4124

module/zfs/zfs_znode.c

index 03274a9b9fcaee1449820cf342b90286f6152b10..e4bd62fd2713910a9a5f195b992137047382a9f2 100644 (file)
@@ -248,17 +248,16 @@ zfs_znode_held(zfs_sb_t *zsb, uint64_t obj)
 {
        znode_hold_t *zh, search;
        int i = ZFS_OBJ_HASH(zsb, obj);
+       boolean_t held;
 
        search.zh_obj = obj;
 
        mutex_enter(&zsb->z_hold_locks[i]);
        zh = avl_find(&zsb->z_hold_trees[i], &search, NULL);
+       held = (zh && MUTEX_HELD(&zh->zh_lock)) ? B_TRUE : B_FALSE;
        mutex_exit(&zsb->z_hold_locks[i]);
 
-       if (zh && MUTEX_HELD(&zh->zh_lock))
-               return (B_TRUE);
-
-       return (B_FALSE);
+       return (held);
 }
 
 static znode_hold_t *