From 743e18377cae643f88ff62b4c2b87c45e4ecd024 Mon Sep 17 00:00:00 2001 From: Sakari Ailus Date: Mon, 22 Apr 2013 10:24:51 -0300 Subject: [media] v4l: Check pad arguments for [gs]_frame_interval VIDIOC_SUBDEV_[GS]_FRAME_INTERVAL IOCTLs argument structs contain the pad field but the validity check was missing. There should be no implications security-wise from this since no driver currently uses the pad field in the struct. Signed-off-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- drivers/media/v4l2-core/v4l2-subdev.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) (limited to 'drivers/media/v4l2-core/v4l2-subdev.c') diff --git a/drivers/media/v4l2-core/v4l2-subdev.c b/drivers/media/v4l2-core/v4l2-subdev.c index aea84ac5688..0ed4c5be1b3 100644 --- a/drivers/media/v4l2-core/v4l2-subdev.c +++ b/drivers/media/v4l2-core/v4l2-subdev.c @@ -305,11 +305,23 @@ static long subdev_do_ioctl(struct file *file, unsigned int cmd, void *arg) fse); } - case VIDIOC_SUBDEV_G_FRAME_INTERVAL: + case VIDIOC_SUBDEV_G_FRAME_INTERVAL: { + struct v4l2_subdev_frame_interval *fi = arg; + + if (fi->pad >= sd->entity.num_pads) + return -EINVAL; + return v4l2_subdev_call(sd, video, g_frame_interval, arg); + } + + case VIDIOC_SUBDEV_S_FRAME_INTERVAL: { + struct v4l2_subdev_frame_interval *fi = arg; + + if (fi->pad >= sd->entity.num_pads) + return -EINVAL; - case VIDIOC_SUBDEV_S_FRAME_INTERVAL: return v4l2_subdev_call(sd, video, s_frame_interval, arg); + } case VIDIOC_SUBDEV_ENUM_FRAME_INTERVAL: { struct v4l2_subdev_frame_interval_enum *fie = arg; -- cgit v1.2.3-70-g09d2 From 9cfd65e80959836fed78704e8a127d4e10448d56 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Wed, 29 Jan 2014 10:07:13 -0300 Subject: [media] v4l: Add support for DV timings ioctls on subdev nodes Validate the pad field in the core code whenever specified. Signed-off-by: Laurent Pinchart Reviewed-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- .../DocBook/media/v4l/vidioc-dv-timings-cap.xml | 27 +++++++++++++++---- .../DocBook/media/v4l/vidioc-enum-dv-timings.xml | 30 +++++++++++++++++----- drivers/media/v4l2-core/v4l2-subdev.c | 27 +++++++++++++++++++ include/uapi/linux/v4l2-subdev.h | 7 ++++- 4 files changed, 78 insertions(+), 13 deletions(-) (limited to 'drivers/media/v4l2-core/v4l2-subdev.c') diff --git a/Documentation/DocBook/media/v4l/vidioc-dv-timings-cap.xml b/Documentation/DocBook/media/v4l/vidioc-dv-timings-cap.xml index cd7720d404e..28a8c1e1c70 100644 --- a/Documentation/DocBook/media/v4l/vidioc-dv-timings-cap.xml +++ b/Documentation/DocBook/media/v4l/vidioc-dv-timings-cap.xml @@ -1,11 +1,12 @@ - ioctl VIDIOC_DV_TIMINGS_CAP + ioctl VIDIOC_DV_TIMINGS_CAP, VIDIOC_SUBDEV_DV_TIMINGS_CAP &manvol; VIDIOC_DV_TIMINGS_CAP + VIDIOC_SUBDEV_DV_TIMINGS_CAP The capabilities of the Digital Video receiver/transmitter @@ -33,7 +34,7 @@ request - VIDIOC_DV_TIMINGS_CAP + VIDIOC_DV_TIMINGS_CAP, VIDIOC_SUBDEV_DV_TIMINGS_CAP @@ -54,10 +55,19 @@ interface and may change in the future. - To query the capabilities of the DV receiver/transmitter applications can call -this ioctl and the driver will fill in the structure. Note that drivers may return + To query the capabilities of the DV receiver/transmitter applications +can call the VIDIOC_DV_TIMINGS_CAP ioctl on a video node +and the driver will fill in the structure. Note that drivers may return different values after switching the video input or output. + When implemented by the driver DV capabilities of subdevices can be +queried by calling the VIDIOC_SUBDEV_DV_TIMINGS_CAP ioctl +directly on a subdevice node. The capabilities are specific to inputs (for DV +receivers) or outputs (for DV transmitters), applications must specify the +desired pad number in the &v4l2-dv-timings-cap; pad +field. Attempts to query capabilities on a pad that doesn't support them will +return an &EINVAL;. + struct <structname>v4l2_bt_timings_cap</structname> @@ -127,7 +137,14 @@ different values after switching the video input or output. __u32 - reserved[3] + pad + Pad number as reported by the media controller API. This field + is only used when operating on a subdevice node. When operating on a + video node applications must set this field to zero. + + + __u32 + reserved[2] Reserved for future extensions. Drivers must set the array to zero. diff --git a/Documentation/DocBook/media/v4l/vidioc-enum-dv-timings.xml b/Documentation/DocBook/media/v4l/vidioc-enum-dv-timings.xml index b3e17c1dfaf..b9fdfeacdbc 100644 --- a/Documentation/DocBook/media/v4l/vidioc-enum-dv-timings.xml +++ b/Documentation/DocBook/media/v4l/vidioc-enum-dv-timings.xml @@ -1,11 +1,12 @@ - ioctl VIDIOC_ENUM_DV_TIMINGS + ioctl VIDIOC_ENUM_DV_TIMINGS, VIDIOC_SUBDEV_ENUM_DV_TIMINGS &manvol; VIDIOC_ENUM_DV_TIMINGS + VIDIOC_SUBDEV_ENUM_DV_TIMINGS Enumerate supported Digital Video timings @@ -33,7 +34,7 @@ request - VIDIOC_ENUM_DV_TIMINGS + VIDIOC_ENUM_DV_TIMINGS, VIDIOC_SUBDEV_ENUM_DV_TIMINGS @@ -61,14 +62,21 @@ standards or even custom timings that are not in this list. To query the available timings, applications initialize the index field and zero the reserved array of &v4l2-enum-dv-timings; -and call the VIDIOC_ENUM_DV_TIMINGS ioctl with a pointer to this -structure. Drivers fill the rest of the structure or return an +and call the VIDIOC_ENUM_DV_TIMINGS ioctl on a video node with a +pointer to this structure. Drivers fill the rest of the structure or return an &EINVAL; when the index is out of bounds. To enumerate all supported DV timings, applications shall begin at index zero, incrementing by one until the driver returns EINVAL. Note that drivers may enumerate a different set of DV timings after switching the video input or output. + When implemented by the driver DV timings of subdevices can be queried +by calling the VIDIOC_SUBDEV_ENUM_DV_TIMINGS ioctl directly +on a subdevice node. The DV timings are specific to inputs (for DV receivers) or +outputs (for DV transmitters), applications must specify the desired pad number +in the &v4l2-enum-dv-timings; pad field. Attempts to +enumerate timings on a pad that doesn't support them will return an &EINVAL;. +
struct <structname>v4l2_enum_dv_timings</structname> @@ -82,8 +90,16 @@ application. __u32 - reserved[3] - Reserved for future extensions. Drivers must set the array to zero. + pad + Pad number as reported by the media controller API. This field + is only used when operating on a subdevice node. When operating on a + video node applications must set this field to zero. + + + __u32 + reserved[2] + Reserved for future extensions. Drivers and applications must + set the array to zero. &v4l2-dv-timings; @@ -103,7 +119,7 @@ application. EINVAL The &v4l2-enum-dv-timings; index -is out of bounds. +is out of bounds or the pad number is invalid. diff --git a/drivers/media/v4l2-core/v4l2-subdev.c b/drivers/media/v4l2-core/v4l2-subdev.c index 0ed4c5be1b3..db126dbc19c 100644 --- a/drivers/media/v4l2-core/v4l2-subdev.c +++ b/drivers/media/v4l2-core/v4l2-subdev.c @@ -366,6 +366,33 @@ static long subdev_do_ioctl(struct file *file, unsigned int cmd, void *arg) case VIDIOC_S_EDID: return v4l2_subdev_call(sd, pad, set_edid, arg); + + case VIDIOC_SUBDEV_DV_TIMINGS_CAP: { + struct v4l2_dv_timings_cap *cap = arg; + + if (cap->pad >= sd->entity.num_pads) + return -EINVAL; + + return v4l2_subdev_call(sd, pad, dv_timings_cap, cap); + } + + case VIDIOC_SUBDEV_ENUM_DV_TIMINGS: { + struct v4l2_enum_dv_timings *dvt = arg; + + if (dvt->pad >= sd->entity.num_pads) + return -EINVAL; + + return v4l2_subdev_call(sd, pad, enum_dv_timings, dvt); + } + + case VIDIOC_SUBDEV_QUERY_DV_TIMINGS: + return v4l2_subdev_call(sd, video, query_dv_timings, arg); + + case VIDIOC_SUBDEV_G_DV_TIMINGS: + return v4l2_subdev_call(sd, video, g_dv_timings, arg); + + case VIDIOC_SUBDEV_S_DV_TIMINGS: + return v4l2_subdev_call(sd, video, s_dv_timings, arg); #endif default: return v4l2_subdev_call(sd, core, ioctl, cmd, arg); diff --git a/include/uapi/linux/v4l2-subdev.h b/include/uapi/linux/v4l2-subdev.h index db28964a697..a619cdd300a 100644 --- a/include/uapi/linux/v4l2-subdev.h +++ b/include/uapi/linux/v4l2-subdev.h @@ -162,8 +162,13 @@ struct v4l2_subdev_selection { #define VIDIOC_SUBDEV_S_CROP _IOWR('V', 60, struct v4l2_subdev_crop) #define VIDIOC_SUBDEV_G_SELECTION _IOWR('V', 61, struct v4l2_subdev_selection) #define VIDIOC_SUBDEV_S_SELECTION _IOWR('V', 62, struct v4l2_subdev_selection) -/* These two G/S_EDID ioctls are identical to the ioctls in videodev2.h */ +/* The following ioctls are identical to the ioctls in videodev2.h */ #define VIDIOC_SUBDEV_G_EDID _IOWR('V', 40, struct v4l2_edid) #define VIDIOC_SUBDEV_S_EDID _IOWR('V', 41, struct v4l2_edid) +#define VIDIOC_SUBDEV_S_DV_TIMINGS _IOWR('V', 87, struct v4l2_dv_timings) +#define VIDIOC_SUBDEV_G_DV_TIMINGS _IOWR('V', 88, struct v4l2_dv_timings) +#define VIDIOC_SUBDEV_ENUM_DV_TIMINGS _IOWR('V', 98, struct v4l2_enum_dv_timings) +#define VIDIOC_SUBDEV_QUERY_DV_TIMINGS _IOR('V', 99, struct v4l2_dv_timings) +#define VIDIOC_SUBDEV_DV_TIMINGS_CAP _IOWR('V', 100, struct v4l2_dv_timings_cap) #endif -- cgit v1.2.3-70-g09d2 From f2e9084779d3ad3b51ee45a3a53fead3f16516ca Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Wed, 29 Jan 2014 10:07:13 -0300 Subject: [media] v4l: Validate fields in the core code for subdev EDID ioctls The subdev EDID ioctls receive a pad field that must reference an existing pad and an EDID field that must point to a buffer. Validate both fields in the core code instead of duplicating validation in all drivers. Signed-off-by: Laurent Pinchart Acked-by: Sakari Ailus Reviewed-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/ad9389b.c | 2 -- drivers/media/i2c/adv7511.c | 2 -- drivers/media/i2c/adv7604.c | 4 ---- drivers/media/i2c/adv7842.c | 4 ---- drivers/media/v4l2-core/v4l2-subdev.c | 24 ++++++++++++++++++++---- 5 files changed, 20 insertions(+), 16 deletions(-) (limited to 'drivers/media/v4l2-core/v4l2-subdev.c') diff --git a/drivers/media/i2c/ad9389b.c b/drivers/media/i2c/ad9389b.c index f00b3dd2b45..fada1756620 100644 --- a/drivers/media/i2c/ad9389b.c +++ b/drivers/media/i2c/ad9389b.c @@ -682,8 +682,6 @@ static int ad9389b_get_edid(struct v4l2_subdev *sd, struct v4l2_edid *edid) return -EINVAL; if (edid->blocks == 0 || edid->blocks > 256) return -EINVAL; - if (!edid->edid) - return -EINVAL; if (!state->edid.segments) { v4l2_dbg(1, debug, sd, "EDID segment 0 not found\n"); return -ENODATA; diff --git a/drivers/media/i2c/adv7511.c b/drivers/media/i2c/adv7511.c index d77a1db4f94..f98acf4aafd 100644 --- a/drivers/media/i2c/adv7511.c +++ b/drivers/media/i2c/adv7511.c @@ -783,8 +783,6 @@ static int adv7511_get_edid(struct v4l2_subdev *sd, struct v4l2_edid *edid) return -EINVAL; if ((edid->blocks == 0) || (edid->blocks > 256)) return -EINVAL; - if (!edid->edid) - return -EINVAL; if (!state->edid.segments) { v4l2_dbg(1, debug, sd, "EDID segment 0 not found\n"); return -ENODATA; diff --git a/drivers/media/i2c/adv7604.c b/drivers/media/i2c/adv7604.c index 98cc5407f1b..338baa4c23e 100644 --- a/drivers/media/i2c/adv7604.c +++ b/drivers/media/i2c/adv7604.c @@ -1673,8 +1673,6 @@ static int adv7604_get_edid(struct v4l2_subdev *sd, struct v4l2_edid *edid) return -EINVAL; if (edid->start_block == 1) edid->blocks = 1; - if (!edid->edid) - return -EINVAL; if (edid->blocks > state->edid.blocks) edid->blocks = state->edid.blocks; @@ -1761,8 +1759,6 @@ static int adv7604_set_edid(struct v4l2_subdev *sd, struct v4l2_edid *edid) edid->blocks = 2; return -E2BIG; } - if (!edid->edid) - return -EINVAL; v4l2_dbg(2, debug, sd, "%s: write EDID pad %d, edid.present = 0x%x\n", __func__, edid->pad, state->edid.present); diff --git a/drivers/media/i2c/adv7842.c b/drivers/media/i2c/adv7842.c index d85e125aa8d..0d554919cdd 100644 --- a/drivers/media/i2c/adv7842.c +++ b/drivers/media/i2c/adv7842.c @@ -2036,8 +2036,6 @@ static int adv7842_get_edid(struct v4l2_subdev *sd, struct v4l2_edid *edid) return -EINVAL; if (edid->start_block == 1) edid->blocks = 1; - if (!edid->edid) - return -EINVAL; switch (edid->pad) { case ADV7842_EDID_PORT_A: @@ -2072,8 +2070,6 @@ static int adv7842_set_edid(struct v4l2_subdev *sd, struct v4l2_edid *e) return -EINVAL; if (e->blocks > 2) return -E2BIG; - if (!e->edid) - return -EINVAL; /* todo, per edid */ state->aspect_ratio = v4l2_calc_aspect_ratio(e->edid[0x15], diff --git a/drivers/media/v4l2-core/v4l2-subdev.c b/drivers/media/v4l2-core/v4l2-subdev.c index db126dbc19c..058c1a6e839 100644 --- a/drivers/media/v4l2-core/v4l2-subdev.c +++ b/drivers/media/v4l2-core/v4l2-subdev.c @@ -361,11 +361,27 @@ static long subdev_do_ioctl(struct file *file, unsigned int cmd, void *arg) sd, pad, set_selection, subdev_fh, sel); } - case VIDIOC_G_EDID: - return v4l2_subdev_call(sd, pad, get_edid, arg); + case VIDIOC_G_EDID: { + struct v4l2_subdev_edid *edid = arg; - case VIDIOC_S_EDID: - return v4l2_subdev_call(sd, pad, set_edid, arg); + if (edid->pad >= sd->entity.num_pads) + return -EINVAL; + if (edid->blocks && edid->edid == NULL) + return -EINVAL; + + return v4l2_subdev_call(sd, pad, get_edid, edid); + } + + case VIDIOC_S_EDID: { + struct v4l2_subdev_edid *edid = arg; + + if (edid->pad >= sd->entity.num_pads) + return -EINVAL; + if (edid->blocks && edid->edid == NULL) + return -EINVAL; + + return v4l2_subdev_call(sd, pad, set_edid, edid); + } case VIDIOC_SUBDEV_DV_TIMINGS_CAP: { struct v4l2_dv_timings_cap *cap = arg; -- cgit v1.2.3-70-g09d2