Dear Linux Developers for USB Gadget and Media, We encountered "divide error in uvc_queue_setup" when testing with Syzkaller and our generated specifications Linux version: Linux 6.12-rc2 (8cf0b93919e13d1e8d4466eb4080a4c4d9d66d7b) Configuration is attached. Syz and C reproducers are as below: ``` Syzkaller hit 'divide error in uvc_queue_setup' bug. Oops: divide error: 0000 [#1] PREEMPT SMP KASAN NOPTI CPU: 0 UID: 0 PID: 10411 Comm: syz-executor181 Not tainted 6.12.0-rc2-g8cf0b93919e1 #2 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.15.0-1 04/01/2014 RIP: 0010:uvc_queue_setup+0x17e/0x2d0 drivers/usb/gadget/function/uvc_queue.c:64 Code: 00 00 89 de e8 43 3d 4c f9 84 db 44 0f 45 f3 41 0f b6 c6 83 e5 03 41 0f af ef 0f af e8 41 ff c5 41 d1 ed 41 8d 44 2d ff 31 d2 <f7> f5 89 c5 bb 04 00 00 00 bf 04 00 00 00 89 c6 e8 6d 3e 4c f9 83 RSP: 0018:ffffc9000941f980 EFLAGS: 00010246 RAX: 0000000000012bff RBX: 0000000000000000 RCX: 0000000000000000 RDX: 0000000000000000 RSI: 0000000000000000 RDI: 0000000000000001 RBP: 0000000000000000 R08: ffffffff884e293d R09: 1ffff92001283f28 R10: dffffc0000000000 R11: ffffffff884e27e0 R12: ffff888041ede9e8 R13: 0000000000012c00 R14: 0000000000000001 R15: 000000000000ffff FS: 0000555571b063c0(0000) GS:ffff88802c200000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 0000000020004848 CR3: 000000004a948000 CR4: 0000000000752ef0 DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 DR3: 0000000000000000 DR6: 00000000fffe07f0 DR7: 0000000000000400 PKRU: 55555554 Call Trace: <TASK> vb2_core_reqbufs+0xbc4/0x17a0 drivers/media/common/videobuf2/videobuf2-core.c:945 uvcg_alloc_buffers+0x21/0x80 drivers/usb/gadget/function/uvc_queue.c:184 __video_do_ioctl+0xc88/0xde0 drivers/media/v4l2-core/v4l2-ioctl.c:3119 video_usercopy+0x8ff/0x11d0 drivers/media/v4l2-core/v4l2-ioctl.c:3460 v4l2_ioctl+0x18d/0x1e0 drivers/media/v4l2-core/v4l2-dev.c:364 vfs_ioctl fs/ioctl.c:51 [inline] __do_sys_ioctl fs/ioctl.c:907 [inline] __se_sys_ioctl+0xfa/0x170 fs/ioctl.c:893 do_syscall_x64 arch/x86/entry/common.c:52 [inline] do_syscall_64+0xf9/0x280 arch/x86/entry/common.c:83 entry_SYSCALL_64_after_hwframe+0x67/0x6f RIP: 0033:0x7fc8787f5b0d Code: 28 c3 e8 46 1e 00 00 66 0f 1f 44 00 00 f3 0f 1e fa 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 c7 c1 b8 ff ff ff f7 d8 64 89 01 48 RSP: 002b:00007ffc912327e8 EFLAGS: 00000246 ORIG_RAX: 0000000000000010 RAX: ffffffffffffffda RBX: 00007ffc912329e8 RCX: 00007fc8787f5b0d RDX: 0000000020004880 RSI: 00000000c0145608 RDI: 0000000000000003 RBP: 0000000000000001 R08: 00236f656469762f R09: 00007ffc912329e8 R10: 000000000000000f R11: 0000000000000246 R12: 0000000000000001 R13: 00007ffc912329d8 R14: 00007fc878873530 R15: 0000000000000001 </TASK> Modules linked in: ---[ end trace 0000000000000000 ]--- RIP: 0010:uvc_queue_setup+0x17e/0x2d0 drivers/usb/gadget/function/uvc_queue.c:64 Code: 00 00 89 de e8 43 3d 4c f9 84 db 44 0f 45 f3 41 0f b6 c6 83 e5 03 41 0f af ef 0f af e8 41 ff c5 41 d1 ed 41 8d 44 2d ff 31 d2 <f7> f5 89 c5 bb 04 00 00 00 bf 04 00 00 00 89 c6 e8 6d 3e 4c f9 83 RSP: 0018:ffffc9000941f980 EFLAGS: 00010246 RAX: 0000000000012bff RBX: 0000000000000000 RCX: 0000000000000000 RDX: 0000000000000000 RSI: 0000000000000000 RDI: 0000000000000001 RBP: 0000000000000000 R08: ffffffff884e293d R09: 1ffff92001283f28 R10: dffffc0000000000 R11: ffffffff884e27e0 R12: ffff888041ede9e8 R13: 0000000000012c00 R14: 0000000000000001 R15: 000000000000ffff FS: 0000555571b063c0(0000) GS:ffff88802c200000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 00007f2c816e7fd8 CR3: 000000004a948000 CR4: 0000000000752ef0 DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 DR3: 0000000000000000 DR6: 00000000fffe07f0 DR7: 0000000000000400 PKRU: 55555554 ---------------- Code disassembly (best guess): 0: 00 00 add %al,(%rax) 2: 89 de mov %ebx,%esi 4: e8 43 3d 4c f9 call 0xf94c3d4c 9: 84 db test %bl,%bl b: 44 0f 45 f3 cmovne %ebx,%r14d f: 41 0f b6 c6 movzbl %r14b,%eax 13: 83 e5 03 and $0x3,%ebp 16: 41 0f af ef imul %r15d,%ebp 1a: 0f af e8 imul %eax,%ebp 1d: 41 ff c5 inc %r13d 20: 41 d1 ed shr %r13d 23: 41 8d 44 2d ff lea -0x1(%r13,%rbp,1),%eax 28: 31 d2 xor %edx,%edx * 2a: f7 f5 div %ebp <-- trapping instruction 2c: 89 c5 mov %eax,%ebp 2e: bb 04 00 00 00 mov $0x4,%ebx 33: bf 04 00 00 00 mov $0x4,%edi 38: 89 c6 mov %eax,%esi 3a: e8 6d 3e 4c f9 call 0xf94c3eac 3f: 83 .byte 0x83 Syzkaller reproducer: # {Threaded:false Repeat:false RepeatTimes:0 Procs:1 Slowdown:1 Sandbox: SandboxArg:0 Leak:false NetInjection:false NetDevices:false NetReset:false Cgroups:false BinfmtMisc:false CloseFDs:false KCSAN:false DevlinkPCI:false NicVF:false USB:false VhciInjection:false Wifi:false IEEE802154:false Sysctl:false Swap:false UseTmpDir:false HandleSegv:false Repro:false Trace:false LegacyOptions:{Collide:false Fault:false FaultCall:0 FaultNth:0}} r0 = syz_open_dev$KGPT_video_syzkalm_dup(&(0x7f0000004840), 0x0, 0x0) ioctl$KGPT_GSMIOC_SETCONF_DLCI(r0, 0xc0145608, &(0x7f0000004880)={0xb, 0x2, 0x1}) C reproducer: // autogenerated by syzkaller (https://github.com/google/syzkaller) #define _GNU_SOURCE #include <endian.h> #include <fcntl.h> #include <stdint.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/stat.h> #include <sys/syscall.h> #include <sys/types.h> #include <unistd.h> static long syz_open_dev(volatile long a0, volatile long a1, volatile long a2) { if (a0 == 0xc || a0 == 0xb) { char buf[128]; sprintf(buf, "/dev/%s/%d:%d", a0 == 0xc ? "char" : "block", (uint8_t)a1, (uint8_t)a2); return open(buf, O_RDWR, 0); } else { char buf[1024]; char* hash; strncpy(buf, (char*)a0, sizeof(buf) - 1); buf[sizeof(buf) - 1] = 0; while ((hash = strchr(buf, '#'))) { *hash = '0' + (char)(a1 % 10); a1 /= 10; } return open(buf, a2, 0); } } uint64_t r[1] = {0xffffffffffffffff}; int main(void) { syscall(__NR_mmap, /*addr=*/0x1ffff000ul, /*len=*/0x1000ul, /*prot=*/0ul, /*flags=*/0x32ul, /*fd=*/-1, /*offset=*/0ul); syscall(__NR_mmap, /*addr=*/0x20000000ul, /*len=*/0x1000000ul, /*prot=*/7ul, /*flags=*/0x32ul, /*fd=*/-1, /*offset=*/0ul); syscall(__NR_mmap, /*addr=*/0x21000000ul, /*len=*/0x1000ul, /*prot=*/0ul, /*flags=*/0x32ul, /*fd=*/-1, /*offset=*/0ul); intptr_t res = 0; memcpy((void*)0x20004840, "/dev/video#\000", 12); res = -1; res = syz_open_dev(/*dev=*/0x20004840, /*id=*/0, /*flags=*/0); if (res != -1) r[0] = res; *(uint32_t*)0x20004880 = 0xb; *(uint32_t*)0x20004884 = 2; *(uint32_t*)0x20004888 = 1; *(uint32_t*)0x2000488c = 0; *(uint32_t*)0x20004890 = 0; *(uint32_t*)0x20004894 = 0; *(uint32_t*)0x20004898 = 0; *(uint32_t*)0x2000489c = 0; *(uint32_t*)0x200048a0 = 0; *(uint32_t*)0x200048a4 = 0; *(uint32_t*)0x200048a8 = 0; *(uint32_t*)0x200048ac = 0; *(uint32_t*)0x200048b0 = 0; *(uint32_t*)0x200048b4 = 0; syscall(__NR_ioctl, /*fd=*/r[0], /*cmd=*/0xc0145608, /*arg=*/0x20004880ul); return 0; } ``` For the fix, I am not sure whether it would be better to add the check for `req_size` in `uvc_queue_setup`. Besides, this issue could be related to this: https://www.spinics.net/lists/linux-usb/msg249147.html. If you have any questions or require more information, please feel free to contact us. Reported-by: Chenyuan Yang <chenyuan0y@xxxxxxxxx> Best, Chenyuan
Attachment:
config
Description: Binary data