media: v4l2: Sanitize colorspace values in the framework
authorLaurent Pinchart <laurent.pinchart@ideasonboard.com>
Thu, 17 Mar 2022 12:37:12 +0000 (12:37 +0000)
committerMauro Carvalho Chehab <mchehab@kernel.org>
Fri, 15 Jul 2022 14:03:36 +0000 (15:03 +0100)
Extend the format sanitization code in the framework to handle invalid
values for the colorspace-related fields.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Acked-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Reviewed-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
Signed-off-by: Mauro Carvalho Chehab <mchehab@kernel.org>
drivers/media/v4l2-core/v4l2-ioctl.c

index 11f19099f33bd032113a991aab9abb52ca81a9bc..d9b6b8a678bc96dc70a161ed23f2980ee3a037d1 100644 (file)
@@ -1007,6 +1007,31 @@ static int check_fmt(struct file *file, enum v4l2_buf_type type)
        return -EINVAL;
 }
 
+static void v4l_sanitize_colorspace(u32 pixelformat, u32 *colorspace,
+                                   u32 *encoding, u32 *quantization,
+                                   u32 *xfer_func)
+{
+       bool is_hsv = pixelformat == V4L2_PIX_FMT_HSV24 ||
+                     pixelformat == V4L2_PIX_FMT_HSV32;
+
+       if (!v4l2_is_colorspace_valid(*colorspace)) {
+               *colorspace = V4L2_COLORSPACE_DEFAULT;
+               *encoding = V4L2_YCBCR_ENC_DEFAULT;
+               *quantization = V4L2_QUANTIZATION_DEFAULT;
+               *xfer_func = V4L2_XFER_FUNC_DEFAULT;
+       }
+
+       if ((!is_hsv && !v4l2_is_ycbcr_enc_valid(*encoding)) ||
+           (is_hsv && !v4l2_is_hsv_enc_valid(*encoding)))
+               *encoding = V4L2_YCBCR_ENC_DEFAULT;
+
+       if (!v4l2_is_quant_valid(*quantization))
+               *quantization = V4L2_QUANTIZATION_DEFAULT;
+
+       if (!v4l2_is_xfer_func_valid(*xfer_func))
+               *xfer_func = V4L2_XFER_FUNC_DEFAULT;
+}
+
 static void v4l_sanitize_format(struct v4l2_format *fmt)
 {
        unsigned int offset;
@@ -1026,20 +1051,40 @@ static void v4l_sanitize_format(struct v4l2_format *fmt)
         * field to the magic value when the extended pixel format structure
         * isn't used by applications.
         */
+       if (fmt->type == V4L2_BUF_TYPE_VIDEO_CAPTURE ||
+           fmt->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) {
+               if (fmt->fmt.pix.priv != V4L2_PIX_FMT_PRIV_MAGIC) {
+                       fmt->fmt.pix.priv = V4L2_PIX_FMT_PRIV_MAGIC;
+
+                       offset = offsetof(struct v4l2_pix_format, priv)
+                              + sizeof(fmt->fmt.pix.priv);
+                       memset(((void *)&fmt->fmt.pix) + offset, 0,
+                              sizeof(fmt->fmt.pix) - offset);
+               }
+       }
 
-       if (fmt->type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&
-           fmt->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)
-               return;
-
-       if (fmt->fmt.pix.priv == V4L2_PIX_FMT_PRIV_MAGIC)
-               return;
-
-       fmt->fmt.pix.priv = V4L2_PIX_FMT_PRIV_MAGIC;
-
-       offset = offsetof(struct v4l2_pix_format, priv)
-              + sizeof(fmt->fmt.pix.priv);
-       memset(((void *)&fmt->fmt.pix) + offset, 0,
-              sizeof(fmt->fmt.pix) - offset);
+       /* Replace invalid colorspace values with defaults. */
+       if (fmt->type == V4L2_BUF_TYPE_VIDEO_CAPTURE ||
+           fmt->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) {
+               v4l_sanitize_colorspace(fmt->fmt.pix.pixelformat,
+                                       &fmt->fmt.pix.colorspace,
+                                       &fmt->fmt.pix.ycbcr_enc,
+                                       &fmt->fmt.pix.quantization,
+                                       &fmt->fmt.pix.xfer_func);
+       } else if (fmt->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE ||
+                  fmt->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+               u32 ycbcr_enc = fmt->fmt.pix_mp.ycbcr_enc;
+               u32 quantization = fmt->fmt.pix_mp.quantization;
+               u32 xfer_func = fmt->fmt.pix_mp.xfer_func;
+
+               v4l_sanitize_colorspace(fmt->fmt.pix_mp.pixelformat,
+                                       &fmt->fmt.pix_mp.colorspace, &ycbcr_enc,
+                                       &quantization, &xfer_func);
+
+               fmt->fmt.pix_mp.ycbcr_enc = ycbcr_enc;
+               fmt->fmt.pix_mp.quantization = quantization;
+               fmt->fmt.pix_mp.xfer_func = xfer_func;
+       }
 }
 
 static int v4l_querycap(const struct v4l2_ioctl_ops *ops,