drivers/media/usb/hackrf/hackrf.c | 8 ++++++++ 1 file changed, 8 insertions(+)
From: Zhan Jun <zhanjun@uniontech.com>
When hackrf_probe() registers the RX video device successfully but the
subsequent TX video device registration fails, the error path falls
through to kfree(dev), immediately freeing the entire hackrf_dev struct.
Since the RX video device is already visible to userspace at this point,
a process such as v4l_id may have opened /dev/swradioN and still hold a
file descriptor. When that fd is closed, v4l2_fh_release() calls
v4l2_fh_del() which tries to acquire the spinlock vdev->fh_lock — but
that lock lives inside the already-freed hackrf_dev, causing a
slab-use-after-free detected by KASAN:
BUG: KASAN: slab-use-after-free in _raw_spin_lock_irqsave+0x40/0x60
Call Trace:
v4l2_fh_del drivers/media/v4l2-core/v4l2-fh.c:74 [inline]
v4l2_fh_release+0x78/0x290 drivers/media/v4l2-core/v4l2-fh.c:99
v4l2_release+0x250/0x370 drivers/media/v4l2-core/v4l2-dev.c:471
The root cause is that the probe error path directly frees the struct
instead of deferring cleanup via the v4l2_device refcount, unlike
hackrf_disconnect() which correctly calls v4l2_device_put() and lets
hackrf_video_release() handle the final kfree() when all references
are dropped.
Fix this by returning early from err_video_unregister_device_rx after
calling v4l2_device_put(), mirroring the disconnect path. This ensures
the hackrf_dev struct remains valid until all open file descriptors are
closed.
Fixes: 8bc4a9ed8504 ("[media] hackrf: add support for transmitter")
Reported-by: syzbot+4a824e616e58ca2b3d25@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=4a824e616e58ca2b3d25
Signed-off-by: Zhan Jun <zhanjun@uniontech.com>
---
drivers/media/usb/hackrf/hackrf.c | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/drivers/media/usb/hackrf/hackrf.c b/drivers/media/usb/hackrf/hackrf.c
index 94d356fba612..ec4ac1b77d0b 100644
--- a/drivers/media/usb/hackrf/hackrf.c
+++ b/drivers/media/usb/hackrf/hackrf.c
@@ -1513,6 +1513,14 @@ static int hackrf_probe(struct usb_interface *intf,
return 0;
err_video_unregister_device_rx:
video_unregister_device(&dev->rx_vdev);
+ /* v4l2_device refcount was incremented by video_register_device().
+ * Use v4l2_device_put() to let hackrf_video_release() handle cleanup
+ * when the last reference is dropped, avoiding a use-after-free if
+ * userspace still holds an open file descriptor.
+ */
+ v4l2_device_put(&dev->v4l2_dev);
+ dev_dbg(&intf->dev, "failed=%d\n", ret);
+ return ret;
err_v4l2_device_unregister:
v4l2_device_unregister(&dev->v4l2_dev);
err_v4l2_ctrl_handler_free_tx:
--
2.50.1
© 2016 - 2026 Red Hat, Inc.