Skip to contentSkip to conversation

WARNING in usb_free_urb

DISCUSSION [email protected] 4 participants 6 messages Jun 26 – Jun 29

Subsystems (3)
lore
Share & tools
lore
#0 lore raw

Good day, dear maintainers,

We found a bug using a modified version of syzkaller.

Kernel Branch: 7.0-rc1
Kernel Config: <https://drive.google.com/open?id=1zJHAs5GUroGFBkxAlzfDaWAd_NVPZTfJ>
Unfortunately, we don't have any reproducer for this bug yet.
Thank you!

Best regards,
Sanan Hasanov

179683 pages reserved
0 pages cma reserved
Memory cgroup min protection 0kB -- low protection 0kB

------------[ cut here ]------------
!PageLargeKmalloc(page)
WARNING: mm/slub.c:6352 at free_large_kmalloc+0xb3/0x160 mm/slub.c:6352, CPU#1: kworker/1:4/12317
Modules linked in:
CPU: 1 UID: 0 PID: 12317 Comm: kworker/1:4 Tainted: G             L      7.0.0-rc1 #1 PREEMPT(full) 
Tainted: [L]=SOFTLOCKUP
Hardware name: QEMU Ubuntu 24.04 PC v2 (i440FX + PIIX, arch_caps fix, 1996), BIOS 1.16.3-debian-1.16.3-2 04/01/2014
Workqueue: events request_module_async
RIP: 0010:free_large_kmalloc+0xb3/0x160 mm/slub.c:6352
Code: 25 00 00 00 ff 3d 00 00 00 f8 0f 85 a6 00 00 00 c7 43 30 ff ff ff ff 48 89 df 44 89 f6 e8 45 d9 fc ff 5b 41 5e 41 5f 5d c3 90 <0f> 0b 90 48 89 df 48 c7 c6 b7 4c 72 8d e8 cb e8 08 ff eb e4 90 0f
RSP: 0018:ffffc900028e76f8 EFLAGS: 00010287
RAX: 00000000f0000000 RBX: ffffea00019a5c00 RCX: ffff888067550001
RDX: 0000000000000000 RSI: ffff888066970000 RDI: ffffea00019a5c00
RBP: ffffc900028e7710 R08: ffff888049c40603 R09: 1ffff110093880c0
R10: dffffc0000000000 R11: ffffed10093880c1 R12: ffff888066970000
R13: ffffffff870bc0f1 R14: 0000000000000000 R15: dffffc0000000000
FS:  0000000000000000(0000) GS:ffff8880ef136000(0000) knlGS:0000000000000000
CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 00007fba7e4bf008 CR3: 000000005776b000 CR4: 00000000000006f0
Call Trace:
 <TASK>
 kfree+0xae/0x630 mm/slub.c:6437
 urb_destroy drivers/usb/core/urb.c:25 [inline]
 kref_put include/linux/kref.h:65 [inline]
 usb_free_urb+0xd1/0x120 drivers/usb/core/urb.c:96
 em28xx_uninit_usb_xfer+0x165/0x310 drivers/media/usb/em28xx/em28xx-core.c:833
 em28xx_alloc_urbs+0xf2a/0x1130 drivers/media/usb/em28xx/em28xx-core.c:-1
 em28xx_dvb_init+0x2b0/0x4a20 drivers/media/usb/em28xx/em28xx-dvb.c:-1
 em28xx_init_extension+0x121/0x1d0 drivers/media/usb/em28xx/em28xx-core.c:1117
 request_module_async+0x5e/0x80 drivers/media/usb/em28xx/em28xx-cards.c:3457
 process_one_work kernel/workqueue.c:3275 [inline]
 process_scheduled_works+0xae1/0x1800 kernel/workqueue.c:3358
 worker_thread+0xa0f/0xf70 kernel/workqueue.c:3439
 kthread+0x37d/0x470 kernel/kthread.c:467
 ret_from_fork+0x507/0xb90 arch/x86/kernel/process.c:158
 ret_from_fork_asm+0x11/0x20 arch/x86/entry/entry_64.S:245
 </TASK>

<<<<<<<<<<<<<<< tail report >>>>>>>>>>>>>>>

Modules linked in:
CPU: 1 UID: 0 PID: 12317 Comm: kworker/1:4 Tainted: G             L      7.0.0-rc1 #1 PREEMPT(full) 
Tainted: [L]=SOFTLOCKUP
Hardware name: QEMU Ubuntu 24.04 PC v2 (i440FX + PIIX, arch_caps fix, 1996), BIOS 1.16.3-debian-1.16.3-2 04/01/2014
Workqueue: events request_module_async
RIP: 0010:free_large_kmalloc+0xb3/0x160
Code: 25 00 00 00 ff 3d 00 00 00 f8 0f 85 a6 00 00 00 c7 43 30 ff ff ff ff 48 89 df 44 89 f6 e8 45 d9 fc ff 5b 41 5e 41 5f 5d c3 90 <0f> 0b 90 48 89 df 48 c7 c6 b7 4c 72 8d e8 cb e8 08 ff eb e4 90 0f
RSP: 0018:ffffc900028e76f8 EFLAGS: 00010287
RAX: 00000000f0000000 RBX: ffffea00019a5c00 RCX: ffff888067550001
RDX: 0000000000000000 RSI: ffff888066970000 RDI: ffffea00019a5c00
RBP: ffffc900028e7710 R08: ffff888049c40603 R09: 1ffff110093880c0
R10: dffffc0000000000 R11: ffffed10093880c1 R12: ffff888066970000
R13: ffffffff870bc0f1 R14: 0000000000000000 R15: dffffc0000000000
FS:  0000000000000000(0000) GS:ffff8880ef136000(0000) knlGS:0000000000000000
CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 00007fba7e4bf008 CR3: 000000005776b000 CR4: 00000000000006f0
Call Trace:
 <TASK>
 kfree+0xae/0x630
 usb_free_urb+0xd1/0x120
 em28xx_uninit_usb_xfer+0x165/0x310
 em28xx_alloc_urbs+0xf2a/0x1130
 em28xx_dvb_init+0x2b0/0x4a20
 em28xx_init_extension+0x121/0x1d0
 request_module_async+0x5e/0x80
 process_scheduled_works+0xae1/0x1800
 worker_thread+0xa0f/0xf70
 kthread+0x37d/0x470
 ret_from_fork+0x507/0xb90
 ret_from_fork_asm+0x11/0x20
 </TASK>
Kernel panic - not syncing: kernel: panic_on_warn set ...
CPU: 1 UID: 0 PID: 12317 Comm: kworker/1:4 Tainted: G             L      7.0.0-rc1 #1 PREEMPT(full) 
Tainted: [L]=SOFTLOCKUP
Hardware name: QEMU Ubuntu 24.04 PC v2 (i440FX + PIIX, arch_caps fix, 1996), BIOS 1.16.3-debian-1.16.3-2 04/01/2014
Workqueue: events request_module_async
Call Trace:
 <TASK>
 __dump_stack+0x21/0x30
 dump_stack_lvl+0x2b/0x150
 dump_stack+0x19/0x20
 vpanic+0x53e/0xa20
 panic+0xb9/0xc0
 __warn+0x320/0x500
 __report_bug+0x28d/0x500
 report_bug+0x175/0x220
 handle_bug+0x9c/0x200
 exc_invalid_op+0x1f/0x50
 asm_exc_invalid_op+0x1f/0x30
RIP: 0010:free_large_kmalloc+0xb3/0x160
Code: 25 00 00 00 ff 3d 00 00 00 f8 0f 85 a6 00 00 00 c7 43 30 ff ff ff ff 48 89 df 44 89 f6 e8 45 d9 fc ff 5b 41 5e 41 5f 5d c3 90 <0f> 0b 90 48 89 df 48 c7 c6 b7 4c 72 8d e8 cb e8 08 ff eb e4 90 0f
RSP: 0018:ffffc900028e76f8 EFLAGS: 00010287
RAX: 00000000f0000000 RBX: ffffea00019a5c00 RCX: ffff888067550001
RDX: 0000000000000000 RSI: ffff888066970000 RDI: ffffea00019a5c00
RBP: ffffc900028e7710 R08: ffff888049c40603 R09: 1ffff110093880c0
R10: dffffc0000000000 R11: ffffed10093880c1 R12: ffff888066970000
R13: ffffffff870bc0f1 R14: 0000000000000000 R15: dffffc0000000000
 kfree+0xae/0x630
 usb_free_urb+0xd1/0x120
 em28xx_uninit_usb_xfer+0x165/0x310
 em28xx_alloc_urbs+0xf2a/0x1130
 em28xx_dvb_init+0x2b0/0x4a20
 em28xx_init_extension+0x121/0x1d0
 request_module_async+0x5e/0x80
 process_scheduled_works+0xae1/0x1800
 worker_thread+0xa0f/0xf70
 kthread+0x37d/0x470
 ret_from_fork+0x507/0xb90
 ret_from_fork_asm+0x11/0x20
 </TASK>

Kernel Offset: disabled
Rebooting in 86400 seconds..

<<<<<<<<<<<<<<< tail report >>>>>>>>>>>>>>>

#1 lore raw
Quoted 3 lines · On 6/26/26 23:27, [email protected] wrote:

Good day, dear maintainers,

We found a bug using a modified version of syzkaller.

Subject says "usb_free_urb" but you only CC'd slab maintainers, where slab slab is most likely a victim here of e.g. double kfree() or a kfree() of otherwise broken pointer.

Ccing USB and EM28XX maintainers. But they can feel free to ignore this per the next point.

Quoted 1 line

Kernel Branch: 7.0-rc1

Why use such a version for fuzzing? rc1 will have many bugs that are already fixed in 7.0 final. And it's not even latest, 7.1 was released 2 weeks ago too.

Quoted 7 lines

Kernel Config: <https://drive.google.com/open?id=1zJHAs5GUroGFBkxAlzfDaWAd_NVPZTfJ>
Unfortunately, we don't have any reproducer for this bug yet.
Thank you!

Best regards,
Sanan Hasanov

Quoted 6 lines

179683 pages reserved
0 pages cma reserved
Memory cgroup min protection 0kB -- low protection 0kB

------------[ cut here ]------------
!PageLargeKmalloc(page)
WARNING: mm/slub.c:6352 at free_large_kmalloc+0xb3/0x160 mm/slub.c:6352, CPU#1: kworker/1:4/12317

A kfree() was attempted on a pointer that's neither from a slab page nor a large kmalloc page. Might be double free or corrupted.

Quoted 12 lines
Modules linked in:
CPU: 1 UID: 0 PID: 12317 Comm: kworker/1:4 Tainted: G             L      7.0.0-rc1 #1 PREEMPT(full) 
Tainted: [L]=SOFTLOCKUP
Hardware name: QEMU Ubuntu 24.04 PC v2 (i440FX + PIIX, arch_caps fix, 1996), BIOS 1.16.3-debian-1.16.3-2 04/01/2014
Workqueue: events request_module_async
RIP: 0010:free_large_kmalloc+0xb3/0x160 mm/slub.c:6352
Code: 25 00 00 00 ff 3d 00 00 00 f8 0f 85 a6 00 00 00 c7 43 30 ff ff ff ff 48 89 df 44 89 f6 e8 45 d9 fc ff 5b 41 5e 41 5f 5d c3 90 <0f> 0b 90 48 89 df 48 c7 c6 b7 4c 72 8d e8 cb e8 08 ff eb e4 90 0f
RSP: 0018:ffffc900028e76f8 EFLAGS: 00010287
RAX: 00000000f0000000 RBX: ffffea00019a5c00 RCX: ffff888067550001
RDX: 0000000000000000 RSI: ffff888066970000 RDI: ffffea00019a5c00
RBP: ffffc900028e7710 R08: ffff888049c40603 R09: 1ffff110093880c0
R10: dffffc0000000000 R11: ffffed10093880c1 R12: ffff888066970000
Quoted 8 lines
R13: ffffffff870bc0f1 R14: 0000000000000000 R15: dffffc0000000000
FS:  0000000000000000(0000) GS:ffff8880ef136000(0000) knlGS:0000000000000000
CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 00007fba7e4bf008 CR3: 000000005776b000 CR4: 00000000000006f0
Call Trace:
 <TASK>
 kfree+0xae/0x630 mm/slub.c:6437
 urb_destroy drivers/usb/core/urb.c:25 [inline]

static void urb_destroy(struct kref *kref)

{
        struct urb *urb = to_urb(kref);

        if (urb->transfer_flags & URB_FREE_BUFFER)
                kfree(urb->transfer_buffer);  <--- this one

        kfree(urb);
}
Quoted 2 lines
 kref_put include/linux/kref.h:65 [inline]
 usb_free_urb+0xd1/0x120 drivers/usb/core/urb.c:96

USB layer itself is likely also not the root cause.

Quoted 4 lines
 em28xx_uninit_usb_xfer+0x165/0x310 drivers/media/usb/em28xx/em28xx-core.c:833
 em28xx_alloc_urbs+0xf2a/0x1130 drivers/media/usb/em28xx/em28xx-core.c:-1
 em28xx_dvb_init+0x2b0/0x4a20 drivers/media/usb/em28xx/em28xx-dvb.c:-1
 em28xx_init_extension+0x121/0x1d0 drivers/media/usb/em28xx/em28xx-core.c:1117

So it might be this driver doing something wrong?

Quoted 85 lines
 request_module_async+0x5e/0x80 drivers/media/usb/em28xx/em28xx-cards.c:3457
 process_one_work kernel/workqueue.c:3275 [inline]
 process_scheduled_works+0xae1/0x1800 kernel/workqueue.c:3358
 worker_thread+0xa0f/0xf70 kernel/workqueue.c:3439
 kthread+0x37d/0x470 kernel/kthread.c:467
 ret_from_fork+0x507/0xb90 arch/x86/kernel/process.c:158
 ret_from_fork_asm+0x11/0x20 arch/x86/entry/entry_64.S:245
 </TASK>

<<<<<<<<<<<<<<< tail report >>>>>>>>>>>>>>>

Modules linked in:
CPU: 1 UID: 0 PID: 12317 Comm: kworker/1:4 Tainted: G             L      7.0.0-rc1 #1 PREEMPT(full) 
Tainted: [L]=SOFTLOCKUP
Hardware name: QEMU Ubuntu 24.04 PC v2 (i440FX + PIIX, arch_caps fix, 1996), BIOS 1.16.3-debian-1.16.3-2 04/01/2014
Workqueue: events request_module_async
RIP: 0010:free_large_kmalloc+0xb3/0x160
Code: 25 00 00 00 ff 3d 00 00 00 f8 0f 85 a6 00 00 00 c7 43 30 ff ff ff ff 48 89 df 44 89 f6 e8 45 d9 fc ff 5b 41 5e 41 5f 5d c3 90 <0f> 0b 90 48 89 df 48 c7 c6 b7 4c 72 8d e8 cb e8 08 ff eb e4 90 0f
RSP: 0018:ffffc900028e76f8 EFLAGS: 00010287
RAX: 00000000f0000000 RBX: ffffea00019a5c00 RCX: ffff888067550001
RDX: 0000000000000000 RSI: ffff888066970000 RDI: ffffea00019a5c00
RBP: ffffc900028e7710 R08: ffff888049c40603 R09: 1ffff110093880c0
R10: dffffc0000000000 R11: ffffed10093880c1 R12: ffff888066970000
R13: ffffffff870bc0f1 R14: 0000000000000000 R15: dffffc0000000000
FS:  0000000000000000(0000) GS:ffff8880ef136000(0000) knlGS:0000000000000000
CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 00007fba7e4bf008 CR3: 000000005776b000 CR4: 00000000000006f0
Call Trace:
 <TASK>
 kfree+0xae/0x630
 usb_free_urb+0xd1/0x120
 em28xx_uninit_usb_xfer+0x165/0x310
 em28xx_alloc_urbs+0xf2a/0x1130
 em28xx_dvb_init+0x2b0/0x4a20
 em28xx_init_extension+0x121/0x1d0
 request_module_async+0x5e/0x80
 process_scheduled_works+0xae1/0x1800
 worker_thread+0xa0f/0xf70
 kthread+0x37d/0x470
 ret_from_fork+0x507/0xb90
 ret_from_fork_asm+0x11/0x20
 </TASK>
Kernel panic - not syncing: kernel: panic_on_warn set ...
CPU: 1 UID: 0 PID: 12317 Comm: kworker/1:4 Tainted: G             L      7.0.0-rc1 #1 PREEMPT(full) 
Tainted: [L]=SOFTLOCKUP
Hardware name: QEMU Ubuntu 24.04 PC v2 (i440FX + PIIX, arch_caps fix, 1996), BIOS 1.16.3-debian-1.16.3-2 04/01/2014
Workqueue: events request_module_async
Call Trace:
 <TASK>
 __dump_stack+0x21/0x30
 dump_stack_lvl+0x2b/0x150
 dump_stack+0x19/0x20
 vpanic+0x53e/0xa20
 panic+0xb9/0xc0
 __warn+0x320/0x500
 __report_bug+0x28d/0x500
 report_bug+0x175/0x220
 handle_bug+0x9c/0x200
 exc_invalid_op+0x1f/0x50
 asm_exc_invalid_op+0x1f/0x30
RIP: 0010:free_large_kmalloc+0xb3/0x160
Code: 25 00 00 00 ff 3d 00 00 00 f8 0f 85 a6 00 00 00 c7 43 30 ff ff ff ff 48 89 df 44 89 f6 e8 45 d9 fc ff 5b 41 5e 41 5f 5d c3 90 <0f> 0b 90 48 89 df 48 c7 c6 b7 4c 72 8d e8 cb e8 08 ff eb e4 90 0f
RSP: 0018:ffffc900028e76f8 EFLAGS: 00010287
RAX: 00000000f0000000 RBX: ffffea00019a5c00 RCX: ffff888067550001
RDX: 0000000000000000 RSI: ffff888066970000 RDI: ffffea00019a5c00
RBP: ffffc900028e7710 R08: ffff888049c40603 R09: 1ffff110093880c0
R10: dffffc0000000000 R11: ffffed10093880c1 R12: ffff888066970000
R13: ffffffff870bc0f1 R14: 0000000000000000 R15: dffffc0000000000
 kfree+0xae/0x630
 usb_free_urb+0xd1/0x120
 em28xx_uninit_usb_xfer+0x165/0x310
 em28xx_alloc_urbs+0xf2a/0x1130
 em28xx_dvb_init+0x2b0/0x4a20
 em28xx_init_extension+0x121/0x1d0
 request_module_async+0x5e/0x80
 process_scheduled_works+0xae1/0x1800
 worker_thread+0xa0f/0xf70
 kthread+0x37d/0x470
 ret_from_fork+0x507/0xb90
 ret_from_fork_asm+0x11/0x20
 </TASK>

Kernel Offset: disabled
Rebooting in 86400 seconds..

<<<<<<<<<<<<<<< tail report >>>>>>>>>>>>>>>

#2 lore raw
Quoted 9 lines · Vlastimil Babka (SUSE)
Quoted 3 lines · On 6/26/26 23:27, [email protected] wrote:

Good day, dear maintainers,

We found a bug using a modified version of syzkaller.

Subject says "usb_free_urb" but you only CC'd slab maintainers, where slab slab is most likely a victim here of e.g. double kfree() or a kfree() of otherwise broken pointer.

Quoted 8 lines

Ccing USB and EM28XX maintainers. But they can feel free to ignore this per the next point.

Quoted 1 line

Kernel Branch: 7.0-rc1

Why use such a version for fuzzing? rc1 will have many bugs that are already fixed in 7.0 final. And it's not even latest, 7.1 was released 2 weeks ago too.

To be fair, em28xx had no changes since 2024 until 7.1-rc1, so the bug must be present in various stable releases and likely in mainline too.

Quoted 23 lines
Quoted 1 line
WARNING: mm/slub.c:6352 at free_large_kmalloc+0xb3/0x160 mm/slub.c:6352, CPU#1: kworker/1:4/12317  

A kfree() was attempted on a pointer that's neither from a slab page nor a large kmalloc page. Might be double free or corrupted.

Quoted 4 lines
Call Trace:
 <TASK>
 kfree+0xae/0x630 mm/slub.c:6437
 urb_destroy drivers/usb/core/urb.c:25 [inline]  

static void urb_destroy(struct kref *kref)

{
        struct urb *urb = to_urb(kref);

        if (urb->transfer_flags & URB_FREE_BUFFER)
                kfree(urb->transfer_buffer);  <--- this one

        kfree(urb);
}
Quoted 2 lines
 kref_put include/linux/kref.h:65 [inline]
 usb_free_urb+0xd1/0x120 drivers/usb/core/urb.c:96  
Quoted 8 lines

USB layer itself is likely also not the root cause.

Quoted 4 lines
 em28xx_uninit_usb_xfer+0x165/0x310 drivers/media/usb/em28xx/em28xx-core.c:833
 em28xx_alloc_urbs+0xf2a/0x1130 drivers/media/usb/em28xx/em28xx-core.c:-1
 em28xx_dvb_init+0x2b0/0x4a20 drivers/media/usb/em28xx/em28xx-dvb.c:-1
 em28xx_init_extension+0x121/0x1d0 drivers/media/usb/em28xx/em28xx-core.c:1117  

So it might be this driver doing something wrong?

Yes, it is.

        /* allocate urbs and transfer buffers */
        for (i = 0; i < usb_bufs->num_bufs; i++) {
                urb = usb_alloc_urb(usb_bufs->num_packets, GFP_KERNEL);
                if (!urb) {
                        em28xx_uninit_usb_xfer(dev, mode);
                        return -ENOMEM;
                }
                usb_bufs->urb[i] = urb;

                usb_bufs->buf[i] = kzalloc(sb_size, GFP_KERNEL);
                if (!usb_bufs->buf[i]) {
                        for (i--; i >= 0; i--)
                                kfree(usb_bufs->buf[i]);

                        em28xx_uninit_usb_xfer(dev, mode);
                        return -ENOMEM;
                }

                urb->transfer_flags = URB_FREE_BUFFER;

If buf[i] allocation fails, all previous buffers are freed and then all previous URBs are destroyed. But they already have the URB_FREE_BUFFER flag set, which causes a double free as shown above.

The free(buf[i]) loop should simply be removed. It was mistakenly added by d571b592c6206, then a26efd1961a18 recognized the double free but attempted to fix it only by changing the order of freeing. Sent from .edu domain, so probably an automatic static analyzer fix...

Regards,
Michal

#3 lore raw
Quoted 4 lines · Michal Pecio

The free(buf[i]) loop should simply be removed. It was mistakenly added by d571b592c6206, then a26efd1961a18 recognized the double free but attempted to fix it only by changing the order of freeing. Sent from .edu domain, so probably an automatic static analyzer fix...

Correction: it failed to recognize the double free, but it fixed a different (real) problem that the buf array itself was already NULL and couldn't be scanned for buffer pointers to free.

So it turned this NULL dereferenc into a double free.

#4 lore raw
In reply to Michal Pecio
Quoted 13 lines · Michal Pecio
Quoted 12 lines · Vlastimil Babka (SUSE)
Quoted 3 lines · On 6/26/26 23:27, [email protected] wrote:

Good day, dear maintainers,

We found a bug using a modified version of syzkaller.

Subject says "usb_free_urb" but you only CC'd slab maintainers, where slab slab is most likely a victim here of e.g. double kfree() or a kfree() of otherwise broken pointer.

Ccing USB and EM28XX maintainers. But they can feel free to ignore this per the next point.

Quoted 8 lines
Quoted 5 lines
Quoted 1 line

Kernel Branch: 7.0-rc1

Why use such a version for fuzzing? rc1 will have many bugs that are already fixed in 7.0 final. And it's not even latest, 7.1 was released 2 weeks ago too.

To be fair, em28xx had no changes since 2024 until 7.1-rc1, so the bug must be present in various stable releases and likely in mainline too.

OK I didn't check that, but in general my comment stands.

Quoted 25 lines
Quoted 25 lines
Quoted 1 line
WARNING: mm/slub.c:6352 at free_large_kmalloc+0xb3/0x160 mm/slub.c:6352, CPU#1: kworker/1:4/12317  

A kfree() was attempted on a pointer that's neither from a slab page nor a large kmalloc page. Might be double free or corrupted.

Quoted 4 lines
Call Trace:
 <TASK>
 kfree+0xae/0x630 mm/slub.c:6437
 urb_destroy drivers/usb/core/urb.c:25 [inline]  

static void urb_destroy(struct kref *kref)

{
        struct urb *urb = to_urb(kref);

        if (urb->transfer_flags & URB_FREE_BUFFER)
                kfree(urb->transfer_buffer);  <--- this one

        kfree(urb);
}
Quoted 2 lines
 kref_put include/linux/kref.h:65 [inline]
 usb_free_urb+0xd1/0x120 drivers/usb/core/urb.c:96  

USB layer itself is likely also not the root cause.

Quoted 8 lines
Quoted 6 lines
Quoted 4 lines
 em28xx_uninit_usb_xfer+0x165/0x310 drivers/media/usb/em28xx/em28xx-core.c:833
 em28xx_alloc_urbs+0xf2a/0x1130 drivers/media/usb/em28xx/em28xx-core.c:-1
 em28xx_dvb_init+0x2b0/0x4a20 drivers/media/usb/em28xx/em28xx-dvb.c:-1
 em28xx_init_extension+0x121/0x1d0 drivers/media/usb/em28xx/em28xx-core.c:1117  

So it might be this driver doing something wrong?

Yes, it is.

Cool :)

Quoted 31 lines
        /* allocate urbs and transfer buffers */
        for (i = 0; i < usb_bufs->num_bufs; i++) {
                urb = usb_alloc_urb(usb_bufs->num_packets, GFP_KERNEL);
                if (!urb) {
                        em28xx_uninit_usb_xfer(dev, mode);
                        return -ENOMEM;
                }
                usb_bufs->urb[i] = urb;

                usb_bufs->buf[i] = kzalloc(sb_size, GFP_KERNEL);
                if (!usb_bufs->buf[i]) {
                        for (i--; i >= 0; i--)
                                kfree(usb_bufs->buf[i]);

                        em28xx_uninit_usb_xfer(dev, mode);
                        return -ENOMEM;
                }

                urb->transfer_flags = URB_FREE_BUFFER;

If buf[i] allocation fails, all previous buffers are freed and then all previous URBs are destroyed. But they already have the URB_FREE_BUFFER flag set, which causes a double free as shown above.

The free(buf[i]) loop should simply be removed. It was mistakenly added by d571b592c6206, then a26efd1961a18 recognized the double free but attempted to fix it only by changing the order of freeing. Sent from .edu domain, so probably an automatic static analyzer fix...

Regards,
Michal

#5 lore raw

There are a lot of lifetime issues in em28xx.

This patch series should fix them:

https://patchwork.linuxtv.org/project/linux-media/list/?series=26968

If you can, then please test with this series and see if this issue still appears.

Regards,

Hans

Quoted 94 lines · Vlastimil Babka (SUSE)
Quoted 13 lines · Michal Pecio
Quoted 12 lines · Vlastimil Babka (SUSE)
Quoted 3 lines · On 6/26/26 23:27, [email protected] wrote:

Good day, dear maintainers,

We found a bug using a modified version of syzkaller.

Subject says "usb_free_urb" but you only CC'd slab maintainers, where slab slab is most likely a victim here of e.g. double kfree() or a kfree() of otherwise broken pointer.

Ccing USB and EM28XX maintainers. But they can feel free to ignore this per the next point.

Quoted 8 lines
Quoted 5 lines
Quoted 1 line

Kernel Branch: 7.0-rc1

Why use such a version for fuzzing? rc1 will have many bugs that are already fixed in 7.0 final. And it's not even latest, 7.1 was released 2 weeks ago too.

To be fair, em28xx had no changes since 2024 until 7.1-rc1, so the bug must be present in various stable releases and likely in mainline too.

OK I didn't check that, but in general my comment stands.

Quoted 25 lines
Quoted 25 lines
Quoted 1 line
WARNING: mm/slub.c:6352 at free_large_kmalloc+0xb3/0x160 mm/slub.c:6352, CPU#1: kworker/1:4/12317  

A kfree() was attempted on a pointer that's neither from a slab page nor a large kmalloc page. Might be double free or corrupted.

Quoted 4 lines
Call Trace:
 <TASK>
 kfree+0xae/0x630 mm/slub.c:6437
 urb_destroy drivers/usb/core/urb.c:25 [inline]  

static void urb_destroy(struct kref *kref)

{
        struct urb *urb = to_urb(kref);

        if (urb->transfer_flags & URB_FREE_BUFFER)
                kfree(urb->transfer_buffer);  <--- this one

        kfree(urb);
}
Quoted 2 lines
 kref_put include/linux/kref.h:65 [inline]
 usb_free_urb+0xd1/0x120 drivers/usb/core/urb.c:96  

USB layer itself is likely also not the root cause.

Quoted 8 lines
Quoted 6 lines
Quoted 4 lines
 em28xx_uninit_usb_xfer+0x165/0x310 drivers/media/usb/em28xx/em28xx-core.c:833
 em28xx_alloc_urbs+0xf2a/0x1130 drivers/media/usb/em28xx/em28xx-core.c:-1
 em28xx_dvb_init+0x2b0/0x4a20 drivers/media/usb/em28xx/em28xx-dvb.c:-1
 em28xx_init_extension+0x121/0x1d0 drivers/media/usb/em28xx/em28xx-core.c:1117  

So it might be this driver doing something wrong?

Yes, it is.

Cool :)

Quoted 31 lines
        /* allocate urbs and transfer buffers */
        for (i = 0; i < usb_bufs->num_bufs; i++) {
                urb = usb_alloc_urb(usb_bufs->num_packets, GFP_KERNEL);
                if (!urb) {
                        em28xx_uninit_usb_xfer(dev, mode);
                        return -ENOMEM;
                }
                usb_bufs->urb[i] = urb;

                usb_bufs->buf[i] = kzalloc(sb_size, GFP_KERNEL);
                if (!usb_bufs->buf[i]) {
                        for (i--; i >= 0; i--)
                                kfree(usb_bufs->buf[i]);

                        em28xx_uninit_usb_xfer(dev, mode);
                        return -ENOMEM;
                }

                urb->transfer_flags = URB_FREE_BUFFER;

If buf[i] allocation fails, all previous buffers are freed and then all previous URBs are destroyed. But they already have the URB_FREE_BUFFER flag set, which causes a double free as shown above.

The free(buf[i]) loop should simply be removed. It was mistakenly added by d571b592c6206, then a26efd1961a18 recognized the double free but attempted to fix it only by changing the order of freeing. Sent from .edu domain, so probably an automatic static analyzer fix...

Regards,
Michal