On Wed, Apr 01, 2020 at 08:20:59AM -0700, Steve Longerbeam wrote: > On 3/31/20 5:31 PM, Laurent Pinchart wrote: > > On Tue, Mar 31, 2020 at 04:04:18PM -0700, Steve Longerbeam wrote: > >> On 3/31/20 6:45 AM, Hans Verkuil wrote: > >>> On 3/29/20 10:59 PM, Steve Longerbeam wrote: > >>>> From: Laurent Pinchart <laurent.pinchart@xxxxxxxxxxxxxxxx> > >>>> > >>>> The imx_media_pixfmt structures includes a codes member that stores > >>>> media bus codes as a fixed array of 4 integers. The functions dealing > >>>> with the imx_media_pixfmt structures assume that the array of codes is > >>>> terminated by a 0 elements. This mechanism is fragile, as demonstrated > >>> > >>> elements -> element > >>> > >>>> by several instances of the structure contained 4 non-zero codes. > >>> > >>> contained -> that contained > >> > >> Will fix above language. > >> > >>>> Fix this by turning the array into a pointer, and providing an > >>>> IMX_BUS_FMTS macro to initialize the codes member with a guaranteed 0 > >>>> element at the end. > >>>> > >>>> Signed-off-by: Laurent Pinchart <laurent.pinchart@xxxxxxxxxxxxxxxx> > >>>> > >>>> [Fix a NULL deref when derefencing a NULL cc->codes on return from > >>>> several calls to imx_media_find_format()] > >>>> Signed-off-by: Steve Longerbeam <slongerbeam@xxxxxxxxx> > >>>> --- > >>>> drivers/staging/media/imx/imx-media-capture.c | 4 +- > >>>> drivers/staging/media/imx/imx-media-utils.c | 88 +++++++++++-------- > >>>> drivers/staging/media/imx/imx-media.h | 2 +- > >>>> 3 files changed, 53 insertions(+), 41 deletions(-) > >>>> > >>>> diff --git a/drivers/staging/media/imx/imx-media-capture.c b/drivers/staging/media/imx/imx-media-capture.c > >>>> index d60b49ec4fa4..650c53289f6b 100644 > >>>> --- a/drivers/staging/media/imx/imx-media-capture.c > >>>> +++ b/drivers/staging/media/imx/imx-media-capture.c > >>>> @@ -95,7 +95,7 @@ static int capture_enum_framesizes(struct file *file, void *fh, > >>>> if (!cc) > >>>> return -EINVAL; > >>>> > >>>> - fse.code = cc->codes[0]; > >>>> + fse.code = cc->codes ? cc->codes[0] : 0; > >>>> > >>> I'm wondering: wouldn't it be better to have a format without codes point to > >>> an empty code list containing just 0? That would avoid all the cc->codes checks, > >>> which are a bit fragile IMHO. > >> > >> I'll modify this patch to declare a const codes array 'no_bus_fmts', > >> containing a single 0 value, that the in-memory-only imx_media_pixfmt > >> entries can point to. > >> > >>> It would be nice in that case if there is a WARN_ON or something during probe > >>> time that checks that the codes field in pixel_formats[] is never NULL. > >> > >> I'm not so keen on that idea. How about a comment that the > >> in-memory-only entries should point to no_bus_fmts ? > > > > I don't like either of those options I'm afraid. Someone will one day > > forget to point to that array when adding a new format, and we'll have a > > bug. With code in just a few locations that checks for NULL, we're safe > > as the compiler will initialize the pointer to NULL for us. Let's use > > the compiler when it helps us, I don't see what removing the NULL check > > in the code could bring us except issues :-) > > I wasn't planning on removing the NULL checks, only to add the comment > to advise setting .codes = no_bus_fmts. Although I don't really think > that's necessary either. But if we keep the NULL checks, do we need no_bus_fmts ? As Hans doesn't consider this as a blocker, I'll let you decice which option you like best and use that. > >>> As an aside: 'cc'? The struct is called imx_media_pixfmt, so I don't offhand see > >>> what 'cc' stands for. > >> It's an abbreviation of FourCC. I know, it's obscure and not really > >> accurate. I will add a non-functional patch that makes the naming > >> consistent, using 'fmt' for imx_media_pixfmt pointers throughout. > >> > >>>> ret = v4l2_subdev_call(priv->src_sd, pad, enum_frame_size, NULL, &fse); > >>>> if (ret) > >>>> @@ -137,7 +137,7 @@ static int capture_enum_frameintervals(struct file *file, void *fh, > >>>> if (!cc) > >>>> return -EINVAL; > >>>> > >>>> - fie.code = cc->codes[0]; > >>>> + fie.code = cc->codes ? cc->codes[0] : 0; > >>>> > >>>> ret = v4l2_subdev_call(priv->src_sd, pad, enum_frame_interval, > >>>> NULL, &fie); > >>>> diff --git a/drivers/staging/media/imx/imx-media-utils.c b/drivers/staging/media/imx/imx-media-utils.c > >>>> index 981a8b540a3c..da010eef0ae6 100644 > >>>> --- a/drivers/staging/media/imx/imx-media-utils.c > >>>> +++ b/drivers/staging/media/imx/imx-media-utils.c > >>>> @@ -7,6 +7,12 @@ > >>>> #include <linux/module.h> > >>>> #include "imx-media.h" > >>>> > >>>> +#define IMX_BUS_FMTS(fmts...) \ > >>>> + (const u32[]) { \ > >>>> + fmts, \ > >>>> + 0 \ > >>>> + } > >>>> + > >>>> /* > >>>> * List of supported pixel formats for the subdevs. > >>>> */ > >>>> @@ -14,18 +20,18 @@ static const struct imx_media_pixfmt pixel_formats[] = { > >>>> /*** YUV formats start here ***/ > >>>> { > >>>> .fourcc = V4L2_PIX_FMT_UYVY, > >>>> - .codes = { > >>>> + .codes = IMX_BUS_FMTS( > >>>> MEDIA_BUS_FMT_UYVY8_2X8, > >>>> MEDIA_BUS_FMT_UYVY8_1X16 > >>>> - }, > >>>> + ), > >>>> .cs = IPUV3_COLORSPACE_YUV, > >>>> .bpp = 16, > >>>> }, { > >>>> .fourcc = V4L2_PIX_FMT_YUYV, > >>>> - .codes = { > >>>> + .codes = IMX_BUS_FMTS( > >>>> MEDIA_BUS_FMT_YUYV8_2X8, > >>>> MEDIA_BUS_FMT_YUYV8_1X16 > >>>> - }, > >>>> + ), > >>>> .cs = IPUV3_COLORSPACE_YUV, > >>>> .bpp = 16, > >>>> }, { > >>>> @@ -57,16 +63,16 @@ static const struct imx_media_pixfmt pixel_formats[] = { > >>>> /*** RGB formats start here ***/ > >>>> { > >>>> .fourcc = V4L2_PIX_FMT_RGB565, > >>>> - .codes = {MEDIA_BUS_FMT_RGB565_2X8_LE}, > >>>> + .codes = IMX_BUS_FMTS(MEDIA_BUS_FMT_RGB565_2X8_LE), > >>>> .cs = IPUV3_COLORSPACE_RGB, > >>>> .bpp = 16, > >>>> .cycles = 2, > >>>> }, { > >>>> .fourcc = V4L2_PIX_FMT_RGB24, > >>>> - .codes = { > >>>> + .codes = IMX_BUS_FMTS( > >>>> MEDIA_BUS_FMT_RGB888_1X24, > >>>> MEDIA_BUS_FMT_RGB888_2X12_LE > >>>> - }, > >>>> + ), > >>>> .cs = IPUV3_COLORSPACE_RGB, > >>>> .bpp = 24, > >>>> }, { > >>>> @@ -75,7 +81,7 @@ static const struct imx_media_pixfmt pixel_formats[] = { > >>>> .bpp = 24, > >>>> }, { > >>>> .fourcc = V4L2_PIX_FMT_XRGB32, > >>>> - .codes = {MEDIA_BUS_FMT_ARGB8888_1X32}, > >>>> + .codes = IMX_BUS_FMTS(MEDIA_BUS_FMT_ARGB8888_1X32), > >>>> .cs = IPUV3_COLORSPACE_RGB, > >>>> .bpp = 32, > >>>> .ipufmt = true, > >>>> @@ -95,91 +101,91 @@ static const struct imx_media_pixfmt pixel_formats[] = { > >>>> /*** raw bayer and grayscale formats start here ***/ > >>>> { > >>>> .fourcc = V4L2_PIX_FMT_SBGGR8, > >>>> - .codes = {MEDIA_BUS_FMT_SBGGR8_1X8}, > >>>> + .codes = IMX_BUS_FMTS(MEDIA_BUS_FMT_SBGGR8_1X8), > >>>> .cs = IPUV3_COLORSPACE_RGB, > >>>> .bpp = 8, > >>>> .bayer = true, > >>>> }, { > >>>> .fourcc = V4L2_PIX_FMT_SGBRG8, > >>>> - .codes = {MEDIA_BUS_FMT_SGBRG8_1X8}, > >>>> + .codes = IMX_BUS_FMTS(MEDIA_BUS_FMT_SGBRG8_1X8), > >>>> .cs = IPUV3_COLORSPACE_RGB, > >>>> .bpp = 8, > >>>> .bayer = true, > >>>> }, { > >>>> .fourcc = V4L2_PIX_FMT_SGRBG8, > >>>> - .codes = {MEDIA_BUS_FMT_SGRBG8_1X8}, > >>>> + .codes = IMX_BUS_FMTS(MEDIA_BUS_FMT_SGRBG8_1X8), > >>>> .cs = IPUV3_COLORSPACE_RGB, > >>>> .bpp = 8, > >>>> .bayer = true, > >>>> }, { > >>>> .fourcc = V4L2_PIX_FMT_SRGGB8, > >>>> - .codes = {MEDIA_BUS_FMT_SRGGB8_1X8}, > >>>> + .codes = IMX_BUS_FMTS(MEDIA_BUS_FMT_SRGGB8_1X8), > >>>> .cs = IPUV3_COLORSPACE_RGB, > >>>> .bpp = 8, > >>>> .bayer = true, > >>>> }, { > >>>> .fourcc = V4L2_PIX_FMT_SBGGR16, > >>>> - .codes = { > >>>> + .codes = IMX_BUS_FMTS( > >>>> MEDIA_BUS_FMT_SBGGR10_1X10, > >>>> MEDIA_BUS_FMT_SBGGR12_1X12, > >>>> MEDIA_BUS_FMT_SBGGR14_1X14, > >>>> MEDIA_BUS_FMT_SBGGR16_1X16 > >>>> - }, > >>>> + ), > >>>> .cs = IPUV3_COLORSPACE_RGB, > >>>> .bpp = 16, > >>>> .bayer = true, > >>>> }, { > >>>> .fourcc = V4L2_PIX_FMT_SGBRG16, > >>>> - .codes = { > >>>> + .codes = IMX_BUS_FMTS( > >>>> MEDIA_BUS_FMT_SGBRG10_1X10, > >>>> MEDIA_BUS_FMT_SGBRG12_1X12, > >>>> MEDIA_BUS_FMT_SGBRG14_1X14, > >>>> - MEDIA_BUS_FMT_SGBRG16_1X16, > >>>> - }, > >>>> + MEDIA_BUS_FMT_SGBRG16_1X16 > >>>> + ), > >>>> .cs = IPUV3_COLORSPACE_RGB, > >>>> .bpp = 16, > >>>> .bayer = true, > >>>> }, { > >>>> .fourcc = V4L2_PIX_FMT_SGRBG16, > >>>> - .codes = { > >>>> + .codes = IMX_BUS_FMTS( > >>>> MEDIA_BUS_FMT_SGRBG10_1X10, > >>>> MEDIA_BUS_FMT_SGRBG12_1X12, > >>>> MEDIA_BUS_FMT_SGRBG14_1X14, > >>>> - MEDIA_BUS_FMT_SGRBG16_1X16, > >>>> - }, > >>>> + MEDIA_BUS_FMT_SGRBG16_1X16 > >>>> + ), > >>>> .cs = IPUV3_COLORSPACE_RGB, > >>>> .bpp = 16, > >>>> .bayer = true, > >>>> }, { > >>>> .fourcc = V4L2_PIX_FMT_SRGGB16, > >>>> - .codes = { > >>>> + .codes = IMX_BUS_FMTS( > >>>> MEDIA_BUS_FMT_SRGGB10_1X10, > >>>> MEDIA_BUS_FMT_SRGGB12_1X12, > >>>> MEDIA_BUS_FMT_SRGGB14_1X14, > >>>> - MEDIA_BUS_FMT_SRGGB16_1X16, > >>>> - }, > >>>> + MEDIA_BUS_FMT_SRGGB16_1X16 > >>>> + ), > >>>> .cs = IPUV3_COLORSPACE_RGB, > >>>> .bpp = 16, > >>>> .bayer = true, > >>>> }, { > >>>> .fourcc = V4L2_PIX_FMT_GREY, > >>>> - .codes = { > >>>> + .codes = IMX_BUS_FMTS( > >>>> MEDIA_BUS_FMT_Y8_1X8, > >>>> MEDIA_BUS_FMT_Y10_1X10, > >>>> - MEDIA_BUS_FMT_Y12_1X12, > >>>> - }, > >>>> + MEDIA_BUS_FMT_Y12_1X12 > >>>> + ), > >>>> .cs = IPUV3_COLORSPACE_RGB, > >>>> .bpp = 8, > >>>> .bayer = true, > >>>> }, { > >>>> .fourcc = V4L2_PIX_FMT_Y10, > >>>> - .codes = {MEDIA_BUS_FMT_Y10_1X10}, > >>>> + .codes = IMX_BUS_FMTS(MEDIA_BUS_FMT_Y10_1X10), > >>>> .cs = IPUV3_COLORSPACE_RGB, > >>>> .bpp = 16, > >>>> .bayer = true, > >>>> }, { > >>>> .fourcc = V4L2_PIX_FMT_Y12, > >>>> - .codes = {MEDIA_BUS_FMT_Y12_1X12}, > >>>> + .codes = IMX_BUS_FMTS(MEDIA_BUS_FMT_Y12_1X12), > >>>> .cs = IPUV3_COLORSPACE_RGB, > >>>> .bpp = 16, > >>>> .bayer = true, > >>>> @@ -203,16 +209,16 @@ static const struct imx_media_pixfmt *find_format(u32 fourcc, > >>>> CS_SEL_YUV : CS_SEL_RGB); > >>>> > >>>> if (!(fmt_cs_sel & cs_sel) || > >>>> - (!allow_non_mbus && !fmt->codes[0])) > >>>> + (!allow_non_mbus && !fmt->codes)) > >>>> continue; > >>>> > >>>> if (fourcc && fmt->fourcc == fourcc) > >>>> return fmt; > >>>> > >>>> - if (!code) > >>>> + if (!code || !fmt->codes) > >>>> continue; > >>>> > >>>> - for (j = 0; j < ARRAY_SIZE(fmt->codes) && fmt->codes[j]; j++) { > >>>> + for (j = 0; fmt->codes[j]; j++) { > >>>> if (code == fmt->codes[j]) > >>>> return fmt; > >>>> } > >>>> @@ -237,7 +243,7 @@ static int enum_format(u32 *fourcc, u32 *code, u32 index, > >>>> CS_SEL_YUV : CS_SEL_RGB); > >>>> > >>>> if (!(fmt_cs_sel & cs_sel) || > >>>> - (!allow_non_mbus && !fmt->codes[0])) > >>>> + (!allow_non_mbus && !fmt->codes)) > >>>> continue; > >>>> > >>>> if (fourcc && index == 0) { > >>>> @@ -250,7 +256,7 @@ static int enum_format(u32 *fourcc, u32 *code, u32 index, > >>>> continue; > >>>> } > >>>> > >>>> - for (j = 0; j < ARRAY_SIZE(fmt->codes) && fmt->codes[j]; j++) { > >>>> + for (j = 0; fmt->codes[j]; j++) { > >>>> if (index == 0) { > >>>> *code = fmt->codes[j]; > >>>> return 0; > >>>> @@ -296,13 +302,13 @@ EXPORT_SYMBOL_GPL(imx_media_enum_mbus_format); > >>>> static const struct imx_media_pixfmt ipu_formats[] = { > >>>> { > >>>> .fourcc = V4L2_PIX_FMT_YUV32, > >>>> - .codes = {MEDIA_BUS_FMT_AYUV8_1X32}, > >>>> + .codes = IMX_BUS_FMTS(MEDIA_BUS_FMT_AYUV8_1X32), > >>>> .cs = IPUV3_COLORSPACE_YUV, > >>>> .bpp = 32, > >>>> .ipufmt = true, > >>>> }, { > >>>> .fourcc = V4L2_PIX_FMT_XRGB32, > >>>> - .codes = {MEDIA_BUS_FMT_ARGB8888_1X32}, > >>>> + .codes = IMX_BUS_FMTS(MEDIA_BUS_FMT_ARGB8888_1X32), > >>>> .cs = IPUV3_COLORSPACE_RGB, > >>>> .bpp = 32, > >>>> .ipufmt = true, > >>>> @@ -327,7 +333,10 @@ imx_media_find_ipu_format(u32 code, enum codespace_sel cs_sel) > >>>> (!accept_rgb && fmt->cs == IPUV3_COLORSPACE_RGB)) > >>>> continue; > >>>> > >>>> - for (j = 0; j < ARRAY_SIZE(fmt->codes) && fmt->codes[j]; j++) { > >>>> + if (!fmt->codes) > >>>> + continue; > >>>> + > >>>> + for (j = 0; fmt->codes[j]; j++) { > >>>> if (code == fmt->codes[j]) > >>>> return fmt; > >>>> } > >>>> @@ -351,7 +360,10 @@ int imx_media_enum_ipu_format(u32 *code, u32 index, enum codespace_sel cs_sel) > >>>> (!accept_rgb && fmt->cs == IPUV3_COLORSPACE_RGB)) > >>>> continue; > >>>> > >>>> - for (j = 0; j < ARRAY_SIZE(fmt->codes) && fmt->codes[j]; j++) { > >>>> + if (!fmt->codes) > >>>> + continue; > >>>> + > >>>> + for (j = 0; fmt->codes[j]; j++) { > >>>> if (index == 0) { > >>>> *code = fmt->codes[j]; > >>>> return 0; > >>>> @@ -567,7 +579,7 @@ int imx_media_ipu_image_to_mbus_fmt(struct v4l2_mbus_framefmt *mbus, > >>>> const struct imx_media_pixfmt *fmt; > >>>> > >>>> fmt = imx_media_find_format(image->pix.pixelformat, CS_SEL_ANY); > >>>> - if (!fmt) > >>>> + if (!fmt || !fmt->codes) > >>>> return -EINVAL; > >>>> > >>>> memset(mbus, 0, sizeof(*mbus)); > >>>> diff --git a/drivers/staging/media/imx/imx-media.h b/drivers/staging/media/imx/imx-media.h > >>>> index 652673a703cd..917b4db02985 100644 > >>>> --- a/drivers/staging/media/imx/imx-media.h > >>>> +++ b/drivers/staging/media/imx/imx-media.h > >>>> @@ -69,7 +69,7 @@ enum { > >>>> > >>>> struct imx_media_pixfmt { > >>>> u32 fourcc; > >>>> - u32 codes[4]; > >>>> + const u32 *codes; > >>>> int bpp; /* total bpp */ > >>>> /* cycles per pixel for generic (bayer) formats for the parallel bus */ > >>>> int cycles; -- Regards, Laurent Pinchart