mirror of
https://github.com/Fishwaldo/Star64_linux.git
synced 2025-06-28 17:41:50 +00:00
media: v4l2-ctrl: Lock main_hdl on operations of requests_queued.
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 <pihsun@chromium.org> Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl> Signed-off-by: Mauro Carvalho Chehab <mchehab@kernel.org>
This commit is contained in:
parent
2df200ab23
commit
df4a3e7f88
1 changed files with 7 additions and 0 deletions
|
@ -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_handler *prev_hdl = NULL;
|
||||||
struct v4l2_ctrl_ref *ref_ctrl, *ref_ctrl_prev = NULL;
|
struct v4l2_ctrl_ref *ref_ctrl, *ref_ctrl_prev = NULL;
|
||||||
|
|
||||||
|
mutex_lock(main_hdl->lock);
|
||||||
if (list_empty(&main_hdl->requests_queued))
|
if (list_empty(&main_hdl->requests_queued))
|
||||||
goto queue;
|
goto queue;
|
||||||
|
|
||||||
|
@ -3333,18 +3334,22 @@ static void v4l2_ctrl_request_queue(struct media_request_object *obj)
|
||||||
queue:
|
queue:
|
||||||
list_add_tail(&hdl->requests_queued, &main_hdl->requests_queued);
|
list_add_tail(&hdl->requests_queued, &main_hdl->requests_queued);
|
||||||
hdl->request_is_queued = true;
|
hdl->request_is_queued = true;
|
||||||
|
mutex_unlock(main_hdl->lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void v4l2_ctrl_request_unbind(struct media_request_object *obj)
|
static void v4l2_ctrl_request_unbind(struct media_request_object *obj)
|
||||||
{
|
{
|
||||||
struct v4l2_ctrl_handler *hdl =
|
struct v4l2_ctrl_handler *hdl =
|
||||||
container_of(obj, struct v4l2_ctrl_handler, req_obj);
|
container_of(obj, struct v4l2_ctrl_handler, req_obj);
|
||||||
|
struct v4l2_ctrl_handler *main_hdl = obj->priv;
|
||||||
|
|
||||||
list_del_init(&hdl->requests);
|
list_del_init(&hdl->requests);
|
||||||
|
mutex_lock(main_hdl->lock);
|
||||||
if (hdl->request_is_queued) {
|
if (hdl->request_is_queued) {
|
||||||
list_del_init(&hdl->requests_queued);
|
list_del_init(&hdl->requests_queued);
|
||||||
hdl->request_is_queued = false;
|
hdl->request_is_queued = false;
|
||||||
}
|
}
|
||||||
|
mutex_unlock(main_hdl->lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void v4l2_ctrl_request_release(struct media_request_object *obj)
|
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);
|
v4l2_ctrl_unlock(ctrl);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mutex_lock(main_hdl->lock);
|
||||||
WARN_ON(!hdl->request_is_queued);
|
WARN_ON(!hdl->request_is_queued);
|
||||||
list_del_init(&hdl->requests_queued);
|
list_del_init(&hdl->requests_queued);
|
||||||
hdl->request_is_queued = false;
|
hdl->request_is_queued = false;
|
||||||
|
mutex_unlock(main_hdl->lock);
|
||||||
media_request_object_complete(obj);
|
media_request_object_complete(obj);
|
||||||
media_request_object_put(obj);
|
media_request_object_put(obj);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue