]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
fs/super.c: don't drop ->s_user_ns until we free struct super_block itself
authorAl Viro <viro@zeniv.linux.org.uk>
Fri, 2 Feb 2024 02:10:01 +0000 (21:10 -0500)
committerAl Viro <viro@zeniv.linux.org.uk>
Sun, 25 Feb 2024 07:10:31 +0000 (02:10 -0500)
Avoids fun races in RCU pathwalk...  Same goes for freeing LSM shite
hanging off super_block's arse.

Reviewed-by: Christian Brauner <brauner@kernel.org>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
fs/super.c

index d35e852954892dadcf1df6757c8b491904d2edbb..d6efeba0d0ce7c464c6d32c8d9001007d35259b1 100644 (file)
@@ -274,9 +274,10 @@ static void destroy_super_work(struct work_struct *work)
 {
        struct super_block *s = container_of(work, struct super_block,
                                                        destroy_work);
-       int i;
-
-       for (i = 0; i < SB_FREEZE_LEVELS; i++)
+       security_sb_free(s);
+       put_user_ns(s->s_user_ns);
+       kfree(s->s_subtype);
+       for (int i = 0; i < SB_FREEZE_LEVELS; i++)
                percpu_free_rwsem(&s->s_writers.rw_sem[i]);
        kfree(s);
 }
@@ -296,9 +297,6 @@ static void destroy_unused_super(struct super_block *s)
        super_unlock_excl(s);
        list_lru_destroy(&s->s_dentry_lru);
        list_lru_destroy(&s->s_inode_lru);
-       security_sb_free(s);
-       put_user_ns(s->s_user_ns);
-       kfree(s->s_subtype);
        shrinker_free(s->s_shrink);
        /* no delays needed */
        destroy_super_work(&s->destroy_work);
@@ -409,9 +407,6 @@ static void __put_super(struct super_block *s)
                WARN_ON(s->s_dentry_lru.node);
                WARN_ON(s->s_inode_lru.node);
                WARN_ON(!list_empty(&s->s_mounts));
-               security_sb_free(s);
-               put_user_ns(s->s_user_ns);
-               kfree(s->s_subtype);
                call_rcu(&s->rcu, destroy_super_rcu);
        }
 }