mirror of
https://github.com/torvalds/linux.git
synced 2026-07-27 09:36:22 +02:00
bpf: fix UAF by restoring RCU-delayed inode freeing in bpffs
commit4f375ade6a("bpf: Avoid RCU context warning when unpinning htab with internal structs") moved inode cleanup from ->free_inode() into ->destroy_inode() to avoid sleeping in RCU context when calling bpf_any_put(). However this removed the RCU delay on freeing the inode itself and the cached symlink body (i_link), both of which can be accessed by RCU pathwalk (pick_link, may_lookup etc.). This causes a use-after-free when a concurrent unlinkat() drops the last inode reference and destroy_inode() frees the inode immediately, while another task is still walking the path in RCU mode and reads inode->i_opflags (offset +2) inside current_time() -> is_mgtime(). KASAN reports: BUG: KASAN: slab-use-after-free in is_mgtime include/linux/fs.h:2313 Read of size 2 at addr ffff8880407e4282 (offset +2 = i_opflags) The rules (per Al Viro): ->destroy_inode() called immediately, can sleep, use for blocking cleanup e.g. bpf_any_put() ->free_inode() called after RCU grace period, use for freeing inode and anything RCU-accessible e.g. i_link Fix: split the two concerns properly: - keep bpf_any_put() in bpf_destroy_inode() since it is blocking and needs to run promptly - introduce bpf_free_inode() to handle kfree(i_link) and free_inode_nonrcu() with proper RCU delay, preventing the UAF Fixes:4f375ade6a("bpf: Avoid RCU context warning when unpinning htab with internal structs") Reported-by: syzbot+36e50496c8ac4bcde3f9@syzkaller.appspotmail.com Closes: https://syzkaller.appspot.com/bug?extid=36e50496c8ac4bcde3f9 Suggested-by: Al Viro <viro@zeniv.linux.org.uk> Link: https://lore.kernel.org/all/20260423043906.GN3518998@ZenIV/ Link: https://lore.kernel.org/all/20260602002607.110866-1-kartikey406@gmail.com/T/ [v1] Signed-off-by: Deepanshu Kartikey <kartikey406@gmail.com> Acked-by: Al Viro <viro@zeniv.linux.org.uk> Link: https://lore.kernel.org/r/20260602025249.113828-1-kartikey406@gmail.com Signed-off-by: Alexei Starovoitov <ast@kernel.org>
This commit is contained in:
parent
51321158a3
commit
b93c55b493
|
|
@ -766,10 +766,18 @@ static void bpf_destroy_inode(struct inode *inode)
|
|||
{
|
||||
enum bpf_type type;
|
||||
|
||||
if (S_ISLNK(inode->i_mode))
|
||||
kfree(inode->i_link);
|
||||
if (!bpf_inode_type(inode, &type))
|
||||
bpf_any_put(inode->i_private, type);
|
||||
}
|
||||
|
||||
/*
|
||||
* Called after RCU grace period - safe to free inode and anything
|
||||
* that might be accessed by RCU pathwalk (inode fields, i_link).
|
||||
*/
|
||||
static void bpf_free_inode(struct inode *inode)
|
||||
{
|
||||
if (S_ISLNK(inode->i_mode))
|
||||
kfree(inode->i_link);
|
||||
free_inode_nonrcu(inode);
|
||||
}
|
||||
|
||||
|
|
@ -778,6 +786,7 @@ const struct super_operations bpf_super_ops = {
|
|||
.drop_inode = inode_just_drop,
|
||||
.show_options = bpf_show_options,
|
||||
.destroy_inode = bpf_destroy_inode,
|
||||
.free_inode = bpf_free_inode,
|
||||
};
|
||||
|
||||
enum {
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user