Commit 02bbcb9d authored by Jean-François Moine's avatar Jean-François Moine Committed by Mauro Carvalho Chehab

V4L/DVB: gspca - main: Possible race condition in queue management

The problem may occur with SMP:
- a frame is completed at interrupt level (in gspca_frame_add with
  packet_type == LAST_PACKET,
- just after clearing the bit V4L2_BUF_FLAG_QUEUED and before setting
  the bit V4L2_BUF_FLAG_DONE, on the other processor, the application
  tries to requeue the same frame buffer,
- then, the qbuf function succeeds because ALL_FLAGS are not set.
The fix sets and resets the two flags in one instruction.
Reported-by: default avatarHans de Goede <hdegoede@redhat.com>
Signed-off-by: default avatarJean-François Moine <moinejf@free.fr>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@redhat.com>
parent 9059cd44
...@@ -466,8 +466,9 @@ void gspca_frame_add(struct gspca_dev *gspca_dev, ...@@ -466,8 +466,9 @@ void gspca_frame_add(struct gspca_dev *gspca_dev,
j = gspca_dev->fr_queue[i]; j = gspca_dev->fr_queue[i];
frame = &gspca_dev->frame[j]; frame = &gspca_dev->frame[j];
frame->v4l2_buf.bytesused = gspca_dev->image_len; frame->v4l2_buf.bytesused = gspca_dev->image_len;
frame->v4l2_buf.flags &= ~V4L2_BUF_FLAG_QUEUED; frame->v4l2_buf.flags = (frame->v4l2_buf.flags
frame->v4l2_buf.flags |= V4L2_BUF_FLAG_DONE; | V4L2_BUF_FLAG_DONE)
& ~V4L2_BUF_FLAG_QUEUED;
wake_up_interruptible(&gspca_dev->wq); /* event = new frame */ wake_up_interruptible(&gspca_dev->wq); /* event = new frame */
i = (i + 1) % gspca_dev->nframes; i = (i + 1) % gspca_dev->nframes;
gspca_dev->fr_i = i; gspca_dev->fr_i = i;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment