[PATCH] media: em28xx: fix double free in em28xx_alloc_urbs

From: kj2864

Date: Mon Sep 28 2026 - 20:48:06 EST


From: Kaho Jiang <kj2864@xxxxxxx>

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: stable@xxxxxxxxxxxxxxx
Reported-by: co+6a04efcebe0fc0ce@xxxxxxx
Assisted-by: LLM
Signed-off-by: Kaho Jiang <kj2864@xxxxxxx>
---
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 5bbb082dbed9..86c74c55908c 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;
}
--
2.43.0