fs: prefer kfree_rcu() in fasync_remove_entry()
In 'fasync_remove_entry()', prefer 'kfree_rcu()' over 'call_rcu()' with dummy 'fasync_free_rcu()' callback. This is mostly intended in attempt to fix weird https://syzkaller.appspot.com/bug?id=6a64ad907e361e49e92d1c4c114128a1bda2ed7f, where kmemleak may consider 'fa' as unreferenced during RCU grace period. See https://lore.kernel.org/stable/20230930174657.800551-1-joel@joelfernandes.org as well. Comments are highly appreciated. Ever sinceae65a5211d
("mm/slab: document kfree() as allowed for kmem_cache_alloc() objects") kfree() can be used for both kmalloc() and kmem_cache_alloc() so this is no safe. Do not backport this to stable, please. Linkae65a5211d
("mm/slab: document kfree() as > allowed for kmem_cache_alloc() objects") Signed-off-by: Dmitry Antipov <dmantipov@yandex.ru> Link: https://lore.kernel.org/r/20240209125220.330383-1-dmantipov@yandex.ru Signed-off-by: Christian Brauner <brauner@kernel.org>
This commit is contained in:
parent
ef560389ca
commit
d0089603fa
@ -846,12 +846,6 @@ int send_sigurg(struct fown_struct *fown)
|
|||||||
static DEFINE_SPINLOCK(fasync_lock);
|
static DEFINE_SPINLOCK(fasync_lock);
|
||||||
static struct kmem_cache *fasync_cache __ro_after_init;
|
static struct kmem_cache *fasync_cache __ro_after_init;
|
||||||
|
|
||||||
static void fasync_free_rcu(struct rcu_head *head)
|
|
||||||
{
|
|
||||||
kmem_cache_free(fasync_cache,
|
|
||||||
container_of(head, struct fasync_struct, fa_rcu));
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Remove a fasync entry. If successfully removed, return
|
* Remove a fasync entry. If successfully removed, return
|
||||||
* positive and clear the FASYNC flag. If no entry exists,
|
* positive and clear the FASYNC flag. If no entry exists,
|
||||||
@ -877,7 +871,7 @@ int fasync_remove_entry(struct file *filp, struct fasync_struct **fapp)
|
|||||||
write_unlock_irq(&fa->fa_lock);
|
write_unlock_irq(&fa->fa_lock);
|
||||||
|
|
||||||
*fp = fa->fa_next;
|
*fp = fa->fa_next;
|
||||||
call_rcu(&fa->fa_rcu, fasync_free_rcu);
|
kfree_rcu(fa, fa_rcu);
|
||||||
filp->f_flags &= ~FASYNC;
|
filp->f_flags &= ~FASYNC;
|
||||||
result = 1;
|
result = 1;
|
||||||
break;
|
break;
|
||||||
|
Loading…
Reference in New Issue
Block a user