diff options
author | Pavel Snajdr <[email protected]> | 2024-11-22 00:30:43 +0100 |
---|---|---|
committer | GitHub <[email protected]> | 2024-11-21 15:30:43 -0800 |
commit | 38c0324c0fb6b53286f00b7e36d1edca70d863d8 (patch) | |
tree | 386f2960bff2d8d98184b0631a3fe159e18327ef | |
parent | ae1d11882d10afb388e749684f8020b38de8504a (diff) |
Linux: Fix zfs_prune panics
by protecting against sb->s_shrink eviction on umount with newer kernels
deactivate_locked_super calls shrinker_free and only then
sops->kill_sb cb, resulting in UAF on umount when trying
to reach for the shrinker functions in zpl_prune_sb of
in-umount dataset
Reviewed-by: Brian Behlendorf <[email protected]>
Reviewed-by: Adam Moss <[email protected]>
Signed-off-by: Pavel Snajdr <[email protected]>
Closes #16770
-rw-r--r-- | module/os/linux/zfs/zpl_super.c | 13 |
1 files changed, 12 insertions, 1 deletions
diff --git a/module/os/linux/zfs/zpl_super.c b/module/os/linux/zfs/zpl_super.c index 287f5f36f..b97b701b7 100644 --- a/module/os/linux/zfs/zpl_super.c +++ b/module/os/linux/zfs/zpl_super.c @@ -375,7 +375,18 @@ zpl_prune_sb(uint64_t nr_to_scan, void *arg) struct super_block *sb = (struct super_block *)arg; int objects = 0; - (void) -zfs_prune(sb, nr_to_scan, &objects); + /* + * deactivate_locked_super calls shrinker_free and only then + * sops->kill_sb cb, resulting in UAF on umount when trying to reach + * for the shrinker functions in zpl_prune_sb of in-umount dataset. + * Increment if s_active is not zero, but don't prune if it is - + * umount could be underway. + */ + if (atomic_inc_not_zero(&sb->s_active)) { + (void) -zfs_prune(sb, nr_to_scan, &objects); + atomic_dec(&sb->s_active); + } + } const struct super_operations zpl_super_operations = { |