fs/super.c: don't drop ->s_user_ns until we free struct super_block itself
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>
This commit is contained in:
+4
-9
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user