Skip to content

Commit 7f9a7cd

Browse files
committed
Merge tag 'media/v6.1-3' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media
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
2 parents 200204f + de54789 commit 7f9a7cd

File tree

7 files changed

+83
-13
lines changed

7 files changed

+83
-13
lines changed

Documentation/admin-guide/media/vivid.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1318,7 +1318,7 @@ instance. This setup would require the following commands:
13181318
$ v4l2-ctl -d2 -i2
13191319
$ v4l2-ctl -d2 -c horizontal_movement=4
13201320
$ v4l2-ctl -d1 --overlay=1
1321-
$ v4l2-ctl -d1 -c loop_video=1
1321+
$ v4l2-ctl -d0 -c loop_video=1
13221322
$ v4l2-ctl -d2 --stream-mmap --overlay=1
13231323
13241324
And from another console:

drivers/media/test-drivers/vivid/vivid-core.c

Lines changed: 34 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -339,6 +339,28 @@ static int vidioc_g_fbuf(struct file *file, void *fh, struct v4l2_framebuffer *a
339339
return vivid_vid_out_g_fbuf(file, fh, a);
340340
}
341341

342+
/*
343+
* Only support the framebuffer of one of the vivid instances.
344+
* Anything else is rejected.
345+
*/
346+
bool vivid_validate_fb(const struct v4l2_framebuffer *a)
347+
{
348+
struct vivid_dev *dev;
349+
int i;
350+
351+
for (i = 0; i < n_devs; i++) {
352+
dev = vivid_devs[i];
353+
if (!dev || !dev->video_pbase)
354+
continue;
355+
if ((unsigned long)a->base == dev->video_pbase &&
356+
a->fmt.width <= dev->display_width &&
357+
a->fmt.height <= dev->display_height &&
358+
a->fmt.bytesperline <= dev->display_byte_stride)
359+
return true;
360+
}
361+
return false;
362+
}
363+
342364
static int vidioc_s_fbuf(struct file *file, void *fh, const struct v4l2_framebuffer *a)
343365
{
344366
struct video_device *vdev = video_devdata(file);
@@ -920,8 +942,12 @@ static int vivid_detect_feature_set(struct vivid_dev *dev, int inst,
920942

921943
/* how many inputs do we have and of what type? */
922944
dev->num_inputs = num_inputs[inst];
923-
if (dev->num_inputs < 1)
924-
dev->num_inputs = 1;
945+
if (node_type & 0x20007) {
946+
if (dev->num_inputs < 1)
947+
dev->num_inputs = 1;
948+
} else {
949+
dev->num_inputs = 0;
950+
}
925951
if (dev->num_inputs >= MAX_INPUTS)
926952
dev->num_inputs = MAX_INPUTS;
927953
for (i = 0; i < dev->num_inputs; i++) {
@@ -938,8 +964,12 @@ static int vivid_detect_feature_set(struct vivid_dev *dev, int inst,
938964

939965
/* how many outputs do we have and of what type? */
940966
dev->num_outputs = num_outputs[inst];
941-
if (dev->num_outputs < 1)
942-
dev->num_outputs = 1;
967+
if (node_type & 0x40300) {
968+
if (dev->num_outputs < 1)
969+
dev->num_outputs = 1;
970+
} else {
971+
dev->num_outputs = 0;
972+
}
943973
if (dev->num_outputs >= MAX_OUTPUTS)
944974
dev->num_outputs = MAX_OUTPUTS;
945975
for (i = 0; i < dev->num_outputs; i++) {

drivers/media/test-drivers/vivid/vivid-core.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -613,4 +613,6 @@ static inline bool vivid_is_hdmi_out(const struct vivid_dev *dev)
613613
return dev->output_type[dev->output] == HDMI;
614614
}
615615

616+
bool vivid_validate_fb(const struct v4l2_framebuffer *a);
617+
616618
#endif

drivers/media/test-drivers/vivid/vivid-osd.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -357,7 +357,7 @@ int vivid_fb_init(struct vivid_dev *dev)
357357
int ret;
358358

359359
dev->video_buffer_size = MAX_OSD_HEIGHT * MAX_OSD_WIDTH * 2;
360-
dev->video_vbase = kzalloc(dev->video_buffer_size, GFP_KERNEL | GFP_DMA32);
360+
dev->video_vbase = kzalloc(dev->video_buffer_size, GFP_KERNEL);
361361
if (dev->video_vbase == NULL)
362362
return -ENOMEM;
363363
dev->video_pbase = virt_to_phys(dev->video_vbase);

drivers/media/test-drivers/vivid/vivid-vid-cap.c

Lines changed: 29 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -453,13 +453,27 @@ void vivid_update_format_cap(struct vivid_dev *dev, bool keep_controls)
453453
tpg_reset_source(&dev->tpg, dev->src_rect.width, dev->src_rect.height, dev->field_cap);
454454
dev->crop_cap = dev->src_rect;
455455
dev->crop_bounds_cap = dev->src_rect;
456+
if (dev->bitmap_cap &&
457+
(dev->compose_cap.width != dev->crop_cap.width ||
458+
dev->compose_cap.height != dev->crop_cap.height)) {
459+
vfree(dev->bitmap_cap);
460+
dev->bitmap_cap = NULL;
461+
}
456462
dev->compose_cap = dev->crop_cap;
457463
if (V4L2_FIELD_HAS_T_OR_B(dev->field_cap))
458464
dev->compose_cap.height /= 2;
459465
dev->fmt_cap_rect = dev->compose_cap;
460466
tpg_s_video_aspect(&dev->tpg, vivid_get_video_aspect(dev));
461467
tpg_s_pixel_aspect(&dev->tpg, vivid_get_pixel_aspect(dev));
462468
tpg_update_mv_step(&dev->tpg);
469+
470+
/*
471+
* We can be called from within s_ctrl, in that case we can't
472+
* modify controls. Luckily we don't need to in that case.
473+
*/
474+
if (keep_controls)
475+
return;
476+
463477
dims[0] = roundup(dev->src_rect.width, PIXEL_ARRAY_DIV);
464478
dims[1] = roundup(dev->src_rect.height, PIXEL_ARRAY_DIV);
465479
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
913927
struct vivid_dev *dev = video_drvdata(file);
914928
struct v4l2_rect *crop = &dev->crop_cap;
915929
struct v4l2_rect *compose = &dev->compose_cap;
930+
unsigned orig_compose_w = compose->width;
931+
unsigned orig_compose_h = compose->height;
916932
unsigned factor = V4L2_FIELD_HAS_T_OR_B(dev->field_cap) ? 2 : 1;
917933
int ret;
918934

@@ -1029,17 +1045,17 @@ int vivid_vid_cap_s_selection(struct file *file, void *fh, struct v4l2_selection
10291045
s->r.height /= factor;
10301046
}
10311047
v4l2_rect_map_inside(&s->r, &dev->fmt_cap_rect);
1032-
if (dev->bitmap_cap && (compose->width != s->r.width ||
1033-
compose->height != s->r.height)) {
1034-
vfree(dev->bitmap_cap);
1035-
dev->bitmap_cap = NULL;
1036-
}
10371048
*compose = s->r;
10381049
break;
10391050
default:
10401051
return -EINVAL;
10411052
}
10421053

1054+
if (dev->bitmap_cap && (compose->width != orig_compose_w ||
1055+
compose->height != orig_compose_h)) {
1056+
vfree(dev->bitmap_cap);
1057+
dev->bitmap_cap = NULL;
1058+
}
10431059
tpg_s_crop_compose(&dev->tpg, crop, compose);
10441060
return 0;
10451061
}
@@ -1276,7 +1292,14 @@ int vivid_vid_cap_s_fbuf(struct file *file, void *fh,
12761292
return -EINVAL;
12771293
if (a->fmt.bytesperline < (a->fmt.width * fmt->bit_depth[0]) / 8)
12781294
return -EINVAL;
1279-
if (a->fmt.height * a->fmt.bytesperline < a->fmt.sizeimage)
1295+
if (a->fmt.bytesperline > a->fmt.sizeimage / a->fmt.height)
1296+
return -EINVAL;
1297+
1298+
/*
1299+
* Only support the framebuffer of one of the vivid instances.
1300+
* Anything else is rejected.
1301+
*/
1302+
if (!vivid_validate_fb(a))
12801303
return -EINVAL;
12811304

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

drivers/media/v4l2-core/v4l2-dv-timings.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,20 @@ bool v4l2_valid_dv_timings(const struct v4l2_dv_timings *t,
161161
(bt->interlaced && !(caps & V4L2_DV_BT_CAP_INTERLACED)) ||
162162
(!bt->interlaced && !(caps & V4L2_DV_BT_CAP_PROGRESSIVE)))
163163
return false;
164+
165+
/* sanity checks for the blanking timings */
166+
if (!bt->interlaced &&
167+
(bt->il_vbackporch || bt->il_vsync || bt->il_vfrontporch))
168+
return false;
169+
if (bt->hfrontporch > 2 * bt->width ||
170+
bt->hsync > 1024 || bt->hbackporch > 1024)
171+
return false;
172+
if (bt->vfrontporch > 4096 ||
173+
bt->vsync > 128 || bt->vbackporch > 4096)
174+
return false;
175+
if (bt->interlaced && (bt->il_vfrontporch > 4096 ||
176+
bt->il_vsync > 128 || bt->il_vbackporch > 4096))
177+
return false;
164178
return fnc == NULL || fnc(t, fnc_handle);
165179
}
166180
EXPORT_SYMBOL_GPL(v4l2_valid_dv_timings);

include/uapi/linux/videodev2.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1601,7 +1601,8 @@ struct v4l2_bt_timings {
16011601
((bt)->width + V4L2_DV_BT_BLANKING_WIDTH(bt))
16021602
#define V4L2_DV_BT_BLANKING_HEIGHT(bt) \
16031603
((bt)->vfrontporch + (bt)->vsync + (bt)->vbackporch + \
1604-
(bt)->il_vfrontporch + (bt)->il_vsync + (bt)->il_vbackporch)
1604+
((bt)->interlaced ? \
1605+
((bt)->il_vfrontporch + (bt)->il_vsync + (bt)->il_vbackporch) : 0))
16051606
#define V4L2_DV_BT_FRAME_HEIGHT(bt) \
16061607
((bt)->height + V4L2_DV_BT_BLANKING_HEIGHT(bt))
16071608

0 commit comments

Comments
 (0)