mirror of
https://github.com/torvalds/linux.git
synced 2026-07-27 17:47:41 +02:00
media: vivid: check for vb2_is_busy() when toggling caps
The vivid_update_format_cap/out() functions must only be called if the
capture/output queue are not busy. But for the controls that select
the CROP/COMPOSE/SCALE capability that is not checked.
Only when streaming starts will they be set to 'grabbed' and it is
impossible to change the control, but between REQBUFS and STREAMON you
are still allowed to set these controls. Since vivid_update_format_cap/out
will change the format, this can cause unexpected results.
Besides adding these checks, also add a WARN_ON in
vivid_update_format_cap/out() if the queue is busy.
I'm 90% certain that this is the cause of this syzbot bug:
https://syzkaller.appspot.com/bug?extid=dac8f5eaa46837e97b89
But since we never have reproducers, it is hard to be certain. In any case,
these checks are needed regardless.
Reviewed-by: Nicolas Dufresne <nicolas.dufresne@collabora.com>
Fixes: 73c3f48230 ("[media] vivid: add the control handling code")
Cc: stable@vger.kernel.org
Reported-by: syzbot+dac8f5eaa46837e97b89@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=dac8f5eaa46837e97b89
Signed-off-by: Hans Verkuil <hverkuil+cisco@kernel.org>
This commit is contained in:
parent
1d793a29ef
commit
c2d1a2130c
|
|
@ -613,14 +613,20 @@ static int vivid_vid_cap_s_ctrl(struct v4l2_ctrl *ctrl)
|
|||
vivid_update_reduced_fps(dev);
|
||||
break;
|
||||
case VIVID_CID_HAS_CROP_CAP:
|
||||
if (vb2_is_busy(&dev->vb_vid_cap_q))
|
||||
return -EBUSY;
|
||||
dev->has_crop_cap = ctrl->val;
|
||||
vivid_update_format_cap(dev, true);
|
||||
break;
|
||||
case VIVID_CID_HAS_COMPOSE_CAP:
|
||||
if (vb2_is_busy(&dev->vb_vid_cap_q))
|
||||
return -EBUSY;
|
||||
dev->has_compose_cap = ctrl->val;
|
||||
vivid_update_format_cap(dev, true);
|
||||
break;
|
||||
case VIVID_CID_HAS_SCALER_CAP:
|
||||
if (vb2_is_busy(&dev->vb_vid_cap_q))
|
||||
return -EBUSY;
|
||||
dev->has_scaler_cap = ctrl->val;
|
||||
vivid_update_format_cap(dev, true);
|
||||
break;
|
||||
|
|
@ -1117,14 +1123,20 @@ static int vivid_vid_out_s_ctrl(struct v4l2_ctrl *ctrl)
|
|||
|
||||
switch (ctrl->id) {
|
||||
case VIVID_CID_HAS_CROP_OUT:
|
||||
if (vb2_is_busy(&dev->vb_vid_out_q))
|
||||
return -EBUSY;
|
||||
dev->has_crop_out = ctrl->val;
|
||||
vivid_update_format_out(dev);
|
||||
break;
|
||||
case VIVID_CID_HAS_COMPOSE_OUT:
|
||||
if (vb2_is_busy(&dev->vb_vid_out_q))
|
||||
return -EBUSY;
|
||||
dev->has_compose_out = ctrl->val;
|
||||
vivid_update_format_out(dev);
|
||||
break;
|
||||
case VIVID_CID_HAS_SCALER_OUT:
|
||||
if (vb2_is_busy(&dev->vb_vid_out_q))
|
||||
return -EBUSY;
|
||||
dev->has_scaler_out = ctrl->val;
|
||||
vivid_update_format_out(dev);
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -391,6 +391,12 @@ void vivid_update_format_cap(struct vivid_dev *dev, bool keep_controls)
|
|||
struct v4l2_bt_timings *bt = &dev->dv_timings_cap[dev->input].bt;
|
||||
u32 dims[V4L2_CTRL_MAX_DIMS] = {};
|
||||
|
||||
/*
|
||||
* This resets the format, so must never be called while vb2_is_busy().
|
||||
*/
|
||||
if (WARN_ON(vb2_is_busy(&dev->vb_vid_cap_q)))
|
||||
return;
|
||||
|
||||
switch (dev->input_type[dev->input]) {
|
||||
case WEBCAM:
|
||||
default:
|
||||
|
|
|
|||
|
|
@ -214,6 +214,12 @@ void vivid_update_format_out(struct vivid_dev *dev)
|
|||
unsigned size, p;
|
||||
u64 pixelclock;
|
||||
|
||||
/*
|
||||
* This resets the format, so must never be called while vb2_is_busy().
|
||||
*/
|
||||
if (WARN_ON(vb2_is_busy(&dev->vb_vid_out_q)))
|
||||
return;
|
||||
|
||||
switch (dev->output_type[dev->output]) {
|
||||
case SVID:
|
||||
default:
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user