[PATCH 1/2] media: au0828: fix slab-use-after-free in au0828_dvb_register

From: xiaopeitux

Date: Tue Jun 02 2026 - 02:57:36 EST


From: Pei Xiao <xiaopei01@xxxxxxxxxx>

A use-after-free (UAF) issue was reported by KASAN when the au0828 driver
attempts to register a DVB frontend and the operation fails (returning
-ENOMEM). The error path leads to a double free of the frontend object,
causing a slab-use-after-free.

The root cause is that when dvb_register_frontend() fails before the kref
of the frontend is initialized (-ENOMEM in kzalloc of fe->frontend_priv),
the error handler still calls dvb_frontend_detach() which eventually
invokes dvb_frontend_put(). Since the kref is not yet initialized,
immediately frees the frontend via __dvb_frontend_free(). Later, the outer
error path in au0828_dvb_register() calls dvb->frontend->ops.release()
again, resulting in a double free and UAF.

Specifically, the call chain is:

au0828_dvb_register()
-> dvb_register()
-> dvb_register_frontend()
(fails before kref_init, returns -ENOMEM)
-> goto fail_frontend
-> dvb_frontend_detach()
-> dvb_frontend_put()
-> __dvb_frontend_free()
-> dvb_frontend_invoke_release(fe, fe->ops.release)
-> au8522_release()
-> kfree(state) [frontend memory freed]
(back to au0828_dvb_register)
if (ret < 0) {
if (dvb->frontend->ops.release)
dvb->frontend->ops.release(dvb->frontend); // USE-AFTER-FREE
dvb->frontend = NULL;
}

Thus, the second release is redundant and unsafe because the frontend
has already been freed by the first release via dvb_frontend_put.

Fix this by removing the redundant manual release call in the outer
error path. The frontend is already destroyed by dvb_frontend_put() in
the inner error path, so we only need to set dvb->frontend to NULL.

Logs:
usb 3-1: new high-speed USB device number 2 using dummy_hcd
usb 3-1: New USB device found, idVendor=0fe9, idProduct=d620, bcdDevice=
1.00
usb 3-1: New USB device strings: Mfr=0, Product=0, SerialNumber=0
au0828: i2c bus registered
au8522 1-0047: creating new instance
DVB: Unable to find symbol xc5000_attach()
dvbdev: DVB: registering new adapter (au0828)
au0828: dvb_register_frontend failed (errno = -12)
au8522 1-0047: destroying instance
==================================================================
BUG: KASAN: slab-use-after-free in au0828_dvb_register+0x1280/0x15f0
Read of size 8 at addr ffff8881685f4118 by task kworker/1:1/42

Workqueue: usb_hub_wq hub_event
Call Trace:
dump_stack_lvl+0x26/0x80
print_report+0x16a/0x5d0
kasan_report+0xc3/0x100
au0828_dvb_register+0x1280/0x15f0
au0828_usb_probe+0x353/0x4b0
usb_probe_interface+0x4aa/0xa40
...

Freed by task 42 on cpu 1 at 65.659497s:
kasan_save_track+0x2e/0x90
kasan_save_free_info+0x3c/0x50
__kasan_slab_free+0x36/0x60
kfree+0x154/0x450
au8522_release_state+0x1b6/0x210
dvb_frontend_put+0x12a/0x170
au0828_dvb_register+0xfd9/0x15f0
au0828_usb_probe+0x353/0x4b0
usb_probe_interface+0x4aa/0xa40
...

Fixes: ead666000a5f ("media: dvb_frontend: only use kref after initialized")
Reported-by: Shuangpeng Bai <shuangpeng.kernel@xxxxxxxxx>
Closes: https://lore.kernel.org/lkml/AAC17221-93BF-436F-92AC-906A18F882F0@xxxxxxxxx/
Tested-by: Shuangpeng Bai <shuangpeng.kernel@xxxxxxxxx>
Cc: stable@xxxxxxxxxxxxxxx
Signed-off-by: Pei Xiao <xiaopei01@xxxxxxxxxx>
---
drivers/media/usb/au0828/au0828-dvb.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/drivers/media/usb/au0828/au0828-dvb.c b/drivers/media/usb/au0828/au0828-dvb.c
index 31123e6f9fc3..3c74b85c3a40 100644
--- a/drivers/media/usb/au0828/au0828-dvb.c
+++ b/drivers/media/usb/au0828/au0828-dvb.c
@@ -633,8 +633,9 @@ int au0828_dvb_register(struct au0828_dev *dev)
/* register everything */
ret = dvb_register(dev);
if (ret < 0) {
- if (dvb->frontend->ops.release)
- dvb->frontend->ops.release(dvb->frontend);
+ /* dvb->frontend freed in dvb_frontend_put, now we can set
+ * frontend to NULL
+ */
dvb->frontend = NULL;
return ret;
}
--
2.25.1