On Mon Jul 13 11:18:39 2026 +0100, Sean Young wrote:
> If rc_unregister_device() is called while IR is being processed, then
> ir_raw_event_handle() could call wake_up_process(dev->raw->thread)
> after kthread_stop(dev->raw->thread). Avoid use after free by using
> get_task_struct().
> 
> Fixes: dccc0c3ddf8f ("media: rc: fix race between unregister and urb/irq 
> callbacks")
> Signed-off-by: Sean Young <[email protected]>
> Cc: [email protected]
> Reviewed-by: Hans Verkuil <[email protected]>

Patch committed.

Thanks,
Sean Young

 drivers/media/rc/rc-ir-raw.c | 16 ++++++++++++++--
 1 file changed, 14 insertions(+), 2 deletions(-)

---

diff --git a/drivers/media/rc/rc-ir-raw.c b/drivers/media/rc/rc-ir-raw.c
index 46c50f423798..86de1b26731d 100644
--- a/drivers/media/rc/rc-ir-raw.c
+++ b/drivers/media/rc/rc-ir-raw.c
@@ -630,8 +630,13 @@ int ir_raw_event_register(struct rc_dev *dev)
 
 void ir_raw_event_free(struct rc_dev *dev)
 {
-       kfree(dev->raw);
-       dev->raw = NULL;
+       if (dev->raw) {
+               timer_delete_sync(&dev->raw->edge_handle);
+               if (dev->raw->thread)
+                       put_task_struct(dev->raw->thread);
+               kfree(dev->raw);
+               dev->raw = NULL;
+       }
 }
 
 void ir_raw_event_unregister(struct rc_dev *dev)
@@ -641,6 +646,13 @@ void ir_raw_event_unregister(struct rc_dev *dev)
        if (!dev || !dev->raw)
                return;
 
+       /*
+        * After ir_raw_event_unregister() is called, an sync
+        * call to ir_raw_event_handle() can still arrive. This function
+        * may call wake_up_process(dev->raw->thread). Ensure this memory
+        * is not freed by kthread_stop().
+        */
+       get_task_struct(dev->raw->thread);
        kthread_stop(dev->raw->thread);
        timer_delete_sync(&dev->raw->edge_handle);
 
_______________________________________________
linuxtv-commits mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to