Skip to content

Commit

Permalink
Fix get_zfs_sb race with concurrent umount
Browse files Browse the repository at this point in the history
Certain ioctl operations will call get_zfs_sb, which will holds an active
count on sb without checking whether it's active or not. This will result
in use-after-free. We fix this by using atomic_inc_not_zero to make sure
we got an active sb.

P1                                          P2
---                                         ---
deactivate_locked_super(): s_active = 0
                                            zfs_sb_hold()
                                            ->get_zfs_sb(): s_active = 1
->zpl_kill_sb()
-->zpl_put_super()
--->zfs_umount()
---->zfs_sb_free(zsb)
                                            zfs_sb_rele(zsb)

Signed-off-by: Chunwei Chen <david.chen@osnexus.com>
Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov>
  • Loading branch information
Chunwei Chen authored and nedbass committed Sep 9, 2016
1 parent ec9b8fa commit d5b0e7f
Showing 1 changed file with 3 additions and 3 deletions.
6 changes: 3 additions & 3 deletions module/zfs/zfs_ioctl.c
Original file line number Diff line number Diff line change
Expand Up @@ -1379,9 +1379,9 @@ get_zfs_sb(const char *dsname, zfs_sb_t **zsbp)

mutex_enter(&os->os_user_ptr_lock);
*zsbp = dmu_objset_get_user(os);
if (*zsbp && (*zsbp)->z_sb) {
atomic_inc(&((*zsbp)->z_sb->s_active));
} else {
/* bump s_active only when non-zero to prevent umount race */
if (*zsbp == NULL || (*zsbp)->z_sb == NULL ||
!atomic_inc_not_zero(&((*zsbp)->z_sb->s_active))) {
error = SET_ERROR(ESRCH);
}
mutex_exit(&os->os_user_ptr_lock);
Expand Down

0 comments on commit d5b0e7f

Please sign in to comment.