Skip to content

Commit 97e58b9

Browse files
committed
Linux: Fix zfs_prune panics v2
It turns out that approach taken in the original version of the patch was wrong. So now, we're taking approach in-line with how kernel actually does it - when sb is being torn down, access to it is serialized via sb->s_umount rwsem, only when that lock is taken is it okay to work with s_flags - and the other mistake I was doing was trying to make SB_ACTIVE work, but apparently the kernel checks the negative variant - not SB_DYING and not SB_BORN. This way it finally seems to work without issues. Signed-off-by: Pavel Snajdr <[email protected]>
1 parent 57f192f commit 97e58b9

File tree

1 file changed

+7
-9
lines changed

1 file changed

+7
-9
lines changed

module/os/linux/zfs/zpl_super.c

+7-9
Original file line numberDiff line numberDiff line change
@@ -376,17 +376,15 @@ zpl_prune_sb(uint64_t nr_to_scan, void *arg)
376376
int objects = 0;
377377

378378
/*
379-
* deactivate_locked_super calls shrinker_free and only then
380-
* sops->kill_sb cb, resulting in UAF on umount when trying to reach
381-
* for the shrinker functions in zpl_prune_sb of in-umount dataset.
382-
* Increment if s_active is not zero, but don't prune if it is -
383-
* umount could be underway.
379+
* Ensure the superblock is not in the process of being torn down.
384380
*/
385-
if (atomic_inc_not_zero(&sb->s_active)) {
386-
(void) -zfs_prune(sb, nr_to_scan, &objects);
387-
atomic_dec(&sb->s_active);
381+
if (down_read_trylock(&sb->s_umount)) {
382+
if (!(sb->s_flags & SB_DYING) && sb->s_root &&
383+
(sb->s_flags & SB_BORN)) {
384+
(void) -zfs_prune(sb, nr_to_scan, &objects);
385+
}
386+
up_read(&sb->s_umount);
388387
}
389-
390388
}
391389

392390
const struct super_operations zpl_super_operations = {

0 commit comments

Comments
 (0)