There is a potential race between fuse_read_interrupt and fuse_dev_do_write contexts as shown below: TASK1: fuse_dev_do_write: TASK2: fuse_dev_do_read: spin_lock(&fiq->lock); fuse_read_interrupt(); list_del_init(&req->intr_entry); fuse_request_end()//now req->intr_entry //is empty so put this req TASK3: fuse_flash: fuse_simple_request(); fuse_put_request(); kmem_cache_free();//free req After TASK3 free req, TASK2 access this req in fuse_read_interrupt and gets below crash: ================================================================== [ 63.712079] BUG: KASAN: use-after-free in fuse_read_interrupt+0x18c/0x948 [ 63.712084] Read of size 8 at addr ffffff8049797d50 by task Thread-5/5508 [ 63.712093] CPU: 4 PID: 5508 Comm: Thread-5 Tainted: G S O 5.4.86-qgki-debug-ge1de60c2024c #1 [ 63.712096] Call trace: [ 63.712100] dump_backtrace+0x0/0x2cc [ 63.712102] show_stack+0x18/0x24 [ 63.712106] dump_stack+0x134/0x1c4 [ 63.712109] print_address_description+0x88/0x578 [ 63.712111] __kasan_report+0x1c4/0x1e0 [ 63.712113] kasan_report+0x14/0x20 [ 63.712115] __asan_report_load8_noabort+0x1c/0x28 [ 63.712117] fuse_read_interrupt+0x18c/0x948 [ 63.712119] fuse_dev_do_read+0x678/0x11a0 [ 63.712121] fuse_dev_read+0x108/0x17c [ 63.712124] __vfs_read+0x408/0x544 [ 63.712126] vfs_read+0x114/0x2a8 [ 63.712127] ksys_read+0xd8/0x18c [ 63.712129] __arm64_sys_read+0x78/0x8c [ 63.712132] el0_svc_common+0x134/0x2cc [ 63.712134] el0_svc_handler+0xd0/0xe0 [ 63.712136] el0_svc+0x8/0xc [ 63.712137] [ 63.712141] Allocated by task 5535: [ 63.712146] __kasan_kmalloc+0x100/0x1c0 [ 63.712148] kasan_slab_alloc+0x18/0x24 [ 63.712150] kmem_cache_alloc+0x320/0x3c4 [ 63.712152] fuse_get_req+0x1f0/0x6a4 [ 63.712154] fuse_simple_request+0x5c/0xb90 [ 63.712156] fuse_flush_times+0x340/0x474 [ 63.712158] fuse_write_inode+0x90/0xc4 [ 63.712160] write_inode+0x1ec/0x478 [ 63.712162] __writeback_single_inode+0x420/0x838 [ 63.712165] writeback_single_inode+0x128/0x708 [ 63.712167] write_inode_now+0x2b0/0x370 [ 63.712169] fuse_release+0x9c/0x100 [ 63.712171] __fput+0x18c/0x4a8 [ 63.712173] ____fput+0x10/0x1c [ 63.712176] task_work_run+0x118/0x1ec [ 63.712178] do_exit+0x500/0x1810 [ 63.712179] do_group_exit+0x1c8/0x200 [ 63.712182] get_signal+0xc44/0x1194 [ 63.712183] do_signal+0x134/0x464 [ 63.712185] do_notify_resume+0x110/0x1c4 [ 63.712187] work_pending+0x8/0x14 [ 63.712188] [ 63.712191] Freed by task 5535: [ 63.712194] __kasan_slab_free+0x168/0x238 [ 63.712196] kasan_slab_free+0x14/0x24 [ 63.712198] slab_free_freelist_hook+0xe0/0x164 [ 63.712201] kmem_cache_free+0xfc/0x358 [ 63.712202] fuse_put_request+0x148/0x1a4 [ 63.712204] fuse_simple_request+0x810/0xb90 [ 63.712206] fuse_flush_times+0x340/0x474 [ 63.712208] fuse_write_inode+0x90/0xc4 [ 63.712210] write_inode+0x1ec/0x478 [ 63.712212] __writeback_single_inode+0x420/0x838 [ 63.712214] writeback_single_inode+0x128/0x708 [ 63.712217] write_inode_now+0x2b0/0x370 [ 63.712219] fuse_release+0x9c/0x100 [ 63.712221] __fput+0x18c/0x4a8 [ 63.712222] ____fput+0x10/0x1c [ 63.712224] task_work_run+0x118/0x1ec [ 63.712226] do_exit+0x500/0x1810 [ 63.712228] do_group_exit+0x1c8/0x200 [ 63.712229] get_signal+0xc44/0x1194 [ 63.712231] do_signal+0x134/0x464 [ 63.712233] do_notify_resume+0x110/0x1c4 [ 63.712235] work_pending+0x8/0x14 Put list_del_init after the code access req, if intr_entry not empty, fuse_request_end will wait for fiq->lock, req will not free before TASK2 unlock fiq->lock. Signed-off-by: lijiazi <lijiazi@xxxxxxxxxx> --- fs/fuse/dev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c index 817a0b1..bef21b2 100644 --- a/fs/fuse/dev.c +++ b/fs/fuse/dev.c @@ -1045,13 +1045,13 @@ __releases(fiq->lock) unsigned reqsize = sizeof(ih) + sizeof(arg); int err; - list_del_init(&req->intr_entry); memset(&ih, 0, sizeof(ih)); memset(&arg, 0, sizeof(arg)); ih.len = reqsize; ih.opcode = FUSE_INTERRUPT; ih.unique = (req->in.h.unique | FUSE_INT_REQ_BIT); arg.unique = req->in.h.unique; + list_del_init(&req->intr_entry); spin_unlock(&fiq->lock); if (nbytes < reqsize) -- 2.7.4