* [PATCH v3 1/9] media: v4l2-ctrls: validate HEVC tile counts
2026-06-17 2:18 [PATCH v3 0/9] media: bound stateless HEVC/AV1 tile counts Michael Bommarito
@ 2026-06-17 2:18 ` Michael Bommarito
2026-09-03 6:50 ` Benjamin Gaignard
2026-06-17 2:18 ` [PATCH v3 2/9] media: v4l2-ctrls: validate AV1 " Michael Bommarito
` (8 subsequent siblings)
9 siblings, 1 reply; 17+ messages in thread
From: Michael Bommarito @ 2026-06-17 2:18 UTC (permalink / raw)
To: Hans Verkuil, Mauro Carvalho Chehab, Sakari Ailus,
Nicolas Dufresne
Cc: Laurent Pinchart, Benjamin Gaignard, Detlev Casanova,
Ezequiel Garcia, Yunfei Dong, Jonas Karlman, Heiko Stuebner,
Kees Cook, linux-media, linux-rockchip, linux-mediatek,
linux-kernel
The stateless HEVC decoders read num_tile_columns_minus1 + 1 entries from
column_width_minus1[] and num_tile_rows_minus1 + 1 from row_height_minus1[]
and use them as tile-loop bounds, but std_validate_compound() does not
bound these u8 counts. Reject a V4L2_CTRL_TYPE_HEVC_PPS with tiling
enabled whose tile counts exceed the uAPI array capacity, mirroring the
existing compound-control range checks.
Fixes: 256fa3920874 ("media: v4l: Add definitions for HEVC stateless decoding")
Assisted-by: Claude:claude-opus-4-8
Signed-off-by: Michael Bommarito <michael.bommarito@gmail.com>
---
drivers/media/v4l2-core/v4l2-ctrls-core.c | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/drivers/media/v4l2-core/v4l2-ctrls-core.c b/drivers/media/v4l2-core/v4l2-ctrls-core.c
index 6b375720e395c..6d478e1a5ef22 100644
--- a/drivers/media/v4l2-core/v4l2-ctrls-core.c
+++ b/drivers/media/v4l2-core/v4l2-ctrls-core.c
@@ -1242,6 +1242,18 @@ static int std_validate_compound(const struct v4l2_ctrl *ctrl, u32 idx,
p_hevc_pps->flags &=
~V4L2_HEVC_PPS_FLAG_LOOP_FILTER_ACROSS_TILES_ENABLED;
+ } else {
+ /*
+ * These count the entries the stateless HEVC drivers
+ * read from column_width_minus1[] / row_height_minus1[]
+ * and use as tile-loop bounds.
+ */
+ if (p_hevc_pps->num_tile_columns_minus1 >=
+ ARRAY_SIZE(p_hevc_pps->column_width_minus1))
+ return -EINVAL;
+ if (p_hevc_pps->num_tile_rows_minus1 >=
+ ARRAY_SIZE(p_hevc_pps->row_height_minus1))
+ return -EINVAL;
}
if (p_hevc_pps->flags &
--
2.53.0
^ permalink raw reply related [flat|nested] 17+ messages in thread* Re: [PATCH v3 1/9] media: v4l2-ctrls: validate HEVC tile counts
2026-06-17 2:18 ` [PATCH v3 1/9] media: v4l2-ctrls: validate HEVC " Michael Bommarito
@ 2026-09-03 6:50 ` Benjamin Gaignard
0 siblings, 0 replies; 17+ messages in thread
From: Benjamin Gaignard @ 2026-09-03 6:50 UTC (permalink / raw)
To: Michael Bommarito, Hans Verkuil, Mauro Carvalho Chehab,
Sakari Ailus, Nicolas Dufresne
Cc: Laurent Pinchart, Detlev Casanova, Ezequiel Garcia, Yunfei Dong,
Jonas Karlman, Heiko Stuebner, Kees Cook, linux-media,
linux-rockchip, linux-mediatek, linux-kernel
Le 17/06/2026 à 04:18, Michael Bommarito a écrit :
> The stateless HEVC decoders read num_tile_columns_minus1 + 1 entries from
> column_width_minus1[] and num_tile_rows_minus1 + 1 from row_height_minus1[]
> and use them as tile-loop bounds, but std_validate_compound() does not
> bound these u8 counts. Reject a V4L2_CTRL_TYPE_HEVC_PPS with tiling
> enabled whose tile counts exceed the uAPI array capacity, mirroring the
> existing compound-control range checks.
>
> Fixes: 256fa3920874 ("media: v4l: Add definitions for HEVC stateless decoding")
> Assisted-by: Claude:claude-opus-4-8
> Signed-off-by: Michael Bommarito <michael.bommarito@gmail.com>
Reviewed-by: Benjamin Gaignard <benjamin.gaignard@collabora.com>
> ---
> drivers/media/v4l2-core/v4l2-ctrls-core.c | 12 ++++++++++++
> 1 file changed, 12 insertions(+)
>
> diff --git a/drivers/media/v4l2-core/v4l2-ctrls-core.c b/drivers/media/v4l2-core/v4l2-ctrls-core.c
> index 6b375720e395c..6d478e1a5ef22 100644
> --- a/drivers/media/v4l2-core/v4l2-ctrls-core.c
> +++ b/drivers/media/v4l2-core/v4l2-ctrls-core.c
> @@ -1242,6 +1242,18 @@ static int std_validate_compound(const struct v4l2_ctrl *ctrl, u32 idx,
>
> p_hevc_pps->flags &=
> ~V4L2_HEVC_PPS_FLAG_LOOP_FILTER_ACROSS_TILES_ENABLED;
> + } else {
> + /*
> + * These count the entries the stateless HEVC drivers
> + * read from column_width_minus1[] / row_height_minus1[]
> + * and use as tile-loop bounds.
> + */
> + if (p_hevc_pps->num_tile_columns_minus1 >=
> + ARRAY_SIZE(p_hevc_pps->column_width_minus1))
> + return -EINVAL;
> + if (p_hevc_pps->num_tile_rows_minus1 >=
> + ARRAY_SIZE(p_hevc_pps->row_height_minus1))
> + return -EINVAL;
> }
>
> if (p_hevc_pps->flags &
^ permalink raw reply [flat|nested] 17+ messages in thread
* [PATCH v3 2/9] media: v4l2-ctrls: validate AV1 tile counts
2026-06-17 2:18 [PATCH v3 0/9] media: bound stateless HEVC/AV1 tile counts Michael Bommarito
2026-06-17 2:18 ` [PATCH v3 1/9] media: v4l2-ctrls: validate HEVC " Michael Bommarito
@ 2026-06-17 2:18 ` Michael Bommarito
2026-09-03 6:50 ` Benjamin Gaignard
2026-06-17 2:19 ` [PATCH v3 3/9] media: hevc: add bounded tile-count helpers Michael Bommarito
` (7 subsequent siblings)
9 siblings, 1 reply; 17+ messages in thread
From: Michael Bommarito @ 2026-06-17 2:18 UTC (permalink / raw)
To: Hans Verkuil, Mauro Carvalho Chehab, Sakari Ailus,
Nicolas Dufresne
Cc: Laurent Pinchart, Benjamin Gaignard, Detlev Casanova,
Ezequiel Garcia, Yunfei Dong, Jonas Karlman, Heiko Stuebner,
Kees Cook, linux-media, linux-rockchip, linux-mediatek,
linux-kernel
The stateless AV1 decoders use tile_info.tile_cols and tile_rows as loop
bounds and as indices into the mi_*_starts[] and *_in_sbs_minus_1[]
arrays, as the divisor for context_update_tile_id, and their product
bounds the per-tile descriptor buffers, but std_validate_compound() does
not bound these u8 fields. Reject a V4L2_CTRL_TYPE_AV1_FRAME whose
tile_cols or tile_rows exceeds V4L2_AV1_MAX_TILE_COLS / _ROWS, or whose
product exceeds V4L2_AV1_MAX_TILE_COUNT. A zero tile count is left to the
consuming driver so the zero-initialised control that existing userspace
submits is still accepted.
Fixes: 9de30f579980 ("media: Add AV1 uAPI")
Assisted-by: Claude:claude-opus-4-8
Signed-off-by: Michael Bommarito <michael.bommarito@gmail.com>
---
drivers/media/v4l2-core/v4l2-ctrls-core.c | 20 ++++++++++++++++++++
1 file changed, 20 insertions(+)
diff --git a/drivers/media/v4l2-core/v4l2-ctrls-core.c b/drivers/media/v4l2-core/v4l2-ctrls-core.c
index 6d478e1a5ef22..fb20ad13dfec7 100644
--- a/drivers/media/v4l2-core/v4l2-ctrls-core.c
+++ b/drivers/media/v4l2-core/v4l2-ctrls-core.c
@@ -790,10 +790,30 @@ static int validate_av1_film_grain(struct v4l2_ctrl_av1_film_grain *fg)
return 0;
}
+static int validate_av1_tile_info(struct v4l2_av1_tile_info *t)
+{
+ /*
+ * tile_cols and tile_rows index the per-tile descriptor arrays and
+ * bound the tile loops in the stateless AV1 drivers; the product
+ * bounds the total tile descriptor count.
+ */
+ if (t->tile_cols > V4L2_AV1_MAX_TILE_COLS ||
+ t->tile_rows > V4L2_AV1_MAX_TILE_ROWS)
+ return -EINVAL;
+
+ if ((u32)t->tile_cols * t->tile_rows > V4L2_AV1_MAX_TILE_COUNT)
+ return -EINVAL;
+
+ return 0;
+}
+
static int validate_av1_frame(struct v4l2_ctrl_av1_frame *f)
{
int ret = 0;
+ ret = validate_av1_tile_info(&f->tile_info);
+ if (ret)
+ return ret;
ret = validate_av1_quantization(&f->quantization);
if (ret)
return ret;
--
2.53.0
^ permalink raw reply related [flat|nested] 17+ messages in thread* Re: [PATCH v3 2/9] media: v4l2-ctrls: validate AV1 tile counts
2026-06-17 2:18 ` [PATCH v3 2/9] media: v4l2-ctrls: validate AV1 " Michael Bommarito
@ 2026-09-03 6:50 ` Benjamin Gaignard
0 siblings, 0 replies; 17+ messages in thread
From: Benjamin Gaignard @ 2026-09-03 6:50 UTC (permalink / raw)
To: Michael Bommarito, Hans Verkuil, Mauro Carvalho Chehab,
Sakari Ailus, Nicolas Dufresne
Cc: Laurent Pinchart, Detlev Casanova, Ezequiel Garcia, Yunfei Dong,
Jonas Karlman, Heiko Stuebner, Kees Cook, linux-media,
linux-rockchip, linux-mediatek, linux-kernel
Le 17/06/2026 à 04:18, Michael Bommarito a écrit :
> The stateless AV1 decoders use tile_info.tile_cols and tile_rows as loop
> bounds and as indices into the mi_*_starts[] and *_in_sbs_minus_1[]
> arrays, as the divisor for context_update_tile_id, and their product
> bounds the per-tile descriptor buffers, but std_validate_compound() does
> not bound these u8 fields. Reject a V4L2_CTRL_TYPE_AV1_FRAME whose
> tile_cols or tile_rows exceeds V4L2_AV1_MAX_TILE_COLS / _ROWS, or whose
> product exceeds V4L2_AV1_MAX_TILE_COUNT. A zero tile count is left to the
> consuming driver so the zero-initialised control that existing userspace
> submits is still accepted.
>
> Fixes: 9de30f579980 ("media: Add AV1 uAPI")
> Assisted-by: Claude:claude-opus-4-8
> Signed-off-by: Michael Bommarito <michael.bommarito@gmail.com>
Reviewed-by: Benjamin Gaignard <benjamin.gaignard@collabora.com>
> ---
> drivers/media/v4l2-core/v4l2-ctrls-core.c | 20 ++++++++++++++++++++
> 1 file changed, 20 insertions(+)
>
> diff --git a/drivers/media/v4l2-core/v4l2-ctrls-core.c b/drivers/media/v4l2-core/v4l2-ctrls-core.c
> index 6d478e1a5ef22..fb20ad13dfec7 100644
> --- a/drivers/media/v4l2-core/v4l2-ctrls-core.c
> +++ b/drivers/media/v4l2-core/v4l2-ctrls-core.c
> @@ -790,10 +790,30 @@ static int validate_av1_film_grain(struct v4l2_ctrl_av1_film_grain *fg)
> return 0;
> }
>
> +static int validate_av1_tile_info(struct v4l2_av1_tile_info *t)
> +{
> + /*
> + * tile_cols and tile_rows index the per-tile descriptor arrays and
> + * bound the tile loops in the stateless AV1 drivers; the product
> + * bounds the total tile descriptor count.
> + */
> + if (t->tile_cols > V4L2_AV1_MAX_TILE_COLS ||
> + t->tile_rows > V4L2_AV1_MAX_TILE_ROWS)
> + return -EINVAL;
> +
> + if ((u32)t->tile_cols * t->tile_rows > V4L2_AV1_MAX_TILE_COUNT)
> + return -EINVAL;
> +
> + return 0;
> +}
> +
> static int validate_av1_frame(struct v4l2_ctrl_av1_frame *f)
> {
> int ret = 0;
>
> + ret = validate_av1_tile_info(&f->tile_info);
> + if (ret)
> + return ret;
> ret = validate_av1_quantization(&f->quantization);
> if (ret)
> return ret;
^ permalink raw reply [flat|nested] 17+ messages in thread
* [PATCH v3 3/9] media: hevc: add bounded tile-count helpers
2026-06-17 2:18 [PATCH v3 0/9] media: bound stateless HEVC/AV1 tile counts Michael Bommarito
2026-06-17 2:18 ` [PATCH v3 1/9] media: v4l2-ctrls: validate HEVC " Michael Bommarito
2026-06-17 2:18 ` [PATCH v3 2/9] media: v4l2-ctrls: validate AV1 " Michael Bommarito
@ 2026-06-17 2:19 ` Michael Bommarito
2026-09-03 6:51 ` Benjamin Gaignard
2026-06-17 2:19 ` [PATCH v3 4/9] media: rkvdec: bound HEVC tile loops and PPS id to the array capacity Michael Bommarito
` (6 subsequent siblings)
9 siblings, 1 reply; 17+ messages in thread
From: Michael Bommarito @ 2026-06-17 2:19 UTC (permalink / raw)
To: Hans Verkuil, Mauro Carvalho Chehab, Sakari Ailus,
Nicolas Dufresne
Cc: Laurent Pinchart, Benjamin Gaignard, Detlev Casanova,
Ezequiel Garcia, Yunfei Dong, Jonas Karlman, Heiko Stuebner,
Kees Cook, linux-media, linux-rockchip, linux-mediatek,
linux-kernel
The stateless HEVC decoders compute the number of tile columns and rows
from num_tile_columns_minus1 / num_tile_rows_minus1 and clamp it to the
column_width_minus1[] / row_height_minus1[] capacity before using it as a
loop bound. Add shared helpers in a new <media/v4l2-hevc.h> so the rkvdec
and hantro drivers do not each open-code the min_t() clamp.
Assisted-by: Claude:claude-opus-4-8
Signed-off-by: Michael Bommarito <michael.bommarito@gmail.com>
---
include/media/v4l2-hevc.h | 41 +++++++++++++++++++++++++++++++++++++++
1 file changed, 41 insertions(+)
create mode 100644 include/media/v4l2-hevc.h
diff --git a/include/media/v4l2-hevc.h b/include/media/v4l2-hevc.h
new file mode 100644
index 0000000000000..973c96be16be4
--- /dev/null
+++ b/include/media/v4l2-hevc.h
@@ -0,0 +1,41 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Helper functions for HEVC stateless codecs.
+ */
+
+#ifndef _MEDIA_V4L2_HEVC_H
+#define _MEDIA_V4L2_HEVC_H
+
+#include <linux/minmax.h>
+#include <media/v4l2-ctrls.h>
+
+/**
+ * v4l2_hevc_pps_num_tile_columns - number of HEVC tile columns, bounded
+ * @pps: the V4L2 HEVC PPS control
+ *
+ * Return the number of tile columns (num_tile_columns_minus1 + 1) clamped to
+ * the capacity of column_width_minus1[]. The control validation already
+ * rejects out-of-range counts; this keeps the consuming drivers bounded too.
+ */
+static inline unsigned int
+v4l2_hevc_pps_num_tile_columns(const struct v4l2_ctrl_hevc_pps *pps)
+{
+ return min_t(unsigned int, pps->num_tile_columns_minus1 + 1,
+ ARRAY_SIZE(pps->column_width_minus1));
+}
+
+/**
+ * v4l2_hevc_pps_num_tile_rows - number of HEVC tile rows, bounded
+ * @pps: the V4L2 HEVC PPS control
+ *
+ * Return the number of tile rows (num_tile_rows_minus1 + 1) clamped to the
+ * capacity of row_height_minus1[].
+ */
+static inline unsigned int
+v4l2_hevc_pps_num_tile_rows(const struct v4l2_ctrl_hevc_pps *pps)
+{
+ return min_t(unsigned int, pps->num_tile_rows_minus1 + 1,
+ ARRAY_SIZE(pps->row_height_minus1));
+}
+
+#endif /* _MEDIA_V4L2_HEVC_H */
--
2.53.0
^ permalink raw reply related [flat|nested] 17+ messages in thread* Re: [PATCH v3 3/9] media: hevc: add bounded tile-count helpers
2026-06-17 2:19 ` [PATCH v3 3/9] media: hevc: add bounded tile-count helpers Michael Bommarito
@ 2026-09-03 6:51 ` Benjamin Gaignard
0 siblings, 0 replies; 17+ messages in thread
From: Benjamin Gaignard @ 2026-09-03 6:51 UTC (permalink / raw)
To: Michael Bommarito, Hans Verkuil, Mauro Carvalho Chehab,
Sakari Ailus, Nicolas Dufresne
Cc: Laurent Pinchart, Detlev Casanova, Ezequiel Garcia, Yunfei Dong,
Jonas Karlman, Heiko Stuebner, Kees Cook, linux-media,
linux-rockchip, linux-mediatek, linux-kernel
Le 17/06/2026 à 04:19, Michael Bommarito a écrit :
> The stateless HEVC decoders compute the number of tile columns and rows
> from num_tile_columns_minus1 / num_tile_rows_minus1 and clamp it to the
> column_width_minus1[] / row_height_minus1[] capacity before using it as a
> loop bound. Add shared helpers in a new <media/v4l2-hevc.h> so the rkvdec
> and hantro drivers do not each open-code the min_t() clamp.
>
> Assisted-by: Claude:claude-opus-4-8
> Signed-off-by: Michael Bommarito <michael.bommarito@gmail.com>
Reviewed-by: Benjamin Gaignard <benjamin.gaignard@collabora.com>
> ---
> include/media/v4l2-hevc.h | 41 +++++++++++++++++++++++++++++++++++++++
> 1 file changed, 41 insertions(+)
> create mode 100644 include/media/v4l2-hevc.h
>
> diff --git a/include/media/v4l2-hevc.h b/include/media/v4l2-hevc.h
> new file mode 100644
> index 0000000000000..973c96be16be4
> --- /dev/null
> +++ b/include/media/v4l2-hevc.h
> @@ -0,0 +1,41 @@
> +/* SPDX-License-Identifier: GPL-2.0-or-later */
> +/*
> + * Helper functions for HEVC stateless codecs.
> + */
> +
> +#ifndef _MEDIA_V4L2_HEVC_H
> +#define _MEDIA_V4L2_HEVC_H
> +
> +#include <linux/minmax.h>
> +#include <media/v4l2-ctrls.h>
> +
> +/**
> + * v4l2_hevc_pps_num_tile_columns - number of HEVC tile columns, bounded
> + * @pps: the V4L2 HEVC PPS control
> + *
> + * Return the number of tile columns (num_tile_columns_minus1 + 1) clamped to
> + * the capacity of column_width_minus1[]. The control validation already
> + * rejects out-of-range counts; this keeps the consuming drivers bounded too.
> + */
> +static inline unsigned int
> +v4l2_hevc_pps_num_tile_columns(const struct v4l2_ctrl_hevc_pps *pps)
> +{
> + return min_t(unsigned int, pps->num_tile_columns_minus1 + 1,
> + ARRAY_SIZE(pps->column_width_minus1));
> +}
> +
> +/**
> + * v4l2_hevc_pps_num_tile_rows - number of HEVC tile rows, bounded
> + * @pps: the V4L2 HEVC PPS control
> + *
> + * Return the number of tile rows (num_tile_rows_minus1 + 1) clamped to the
> + * capacity of row_height_minus1[].
> + */
> +static inline unsigned int
> +v4l2_hevc_pps_num_tile_rows(const struct v4l2_ctrl_hevc_pps *pps)
> +{
> + return min_t(unsigned int, pps->num_tile_rows_minus1 + 1,
> + ARRAY_SIZE(pps->row_height_minus1));
> +}
> +
> +#endif /* _MEDIA_V4L2_HEVC_H */
^ permalink raw reply [flat|nested] 17+ messages in thread
* [PATCH v3 4/9] media: rkvdec: bound HEVC tile loops and PPS id to the array capacity
2026-06-17 2:18 [PATCH v3 0/9] media: bound stateless HEVC/AV1 tile counts Michael Bommarito
` (2 preceding siblings ...)
2026-06-17 2:19 ` [PATCH v3 3/9] media: hevc: add bounded tile-count helpers Michael Bommarito
@ 2026-06-17 2:19 ` Michael Bommarito
2026-06-17 2:19 ` [PATCH v3 5/9] media: verisilicon: hantro: bound G2 HEVC tile loop to the buffer capacity Michael Bommarito
` (5 subsequent siblings)
9 siblings, 0 replies; 17+ messages in thread
From: Michael Bommarito @ 2026-06-17 2:19 UTC (permalink / raw)
To: Hans Verkuil, Mauro Carvalho Chehab, Sakari Ailus,
Nicolas Dufresne
Cc: Laurent Pinchart, Benjamin Gaignard, Detlev Casanova,
Ezequiel Garcia, Yunfei Dong, Jonas Karlman, Heiko Stuebner,
Kees Cook, linux-media, linux-rockchip, linux-mediatek,
linux-kernel
compute_tiles_uniform() and compute_tiles_non_uniform() loop over
num_tile_columns_minus1 + 1 / num_tile_rows_minus1 + 1 entries, and
assemble_hw_pps() writes one COLUMN_WIDTH / ROW_HEIGHT register per tile
and indexes priv_tbl->param_set[] by pic_parameter_set_id, all taken from
the untrusted PPS. Use the bounded v4l2_hevc_pps_num_tile_columns() /
v4l2_hevc_pps_num_tile_rows() helpers for the tile loops, and bail out of
assemble_hw_pps() before indexing priv_tbl->param_set[] with an
out-of-range pic_parameter_set_id, so the writes stay within the hardware
tables.
Fixes: 3595375c2301 ("media: rkvdec: Add HEVC backend")
Fixes: c9a59dc2acc7 ("media: rkvdec: Add HEVC support for the VDPU381 variant")
Assisted-by: Claude:claude-opus-4-8
Signed-off-by: Michael Bommarito <michael.bommarito@gmail.com>
---
.../platform/rockchip/rkvdec/rkvdec-hevc-common.c | 14 ++++++++++----
.../media/platform/rockchip/rkvdec/rkvdec-hevc.c | 7 +++++--
.../platform/rockchip/rkvdec/rkvdec-vdpu381-hevc.c | 2 ++
3 files changed, 17 insertions(+), 6 deletions(-)
diff --git a/drivers/media/platform/rockchip/rkvdec/rkvdec-hevc-common.c b/drivers/media/platform/rockchip/rkvdec/rkvdec-hevc-common.c
index 3119f3bc9f98b..753aef3aee51e 100644
--- a/drivers/media/platform/rockchip/rkvdec/rkvdec-hevc-common.c
+++ b/drivers/media/platform/rockchip/rkvdec/rkvdec-hevc-common.c
@@ -16,6 +16,7 @@
*/
#include <linux/v4l2-common.h>
+#include <media/v4l2-hevc.h>
#include <media/v4l2-mem2mem.h>
#include "rkvdec.h"
@@ -37,15 +38,17 @@ void compute_tiles_uniform(struct rkvdec_hevc_run *run, u16 log2_min_cb_size,
s32 pic_in_cts_height, u16 *column_width, u16 *row_height)
{
const struct v4l2_ctrl_hevc_pps *pps = run->pps;
+ unsigned int num_cols = v4l2_hevc_pps_num_tile_columns(pps);
+ unsigned int num_rows = v4l2_hevc_pps_num_tile_rows(pps);
int i;
- for (i = 0; i < pps->num_tile_columns_minus1 + 1; i++)
+ for (i = 0; i < num_cols; i++)
column_width[i] = ((i + 1) * pic_in_cts_width) /
(pps->num_tile_columns_minus1 + 1) -
(i * pic_in_cts_width) /
(pps->num_tile_columns_minus1 + 1);
- for (i = 0; i < pps->num_tile_rows_minus1 + 1; i++)
+ for (i = 0; i < num_rows; i++)
row_height[i] = ((i + 1) * pic_in_cts_height) /
(pps->num_tile_rows_minus1 + 1) -
(i * pic_in_cts_height) /
@@ -57,17 +60,20 @@ void compute_tiles_non_uniform(struct rkvdec_hevc_run *run, u16 log2_min_cb_size
s32 pic_in_cts_height, u16 *column_width, u16 *row_height)
{
const struct v4l2_ctrl_hevc_pps *pps = run->pps;
+ unsigned int num_cols = v4l2_hevc_pps_num_tile_columns(pps);
+ unsigned int num_rows = v4l2_hevc_pps_num_tile_rows(pps);
s32 sum = 0;
int i;
- for (i = 0; i < pps->num_tile_columns_minus1; i++) {
+ /* The last tile entry is written after the loop, so iterate one less. */
+ for (i = 0; i < num_cols - 1; i++) {
column_width[i] = pps->column_width_minus1[i] + 1;
sum += column_width[i];
}
column_width[i] = pic_in_cts_width - sum;
sum = 0;
- for (i = 0; i < pps->num_tile_rows_minus1; i++) {
+ for (i = 0; i < num_rows - 1; i++) {
row_height[i] = pps->row_height_minus1[i] + 1;
sum += row_height[i];
}
diff --git a/drivers/media/platform/rockchip/rkvdec/rkvdec-hevc.c b/drivers/media/platform/rockchip/rkvdec/rkvdec-hevc.c
index ac8b825d080a2..568746dae9a61 100644
--- a/drivers/media/platform/rockchip/rkvdec/rkvdec-hevc.c
+++ b/drivers/media/platform/rockchip/rkvdec/rkvdec-hevc.c
@@ -12,6 +12,7 @@
* Jeffy Chen <jeffy.chen@rock-chips.com>
*/
+#include <media/v4l2-hevc.h>
#include <media/v4l2-mem2mem.h>
#include "rkvdec.h"
@@ -156,6 +157,8 @@ static void assemble_hw_pps(struct rkvdec_ctx *ctx,
* packet unit). so the driver copy SPS/PPS information to the exact PPS
* packet unit for HW accessing.
*/
+ if (pps->pic_parameter_set_id >= ARRAY_SIZE(priv_tbl->param_set))
+ return;
hw_ps = &priv_tbl->param_set[pps->pic_parameter_set_id];
memset(hw_ps, 0, sizeof(*hw_ps));
@@ -274,9 +277,9 @@ static void assemble_hw_pps(struct rkvdec_ctx *ctx,
if (pps->flags & V4L2_HEVC_PPS_FLAG_TILES_ENABLED) {
/* Userspace also provide column width and row height for uniform spacing */
- for (i = 0; i <= pps->num_tile_columns_minus1; i++)
+ for (i = 0; i < v4l2_hevc_pps_num_tile_columns(pps); i++)
WRITE_PPS(pps->column_width_minus1[i], COLUMN_WIDTH(i));
- for (i = 0; i <= pps->num_tile_rows_minus1; i++)
+ for (i = 0; i < v4l2_hevc_pps_num_tile_rows(pps); i++)
WRITE_PPS(pps->row_height_minus1[i], ROW_HEIGHT(i));
} else {
WRITE_PPS(((sps->pic_width_in_luma_samples + ctb_size_y - 1) / ctb_size_y) - 1,
diff --git a/drivers/media/platform/rockchip/rkvdec/rkvdec-vdpu381-hevc.c b/drivers/media/platform/rockchip/rkvdec/rkvdec-vdpu381-hevc.c
index fe6414a175510..6dafa1dd28507 100644
--- a/drivers/media/platform/rockchip/rkvdec/rkvdec-vdpu381-hevc.c
+++ b/drivers/media/platform/rockchip/rkvdec/rkvdec-vdpu381-hevc.c
@@ -145,6 +145,8 @@ static void assemble_hw_pps(struct rkvdec_ctx *ctx,
* packet unit). so the driver copy SPS/PPS information to the exact PPS
* packet unit for HW accessing.
*/
+ if (pps->pic_parameter_set_id >= ARRAY_SIZE(priv_tbl->param_set))
+ return;
hw_ps = &priv_tbl->param_set[pps->pic_parameter_set_id];
memset(hw_ps, 0, sizeof(*hw_ps));
--
2.53.0
^ permalink raw reply related [flat|nested] 17+ messages in thread* [PATCH v3 5/9] media: verisilicon: hantro: bound G2 HEVC tile loop to the buffer capacity
2026-06-17 2:18 [PATCH v3 0/9] media: bound stateless HEVC/AV1 tile counts Michael Bommarito
` (3 preceding siblings ...)
2026-06-17 2:19 ` [PATCH v3 4/9] media: rkvdec: bound HEVC tile loops and PPS id to the array capacity Michael Bommarito
@ 2026-06-17 2:19 ` Michael Bommarito
2026-09-03 6:51 ` Benjamin Gaignard
2026-06-17 2:19 ` [PATCH v3 6/9] media: verisilicon: rockchip: guard VPU981 AV1 divisor and tile buffer Michael Bommarito
` (4 subsequent siblings)
9 siblings, 1 reply; 17+ messages in thread
From: Michael Bommarito @ 2026-06-17 2:19 UTC (permalink / raw)
To: Hans Verkuil, Mauro Carvalho Chehab, Sakari Ailus,
Nicolas Dufresne
Cc: Laurent Pinchart, Benjamin Gaignard, Detlev Casanova,
Ezequiel Garcia, Yunfei Dong, Jonas Karlman, Heiko Stuebner,
Kees Cook, linux-media, linux-rockchip, linux-mediatek,
linux-kernel
prepare_tile_info_buffer() writes one entry per tile into the tile_sizes
DMA buffer, sized for a grid equal to the PPS uAPI array capacity. Use the
bounded v4l2_hevc_pps_num_tile_columns() / v4l2_hevc_pps_num_tile_rows()
helpers so the loops stay inside the buffer.
Fixes: cb5dd5a0fa51 ("media: hantro: Introduce G2/HEVC decoder")
Assisted-by: Claude:claude-opus-4-8
Signed-off-by: Michael Bommarito <michael.bommarito@gmail.com>
---
drivers/media/platform/verisilicon/hantro_g2_hevc_dec.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/drivers/media/platform/verisilicon/hantro_g2_hevc_dec.c b/drivers/media/platform/verisilicon/hantro_g2_hevc_dec.c
index e8c2e83379def..e7a7c7a42467a 100644
--- a/drivers/media/platform/verisilicon/hantro_g2_hevc_dec.c
+++ b/drivers/media/platform/verisilicon/hantro_g2_hevc_dec.c
@@ -5,6 +5,8 @@
* Copyright (C) 2020 Safran Passenger Innovations LLC
*/
+#include <media/v4l2-hevc.h>
+
#include "hantro_hw.h"
#include "hantro_g2_regs.h"
@@ -15,8 +17,8 @@ static void prepare_tile_info_buffer(struct hantro_ctx *ctx)
const struct v4l2_ctrl_hevc_pps *pps = ctrls->pps;
const struct v4l2_ctrl_hevc_sps *sps = ctrls->sps;
u16 *p = (u16 *)((u8 *)ctx->hevc_dec.tile_sizes.cpu);
- unsigned int num_tile_rows = pps->num_tile_rows_minus1 + 1;
- unsigned int num_tile_cols = pps->num_tile_columns_minus1 + 1;
+ unsigned int num_tile_rows = v4l2_hevc_pps_num_tile_rows(pps);
+ unsigned int num_tile_cols = v4l2_hevc_pps_num_tile_columns(pps);
unsigned int pic_width_in_ctbs, pic_height_in_ctbs;
unsigned int max_log2_ctb_size, ctb_size;
bool tiles_enabled, uniform_spacing;
--
2.53.0
^ permalink raw reply related [flat|nested] 17+ messages in thread* Re: [PATCH v3 5/9] media: verisilicon: hantro: bound G2 HEVC tile loop to the buffer capacity
2026-06-17 2:19 ` [PATCH v3 5/9] media: verisilicon: hantro: bound G2 HEVC tile loop to the buffer capacity Michael Bommarito
@ 2026-09-03 6:51 ` Benjamin Gaignard
0 siblings, 0 replies; 17+ messages in thread
From: Benjamin Gaignard @ 2026-09-03 6:51 UTC (permalink / raw)
To: Michael Bommarito, Hans Verkuil, Mauro Carvalho Chehab,
Sakari Ailus, Nicolas Dufresne
Cc: Laurent Pinchart, Detlev Casanova, Ezequiel Garcia, Yunfei Dong,
Jonas Karlman, Heiko Stuebner, Kees Cook, linux-media,
linux-rockchip, linux-mediatek, linux-kernel
Le 17/06/2026 à 04:19, Michael Bommarito a écrit :
> prepare_tile_info_buffer() writes one entry per tile into the tile_sizes
> DMA buffer, sized for a grid equal to the PPS uAPI array capacity. Use the
> bounded v4l2_hevc_pps_num_tile_columns() / v4l2_hevc_pps_num_tile_rows()
> helpers so the loops stay inside the buffer.
>
> Fixes: cb5dd5a0fa51 ("media: hantro: Introduce G2/HEVC decoder")
> Assisted-by: Claude:claude-opus-4-8
> Signed-off-by: Michael Bommarito <michael.bommarito@gmail.com>
Reviewed-by: Benjamin Gaignard <benjamin.gaignard@collabora.com>
> ---
> drivers/media/platform/verisilicon/hantro_g2_hevc_dec.c | 6 ++++--
> 1 file changed, 4 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/media/platform/verisilicon/hantro_g2_hevc_dec.c b/drivers/media/platform/verisilicon/hantro_g2_hevc_dec.c
> index e8c2e83379def..e7a7c7a42467a 100644
> --- a/drivers/media/platform/verisilicon/hantro_g2_hevc_dec.c
> +++ b/drivers/media/platform/verisilicon/hantro_g2_hevc_dec.c
> @@ -5,6 +5,8 @@
> * Copyright (C) 2020 Safran Passenger Innovations LLC
> */
>
> +#include <media/v4l2-hevc.h>
> +
> #include "hantro_hw.h"
> #include "hantro_g2_regs.h"
>
> @@ -15,8 +17,8 @@ static void prepare_tile_info_buffer(struct hantro_ctx *ctx)
> const struct v4l2_ctrl_hevc_pps *pps = ctrls->pps;
> const struct v4l2_ctrl_hevc_sps *sps = ctrls->sps;
> u16 *p = (u16 *)((u8 *)ctx->hevc_dec.tile_sizes.cpu);
> - unsigned int num_tile_rows = pps->num_tile_rows_minus1 + 1;
> - unsigned int num_tile_cols = pps->num_tile_columns_minus1 + 1;
> + unsigned int num_tile_rows = v4l2_hevc_pps_num_tile_rows(pps);
> + unsigned int num_tile_cols = v4l2_hevc_pps_num_tile_columns(pps);
> unsigned int pic_width_in_ctbs, pic_height_in_ctbs;
> unsigned int max_log2_ctb_size, ctb_size;
> bool tiles_enabled, uniform_spacing;
^ permalink raw reply [flat|nested] 17+ messages in thread
* [PATCH v3 6/9] media: verisilicon: rockchip: guard VPU981 AV1 divisor and tile buffer
2026-06-17 2:18 [PATCH v3 0/9] media: bound stateless HEVC/AV1 tile counts Michael Bommarito
` (4 preceding siblings ...)
2026-06-17 2:19 ` [PATCH v3 5/9] media: verisilicon: hantro: bound G2 HEVC tile loop to the buffer capacity Michael Bommarito
@ 2026-06-17 2:19 ` Michael Bommarito
2026-09-03 6:52 ` Benjamin Gaignard
2026-06-17 2:19 ` [PATCH v3 7/9] media: verisilicon: rockchip: reject AV1 frames exceeding the tile capacity Michael Bommarito
` (3 subsequent siblings)
9 siblings, 1 reply; 17+ messages in thread
From: Michael Bommarito @ 2026-06-17 2:19 UTC (permalink / raw)
To: Hans Verkuil, Mauro Carvalho Chehab, Sakari Ailus,
Nicolas Dufresne
Cc: Laurent Pinchart, Benjamin Gaignard, Detlev Casanova,
Ezequiel Garcia, Yunfei Dong, Jonas Karlman, Heiko Stuebner,
Kees Cook, linux-media, linux-rockchip, linux-mediatek,
linux-kernel
rockchip_vpu981_av1_dec_set_tile_info() divides context_update_tile_id by
tile_info->tile_cols and writes one descriptor per tile into the tile_info
DMA buffer, which holds AV1_MAX_TILES entries; tile_cols and tile_rows
come from the bitstream. Guard the division against a zero tile_cols by
initialising the context-update values to zero and computing them only
when tile_cols is non-zero, and stop the descriptor writes once the
tile_info buffer is full. The tile geometry written to the hardware
registers is left unmodified; the per-dimension and total tile bounds are
enforced by the control validation.
Fixes: 727a400686a2 ("media: verisilicon: Add Rockchip AV1 decoder")
Assisted-by: Claude:claude-opus-4-8
Signed-off-by: Michael Bommarito <michael.bommarito@gmail.com>
---
.../verisilicon/rockchip_vpu981_hw_av1_dec.c | 32 +++++++++++++++----
1 file changed, 26 insertions(+), 6 deletions(-)
diff --git a/drivers/media/platform/verisilicon/rockchip_vpu981_hw_av1_dec.c b/drivers/media/platform/verisilicon/rockchip_vpu981_hw_av1_dec.c
index e4e21ad373233..fd00dbd79fe46 100644
--- a/drivers/media/platform/verisilicon/rockchip_vpu981_hw_av1_dec.c
+++ b/drivers/media/platform/verisilicon/rockchip_vpu981_hw_av1_dec.c
@@ -578,16 +578,30 @@ static void rockchip_vpu981_av1_dec_set_tile_info(struct hantro_ctx *ctx)
const struct v4l2_av1_tile_info *tile_info = &ctrls->frame->tile_info;
const struct v4l2_ctrl_av1_tile_group_entry *group_entry =
ctrls->tile_group_entry;
- int context_update_y =
- tile_info->context_update_tile_id / tile_info->tile_cols;
- int context_update_x =
- tile_info->context_update_tile_id % tile_info->tile_cols;
- int context_update_tile_id =
- context_update_x * tile_info->tile_rows + context_update_y;
+ int context_update_y = 0;
+ int context_update_x = 0;
+ int context_update_tile_id = 0;
u8 *dst = av1_dec->tile_info.cpu;
+ u8 *dst_end = dst + av1_dec->tile_info.size;
struct hantro_dev *vpu = ctx->dev;
int tile0, tile1;
+ /*
+ * tile_cols and tile_rows are bounded by the V4L2 control validation
+ * (V4L2_AV1_MAX_TILE_{COLS,ROWS} and V4L2_AV1_MAX_TILE_COUNT). Guard
+ * the divisor here, and keep the descriptor writes within the
+ * AV1_MAX_TILES tile_info buffer below; the register values use the
+ * unmodified tile geometry.
+ */
+ if (tile_info->tile_cols) {
+ context_update_y =
+ tile_info->context_update_tile_id / tile_info->tile_cols;
+ context_update_x =
+ tile_info->context_update_tile_id % tile_info->tile_cols;
+ context_update_tile_id =
+ context_update_x * tile_info->tile_rows + context_update_y;
+ }
+
memset(dst, 0, av1_dec->tile_info.size);
for (tile0 = 0; tile0 < tile_info->tile_cols; tile0++) {
@@ -598,6 +612,10 @@ static void rockchip_vpu981_av1_dec_set_tile_info(struct hantro_ctx *ctx)
tile_info->height_in_sbs_minus_1[tile1] + 1;
u32 x0 = tile_info->width_in_sbs_minus_1[tile0] + 1;
+ /* Stop once the tile_info descriptor buffer is full. */
+ if (dst + 16 > dst_end)
+ break;
+
/* tile size in SB units (width,height) */
*dst++ = x0;
*dst++ = 0;
@@ -622,6 +640,8 @@ static void rockchip_vpu981_av1_dec_set_tile_info(struct hantro_ctx *ctx)
*dst++ = (end >> 16) & 255;
*dst++ = (end >> 24) & 255;
}
+ if (dst + 16 > dst_end)
+ break;
}
hantro_reg_write(vpu, &av1_multicore_expect_context_update, !!(context_update_x == 0));
--
2.53.0
^ permalink raw reply related [flat|nested] 17+ messages in thread* Re: [PATCH v3 6/9] media: verisilicon: rockchip: guard VPU981 AV1 divisor and tile buffer
2026-06-17 2:19 ` [PATCH v3 6/9] media: verisilicon: rockchip: guard VPU981 AV1 divisor and tile buffer Michael Bommarito
@ 2026-09-03 6:52 ` Benjamin Gaignard
0 siblings, 0 replies; 17+ messages in thread
From: Benjamin Gaignard @ 2026-09-03 6:52 UTC (permalink / raw)
To: Michael Bommarito, Hans Verkuil, Mauro Carvalho Chehab,
Sakari Ailus, Nicolas Dufresne
Cc: Laurent Pinchart, Detlev Casanova, Ezequiel Garcia, Yunfei Dong,
Jonas Karlman, Heiko Stuebner, Kees Cook, linux-media,
linux-rockchip, linux-mediatek, linux-kernel
Le 17/06/2026 à 04:19, Michael Bommarito a écrit :
> rockchip_vpu981_av1_dec_set_tile_info() divides context_update_tile_id by
> tile_info->tile_cols and writes one descriptor per tile into the tile_info
> DMA buffer, which holds AV1_MAX_TILES entries; tile_cols and tile_rows
> come from the bitstream. Guard the division against a zero tile_cols by
> initialising the context-update values to zero and computing them only
> when tile_cols is non-zero, and stop the descriptor writes once the
> tile_info buffer is full. The tile geometry written to the hardware
> registers is left unmodified; the per-dimension and total tile bounds are
> enforced by the control validation.
>
> Fixes: 727a400686a2 ("media: verisilicon: Add Rockchip AV1 decoder")
> Assisted-by: Claude:claude-opus-4-8
> Signed-off-by: Michael Bommarito <michael.bommarito@gmail.com>
Reviewed-by: Benjamin Gaignard <benjamin.gaignard@collabora.com>
> ---
> .../verisilicon/rockchip_vpu981_hw_av1_dec.c | 32 +++++++++++++++----
> 1 file changed, 26 insertions(+), 6 deletions(-)
>
> diff --git a/drivers/media/platform/verisilicon/rockchip_vpu981_hw_av1_dec.c b/drivers/media/platform/verisilicon/rockchip_vpu981_hw_av1_dec.c
> index e4e21ad373233..fd00dbd79fe46 100644
> --- a/drivers/media/platform/verisilicon/rockchip_vpu981_hw_av1_dec.c
> +++ b/drivers/media/platform/verisilicon/rockchip_vpu981_hw_av1_dec.c
> @@ -578,16 +578,30 @@ static void rockchip_vpu981_av1_dec_set_tile_info(struct hantro_ctx *ctx)
> const struct v4l2_av1_tile_info *tile_info = &ctrls->frame->tile_info;
> const struct v4l2_ctrl_av1_tile_group_entry *group_entry =
> ctrls->tile_group_entry;
> - int context_update_y =
> - tile_info->context_update_tile_id / tile_info->tile_cols;
> - int context_update_x =
> - tile_info->context_update_tile_id % tile_info->tile_cols;
> - int context_update_tile_id =
> - context_update_x * tile_info->tile_rows + context_update_y;
> + int context_update_y = 0;
> + int context_update_x = 0;
> + int context_update_tile_id = 0;
> u8 *dst = av1_dec->tile_info.cpu;
> + u8 *dst_end = dst + av1_dec->tile_info.size;
> struct hantro_dev *vpu = ctx->dev;
> int tile0, tile1;
>
> + /*
> + * tile_cols and tile_rows are bounded by the V4L2 control validation
> + * (V4L2_AV1_MAX_TILE_{COLS,ROWS} and V4L2_AV1_MAX_TILE_COUNT). Guard
> + * the divisor here, and keep the descriptor writes within the
> + * AV1_MAX_TILES tile_info buffer below; the register values use the
> + * unmodified tile geometry.
> + */
> + if (tile_info->tile_cols) {
> + context_update_y =
> + tile_info->context_update_tile_id / tile_info->tile_cols;
> + context_update_x =
> + tile_info->context_update_tile_id % tile_info->tile_cols;
> + context_update_tile_id =
> + context_update_x * tile_info->tile_rows + context_update_y;
> + }
> +
> memset(dst, 0, av1_dec->tile_info.size);
>
> for (tile0 = 0; tile0 < tile_info->tile_cols; tile0++) {
> @@ -598,6 +612,10 @@ static void rockchip_vpu981_av1_dec_set_tile_info(struct hantro_ctx *ctx)
> tile_info->height_in_sbs_minus_1[tile1] + 1;
> u32 x0 = tile_info->width_in_sbs_minus_1[tile0] + 1;
>
> + /* Stop once the tile_info descriptor buffer is full. */
> + if (dst + 16 > dst_end)
> + break;
> +
> /* tile size in SB units (width,height) */
> *dst++ = x0;
> *dst++ = 0;
> @@ -622,6 +640,8 @@ static void rockchip_vpu981_av1_dec_set_tile_info(struct hantro_ctx *ctx)
> *dst++ = (end >> 16) & 255;
> *dst++ = (end >> 24) & 255;
> }
> + if (dst + 16 > dst_end)
> + break;
> }
>
> hantro_reg_write(vpu, &av1_multicore_expect_context_update, !!(context_update_x == 0));
^ permalink raw reply [flat|nested] 17+ messages in thread
* [PATCH v3 7/9] media: verisilicon: rockchip: reject AV1 frames exceeding the tile capacity
2026-06-17 2:18 [PATCH v3 0/9] media: bound stateless HEVC/AV1 tile counts Michael Bommarito
` (5 preceding siblings ...)
2026-06-17 2:19 ` [PATCH v3 6/9] media: verisilicon: rockchip: guard VPU981 AV1 divisor and tile buffer Michael Bommarito
@ 2026-06-17 2:19 ` Michael Bommarito
2026-09-03 6:53 ` Benjamin Gaignard
2026-06-17 2:19 ` [PATCH v3 8/9] media: mediatek: vcodec: bound AV1 tile-start copy to the array capacity Michael Bommarito
` (2 subsequent siblings)
9 siblings, 1 reply; 17+ messages in thread
From: Michael Bommarito @ 2026-06-17 2:19 UTC (permalink / raw)
To: Hans Verkuil, Mauro Carvalho Chehab, Sakari Ailus,
Nicolas Dufresne
Cc: Laurent Pinchart, Benjamin Gaignard, Detlev Casanova,
Ezequiel Garcia, Yunfei Dong, Jonas Karlman, Heiko Stuebner,
Kees Cook, linux-media, linux-rockchip, linux-mediatek,
linux-kernel
rockchip_vpu981_av1_dec_set_tile_info() indexes the tile group entry
array by tile1 * tile_cols + tile0, reading up to tile_cols * tile_rows
entries, lays out one descriptor per tile in the AV1_MAX_TILES tile_info
buffer, and programs the real tile_cols / tile_rows into the hardware.
The tile group entry control is a dynamic array sized to the number of
entries userspace submitted, independent of tile_cols / tile_rows, so a
frame that claims more tiles than entries reads past the array. A frame
that claims more than AV1_MAX_TILES tiles also leaves the hardware
programmed for more tiles than the descriptor buffer holds.
Reject both in prepare_run(): tile_cols * tile_rows must not exceed the
submitted entry count or AV1_MAX_TILES. The entry count is read via
v4l2_ctrl_find() (ctrl->elems). This mirrors the bound the mediatek AV1
decoder already enforces.
Fixes: 727a400686a2 ("media: verisilicon: Add Rockchip AV1 decoder")
Assisted-by: Claude:claude-opus-4-8
Signed-off-by: Michael Bommarito <michael.bommarito@gmail.com>
---
.../verisilicon/rockchip_vpu981_hw_av1_dec.c | 25 ++++++++++++++++---
1 file changed, 22 insertions(+), 3 deletions(-)
diff --git a/drivers/media/platform/verisilicon/rockchip_vpu981_hw_av1_dec.c b/drivers/media/platform/verisilicon/rockchip_vpu981_hw_av1_dec.c
index fd00dbd79fe46..00aa566a4ccdb 100644
--- a/drivers/media/platform/verisilicon/rockchip_vpu981_hw_av1_dec.c
+++ b/drivers/media/platform/verisilicon/rockchip_vpu981_hw_av1_dec.c
@@ -431,20 +431,39 @@ static int rockchip_vpu981_av1_dec_prepare_run(struct hantro_ctx *ctx)
{
struct hantro_av1_dec_hw_ctx *av1_dec = &ctx->av1_dec;
struct hantro_av1_dec_ctrls *ctrls = &av1_dec->ctrls;
+ const struct v4l2_av1_tile_info *tile_info;
+ struct v4l2_ctrl *tge;
+ u32 num_tiles;
ctrls->sequence = hantro_get_ctrl(ctx, V4L2_CID_STATELESS_AV1_SEQUENCE);
if (WARN_ON(!ctrls->sequence))
return -EINVAL;
- ctrls->tile_group_entry =
- hantro_get_ctrl(ctx, V4L2_CID_STATELESS_AV1_TILE_GROUP_ENTRY);
- if (WARN_ON(!ctrls->tile_group_entry))
+ tge = v4l2_ctrl_find(&ctx->ctrl_handler,
+ V4L2_CID_STATELESS_AV1_TILE_GROUP_ENTRY);
+ if (WARN_ON(!tge))
return -EINVAL;
+ ctrls->tile_group_entry = tge->p_cur.p;
ctrls->frame = hantro_get_ctrl(ctx, V4L2_CID_STATELESS_AV1_FRAME);
if (WARN_ON(!ctrls->frame))
return -EINVAL;
+ /*
+ * rockchip_vpu981_av1_dec_set_tile_info() indexes the tile group
+ * entry array by tile1 * tile_cols + tile0, so it reads up to
+ * tile_cols * tile_rows entries, and lays out one descriptor per tile
+ * in the AV1_MAX_TILES tile_info buffer while programming the real
+ * tile geometry into the hardware. Reject a frame that claims more
+ * tiles than userspace submitted, or more than the hardware tile
+ * buffer holds, so the read stays in bounds and the programmed
+ * geometry matches the descriptors written.
+ */
+ tile_info = &ctrls->frame->tile_info;
+ num_tiles = (u32)tile_info->tile_cols * tile_info->tile_rows;
+ if (num_tiles > tge->elems || num_tiles > AV1_MAX_TILES)
+ return -EINVAL;
+
ctrls->film_grain =
hantro_get_ctrl(ctx, V4L2_CID_STATELESS_AV1_FILM_GRAIN);
--
2.53.0
^ permalink raw reply related [flat|nested] 17+ messages in thread* Re: [PATCH v3 7/9] media: verisilicon: rockchip: reject AV1 frames exceeding the tile capacity
2026-06-17 2:19 ` [PATCH v3 7/9] media: verisilicon: rockchip: reject AV1 frames exceeding the tile capacity Michael Bommarito
@ 2026-09-03 6:53 ` Benjamin Gaignard
0 siblings, 0 replies; 17+ messages in thread
From: Benjamin Gaignard @ 2026-09-03 6:53 UTC (permalink / raw)
To: Michael Bommarito, Hans Verkuil, Mauro Carvalho Chehab,
Sakari Ailus, Nicolas Dufresne
Cc: Laurent Pinchart, Detlev Casanova, Ezequiel Garcia, Yunfei Dong,
Jonas Karlman, Heiko Stuebner, Kees Cook, linux-media,
linux-rockchip, linux-mediatek, linux-kernel
Le 17/06/2026 à 04:19, Michael Bommarito a écrit :
> rockchip_vpu981_av1_dec_set_tile_info() indexes the tile group entry
> array by tile1 * tile_cols + tile0, reading up to tile_cols * tile_rows
> entries, lays out one descriptor per tile in the AV1_MAX_TILES tile_info
> buffer, and programs the real tile_cols / tile_rows into the hardware.
>
> The tile group entry control is a dynamic array sized to the number of
> entries userspace submitted, independent of tile_cols / tile_rows, so a
> frame that claims more tiles than entries reads past the array. A frame
> that claims more than AV1_MAX_TILES tiles also leaves the hardware
> programmed for more tiles than the descriptor buffer holds.
>
> Reject both in prepare_run(): tile_cols * tile_rows must not exceed the
> submitted entry count or AV1_MAX_TILES. The entry count is read via
> v4l2_ctrl_find() (ctrl->elems). This mirrors the bound the mediatek AV1
> decoder already enforces.
>
> Fixes: 727a400686a2 ("media: verisilicon: Add Rockchip AV1 decoder")
> Assisted-by: Claude:claude-opus-4-8
> Signed-off-by: Michael Bommarito <michael.bommarito@gmail.com>
Reviewed-by: Benjamin Gaignard <benjamin.gaignard@collabora.com>
> ---
> .../verisilicon/rockchip_vpu981_hw_av1_dec.c | 25 ++++++++++++++++---
> 1 file changed, 22 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/media/platform/verisilicon/rockchip_vpu981_hw_av1_dec.c b/drivers/media/platform/verisilicon/rockchip_vpu981_hw_av1_dec.c
> index fd00dbd79fe46..00aa566a4ccdb 100644
> --- a/drivers/media/platform/verisilicon/rockchip_vpu981_hw_av1_dec.c
> +++ b/drivers/media/platform/verisilicon/rockchip_vpu981_hw_av1_dec.c
> @@ -431,20 +431,39 @@ static int rockchip_vpu981_av1_dec_prepare_run(struct hantro_ctx *ctx)
> {
> struct hantro_av1_dec_hw_ctx *av1_dec = &ctx->av1_dec;
> struct hantro_av1_dec_ctrls *ctrls = &av1_dec->ctrls;
> + const struct v4l2_av1_tile_info *tile_info;
> + struct v4l2_ctrl *tge;
> + u32 num_tiles;
>
> ctrls->sequence = hantro_get_ctrl(ctx, V4L2_CID_STATELESS_AV1_SEQUENCE);
> if (WARN_ON(!ctrls->sequence))
> return -EINVAL;
>
> - ctrls->tile_group_entry =
> - hantro_get_ctrl(ctx, V4L2_CID_STATELESS_AV1_TILE_GROUP_ENTRY);
> - if (WARN_ON(!ctrls->tile_group_entry))
> + tge = v4l2_ctrl_find(&ctx->ctrl_handler,
> + V4L2_CID_STATELESS_AV1_TILE_GROUP_ENTRY);
> + if (WARN_ON(!tge))
> return -EINVAL;
> + ctrls->tile_group_entry = tge->p_cur.p;
>
> ctrls->frame = hantro_get_ctrl(ctx, V4L2_CID_STATELESS_AV1_FRAME);
> if (WARN_ON(!ctrls->frame))
> return -EINVAL;
>
> + /*
> + * rockchip_vpu981_av1_dec_set_tile_info() indexes the tile group
> + * entry array by tile1 * tile_cols + tile0, so it reads up to
> + * tile_cols * tile_rows entries, and lays out one descriptor per tile
> + * in the AV1_MAX_TILES tile_info buffer while programming the real
> + * tile geometry into the hardware. Reject a frame that claims more
> + * tiles than userspace submitted, or more than the hardware tile
> + * buffer holds, so the read stays in bounds and the programmed
> + * geometry matches the descriptors written.
> + */
> + tile_info = &ctrls->frame->tile_info;
> + num_tiles = (u32)tile_info->tile_cols * tile_info->tile_rows;
> + if (num_tiles > tge->elems || num_tiles > AV1_MAX_TILES)
> + return -EINVAL;
> +
> ctrls->film_grain =
> hantro_get_ctrl(ctx, V4L2_CID_STATELESS_AV1_FILM_GRAIN);
>
^ permalink raw reply [flat|nested] 17+ messages in thread
* [PATCH v3 8/9] media: mediatek: vcodec: bound AV1 tile-start copy to the array capacity
2026-06-17 2:18 [PATCH v3 0/9] media: bound stateless HEVC/AV1 tile counts Michael Bommarito
` (6 preceding siblings ...)
2026-06-17 2:19 ` [PATCH v3 7/9] media: verisilicon: rockchip: reject AV1 frames exceeding the tile capacity Michael Bommarito
@ 2026-06-17 2:19 ` Michael Bommarito
2026-06-17 2:19 ` [PATCH v3 9/9] media: v4l2-ctrls: add KUnit tests for compound control tile validation Michael Bommarito
2026-07-16 1:03 ` [PATCH v3 0/9] media: bound stateless HEVC/AV1 tile counts Nicolas Dufresne
9 siblings, 0 replies; 17+ messages in thread
From: Michael Bommarito @ 2026-06-17 2:19 UTC (permalink / raw)
To: Hans Verkuil, Mauro Carvalho Chehab, Sakari Ailus,
Nicolas Dufresne
Cc: Laurent Pinchart, Benjamin Gaignard, Detlev Casanova,
Ezequiel Garcia, Yunfei Dong, Jonas Karlman, Heiko Stuebner,
Kees Cook, linux-media, linux-rockchip, linux-mediatek,
linux-kernel
vdec_av1_slice_setup_tile() copies tile_cols + 1 / tile_rows + 1 entries
into mi_col_starts[] / mi_row_starts[] from the bitstream tile_info. Bound
the copy to the array capacity.
Fixes: 0934d3759615 ("media: mediatek: vcodec: separate decoder and encoder")
Assisted-by: Claude:claude-opus-4-8
Signed-off-by: Michael Bommarito <michael.bommarito@gmail.com>
---
.../mediatek/vcodec/decoder/vdec/vdec_av1_req_lat_if.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/drivers/media/platform/mediatek/vcodec/decoder/vdec/vdec_av1_req_lat_if.c b/drivers/media/platform/mediatek/vcodec/decoder/vdec/vdec_av1_req_lat_if.c
index 2d622e85f8271..49d9b4a72387e 100644
--- a/drivers/media/platform/mediatek/vcodec/decoder/vdec/vdec_av1_req_lat_if.c
+++ b/drivers/media/platform/mediatek/vcodec/decoder/vdec/vdec_av1_req_lat_if.c
@@ -1299,11 +1299,12 @@ static void vdec_av1_slice_setup_tile(struct vdec_av1_slice_frame *frame,
tile->uniform_tile_spacing_flag =
BIT_FLAG(ctrl_tile, V4L2_AV1_TILE_INFO_FLAG_UNIFORM_TILE_SPACING);
- for (i = 0; i < tile->tile_cols + 1; i++)
+ /* Bound the copy to the mi_col_starts[]/mi_row_starts[] capacity. */
+ for (i = 0; i < tile->tile_cols + 1 && i < V4L2_AV1_MAX_TILE_COLS + 1; i++)
tile->mi_col_starts[i] =
ALIGN(ctrl_tile->mi_col_starts[i], BIT(mib_size_log2)) >> mib_size_log2;
- for (i = 0; i < tile->tile_rows + 1; i++)
+ for (i = 0; i < tile->tile_rows + 1 && i < V4L2_AV1_MAX_TILE_ROWS + 1; i++)
tile->mi_row_starts[i] =
ALIGN(ctrl_tile->mi_row_starts[i], BIT(mib_size_log2)) >> mib_size_log2;
}
--
2.53.0
^ permalink raw reply related [flat|nested] 17+ messages in thread* [PATCH v3 9/9] media: v4l2-ctrls: add KUnit tests for compound control tile validation
2026-06-17 2:18 [PATCH v3 0/9] media: bound stateless HEVC/AV1 tile counts Michael Bommarito
` (7 preceding siblings ...)
2026-06-17 2:19 ` [PATCH v3 8/9] media: mediatek: vcodec: bound AV1 tile-start copy to the array capacity Michael Bommarito
@ 2026-06-17 2:19 ` Michael Bommarito
2026-07-16 1:03 ` [PATCH v3 0/9] media: bound stateless HEVC/AV1 tile counts Nicolas Dufresne
9 siblings, 0 replies; 17+ messages in thread
From: Michael Bommarito @ 2026-06-17 2:19 UTC (permalink / raw)
To: Hans Verkuil, Mauro Carvalho Chehab, Sakari Ailus,
Nicolas Dufresne
Cc: Laurent Pinchart, Benjamin Gaignard, Detlev Casanova,
Ezequiel Garcia, Yunfei Dong, Jonas Karlman, Heiko Stuebner,
Kees Cook, linux-media, linux-rockchip, linux-mediatek,
linux-kernel
Add KUnit coverage for the HEVC and AV1 tile-count checks in
std_validate_compound(): in-range counts pass, out-of-range per-dimension
counts and an AV1 grid whose product exceeds V4L2_AV1_MAX_TILE_COUNT are
rejected, and the zero-initialised AV1 frame control that userspace
submits still passes.
Assisted-by: Claude:claude-opus-4-8
Signed-off-by: Michael Bommarito <michael.bommarito@gmail.com>
---
drivers/media/v4l2-core/Kconfig | 12 ++
.../media/v4l2-core/v4l2-ctrls-core-test.c | 145 ++++++++++++++++++
drivers/media/v4l2-core/v4l2-ctrls-core.c | 4 +
3 files changed, 161 insertions(+)
create mode 100644 drivers/media/v4l2-core/v4l2-ctrls-core-test.c
diff --git a/drivers/media/v4l2-core/Kconfig b/drivers/media/v4l2-core/Kconfig
index d50ccac9733cc..52c00dfe9322f 100644
--- a/drivers/media/v4l2-core/Kconfig
+++ b/drivers/media/v4l2-core/Kconfig
@@ -3,6 +3,18 @@
# Generic video config states
#
+config V4L2_CTRLS_KUNIT_TEST
+ bool "KUnit tests for V4L2 compound control validation" if !KUNIT_ALL_TESTS
+ depends on VIDEO_DEV && KUNIT=y
+ default KUNIT_ALL_TESTS
+ help
+ This builds KUnit tests for the stateless-codec compound control
+ validation in std_validate_compound(). They check that out-of-range
+ HEVC and AV1 tile counts are rejected before the stateless decoders
+ consume them as loop bounds and array indices.
+
+ If unsure, say N.
+
config VIDEO_V4L2_I2C
bool
depends on I2C && VIDEO_DEV
diff --git a/drivers/media/v4l2-core/v4l2-ctrls-core-test.c b/drivers/media/v4l2-core/v4l2-ctrls-core-test.c
new file mode 100644
index 0000000000000..c0141f3defa82
--- /dev/null
+++ b/drivers/media/v4l2-core/v4l2-ctrls-core-test.c
@@ -0,0 +1,145 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * KUnit tests for HEVC/AV1 tile-count validation in std_validate_compound().
+ * #included at the end of v4l2-ctrls-core.c to reach the static helper.
+ */
+
+#include <kunit/test.h>
+
+static int call_validate_compound(enum v4l2_ctrl_type type, void *payload,
+ u32 elem_size)
+{
+ struct v4l2_ctrl ctrl = {
+ .type = type,
+ .elem_size = elem_size,
+ };
+ union v4l2_ctrl_ptr ptr = { .p = payload };
+
+ return std_validate_compound(&ctrl, 0, ptr);
+}
+
+/* HEVC PPS: num_tile_columns_minus1 / num_tile_rows_minus1 bounds. */
+static void v4l2_ctrls_hevc_pps_tile_cols(struct kunit *test)
+{
+ struct v4l2_ctrl_hevc_pps *pps;
+
+ pps = kunit_kzalloc(test, sizeof(*pps), GFP_KERNEL);
+ KUNIT_ASSERT_NOT_NULL(test, pps);
+
+ pps->flags = V4L2_HEVC_PPS_FLAG_TILES_ENABLED;
+
+ /* In range: count == array capacity (minus1 == capacity - 1). */
+ pps->num_tile_columns_minus1 = ARRAY_SIZE(pps->column_width_minus1) - 1;
+ pps->num_tile_rows_minus1 = ARRAY_SIZE(pps->row_height_minus1) - 1;
+ KUNIT_EXPECT_EQ(test,
+ call_validate_compound(V4L2_CTRL_TYPE_HEVC_PPS, pps,
+ sizeof(*pps)),
+ 0);
+
+ /* Out of range: one past the column array. */
+ pps->num_tile_columns_minus1 = ARRAY_SIZE(pps->column_width_minus1);
+ pps->num_tile_rows_minus1 = 0;
+ KUNIT_EXPECT_EQ(test,
+ call_validate_compound(V4L2_CTRL_TYPE_HEVC_PPS, pps,
+ sizeof(*pps)),
+ -EINVAL);
+
+ /* Out of range: maximal attacker value. */
+ pps->num_tile_columns_minus1 = 0xff;
+ pps->num_tile_rows_minus1 = 0xff;
+ KUNIT_EXPECT_EQ(test,
+ call_validate_compound(V4L2_CTRL_TYPE_HEVC_PPS, pps,
+ sizeof(*pps)),
+ -EINVAL);
+}
+
+/* AV1 frame: tile_cols / tile_rows upper bounds. */
+static void v4l2_ctrls_av1_frame_tile(struct kunit *test)
+{
+ struct v4l2_ctrl_av1_frame *f;
+
+ f = kunit_kzalloc(test, sizeof(*f), GFP_KERNEL);
+ KUNIT_ASSERT_NOT_NULL(test, f);
+
+ /*
+ * Benign control: a zero-initialised frame (tile_cols == 0) must
+ * still pass. Userspace and v4l2-compliance set the zeroed default,
+ * and the divisor that a zero tile_cols would feed is guarded in the
+ * consuming driver rather than rejected here.
+ */
+ KUNIT_EXPECT_EQ(test,
+ call_validate_compound(V4L2_CTRL_TYPE_AV1_FRAME, f,
+ sizeof(*f)),
+ 0);
+
+ /* In range: a 1x1 tiling. */
+ f->tile_info.tile_cols = 1;
+ f->tile_info.tile_rows = 1;
+ KUNIT_EXPECT_EQ(test,
+ call_validate_compound(V4L2_CTRL_TYPE_AV1_FRAME, f,
+ sizeof(*f)),
+ 0);
+
+ /*
+ * In range: total tiles == V4L2_AV1_MAX_TILE_COUNT with each
+ * dimension at or below its per-dimension maximum (64 * 8 == 512).
+ */
+ f->tile_info.tile_cols = V4L2_AV1_MAX_TILE_COLS;
+ f->tile_info.tile_rows = V4L2_AV1_MAX_TILE_COUNT / V4L2_AV1_MAX_TILE_COLS;
+ KUNIT_EXPECT_EQ(test,
+ call_validate_compound(V4L2_CTRL_TYPE_AV1_FRAME, f,
+ sizeof(*f)),
+ 0);
+
+ /*
+ * Out of range: each dimension is legal on its own but the product
+ * exceeds V4L2_AV1_MAX_TILE_COUNT (64 * 64 == 4096 > 512), which would
+ * overflow the per-tile descriptor buffers.
+ */
+ f->tile_info.tile_cols = V4L2_AV1_MAX_TILE_COLS;
+ f->tile_info.tile_rows = V4L2_AV1_MAX_TILE_ROWS;
+ KUNIT_EXPECT_EQ(test,
+ call_validate_compound(V4L2_CTRL_TYPE_AV1_FRAME, f,
+ sizeof(*f)),
+ -EINVAL);
+
+ /* Out of range: tile_cols past the array. */
+ f->tile_info.tile_cols = V4L2_AV1_MAX_TILE_COLS + 1;
+ f->tile_info.tile_rows = 1;
+ KUNIT_EXPECT_EQ(test,
+ call_validate_compound(V4L2_CTRL_TYPE_AV1_FRAME, f,
+ sizeof(*f)),
+ -EINVAL);
+
+ /* Out of range: maximal attacker value. */
+ f->tile_info.tile_cols = 0xff;
+ f->tile_info.tile_rows = 0xff;
+ KUNIT_EXPECT_EQ(test,
+ call_validate_compound(V4L2_CTRL_TYPE_AV1_FRAME, f,
+ sizeof(*f)),
+ -EINVAL);
+
+ /* Out of range: tile_rows past the array. */
+ f->tile_info.tile_cols = 1;
+ f->tile_info.tile_rows = V4L2_AV1_MAX_TILE_ROWS + 1;
+ KUNIT_EXPECT_EQ(test,
+ call_validate_compound(V4L2_CTRL_TYPE_AV1_FRAME, f,
+ sizeof(*f)),
+ -EINVAL);
+}
+
+static struct kunit_case v4l2_ctrls_test_cases[] = {
+ KUNIT_CASE(v4l2_ctrls_hevc_pps_tile_cols),
+ KUNIT_CASE(v4l2_ctrls_av1_frame_tile),
+ {}
+};
+
+static struct kunit_suite v4l2_ctrls_test_suite = {
+ .name = "v4l2-ctrls-compound",
+ .test_cases = v4l2_ctrls_test_cases,
+};
+
+kunit_test_suite(v4l2_ctrls_test_suite);
+
+MODULE_DESCRIPTION("KUnit tests for V4L2 stateless-codec compound control validation");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/v4l2-core/v4l2-ctrls-core.c b/drivers/media/v4l2-core/v4l2-ctrls-core.c
index fb20ad13dfec7..1409b06eee0a8 100644
--- a/drivers/media/v4l2-core/v4l2-ctrls-core.c
+++ b/drivers/media/v4l2-core/v4l2-ctrls-core.c
@@ -2860,3 +2860,7 @@ int v4l2_ctrl_new_fwnode_properties(struct v4l2_ctrl_handler *hdl,
return hdl->error;
}
EXPORT_SYMBOL(v4l2_ctrl_new_fwnode_properties);
+
+#if IS_ENABLED(CONFIG_V4L2_CTRLS_KUNIT_TEST)
+#include "v4l2-ctrls-core-test.c"
+#endif
--
2.53.0
^ permalink raw reply related [flat|nested] 17+ messages in thread* Re: [PATCH v3 0/9] media: bound stateless HEVC/AV1 tile counts
2026-06-17 2:18 [PATCH v3 0/9] media: bound stateless HEVC/AV1 tile counts Michael Bommarito
` (8 preceding siblings ...)
2026-06-17 2:19 ` [PATCH v3 9/9] media: v4l2-ctrls: add KUnit tests for compound control tile validation Michael Bommarito
@ 2026-07-16 1:03 ` Nicolas Dufresne
9 siblings, 0 replies; 17+ messages in thread
From: Nicolas Dufresne @ 2026-07-16 1:03 UTC (permalink / raw)
To: Michael Bommarito, Hans Verkuil, Mauro Carvalho Chehab,
Sakari Ailus
Cc: Laurent Pinchart, Benjamin Gaignard, Detlev Casanova,
Ezequiel Garcia, Yunfei Dong, Jonas Karlman, Heiko Stuebner,
Kees Cook, linux-media, linux-rockchip, linux-mediatek,
linux-kernel
[-- Attachment #1: Type: text/plain, Size: 5368 bytes --]
Hi,
there was a problem with patchwork regarding that series. Mind trying to resent
to see if it can fix it ?
Nicolas
Le mardi 16 juin 2026 à 22:18 -0400, Michael Bommarito a écrit :
> The stateless HEVC and AV1 controls carry tile counts that several SoC
> decoder drivers consume as loop bounds and array indices when laying out
> fixed-size hardware descriptor buffers. std_validate_compound() does not
> bound them, so a crafted HEVC PPS or AV1 frame control can drive
> out-of-bounds writes and an AV1 divide-by-zero in the rkvdec, hantro,
> rockchip and mediatek decoders.
>
> 1-2 reject out-of-range HEVC and AV1 tile counts in
> std_validate_compound() (one patch per codec). For AV1 the per-
> dimension bound is V4L2_AV1_MAX_TILE_{COLS,ROWS} and the total is
> V4L2_AV1_MAX_TILE_COUNT.
> 3 add <media/v4l2-hevc.h> with bounded tile-count helpers.
> 4-5 use the helpers in rkvdec and hantro instead of open-coding the
> clamp; rkvdec also bails before indexing the hardware
> parameter-set table with an out-of-range HEVC PPS id.
> 6 guard the rockchip VPU981 AV1 divisor against tile_cols == 0 and
> keep the descriptor writes inside the AV1_MAX_TILES buffer.
> 7 reject a rockchip AV1 frame whose tile_cols * tile_rows exceeds the
> submitted tile group entry count or the AV1_MAX_TILES descriptor
> capacity, which set_tile_info() would otherwise read past or leave
> under-described while programming the larger geometry.
> 8 bound the mediatek AV1 tile-start copy.
> 9 KUnit coverage for the tile-count validation.
>
> Changes since v2:
> - Split the combined HEVC+AV1 validation into one patch per codec, each
> with a single Fixes tag (Benjamin Gaignard).
> - Move the AV1 total-tile bound into validate_av1_tile_info() using the
> uAPI V4L2_AV1_MAX_TILE_COUNT, instead of clamping tile_cols/tile_rows
> in the rockchip driver, which would have corrupted the values written
> to the hardware registers (Benjamin Gaignard's NACK on v2 4/6).
> - Add <media/v4l2-hevc.h> with shared bounded tile-count helpers so
> rkvdec and hantro no longer duplicate the clamp (Benjamin Gaignard).
> - New patch 7: reject a rockchip AV1 frame that claims more tiles than
> the submitted tile group entry array holds (set_tile_info() indexes
> it by tile_cols * tile_rows) or more than AV1_MAX_TILES (the hardware
> descriptor buffer), which would otherwise leave the hardware
> programmed for more tiles than the buffer describes. mediatek already
> guards the entry count; rockchip now guards both.
>
> checkpatch --strict: 0 errors on all nine. Patches 3 and 9 each carry one
> "added file ... does MAINTAINERS need updating?" warning for the new
> <media/v4l2-hevc.h> and the KUnit test file; both already fall under the
> existing include/media/ and drivers/media/v4l2-core/ MAINTAINERS entries,
> so no MAINTAINERS change is needed. (checkpatch's SPDX sub-check did not
> run in my environment -- spdxcheck.py needs python3-ply -- but the SPDX
> headers are present on both new files.)
>
> The tile-count validation is exercised with KUnit (patch 9): in-range
> HEVC/AV1 counts pass, out-of-range per-dimension counts and an AV1 grid
> whose product exceeds V4L2_AV1_MAX_TILE_COUNT are rejected, and the
> zero-initialised AV1 frame control that v4l2-compliance and existing
> userspace submit still passes.
>
> v2:
> https://lore.kernel.org/all/20260614155609.3107600-1-michael.bommarito@gmail.com/
>
> Michael Bommarito (9):
> media: v4l2-ctrls: validate HEVC tile counts
> media: v4l2-ctrls: validate AV1 tile counts
> media: hevc: add bounded tile-count helpers
> media: rkvdec: bound HEVC tile loops and PPS id to the array capacity
> media: verisilicon: hantro: bound G2 HEVC tile loop to the buffer
> capacity
> media: verisilicon: rockchip: guard VPU981 AV1 divisor and tile buffer
> media: verisilicon: rockchip: reject AV1 frames exceeding the tile
> capacity
> media: mediatek: vcodec: bound AV1 tile-start copy to the array
> capacity
> media: v4l2-ctrls: add KUnit tests for compound control tile
> validation
>
> .../vcodec/decoder/vdec/vdec_av1_req_lat_if.c | 5 +-
> .../rockchip/rkvdec/rkvdec-hevc-common.c | 14 +-
> .../platform/rockchip/rkvdec/rkvdec-hevc.c | 7 +-
> .../rockchip/rkvdec/rkvdec-vdpu381-hevc.c | 2 +
> .../platform/verisilicon/hantro_g2_hevc_dec.c | 6 +-
> .../verisilicon/rockchip_vpu981_hw_av1_dec.c | 57 +++++--
> drivers/media/v4l2-core/Kconfig | 12 ++
> .../media/v4l2-core/v4l2-ctrls-core-test.c | 145 ++++++++++++++++++
> drivers/media/v4l2-core/v4l2-ctrls-core.c | 36 +++++
> include/media/v4l2-hevc.h | 41 +++++
> 10 files changed, 306 insertions(+), 19 deletions(-)
> create mode 100644 drivers/media/v4l2-core/v4l2-ctrls-core-test.c
> create mode 100644 include/media/v4l2-hevc.h
>
>
> base-commit: e24a98d6884a6e4203a77a94f070a59fcab95208
[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
^ permalink raw reply [flat|nested] 17+ messages in thread