[syzbot] [media?] [usb?] KASAN: slab-use-after-free Read in v4l2_open

1 view
Skip to first unread message

syzbot

unread,
3:21 AMĀ (11 hours ago)Ā 3:21 AM
to linux-...@vger.kernel.org, linux...@vger.kernel.org, linu...@vger.kernel.org, mch...@kernel.org, syzkall...@googlegroups.com
Hello,

syzbot found the following issue on:

HEAD commit: 8e5a478b6d6a Add linux-next specific files for 20260317
git tree: linux-next
console output: https://syzkaller.appspot.com/x/log.txt?x=1197006a580000
kernel config: https://syzkaller.appspot.com/x/.config?x=6f3ef9419150a4b1
dashboard link: https://syzkaller.appspot.com/bug?extid=1a7507a194fff09e5c44
compiler: Debian clang version 21.1.8 (++20251221033036+2078da43e25a-1~exp1~20251221153213.50), Debian LLD 21.1.8
syz repro: https://syzkaller.appspot.com/x/repro.syz?x=1161bd52580000
C reproducer: https://syzkaller.appspot.com/x/repro.c?x=16bfc216580000

Downloadable assets:
disk image: https://storage.googleapis.com/syzbot-assets/4fb0843c2e97/disk-8e5a478b.raw.xz
vmlinux: https://storage.googleapis.com/syzbot-assets/59d50c6221b4/vmlinux-8e5a478b.xz
kernel image: https://storage.googleapis.com/syzbot-assets/891eb3906306/bzImage-8e5a478b.xz

IMPORTANT: if you fix the issue, please add the following tag to the commit:
Reported-by: syzbot+1a7507...@syzkaller.appspotmail.com

==================================================================
BUG: KASAN: slab-use-after-free in v4l2_open+0x395/0x3a0 drivers/media/v4l2-core/v4l2-dev.c:444
Read of size 4 at addr ffff88801b168810 by task v4l_id/6152

CPU: 1 UID: 0 PID: 6152 Comm: v4l_id Not tainted syzkaller #0 PREEMPT(full)
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 02/12/2026
Call Trace:
<TASK>
dump_stack_lvl+0xe8/0x150 lib/dump_stack.c:120
print_address_description+0x55/0x1e0 mm/kasan/report.c:378
print_report+0x58/0x70 mm/kasan/report.c:482
kasan_report+0x117/0x150 mm/kasan/report.c:595
v4l2_open+0x395/0x3a0 drivers/media/v4l2-core/v4l2-dev.c:444
chrdev_open+0x4cd/0x5e0 fs/char_dev.c:411
do_dentry_open+0x785/0x14e0 fs/open.c:949
vfs_open+0x3b/0x340 fs/open.c:1081
do_open fs/namei.c:4693 [inline]
path_openat+0x2e08/0x3860 fs/namei.c:4852
do_file_open+0x23e/0x4a0 fs/namei.c:4881
do_sys_openat2+0x113/0x200 fs/open.c:1366
do_sys_open fs/open.c:1372 [inline]
__do_sys_openat fs/open.c:1388 [inline]
__se_sys_openat fs/open.c:1383 [inline]
__x64_sys_openat+0x138/0x170 fs/open.c:1383
do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
do_syscall_64+0x14d/0xf80 arch/x86/entry/syscall_64.c:94
entry_SYSCALL_64_after_hwframe+0x77/0x7f
RIP: 0033:0x7fa818fde407
Code: 48 89 fa 4c 89 df e8 38 aa 00 00 8b 93 08 03 00 00 59 5e 48 83 f8 fc 74 1a 5b c3 0f 1f 84 00 00 00 00 00 48 8b 44 24 10 0f 05 <5b> c3 0f 1f 80 00 00 00 00 83 e2 39 83 fa 08 75 de e8 23 ff ff ff
RSP: 002b:00007ffdbeaca3e0 EFLAGS: 00000202 ORIG_RAX: 0000000000000101
RAX: ffffffffffffffda RBX: 00007fa818f52880 RCX: 00007fa818fde407
RDX: 0000000000000000 RSI: 00007ffdbeacaf1c RDI: ffffffffffffff9c
RBP: 0000000000000002 R08: 0000000000000000 R09: 0000000000000000
R10: 0000000000000000 R11: 0000000000000202 R12: 0000000000000000
R13: 00007ffdbeaca630 R14: 00007fa819237000 R15: 0000562990aec4d8
</TASK>

Allocated by task 809:
kasan_save_stack mm/kasan/common.c:57 [inline]
kasan_save_track+0x3e/0x80 mm/kasan/common.c:78
poison_kmalloc_redzone mm/kasan/common.c:398 [inline]
__kasan_kmalloc+0x93/0xb0 mm/kasan/common.c:415
kasan_kmalloc include/linux/kasan.h:263 [inline]
__kmalloc_cache_noprof+0x31c/0x660 mm/slub.c:5412
kmalloc_noprof include/linux/slab.h:950 [inline]
kzalloc_noprof include/linux/slab.h:1188 [inline]
em28xx_v4l2_init+0x10b/0x2e70 drivers/media/usb/em28xx/em28xx-video.c:2538
em28xx_init_extension+0x120/0x1c0 drivers/media/usb/em28xx/em28xx-core.c:1117
process_one_work+0x9ab/0x1780 kernel/workqueue.c:3289
process_scheduled_works kernel/workqueue.c:3380 [inline]
worker_thread+0xba8/0x11e0 kernel/workqueue.c:3466
kthread+0x388/0x470 kernel/kthread.c:436
ret_from_fork+0x51e/0xb90 arch/x86/kernel/process.c:158
ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:245

Freed by task 809:
kasan_save_stack mm/kasan/common.c:57 [inline]
kasan_save_track+0x3e/0x80 mm/kasan/common.c:78
kasan_save_free_info+0x46/0x50 mm/kasan/generic.c:584
poison_slab_object mm/kasan/common.c:253 [inline]
__kasan_slab_free+0x5c/0x80 mm/kasan/common.c:285
kasan_slab_free include/linux/kasan.h:235 [inline]
slab_free_hook mm/slub.c:2689 [inline]
slab_free mm/slub.c:6242 [inline]
kfree+0x1c5/0x650 mm/slub.c:6557
em28xx_free_v4l2 drivers/media/usb/em28xx/em28xx-video.c:2118 [inline]
kref_put include/linux/kref.h:65 [inline]
em28xx_v4l2_init+0x1683/0x2e70 drivers/media/usb/em28xx/em28xx-video.c:2907
em28xx_init_extension+0x120/0x1c0 drivers/media/usb/em28xx/em28xx-core.c:1117
process_one_work+0x9ab/0x1780 kernel/workqueue.c:3289
process_scheduled_works kernel/workqueue.c:3380 [inline]
worker_thread+0xba8/0x11e0 kernel/workqueue.c:3466
kthread+0x388/0x470 kernel/kthread.c:436
ret_from_fork+0x51e/0xb90 arch/x86/kernel/process.c:158
ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:245

The buggy address belongs to the object at ffff88801b168000
which belongs to the cache kmalloc-8k of size 8192
The buggy address is located 2064 bytes inside of
freed 8192-byte region [ffff88801b168000, ffff88801b16a000)

The buggy address belongs to the physical page:
page: refcount:0 mapcount:0 mapping:0000000000000000 index:0x0 pfn:0x1b168
head: order:3 mapcount:0 entire_mapcount:0 nr_pages_mapped:0 pincount:0
flags: 0xfff00000000040(head|node=0|zone=1|lastcpupid=0x7ff)
page_type: f5(slab)
raw: 00fff00000000040 ffff88801b042280 dead000000000100 dead000000000122
raw: 0000000000000000 0000000800020002 00000000f5000000 0000000000000000
head: 00fff00000000040 ffff88801b042280 dead000000000100 dead000000000122
head: 0000000000000000 0000000800020002 00000000f5000000 0000000000000000
head: 00fff00000000003 fffffffffffffe01 00000000ffffffff 00000000ffffffff
head: ffffffffffffffff 0000000000000000 00000000ffffffff 0000000000000008
page dumped because: kasan: bad access detected
page_owner tracks the page as allocated
page last allocated via order 3, migratetype Unmovable, gfp_mask 0xd2040(__GFP_IO|__GFP_NOWARN|__GFP_NORETRY|__GFP_COMP|__GFP_NOMEMALLOC), pid 5499, tgid 5499 (S40network), ts 54008512816, free_ts 53918866034
set_page_owner include/linux/page_owner.h:32 [inline]
post_alloc_hook+0x231/0x280 mm/page_alloc.c:1857
prep_new_page mm/page_alloc.c:1865 [inline]
get_page_from_freelist+0x2418/0x24b0 mm/page_alloc.c:3924
__alloc_frozen_pages_noprof+0x233/0x3d0 mm/page_alloc.c:5211
alloc_slab_page mm/slub.c:3278 [inline]
allocate_slab+0x77/0x660 mm/slub.c:3467
new_slab mm/slub.c:3525 [inline]
refill_objects+0x339/0x3d0 mm/slub.c:7247
refill_sheaf mm/slub.c:2816 [inline]
__pcs_replace_empty_main+0x321/0x720 mm/slub.c:4651
alloc_from_pcs mm/slub.c:4749 [inline]
slab_alloc_node mm/slub.c:4883 [inline]
__kmalloc_cache_noprof+0x392/0x660 mm/slub.c:5407
kmalloc_noprof include/linux/slab.h:950 [inline]
kzalloc_noprof include/linux/slab.h:1188 [inline]
tomoyo_print_bprm security/tomoyo/audit.c:26 [inline]
tomoyo_init_log+0x112e/0x1fb0 security/tomoyo/audit.c:264
tomoyo_supervisor+0x353/0x1570 security/tomoyo/common.c:2232
tomoyo_audit_env_log security/tomoyo/environ.c:37 [inline]
tomoyo_env_perm+0x151/0x1f0 security/tomoyo/environ.c:64
tomoyo_environ security/tomoyo/domain.c:673 [inline]
tomoyo_find_next_domain+0x15cb/0x1aa0 security/tomoyo/domain.c:889
tomoyo_bprm_check_security+0x11b/0x180 security/tomoyo/tomoyo.c:102
security_bprm_check+0x85/0x240 security/security.c:794
search_binary_handler fs/exec.c:1654 [inline]
exec_binprm fs/exec.c:1696 [inline]
bprm_execve+0x8a2/0x1470 fs/exec.c:1748
do_execveat_common+0x50d/0x690 fs/exec.c:1846
__do_sys_execve fs/exec.c:1930 [inline]
__se_sys_execve fs/exec.c:1924 [inline]
__x64_sys_execve+0x97/0xc0 fs/exec.c:1924
page last free pid 5497 tgid 5497 stack trace:
reset_page_owner include/linux/page_owner.h:25 [inline]
__free_pages_prepare mm/page_alloc.c:1401 [inline]
__free_frozen_pages+0xbf0/0xd00 mm/page_alloc.c:2942
__slab_free+0x274/0x2c0 mm/slub.c:5605
qlink_free mm/kasan/quarantine.c:163 [inline]
qlist_free_all+0x99/0x100 mm/kasan/quarantine.c:179
kasan_quarantine_reduce+0x148/0x160 mm/kasan/quarantine.c:286
__kasan_slab_alloc+0x22/0x80 mm/kasan/common.c:350
kasan_slab_alloc include/linux/kasan.h:253 [inline]
slab_post_alloc_hook mm/slub.c:4569 [inline]
slab_alloc_node mm/slub.c:4898 [inline]
__kmalloc_cache_noprof+0x2ba/0x660 mm/slub.c:5407
kmalloc_noprof include/linux/slab.h:950 [inline]
tomoyo_print_header security/tomoyo/audit.c:156 [inline]
tomoyo_init_log+0x195/0x1fb0 security/tomoyo/audit.c:255
tomoyo_supervisor+0x353/0x1570 security/tomoyo/common.c:2232
tomoyo_audit_path_log security/tomoyo/file.c:169 [inline]
tomoyo_path_permission+0x25a/0x380 security/tomoyo/file.c:592
tomoyo_check_open_permission+0x2b2/0x470 security/tomoyo/file.c:782
security_file_open+0xa9/0x240 security/security.c:2661
do_dentry_open+0x384/0x14e0 fs/open.c:926
vfs_open+0x3b/0x340 fs/open.c:1081
do_open fs/namei.c:4693 [inline]
path_openat+0x2e08/0x3860 fs/namei.c:4852
do_file_open+0x23e/0x4a0 fs/namei.c:4881
do_sys_openat2+0x113/0x200 fs/open.c:1366

Memory state around the buggy address:
ffff88801b168700: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
ffff88801b168780: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
>ffff88801b168800: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
^
ffff88801b168880: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
ffff88801b168900: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
==================================================================


---
This report is generated by a bot. It may contain errors.
See https://goo.gl/tpsmEJ for more information about syzbot.
syzbot engineers can be reached at syzk...@googlegroups.com.

syzbot will keep track of this issue. See:
https://goo.gl/tpsmEJ#status for how to communicate with syzbot.

If the report is already addressed, let syzbot know by replying with:
#syz fix: exact-commit-title

If you want syzbot to run the reproducer, reply with:
#syz test: git://repo/address.git branch-or-commit-hash
If you attach or paste a git patch, syzbot will apply it before testing.

If you want to overwrite report's subsystems, reply with:
#syz set subsystems: new-subsystem
(See the list of subsystem names on the web dashboard)

If the report is a duplicate of another one, reply with:
#syz dup: exact-subject-of-another-report

If you want to undo deduplication, reply with:
#syz undup

Edward Adam Davis

unread,
5:00 AMĀ (9 hours ago)Ā 5:00 AM
to syzbot+1a7507...@syzkaller.appspotmail.com, linux-...@vger.kernel.org, syzkall...@googlegroups.com
#syz test

diff --git a/drivers/media/v4l2-core/v4l2-dev.c b/drivers/media/v4l2-core/v4l2-dev.c
index 6ce623a1245a..0639315f9611 100644
--- a/drivers/media/v4l2-core/v4l2-dev.c
+++ b/drivers/media/v4l2-core/v4l2-dev.c
@@ -423,7 +423,6 @@ static int v4l2_open(struct inode *inode, struct file *filp)
}
/* and increase the device refcount */
video_get(vdev);
- mutex_unlock(&videodev_lock);

if (!video_is_registered(vdev)) {
ret = -ENODEV;
@@ -448,6 +447,7 @@ static int v4l2_open(struct inode *inode, struct file *filp)
/* decrease the refcount in case of an error */
if (ret)
video_put(vdev);
+ mutex_unlock(&videodev_lock);
return ret;
}


syzbot

unread,
5:29 AMĀ (8 hours ago)Ā 5:29 AM
to ead...@qq.com, linux-...@vger.kernel.org, syzkall...@googlegroups.com
Hello,

syzbot has tested the proposed patch but the reproducer is still triggering an issue:
possible deadlock in em28xx_v4l2_open

======================================================
WARNING: possible circular locking dependency detected
syzkaller #0 Not tainted
------------------------------------------------------
v4l_id/6669 is trying to acquire lock:
ffff888030ac9cd0 (&dev->lock#3){+.+.}-{4:4}
, at: em28xx_v4l2_open+0xf0/0xa20 drivers/media/usb/em28xx/em28xx-video.c:2146

but task is already holding lock:
ffffffff8f6a0520 (videodev_lock){+.+.}-{4:4}, at: v4l2_open+0x32/0x3a0 drivers/media/v4l2-core/v4l2-dev.c:417

which lock already depends on the new lock.


the existing dependency chain (in reverse order) is:

-> #1 (videodev_lock
){+.+.}-{4:4}:
__mutex_lock_common kernel/locking/mutex.c:632 [inline]
__mutex_lock+0x19e/0x1420 kernel/locking/mutex.c:794
__video_register_device+0x54e/0x4d20 drivers/media/v4l2-core/v4l2-dev.c:1008
video_register_device include/media/v4l2-dev.h:390 [inline]
em28xx_v4l2_init+0x1d32/0x2e70 drivers/media/usb/em28xx/em28xx-video.c:2788
em28xx_init_extension+0x120/0x1c0 drivers/media/usb/em28xx/em28xx-core.c:1117
process_one_work+0x9ab/0x1780 kernel/workqueue.c:3288
process_scheduled_works kernel/workqueue.c:3379 [inline]
worker_thread+0xba8/0x11e0 kernel/workqueue.c:3465
kthread+0x388/0x470 kernel/kthread.c:436
ret_from_fork+0x51e/0xb90 arch/x86/kernel/process.c:158
ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:245

-> #0 (&dev->lock#3){+.+.}-{4:4}:
check_prev_add kernel/locking/lockdep.c:3165 [inline]
check_prevs_add kernel/locking/lockdep.c:3284 [inline]
validate_chain kernel/locking/lockdep.c:3908 [inline]
__lock_acquire+0x15a5/0x2cf0 kernel/locking/lockdep.c:5237
lock_acquire+0xf0/0x2e0 kernel/locking/lockdep.c:5868
__mutex_lock_common kernel/locking/mutex.c:632 [inline]
__mutex_lock+0x19e/0x1420 kernel/locking/mutex.c:794
em28xx_v4l2_open+0xf0/0xa20 drivers/media/usb/em28xx/em28xx-video.c:2146
v4l2_open+0x1b1/0x3a0 drivers/media/v4l2-core/v4l2-dev.c:432
chrdev_open+0x4cd/0x5e0 fs/char_dev.c:411
do_dentry_open+0x785/0x14e0 fs/open.c:949
vfs_open+0x3b/0x340 fs/open.c:1081
do_open fs/namei.c:4693 [inline]
path_openat+0x2e08/0x3860 fs/namei.c:4852
do_file_open+0x23e/0x4a0 fs/namei.c:4881
do_sys_openat2+0x113/0x200 fs/open.c:1366
do_sys_open fs/open.c:1372 [inline]
__do_sys_openat fs/open.c:1388 [inline]
__se_sys_openat fs/open.c:1383 [inline]
__x64_sys_openat+0x138/0x170 fs/open.c:1383
do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
do_syscall_64+0x14d/0xf80 arch/x86/entry/syscall_64.c:94
entry_SYSCALL_64_after_hwframe+0x77/0x7f

other info that might help us debug this:

Possible unsafe locking scenario:

CPU0 CPU1
---- ----
lock(videodev_lock);
lock(&dev->lock#3);
lock(videodev_lock);
lock(&dev->lock#3
);

*** DEADLOCK ***

1 lock held by v4l_id/6669:
#0:
ffffffff8f6a0520 (videodev_lock){+.+.}-{4:4}, at: v4l2_open+0x32/0x3a0 drivers/media/v4l2-core/v4l2-dev.c:417

stack backtrace:
CPU: 0 UID: 0 PID: 6669 Comm: v4l_id Not tainted syzkaller #0 PREEMPT(full)
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 02/12/2026
Call Trace:
<TASK>
dump_stack_lvl+0xe8/0x150 lib/dump_stack.c:120
print_circular_bug+0x2e1/0x300 kernel/locking/lockdep.c:2043
check_noncircular+0x12e/0x150 kernel/locking/lockdep.c:2175
check_prev_add kernel/locking/lockdep.c:3165 [inline]
check_prevs_add kernel/locking/lockdep.c:3284 [inline]
validate_chain kernel/locking/lockdep.c:3908 [inline]
__lock_acquire+0x15a5/0x2cf0 kernel/locking/lockdep.c:5237
lock_acquire+0xf0/0x2e0 kernel/locking/lockdep.c:5868
__mutex_lock_common kernel/locking/mutex.c:632 [inline]
__mutex_lock+0x19e/0x1420 kernel/locking/mutex.c:794
em28xx_v4l2_open+0xf0/0xa20 drivers/media/usb/em28xx/em28xx-video.c:2146
v4l2_open+0x1b1/0x3a0 drivers/media/v4l2-core/v4l2-dev.c:432
chrdev_open+0x4cd/0x5e0 fs/char_dev.c:411
do_dentry_open+0x785/0x14e0 fs/open.c:949
vfs_open+0x3b/0x340 fs/open.c:1081
do_open fs/namei.c:4693 [inline]
path_openat+0x2e08/0x3860 fs/namei.c:4852
do_file_open+0x23e/0x4a0 fs/namei.c:4881
do_sys_openat2+0x113/0x200 fs/open.c:1366
do_sys_open fs/open.c:1372 [inline]
__do_sys_openat fs/open.c:1388 [inline]
__se_sys_openat fs/open.c:1383 [inline]
__x64_sys_openat+0x138/0x170 fs/open.c:1383
do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
do_syscall_64+0x14d/0xf80 arch/x86/entry/syscall_64.c:94
entry_SYSCALL_64_after_hwframe+0x77/0x7f
RIP: 0033:0x7f80328a7407
Code: 48 89 fa 4c 89 df e8 38 aa 00 00 8b 93 08 03 00 00 59 5e 48 83 f8 fc 74 1a 5b c3 0f 1f 84 00 00 00 00 00 48 8b 44 24 10 0f 05 <5b> c3 0f 1f 80 00 00 00 00 83 e2 39 83 fa 08 75 de e8 23 ff ff ff
RSP: 002b:00007ffdfce9d3b0 EFLAGS: 00000202 ORIG_RAX: 0000000000000101
RAX: ffffffffffffffda RBX: 00007f8033087880 RCX: 00007f80328a7407
RDX: 0000000000000000 RSI: 00007ffdfce9df1d RDI: ffffffffffffff9c
RBP: 0000000000000002 R08: 0000000000000000 R09: 0000000000000000
R10: 0000000000000000 R11: 0000000000000202 R12: 0000000000000000
R13: 00007ffdfce9d600 R14: 00007f80331ee000 R15: 0000556e3f2c74d8
</TASK>


Tested on:

commit: 8e42d251 Add linux-next specific files for 20260318
git tree: linux-next
console output: https://syzkaller.appspot.com/x/log.txt?x=178e4a06580000
kernel config: https://syzkaller.appspot.com/x/.config?x=7f5b21566f9d8af6
dashboard link: https://syzkaller.appspot.com/bug?extid=1a7507a194fff09e5c44
compiler: Debian clang version 21.1.8 (++20251221033036+2078da43e25a-1~exp1~20251221153213.50), Debian LLD 21.1.8
patch: https://syzkaller.appspot.com/x/patch.diff?x=12e57352580000

Edward Adam Davis

unread,
8:20 AMĀ (6 hours ago)Ā 8:20 AM
to syzbot+1a7507...@syzkaller.appspotmail.com, linux-...@vger.kernel.org, syzkall...@googlegroups.com
#syz test

diff --git a/drivers/media/v4l2-core/v4l2-dev.c b/drivers/media/v4l2-core/v4l2-dev.c
index 6ce623a1245a..cf9279a2d990 100644
--- a/drivers/media/v4l2-core/v4l2-dev.c
+++ b/drivers/media/v4l2-core/v4l2-dev.c
@@ -423,14 +423,18 @@ static int v4l2_open(struct inode *inode, struct file *filp)
}
/* and increase the device refcount */
video_get(vdev);
- mutex_unlock(&videodev_lock);

if (!video_is_registered(vdev)) {
ret = -ENODEV;
goto done;
}

+ set_bit(V4L2_FL_BUSY, &vdev->flags);
+ mutex_unlock(&videodev_lock);
+
ret = vdev->fops->open(filp);
+
+ mutex_lock(&videodev_lock);
if (ret)
goto done;

@@ -448,6 +452,8 @@ static int v4l2_open(struct inode *inode, struct file *filp)
/* decrease the refcount in case of an error */
if (ret)
video_put(vdev);
+ clear_bit(V4L2_FL_BUSY, &vdev->flags);
+ mutex_unlock(&videodev_lock);
return ret;
}

@@ -1121,6 +1127,11 @@ void video_unregister_device(struct video_device *vdev)
return;

mutex_lock(&videodev_lock);
+ while (test_bit(V4L2_FL_BUSY, &vdev->flags)) {
+ mutex_unlock(&videodev_lock);
+ cond_resched();
+ mutex_lock(&videodev_lock);
+ }
/* This must be in a critical section to prevent a race with v4l2_open.
* Once this bit has been cleared video_get may never be called again.
*/
diff --git a/include/media/v4l2-dev.h b/include/media/v4l2-dev.h
index 2e0f6d2e6a78..83feb0a4f4d3 100644
--- a/include/media/v4l2-dev.h
+++ b/include/media/v4l2-dev.h
@@ -95,6 +95,7 @@ enum v4l2_video_device_flags {
V4L2_FL_USES_V4L2_FH = 1,
V4L2_FL_QUIRK_INVERTED_CROP = 2,
V4L2_FL_SUBDEV_RO_DEVNODE = 3,
+ V4L2_FL_BUSY = 4,
};

/* Priority helper functions */

syzbot

unread,
8:40 AMĀ (5 hours ago)Ā 8:40 AM
to linux-...@vger.kernel.org, syzkall...@googlegroups.com
For archival purposes, forwarding an incoming command email to
linux-...@vger.kernel.org, syzkall...@googlegroups.com.

***

Subject: [PATCH] media: em28xx: fix use-after-free in v4l2_open() during init error path
Author: karti...@gmail.com

#syz test: git://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git master


em28xx_v4l2_init() calls video_register_device() which makes the video
device immediately visible to userspace. At this point, v4l2_open() can
be called concurrently and access vdev->dev_debug which is embedded
inside the em28xx_v4l2 structure.

If a subsequent initialization step fails after video_register_device()
succeeds, the error cleanup path calls kref_put(&v4l2->ref) which drops
the reference count to zero and frees the em28xx_v4l2 structure via
em28xx_free_v4l2(). This results in a use-after-free when v4l2_open()
reads vdev->dev_debug from the already freed structure.

Fix this by adding kref_get(&v4l2->ref) at the end of successful
initialization, matching the kref_put() already present in
em28xx_v4l2_fini(). This ensures the v4l2 structure is not freed while
it is still accessible through the registered video device.

The following race triggers the bug:
em28xx_v4l2_init()
video_register_device() <- device visible to userspace
later step fails
goto unregister_dev
kref_put(&v4l2->ref) <- ref hits 0, struct freed!

v4l2_open() <- runs concurrently
reads vdev->dev_debug <- use-after-free!

Fixes: 47677e51e2a4 ("[media] em28xx: Only deallocate struct em28xx after finishing all extensions")
Reported-by: syzbot+1a7507...@syzkaller.appspotmail.com
Link: https://syzkaller.appspot.com/bug?extid=1a7507a194fff09e5c44
Signed-off-by: Deepanshu Kartikey <Karti...@gmail.com>
---
drivers/media/usb/em28xx/em28xx-video.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/media/usb/em28xx/em28xx-video.c b/drivers/media/usb/em28xx/em28xx-video.c
index 5f13f63fbdee..fe2a7771275d 100644
--- a/drivers/media/usb/em28xx/em28xx-video.c
+++ b/drivers/media/usb/em28xx/em28xx-video.c
@@ -2876,7 +2876,7 @@ static int em28xx_v4l2_init(struct em28xx *dev)
"V4L2 extension successfully initialized\n");

kref_get(&dev->ref);
-
+ kref_get(&v4l2->ref);
mutex_unlock(&dev->lock);
return 0;

--
2.43.0

Edward Adam Davis

unread,
12:45 PMĀ (1 hour ago)Ā 12:45 PM
to syzbot+1a7507...@syzkaller.appspotmail.com, linux-...@vger.kernel.org, syzkall...@googlegroups.com
#syz test

diff --git a/drivers/media/usb/em28xx/em28xx-video.c b/drivers/media/usb/em28xx/em28xx-video.c
index b0c184f237a7..563b4267588e 100644
--- a/drivers/media/usb/em28xx/em28xx-video.c
+++ b/drivers/media/usb/em28xx/em28xx-video.c
@@ -2147,7 +2147,7 @@ static int em28xx_v4l2_open(struct file *filp)
video_device_node_name(vdev), v4l2_type_names[fh_type],
v4l2->users);

- if (mutex_lock_interruptible(&dev->lock))
+ if (!mutex_trylock(&dev->lock))
return -ERESTARTSYS;

ret = v4l2_fh_open(filp);

Edward Adam Davis

unread,
12:49 PMĀ (1 hour ago)Ā 12:49 PM
to syzbot+1a7507...@syzkaller.appspotmail.com, linux-...@vger.kernel.org, linux...@vger.kernel.org, linu...@vger.kernel.org, mch...@kernel.org, syzkall...@googlegroups.com
The em28xx video device utilizes the same em28xx->lock during both the
extension initialization process and the open system call. This design
creates a race condition: if the extension initialization fails, the
video device undergoes a unregister a video4linux device process;
should an open call be initiated during this unregister, it is highly
likely to enter the open routine within the em28xx driver. At this
juncture, however, em28xx->lock remains held by the kwork responsible
for the extension initialization. Consequently, the open routine is
forced to wait for the unregister process to complete before it can
acquire em28xx->lock, once the lock is finally acquired, the subsequent
code execution proceeds to access the video device instance, an instance
that has, by that time, already been deregistered, thereby triggering
the uaf described in [1].

To mitigate this issue and prevent the UAF resulting from lock contention
over em28xx->lock between the open call and the extension initialization
routine, the lock acquisition method within the em28xx open call has been
modified to use trylock.

[1]
BUG: KASAN: slab-use-after-free in v4l2_open+0x395/0x3a0 drivers/media/v4l2-core/v4l2-dev.c:444
Call Trace:
v4l2_open+0x395/0x3a0 drivers/media/v4l2-core/v4l2-dev.c:444
chrdev_open+0x4cd/0x5e0 fs/char_dev.c:411
do_dentry_open+0x785/0x14e0 fs/open.c:949
vfs_open+0x3b/0x340 fs/open.c:1081

Allocated by task 809:
em28xx_v4l2_init+0x10b/0x2e70 drivers/media/usb/em28xx/em28xx-video.c:2538
em28xx_init_extension+0x120/0x1c0 drivers/media/usb/em28xx/em28xx-core.c:1117

Freed by task 809:
em28xx_free_v4l2 drivers/media/usb/em28xx/em28xx-video.c:2118 [inline]
kref_put include/linux/kref.h:65 [inline]
em28xx_v4l2_init+0x1683/0x2e70 drivers/media/usb/em28xx/em28xx-video.c:2907
em28xx_init_extension+0x120/0x1c0 drivers/media/usb/em28xx/em28xx-core.c:1117

Reported-by: syzbot+1a7507...@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=1a7507a194fff09e5c44
Tested-by: syzbot+1a7507...@syzkaller.appspotmail.com
Signed-off-by: Edward Adam Davis <ead...@qq.com>
---
drivers/media/usb/em28xx/em28xx-video.c | 2 +-
1 file changed, 1 insertions(+), 1 deletions(-)
--
2.43.0

Reply all
Reply to author
Forward
0 new messages