Skip to content

Commit bef4f4a

Browse files
Entropy1110mchehab
authored andcommitted
media: mc, v4l2: serialize REINIT and REQBUFS with req_queue_mutex
MEDIA_REQUEST_IOC_REINIT can run concurrently with VIDIOC_REQBUFS(0) queue teardown paths. This can race request object cleanup against vb2 queue cancellation and lead to use-after-free reports. We already serialize request queueing against STREAMON/OFF with req_queue_mutex. Extend that serialization to REQBUFS, and also take the same mutex in media_request_ioctl_reinit() so REINIT is in the same exclusion domain. This keeps request cleanup and queue cancellation from running in parallel for request-capable devices. Fixes: 6093d30 ("media: vb2: keep a reference to the request until dqbuf") Cc: [email protected] Signed-off-by: Yuchan Nam <[email protected]> Signed-off-by: Sakari Ailus <[email protected]> Signed-off-by: Mauro Carvalho Chehab <[email protected]>
1 parent ac62a20 commit bef4f4a

2 files changed

Lines changed: 8 additions & 2 deletions

File tree

drivers/media/mc/mc-request.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,20 +192,24 @@ static long media_request_ioctl_reinit(struct media_request *req)
192192
struct media_device *mdev = req->mdev;
193193
unsigned long flags;
194194

195+
mutex_lock(&mdev->req_queue_mutex);
196+
195197
spin_lock_irqsave(&req->lock, flags);
196198
if (req->state != MEDIA_REQUEST_STATE_IDLE &&
197199
req->state != MEDIA_REQUEST_STATE_COMPLETE) {
198200
dev_dbg(mdev->dev,
199201
"request: %s not in idle or complete state, cannot reinit\n",
200202
req->debug_str);
201203
spin_unlock_irqrestore(&req->lock, flags);
204+
mutex_unlock(&mdev->req_queue_mutex);
202205
return -EBUSY;
203206
}
204207
if (req->access_count) {
205208
dev_dbg(mdev->dev,
206209
"request: %s is being accessed, cannot reinit\n",
207210
req->debug_str);
208211
spin_unlock_irqrestore(&req->lock, flags);
212+
mutex_unlock(&mdev->req_queue_mutex);
209213
return -EBUSY;
210214
}
211215
req->state = MEDIA_REQUEST_STATE_CLEANING;
@@ -216,6 +220,7 @@ static long media_request_ioctl_reinit(struct media_request *req)
216220
spin_lock_irqsave(&req->lock, flags);
217221
req->state = MEDIA_REQUEST_STATE_IDLE;
218222
spin_unlock_irqrestore(&req->lock, flags);
223+
mutex_unlock(&mdev->req_queue_mutex);
219224

220225
return 0;
221226
}

drivers/media/v4l2-core/v4l2-ioctl.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3082,13 +3082,14 @@ static long __video_do_ioctl(struct file *file,
30823082
}
30833083

30843084
/*
3085-
* We need to serialize streamon/off with queueing new requests.
3085+
* We need to serialize streamon/off/reqbufs with queueing new requests.
30863086
* These ioctls may trigger the cancellation of a streaming
30873087
* operation, and that should not be mixed with queueing a new
30883088
* request at the same time.
30893089
*/
30903090
if (v4l2_device_supports_requests(vfd->v4l2_dev) &&
3091-
(cmd == VIDIOC_STREAMON || cmd == VIDIOC_STREAMOFF)) {
3091+
(cmd == VIDIOC_STREAMON || cmd == VIDIOC_STREAMOFF ||
3092+
cmd == VIDIOC_REQBUFS)) {
30923093
req_queue_lock = &vfd->v4l2_dev->mdev->req_queue_mutex;
30933094

30943095
if (mutex_lock_interruptible(req_queue_lock))

0 commit comments

Comments
 (0)