This is an automatic generated email to let you know that the following patch 
were queued:

Subject: media: edia: dvbdev: fix a use-after-free
Author:  Zhipeng Lu <alexi...@zju.edu.cn>
Date:    Sat Feb 3 14:40:43 2024 +0100

In dvb_register_device, *pdvbdev is set equal to dvbdev, which is freed
in several error-handling paths. However, *pdvbdev is not set to NULL
after dvbdev's deallocation, causing use-after-frees in many places,
for example, in the following call chain:

budget_register
  |-> dvb_dmxdev_init
        |-> dvb_register_device
  |-> dvb_dmxdev_release
        |-> dvb_unregister_device
              |-> dvb_remove_device
                    |-> dvb_device_put
                          |-> kref_put

When calling dvb_unregister_device, dmxdev->dvbdev (i.e. *pdvbdev in
dvb_register_device) could point to memory that had been freed in
dvb_register_device. Thereafter, this pointer is transferred to
kref_put and triggering a use-after-free.

Link: 
https://lore.kernel.org/linux-media/20240203134046.3120099-1-alexi...@zju.edu.cn
Fixes: b61901024776 ("V4L/DVB (5244): Dvbdev: fix illegal re-usage of 
fileoperations struct")
Signed-off-by: Zhipeng Lu <alexi...@zju.edu.cn>
Signed-off-by: Mauro Carvalho Chehab <mche...@kernel.org>

 drivers/media/dvb-core/dvbdev.c | 5 +++++
 1 file changed, 5 insertions(+)

---

diff --git a/drivers/media/dvb-core/dvbdev.c b/drivers/media/dvb-core/dvbdev.c
index 49f0eb7d0b9d..733d0bc4b4cc 100644
--- a/drivers/media/dvb-core/dvbdev.c
+++ b/drivers/media/dvb-core/dvbdev.c
@@ -490,6 +490,7 @@ int dvb_register_device(struct dvb_adapter *adap, struct 
dvb_device **pdvbdev,
                dvbdevfops = kmemdup(template->fops, sizeof(*dvbdevfops), 
GFP_KERNEL);
                if (!dvbdevfops) {
                        kfree(dvbdev);
+                       *pdvbdev = NULL;
                        mutex_unlock(&dvbdev_register_lock);
                        return -ENOMEM;
                }
@@ -498,6 +499,7 @@ int dvb_register_device(struct dvb_adapter *adap, struct 
dvb_device **pdvbdev,
                if (!new_node) {
                        kfree(dvbdevfops);
                        kfree(dvbdev);
+                       *pdvbdev = NULL;
                        mutex_unlock(&dvbdev_register_lock);
                        return -ENOMEM;
                }
@@ -531,6 +533,7 @@ int dvb_register_device(struct dvb_adapter *adap, struct 
dvb_device **pdvbdev,
                }
                list_del(&dvbdev->list_head);
                kfree(dvbdev);
+               *pdvbdev = NULL;
                up_write(&minor_rwsem);
                mutex_unlock(&dvbdev_register_lock);
                return -EINVAL;
@@ -553,6 +556,7 @@ int dvb_register_device(struct dvb_adapter *adap, struct 
dvb_device **pdvbdev,
                dvb_media_device_free(dvbdev);
                list_del(&dvbdev->list_head);
                kfree(dvbdev);
+               *pdvbdev = NULL;
                mutex_unlock(&dvbdev_register_lock);
                return ret;
        }
@@ -571,6 +575,7 @@ int dvb_register_device(struct dvb_adapter *adap, struct 
dvb_device **pdvbdev,
                dvb_media_device_free(dvbdev);
                list_del(&dvbdev->list_head);
                kfree(dvbdev);
+               *pdvbdev = NULL;
                mutex_unlock(&dvbdev_register_lock);
                return PTR_ERR(clsdev);
        }

Reply via email to