On Mon Sep 28 20:19:04 2026 -0400, Kaho Jiang wrote:
> When allocation of usb_bufs->buf[i] fails, em28xx_alloc_urbs()
> explicitly frees all items within usb_bufs->buf before calling
> em28xx_uninit_usb_xfer(), which also frees these items, causing them to be
> freed twice.
>
> BUG: KASAN: double-free in usb_free_urb.part.0 (drivers/usb/core/urb.c:25
> ./include/linux/kref.h:65 drivers/usb/core/urb.c:96)
> Free of addr ffff88802fd37c00 by task kworker/1:2/1182
> Workqueue: events request_module_async
> Call Trace:
> kasan_report_invalid_free (mm/kasan/report.c:557)
> check_slab_allocation (mm/kasan/common.c:235)
> kfree (./include/linux/kasan.h:199 (discriminator 1) mm/slub.c:2693
> (discriminator 1) mm/slub.c:6508 (discriminator 1) mm/slub.c:6801
> (discriminator 1))
> usb_free_urb.part.0 (drivers/usb/core/urb.c:25 ./include/linux/kref.h:65
> drivers/usb/core/urb.c:96)
> usb_free_urb (drivers/usb/core/urb.c:95)
> em28xx_uninit_usb_xfer (drivers/media/usb/em28xx/em28xx-core.c:964)
> em28xx_alloc_urbs (drivers/media/usb/em28xx/em28xx-core.c:1076)
> em28xx_dvb_init (drivers/media/usb/em28xx/em28xx-dvb.c:1734
> drivers/media/usb/em28xx/em28xx-dvb.c:1698)
> em28xx_init_extension (drivers/media/usb/em28xx/em28xx-core.c:1248)
> request_module_async (drivers/media/usb/em28xx/em28xx-cards.c:3685)
> process_one_work (kernel/workqueue.c:3396)
> worker_thread (kernel/workqueue.c:3479 kernel/workqueue.c:3560)
> kthread (kernel/kthread.c:436)
> ret_from_fork (arch/x86/kernel/process.c:158)
> ret_from_fork_asm (arch/x86/entry/entry_64.S:245)
> Allocated by task 1182:
> kasan_save_stack (mm/kasan/common.c:57)
> kasan_save_track (mm/kasan/common.c:78)
> __kasan_kmalloc (mm/kasan/common.c:398 mm/kasan/common.c:415)
> __kmalloc_noprof (./include/linux/kasan.h:263 mm/slub.c:5414 mm/slub.c:5439)
> em28xx_alloc_urbs (./include/linux/slab.h:995 ./include/linux/slab.h:1312
> drivers/media/usb/em28xx/em28xx-core.c:1081)
> em28xx_dvb_init (drivers/media/usb/em28xx/em28xx-dvb.c:1734
> drivers/media/usb/em28xx/em28xx-dvb.c:1698)
> em28xx_init_extension (drivers/media/usb/em28xx/em28xx-core.c:1248)
> request_module_async (drivers/media/usb/em28xx/em28xx-cards.c:3685)
> process_one_work (kernel/workqueue.c:3396)
> worker_thread (kernel/workqueue.c:3479 kernel/workqueue.c:3560)
> kthread (kernel/kthread.c:436)
> ret_from_fork (arch/x86/kernel/process.c:158)
> ret_from_fork_asm (arch/x86/entry/entry_64.S:245)
> Freed by task 1182:
> kasan_save_stack (mm/kasan/common.c:57)
> kasan_save_track (mm/kasan/common.c:78)
> kasan_save_free_info (mm/kasan/generic.c:584)
> __kasan_slab_free (mm/kasan/common.c:253 mm/kasan/common.c:285)
> kfree (./include/linux/kasan.h:235 mm/slub.c:2748 mm/slub.c:6508
> mm/slub.c:6801)
> em28xx_alloc_urbs (drivers/media/usb/em28xx/em28xx-core.c:1084)
> em28xx_dvb_init (drivers/media/usb/em28xx/em28xx-dvb.c:1734
> drivers/media/usb/em28xx/em28xx-dvb.c:1698)
> em28xx_init_extension (drivers/media/usb/em28xx/em28xx-core.c:1248)
> request_module_async (drivers/media/usb/em28xx/em28xx-cards.c:3685)
> process_one_work (kernel/workqueue.c:3396)
> worker_thread (kernel/workqueue.c:3479 kernel/workqueue.c:3560)
> kthread (kernel/kthread.c:436)
> ret_from_fork (arch/x86/kernel/process.c:158)
> ret_from_fork_asm (arch/x86/entry/entry_64.S:245)
>
> Remove the explicit cleanup loop and let em28xx_uninit_usb_xfer()
> handle the cleanup.
>
> Fixes: d571b592c6206 ("media: em28xx: don't use coherent buffer for DMA
> transfers")
> Cc: [email protected]
> Reported-by: [email protected]
> Assisted-by: LLM
> Signed-off-by: Kaho Jiang <[email protected]>
> Signed-off-by: Hans Verkuil <[email protected]>
Patch committed.
Thanks,
Hans Verkuil
drivers/media/usb/em28xx/em28xx-core.c | 3 ---
1 file changed, 3 deletions(-)
---
diff --git a/drivers/media/usb/em28xx/em28xx-core.c
b/drivers/media/usb/em28xx/em28xx-core.c
index 0b998e7cafef..62a1c25a2de1 100644
--- a/drivers/media/usb/em28xx/em28xx-core.c
+++ b/drivers/media/usb/em28xx/em28xx-core.c
@@ -1080,9 +1080,6 @@ int em28xx_alloc_urbs(struct em28xx *dev, enum
em28xx_mode mode, int xfer_bulk,
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;
}
_______________________________________________
linuxtv-commits mailing list -- [email protected]
To unsubscribe send an email to [email protected]