[drivers/usb/gadget, drivers/media/v4l2-core] divide error in uvc_queue_setup

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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


[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux