On Sat Sep 12 22:05:54 2026 -0400, Myeonghun Pak wrote:
> The DVBSKY S950C, DVBSKY T980C and TechnoTrend CT2-4500 CI paths register
> the DVB bus before attaching their SP2 CI client. If that client cannot be
> created, bound, or pinned, the current error path removes the I2C frontend
> components and only deallocates the frontend list, leaving the registered
> DVB adapter behind. Removing an I2C demod before unregistering the DVB bus
> can also expose the use-after-free ordering fixed for the normal remove
> path.
> 
> Unregister the DVB bus immediately when SP2 CI setup fails, before the
> existing I2C client cleanup. The bus helper empties the frontend list, so
> the later frontend deallocation has nothing left to release. Keep failures
> from vb2_dvb_register_bus() on the existing cleanup path. Also release an
> unbound SP2 client and propagate the actual I2C creation or CI registration
> error.
> 
> This issue was identified during our ongoing static-analysis research while
> reviewing kernel code.
> 
> Fixes: 2b0aac3011bc ("[media] cx23885: move CI/MAC registration to a separate 
> function")
> Cc: [email protected]
> Assisted-by: OpenAI:GPT-5.6
> Co-developed-by: Ijae Kim <[email protected]>
> Signed-off-by: Ijae Kim <[email protected]>
> Signed-off-by: Myeonghun Pak <[email protected]>
> Signed-off-by: Hans Verkuil <[email protected]>

Patch committed.

Thanks,
Hans Verkuil

 drivers/media/pci/cx23885/cx23885-dvb.c | 14 ++++++++++----
 1 file changed, 10 insertions(+), 4 deletions(-)

---

diff --git a/drivers/media/pci/cx23885/cx23885-dvb.c 
b/drivers/media/pci/cx23885/cx23885-dvb.c
index f240ccda40ed..348abde0ba26 100644
--- a/drivers/media/pci/cx23885/cx23885-dvb.c
+++ b/drivers/media/pci/cx23885/cx23885-dvb.c
@@ -1158,8 +1158,12 @@ static int dvb_register_ci_mac(struct cx23885_tsport 
*port)
                info.platform_data = &sp2_config;
                request_module(info.type);
                client_ci = i2c_new_client_device(&i2c_bus->i2c_adap, &info);
-               if (!i2c_client_has_driver(client_ci))
+               if (IS_ERR(client_ci))
+                       return PTR_ERR(client_ci);
+               if (!client_ci->dev.driver) {
+                       i2c_unregister_device(client_ci);
                        return -ENODEV;
+               }
                if (!try_module_get(client_ci->dev.driver->owner)) {
                        i2c_unregister_device(client_ci);
                        return -ENODEV;
@@ -1202,7 +1206,7 @@ static int dvb_register(struct cx23885_tsport *port)
        int (*p_set_voltage)(struct dvb_frontend *fe,
                             enum fe_sec_voltage voltage) = NULL;
        int mfe_shared = 0; /* bus not shared by default */
-       int ret;
+       int ret = -EINVAL;
 
        /* Get the first frontend */
        fe0 = vb2_dvb_get_frontend(&port->frontends, 1);
@@ -2586,8 +2590,10 @@ static int dvb_register(struct cx23885_tsport *port)
                goto frontend_detach;
 
        ret = dvb_register_ci_mac(port);
-       if (ret)
+       if (ret) {
+               vb2_dvb_unregister_bus(&port->frontends);
                goto frontend_detach;
+       }
 
        return 0;
 
@@ -2618,7 +2624,7 @@ frontend_detach:
 
        port->gate_ctrl = NULL;
        vb2_dvb_dealloc_frontends(&port->frontends);
-       return -EINVAL;
+       return ret;
 }
 
 int cx23885_dvb_register(struct cx23885_tsport *port)
_______________________________________________
linuxtv-commits mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to