Commit 7f9a7cd6 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull media fixes from Mauro Carvalho Chehab:
 "A bunch of patches addressing issues in the vivid driver and adding
  new checks in V4L2 to validate the input parameters from some ioctls"

* tag 'media/v6.1-3' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media:
  media: vivid.rst: loop_video is set on the capture devnode
  media: vivid: set num_in/outputs to 0 if not supported
  media: vivid: drop GFP_DMA32
  media: vivid: fix control handler mutex deadlock
  media: videodev2.h: V4L2_DV_BT_BLANKING_HEIGHT should check 'interlaced'
  media: v4l2-dv-timings: add sanity checks for blanking values
  media: vivid: dev->bitmap_cap wasn't freed in all cases
  media: vivid: s_fbuf: add more sanity checks
parents 200204f5 de547896
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -1318,7 +1318,7 @@ instance. This setup would require the following commands:
	$ v4l2-ctl -d2 -i2
	$ v4l2-ctl -d2 -c horizontal_movement=4
	$ v4l2-ctl -d1 --overlay=1
	$ v4l2-ctl -d1 -c loop_video=1
	$ v4l2-ctl -d0 -c loop_video=1
	$ v4l2-ctl -d2 --stream-mmap --overlay=1

And from another console:
+34 −4
Original line number Diff line number Diff line
@@ -339,6 +339,28 @@ static int vidioc_g_fbuf(struct file *file, void *fh, struct v4l2_framebuffer *a
	return vivid_vid_out_g_fbuf(file, fh, a);
}

/*
 * Only support the framebuffer of one of the vivid instances.
 * Anything else is rejected.
 */
bool vivid_validate_fb(const struct v4l2_framebuffer *a)
{
	struct vivid_dev *dev;
	int i;

	for (i = 0; i < n_devs; i++) {
		dev = vivid_devs[i];
		if (!dev || !dev->video_pbase)
			continue;
		if ((unsigned long)a->base == dev->video_pbase &&
		    a->fmt.width <= dev->display_width &&
		    a->fmt.height <= dev->display_height &&
		    a->fmt.bytesperline <= dev->display_byte_stride)
			return true;
	}
	return false;
}

static int vidioc_s_fbuf(struct file *file, void *fh, const struct v4l2_framebuffer *a)
{
	struct video_device *vdev = video_devdata(file);
@@ -920,8 +942,12 @@ static int vivid_detect_feature_set(struct vivid_dev *dev, int inst,

	/* how many inputs do we have and of what type? */
	dev->num_inputs = num_inputs[inst];
	if (node_type & 0x20007) {
		if (dev->num_inputs < 1)
			dev->num_inputs = 1;
	} else {
		dev->num_inputs = 0;
	}
	if (dev->num_inputs >= MAX_INPUTS)
		dev->num_inputs = MAX_INPUTS;
	for (i = 0; i < dev->num_inputs; i++) {
@@ -938,8 +964,12 @@ static int vivid_detect_feature_set(struct vivid_dev *dev, int inst,

	/* how many outputs do we have and of what type? */
	dev->num_outputs = num_outputs[inst];
	if (node_type & 0x40300) {
		if (dev->num_outputs < 1)
			dev->num_outputs = 1;
	} else {
		dev->num_outputs = 0;
	}
	if (dev->num_outputs >= MAX_OUTPUTS)
		dev->num_outputs = MAX_OUTPUTS;
	for (i = 0; i < dev->num_outputs; i++) {
+2 −0
Original line number Diff line number Diff line
@@ -613,4 +613,6 @@ static inline bool vivid_is_hdmi_out(const struct vivid_dev *dev)
	return dev->output_type[dev->output] == HDMI;
}

bool vivid_validate_fb(const struct v4l2_framebuffer *a);

#endif
+1 −1
Original line number Diff line number Diff line
@@ -357,7 +357,7 @@ int vivid_fb_init(struct vivid_dev *dev)
	int ret;

	dev->video_buffer_size = MAX_OSD_HEIGHT * MAX_OSD_WIDTH * 2;
	dev->video_vbase = kzalloc(dev->video_buffer_size, GFP_KERNEL | GFP_DMA32);
	dev->video_vbase = kzalloc(dev->video_buffer_size, GFP_KERNEL);
	if (dev->video_vbase == NULL)
		return -ENOMEM;
	dev->video_pbase = virt_to_phys(dev->video_vbase);
+29 −6
Original line number Diff line number Diff line
@@ -453,6 +453,12 @@ void vivid_update_format_cap(struct vivid_dev *dev, bool keep_controls)
	tpg_reset_source(&dev->tpg, dev->src_rect.width, dev->src_rect.height, dev->field_cap);
	dev->crop_cap = dev->src_rect;
	dev->crop_bounds_cap = dev->src_rect;
	if (dev->bitmap_cap &&
	    (dev->compose_cap.width != dev->crop_cap.width ||
	     dev->compose_cap.height != dev->crop_cap.height)) {
		vfree(dev->bitmap_cap);
		dev->bitmap_cap = NULL;
	}
	dev->compose_cap = dev->crop_cap;
	if (V4L2_FIELD_HAS_T_OR_B(dev->field_cap))
		dev->compose_cap.height /= 2;
@@ -460,6 +466,14 @@ void vivid_update_format_cap(struct vivid_dev *dev, bool keep_controls)
	tpg_s_video_aspect(&dev->tpg, vivid_get_video_aspect(dev));
	tpg_s_pixel_aspect(&dev->tpg, vivid_get_pixel_aspect(dev));
	tpg_update_mv_step(&dev->tpg);

	/*
	 * We can be called from within s_ctrl, in that case we can't
	 * modify controls. Luckily we don't need to in that case.
	 */
	if (keep_controls)
		return;

	dims[0] = roundup(dev->src_rect.width, PIXEL_ARRAY_DIV);
	dims[1] = roundup(dev->src_rect.height, PIXEL_ARRAY_DIV);
	v4l2_ctrl_modify_dimensions(dev->pixel_array, dims);
@@ -913,6 +927,8 @@ int vivid_vid_cap_s_selection(struct file *file, void *fh, struct v4l2_selection
	struct vivid_dev *dev = video_drvdata(file);
	struct v4l2_rect *crop = &dev->crop_cap;
	struct v4l2_rect *compose = &dev->compose_cap;
	unsigned orig_compose_w = compose->width;
	unsigned orig_compose_h = compose->height;
	unsigned factor = V4L2_FIELD_HAS_T_OR_B(dev->field_cap) ? 2 : 1;
	int ret;

@@ -1029,17 +1045,17 @@ int vivid_vid_cap_s_selection(struct file *file, void *fh, struct v4l2_selection
			s->r.height /= factor;
		}
		v4l2_rect_map_inside(&s->r, &dev->fmt_cap_rect);
		if (dev->bitmap_cap && (compose->width != s->r.width ||
					compose->height != s->r.height)) {
			vfree(dev->bitmap_cap);
			dev->bitmap_cap = NULL;
		}
		*compose = s->r;
		break;
	default:
		return -EINVAL;
	}

	if (dev->bitmap_cap && (compose->width != orig_compose_w ||
				compose->height != orig_compose_h)) {
		vfree(dev->bitmap_cap);
		dev->bitmap_cap = NULL;
	}
	tpg_s_crop_compose(&dev->tpg, crop, compose);
	return 0;
}
@@ -1276,7 +1292,14 @@ int vivid_vid_cap_s_fbuf(struct file *file, void *fh,
		return -EINVAL;
	if (a->fmt.bytesperline < (a->fmt.width * fmt->bit_depth[0]) / 8)
		return -EINVAL;
	if (a->fmt.height * a->fmt.bytesperline < a->fmt.sizeimage)
	if (a->fmt.bytesperline > a->fmt.sizeimage / a->fmt.height)
		return -EINVAL;

	/*
	 * Only support the framebuffer of one of the vivid instances.
	 * Anything else is rejected.
	 */
	if (!vivid_validate_fb(a))
		return -EINVAL;

	dev->fb_vbase_cap = phys_to_virt((unsigned long)a->base);
Loading