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

Subject: media: v4l2-ctrl: Lock main_hdl on operations of requests_queued.
Author:  Pi-Hsun Shih <pih...@chromium.org>
Date:    Sun Nov 10 07:29:10 2019 +0100

There's a race condition between the list_del_init in the
v4l2_ctrl_request_complete, and the list_add_tail in the
v4l2_ctrl_request_queue, since they can be called in different thread
and the requests_queued list is not protected by a lock. This can lead
to that the v4l2_ctrl_handler is still in the requests_queued list while
the request_is_queued is already set to false, which would cause
use-after-free if the v4l2_ctrl_handler is later released.

Fix this by locking the ->lock of main_hdl (which is the owner of the
requests_queued list) when doing list operations on the
->requests_queued list.

Signed-off-by: Pi-Hsun Shih <pih...@chromium.org>
Signed-off-by: Hans Verkuil <hverkuil-ci...@xs4all.nl>
Signed-off-by: Mauro Carvalho Chehab <mche...@kernel.org>

 drivers/media/v4l2-core/v4l2-ctrls.c | 7 +++++++
 1 file changed, 7 insertions(+)

---

diff --git a/drivers/media/v4l2-core/v4l2-ctrls.c 
b/drivers/media/v4l2-core/v4l2-ctrls.c
index a565ae3ba7e4..2928c5e0a73d 100644
--- a/drivers/media/v4l2-core/v4l2-ctrls.c
+++ b/drivers/media/v4l2-core/v4l2-ctrls.c
@@ -3302,6 +3302,7 @@ static void v4l2_ctrl_request_queue(struct 
media_request_object *obj)
        struct v4l2_ctrl_handler *prev_hdl = NULL;
        struct v4l2_ctrl_ref *ref_ctrl, *ref_ctrl_prev = NULL;
 
+       mutex_lock(main_hdl->lock);
        if (list_empty(&main_hdl->requests_queued))
                goto queue;
 
@@ -3333,18 +3334,22 @@ static void v4l2_ctrl_request_queue(struct 
media_request_object *obj)
 queue:
        list_add_tail(&hdl->requests_queued, &main_hdl->requests_queued);
        hdl->request_is_queued = true;
+       mutex_unlock(main_hdl->lock);
 }
 
 static void v4l2_ctrl_request_unbind(struct media_request_object *obj)
 {
        struct v4l2_ctrl_handler *hdl =
                container_of(obj, struct v4l2_ctrl_handler, req_obj);
+       struct v4l2_ctrl_handler *main_hdl = obj->priv;
 
        list_del_init(&hdl->requests);
+       mutex_lock(main_hdl->lock);
        if (hdl->request_is_queued) {
                list_del_init(&hdl->requests_queued);
                hdl->request_is_queued = false;
        }
+       mutex_unlock(main_hdl->lock);
 }
 
 static void v4l2_ctrl_request_release(struct media_request_object *obj)
@@ -4298,9 +4303,11 @@ void v4l2_ctrl_request_complete(struct media_request 
*req,
                v4l2_ctrl_unlock(ctrl);
        }
 
+       mutex_lock(main_hdl->lock);
        WARN_ON(!hdl->request_is_queued);
        list_del_init(&hdl->requests_queued);
        hdl->request_is_queued = false;
+       mutex_unlock(main_hdl->lock);
        media_request_object_complete(obj);
        media_request_object_put(obj);
 }

_______________________________________________
linuxtv-commits mailing list
linuxtv-commits@linuxtv.org
https://www.linuxtv.org/cgi-bin/mailman/listinfo/linuxtv-commits

Reply via email to