From: sashiko-bot@kernel.org
To: "Sofus Forstreuter" <sofus.c@icloud.com>
Cc: devicetree@vger.kernel.org, robh@kernel.org, conor+dt@kernel.org,
media-ci@linuxtv.org
Subject: Re: [PATCH v3 17/17] arm64: dts: apple: t6031: add avd nodes
Date: Tue, 20 Oct 2026 15:02:09 +0000 [thread overview]
Message-ID: <sashiko-outbox-179210@kernel.org> (raw)
In-Reply-To: <20261020-avd-v3-17-85cbaa2125d8@icloud.com>
Thank you for your contribution! Sashiko AI review found 6 potential issue(s) to consider:
- [Critical] media: apple: avd: missing bounds checks on HEVC tile and slice controls
- [High] media: apple: avd: out-of-bounds copy in avd_h264_realloc_slices()
- [High] media: apple: avd: missing bounds and dimension validation in AV1 and H264
- [Medium] media: apple: avd: swapped hdiv and vdiv in fill_comp()
- [Medium] media: apple: avd: missing v4l2_fh_exit() in avd_open() and NUL in avd_boot()
- [Low] arm64: dts: apple: t6031: undocumented apple,t6031-dart compatible string
--
commit 710cbe683a71adce1476927b8edd0e1212525500
Author: Sofus Forstreuter <sofus.c@icloud.com>
arm64: dts: apple: t6031: add avd nodes
This commit adds the Apple Video Decoder (AVD) and its associated DART IOMMU
device tree nodes for the Apple t6031 SoC.
> diff --git a/arch/arm64/boot/dts/apple/t6031-dieX.dtsi b/arch/arm64/boot/dts/apple/t6031-dieX.dtsi
> index 2e9d3d2e6dea4..4959190e13a3c 100644
> --- a/arch/arm64/boot/dts/apple/t6031-dieX.dtsi
> +++ b/arch/arm64/boot/dts/apple/t6031-dieX.dtsi
> @@ -98,6 +98,38 @@ DIE_NODE(pinctrl_ap): pinctrl@2b3000000 {
> #interrupt-cells = <2>;
> };
>
> + DIE_NODE(avd_dart): iommu@2cd010000 {
> + compatible = "apple,t6031-dart", "apple,t8110-dart";
[Severity: Low]
Does the compatible string "apple,t6031-dart" need to be documented in
Documentation/devicetree/bindings/iommu/apple,dart.yaml?
Currently, the schema only permits:
compatible:
oneOf:
- enum:
- apple,t8103-dart
- apple,t8103-usb4-dart
- apple,t8110-dart
- apple,t6000-dart
- items:
- const: apple,t6020-dart
- const: apple,t8110-dart
Without an entry for "apple,t6031-dart", running dtbs_check on device trees
including t6031-dieX.dtsi will report a schema validation failure on
iommu@2cd010000.
> + reg = <0x2 0xcd010000 0x0 0x4000>;
> + interrupt-parent = <&aic>;
> + interrupts = <AIC_IRQ DIE_NO 1192 IRQ_TYPE_LEVEL_HIGH>;
> + #iommu-cells = <1>;
> + power-domains = <&DIE_NODE(ps_avd_sys)>;
> + };
> +
> + video-codec@2cd070000 {
> + compatible = "apple,t6031-avd", "apple,t8122-avd";
[Severity: Medium]
Instantiating video-codec@2cd070000 binds the AVD driver introduced earlier
in this series (drivers/media/platform/apple/avd/). Looking at the driver
implementation that this node enables on t6031, are horizontal and vertical
subsampling divisors swapped in fill_comp()?
In drivers/media/platform/apple/avd/avd-drv.c:fill_comp():
/* uv has 16x16 tiles and 8 bytes of metadata per tile */
calc_tile_meta(width / info->vdiv, height / info->hdiv,
v4l2_format_info_bpp(info, 1), 16, 8, &uv,
&uv_meta);
When avd_open() or format/control ioctls (avd_s_output_fmt(),
avd_try_capture_fmt(), avd_s_capture_fmt(), avd_s_ctrl()) call
avd_fill_decoded_pixfmt() -> fill_comp() with a 4:2:2 format
(AVD_IMG_FMT_ANY, AVD_IMG_FMT_422_8BIT, or AVD_IMG_FMT_422_10BIT),
v4l2_format_info() returns hdiv = 2 and vdiv = 1.
Passing width / info->vdiv and height / info->hdiv divides the width by 1 and
the height by 2 instead of width / info->hdiv and height / info->vdiv. For
resolutions where DIV_ROUND_UP(width / 2, 16) * DIV_ROUND_UP(height, 16)
differs from DIV_ROUND_UP(width, 16) * DIV_ROUND_UP(height / 2, 16) (such as
720x1280), could this under-allocate uv, comp->size, and
pix_mp->plane_fmt[0].sizeimage, causing the hardware to DMA past the end of
the capture buffer when push_comp() programs comp->offsets?
[Severity: High]
Also in the H.264 decoder path enabled by this node, can
avd_h264_realloc_slices() read out of bounds from job->buf.cpu or leave
alloc_slice_num out of sync with job->segments?
In drivers/media/platform/apple/avd/avd-h264.c:avd_h264_run():
if (ctx->job.segments &&
h264_ctx->slice_num >= h264_ctx->alloc_slice_num) {
ret = avd_h264_realloc_slices(ctx);
if (ret)
goto postamble;
}
On the first slice of a frame, avd_h264_run() calls avd_init_job() with
num_segments = h264_ctx->alloc_slice_num + 1, and calls avd_end_segment()
twice (for stream_hdr() and stream_slice()). Each subsequent slice increments
h264_ctx->slice_num and calls avd_end_segment() once, incrementing job->num.
When h264_ctx->slice_num reaches h264_ctx->alloc_slice_num, job->num is
already equal to the old alloc_slice_num + 1 (which equals job->num_alloc, the
full size of job->buf). In avd_h264_realloc_slices():
h264_ctx->alloc_slice_num = alloc_slice_num;
memcpy(h264_ctx->slices, tmp,
sizeof(*h264_ctx->slices) * h264_ctx->slice_num);
kfree(tmp);
/* we could already have the correct size */
if ((alloc_slice_num + 1) * sizeof(*job->segments) < job->buf.size)
return 0;
ret = avd_buf_alloc(ctx->dev, &tmp_buf,
(alloc_slice_num + 1) * sizeof(*job->segments));
if (ret)
return -ENOMEM;
job->segments = tmp_buf.cpu;
job->num_alloc = (alloc_slice_num + 1);
memset(tmp_buf.cpu, 0, tmp_buf.size);
memcpy(job->segments, job->buf.cpu,
sizeof(*job->segments) * (job->num + 1));
Since job->buf only holds job->num elements at this point, doesn't copying
(job->num + 1) elements read one struct avd_segment past the end of
job->buf.cpu?
Furthermore, because h264_ctx->alloc_slice_num is updated before checking
job->buf.size and before avd_buf_alloc(), if the early return is taken
(without updating job->num_alloc) or if avd_buf_alloc() fails with -ENOMEM,
won't subsequent slices in the same frame see slice_num < alloc_slice_num,
skip reallocation, and write out of bounds into job->segments?
[Severity: Critical]
In drivers/media/platform/apple/avd/avd-hevc.c, can crafted V4L2 HEVC
stateless controls trigger out-of-bounds accesses and integer overflows during
avd_hevc_run()?
1. In avd_hevc_validate_pps() and compute_tiles_non_uniform():
static int avd_hevc_validate_pps(struct avd_ctx *ctx,
const struct v4l2_ctrl_hevc_pps *pps)
{
if (pps->num_tile_columns_minus1 + 1 > HEVC_MAX_TILE_COLS ||
pps->num_tile_rows_minus1 + 1 > HEVC_MAX_TILE_ROWS)
return -EINVAL;
for (i = 0; i < pps->num_tile_columns_minus1; i++) {
column_width[i] = MIN(pps->column_width_minus1[i] + 1,
pic_in_cts_width);
sum += column_width[i];
}
column_width[i] = pic_in_cts_width - sum;
HEVC_MAX_TILE_COLS is 40 and HEVC_MAX_TILE_ROWS is 44, whereas struct
v4l2_ctrl_hevc_pps defines column_width_minus1[20] and row_height_minus1[22].
Won't compute_tiles_non_uniform() read past the end of column_width_minus1[]
and row_height_minus1[] when num_tile_columns_minus1 > 20 or
num_tile_rows_minus1 > 22?
In addition, if sum exceeds pic_in_cts_width (or pic_in_cts_height for rows),
pic_in_cts_width - sum underflows u16 column_width[i], causing compute_bd() to
produce col_bd[] / row_bd[] values larger than the picture CTB dimensions and
causing compute_tile_ids() to read ctb_addr_rs_to_ts[] and write tile_ids[]
out of bounds:
for (j = 0, tile_idx = 0; j <= pps->num_tile_rows_minus1; j++)
for (i = 0; i <= pps->num_tile_columns_minus1; i++, tile_idx++)
for (y = row_bd[j]; y < row_bd[j + 1]; y++)
for (x = col_bd[i]; x < col_bd[i + 1]; x++)
tile_ids[ctb_addr_rs_to_ts
[y * pic_in_ctbs_width +
x]] = tile_idx;
2. In stream_slices() -> submit_slice_segment():
if (pps->flags & V4L2_HEVC_PPS_FLAG_TILES_ENABLED)
push(AVD_SL_DIM_END_ROW((hflip ? 4 : 0) |
(vflip ? 8 : 0)) |
AVD_SL_DIM_END_COL(col) |
AVD_SL_DIM_END_Y(row_bd[row + 1] - 1) |
AVD_SL_DIM_END_X(col_bd[col + 1] - 1),
"cm3_set_ctb_xy");
stream_slices() increments pos for each segment with NEW_TILE_ID and computes
row = pos / num_cols without checking that row <= pps->num_tile_rows_minus1.
Can this read row_bd[row + 1] (and row_bd[row]) out of bounds?
3. In avd_hevc_validate_sps() and avd_hevc_compute_tiles(), are zero
pic_width_in_luma_samples / pic_height_in_luma_samples or large coding block
shift exponents (>= 31) rejected before computing max_cu_width = 1 << (...)
and dividing by max_cu_width?
4. In avd_hevc_run_preamble():
for (i = 0; i < run->num_slices; i++)
sum += (*run->sl)[i].num_entry_point_offsets;
if (sum && sum != run->num_entry_point_offsets)
return -EINVAL;
Since sum is a signed int and num_entry_point_offsets is u32, can sum overflow
and wrap to 0 (or a small value matching run->num_entry_point_offsets),
causing avd_init_job() to under-allocate ctx->job.segments and leading to
out-of-bounds accesses on run->entry_point_offsets in stream_slices() and
job->segments in avd_end_segment()?
[Severity: High]
In drivers/media/platform/apple/avd/avd-av1.c and avd-h264.c, could missing
validation on stateless AV1 and H.264 controls lead to out-of-bounds accesses
or divide-by-zero errors?
1. In drivers/media/platform/apple/avd/avd-av1.c:avd_av1_set_prob():
memcpy(vb2_plane_vaddr(&dst->base.vb.vb2_buf, 0) +
AVD_AV1_CDFS_OFFSET(dst->base.vb.vb2_buf.planes[0].length,
dst->av1.color_size),
av1_ctx->bufs.probs.cpu, sizeof(struct avd_av1_cdfs));
Neither avd_av1_try_ctrl() nor avd_av1_run_preamble() checks that
frame->frame_width_minus_1 + 1 and frame->frame_height_minus_1 + 1 fit within
ctx->decoded_fmt.fmt.pix_mp.width and height. If userspace passes larger frame
dimensions, dst->av1.color_size can exceed planes[0].length, underflowing
AVD_AV1_CDFS_OFFSET() and writing sizeof(struct avd_av1_cdfs) bytes before
vb2_plane_vaddr(). Also, if frame_width_minus_1 or frame_height_minus_1 is
U32_MAX, width or height wraps to 0 in set_refs(), causing a division by zero.
2. In drivers/media/platform/apple/avd/avd-av1.c:set_ref_hdr():
for (i = 0; i < 6; i++) {
for (j = i + 1; j < 7; j++) {
if (frame->reference_frame_ts[frame->ref_frame_idx[i]] ==
frame->reference_frame_ts[frame->ref_frame_idx[j]]) {
frame->ref_frame_idx[] contains __s8 values from userspace. Unlike
avd_av1_get_ref_buf(), set_ref_hdr() indexes the 8-element
frame->reference_frame_ts[] array without checking that ref_frame_idx[i] and
ref_frame_idx[j] are within 0..7.
3. In drivers/media/platform/apple/avd/avd-av1.c:calc_upscale():
downscaled_plane_w = AV1_DIV_ROUND_UP_POW2(frame_width, sub_x);
upscaled_plane_w = AV1_DIV_ROUND_UP_POW2(upscaled_width, sub_x);
*step_x = ((downscaled_plane_w << SUPERRES_SCALE_BITS) +
(upscaled_plane_w / 2)) /
upscaled_plane_w;
calc_upscale() is called from set_header() without checking that
frame->upscaled_width is non-zero, which can divide by zero when
upscaled_plane_w is 0.
4. In drivers/media/platform/apple/avd/avd-av1.c:avd_av1_run_preamble():
run->tile_group = ctrl->p_cur.p;
if (run->frame->tile_info.tile_cols * run->frame->tile_info.tile_rows >
ctrl->new_elems)
return -EINVAL;
Since run->tile_group reads from ctrl->p_cur.p, should this check ctrl->elems
rather than ctrl->new_elems?
5. In drivers/media/platform/apple/avd/avd-h264.c:stream_slice():
/* sl->ref_pic_list1[0].index < ARRAY_SIZE(decode->dpb) */
/* bidirectional reference of previous mv */
ref = avd_get_ref_buf(
ctx, &dst->base.vb,
decode->dpb[sl->ref_pic_list1[0].index].reference_ts);
sl->ref_pic_list1[0].index is an unvalidated u8 from userspace (v4l2-ctrls
only validates num_ref_idx_l1_active_minus1, not the index fields in
ref_pic_list1[]), so can this read past the 16-element decode->dpb[] array?
Similarly, should avd_h264_validate_sps() validate the SPS macroblock
dimensions against ctx->coded_fmt or ctx->decoded_fmt?
[Severity: Medium]
Finally, in drivers/media/platform/apple/avd/avd-drv.c, are there two small
issues in avd_boot() and avd_open()?
In avd_boot():
memcpy_fromio(version, avd->sram, sizeof(version));
dev_info_once(avd->dev, "fw version: %s\n", version);
version is a 64-byte stack array filled from avd->sram without ensuring NUL
termination; if SRAM does not contain a NUL byte in the first 64 bytes,
formatting with %s will read past the stack buffer. Should version be
explicitly NUL-terminated or printed with %.*s?
And in avd_open():
v4l2_fh_init(&ctx->fh, video_devdata(filp));
ctx->fh.m2m_ctx = v4l2_m2m_ctx_init(avd->m2m_dev, ctx, avd_queue_init);
if (IS_ERR(ctx->fh.m2m_ctx)) {
ret = PTR_ERR(ctx->fh.m2m_ctx);
goto err_free_ctx;
}
ret = avd_init_ctrls(ctx);
if (ret)
goto err_cleanup_m2m_ctx;
v4l2_fh_add(&ctx->fh, filp);
return 0;
err_cleanup_m2m_ctx:
v4l2_m2m_ctx_release(ctx->fh.m2m_ctx);
err_free_ctx:
avd_buf_free(avd, &ctx->pipe_state);
avd_buf_free(avd, &ctx->inst);
kfree(ctx);
If v4l2_m2m_ctx_init() or avd_init_ctrls() fails after v4l2_fh_init(), should
err_free_ctx call v4l2_fh_exit(&ctx->fh) before freeing ctx?
> + reg = <0x2 0xcd070000 0x0 0x4000>,
> + <0x2 0xcd080000 0x0 0x10000>,
> + <0x2 0xcd090000 0x0 0x14000>,
> + <0x2 0xcd0a4000 0x0 0x4000>,
> + <0x2 0xcd100000 0x0 0x10000>;
> + reg-names = "piodma", "code", "sram", "mbox", "ctrl";
> + interrupt-parent = <&aic>;
> + interrupts = <AIC_IRQ DIE_NO 1185 IRQ_TYPE_LEVEL_HIGH>,
> + <AIC_IRQ DIE_NO 1186 IRQ_TYPE_LEVEL_HIGH>,
> + <AIC_IRQ DIE_NO 1187 IRQ_TYPE_LEVEL_HIGH>,
> + <AIC_IRQ DIE_NO 1188 IRQ_TYPE_LEVEL_HIGH>,
> + <AIC_IRQ DIE_NO 1189 IRQ_TYPE_LEVEL_HIGH>,
> + <AIC_IRQ DIE_NO 1190 IRQ_TYPE_LEVEL_HIGH>,
> + <AIC_IRQ DIE_NO 1191 IRQ_TYPE_LEVEL_HIGH>;
> + interrupt-names = "mbox0", "mbox1", "mbox2", "mbox3",
> + "flag0", "flag1", "piodma";
> + iommus = <&DIE_NODE(avd_dart) 0>, <&DIE_NODE(avd_dart) 1>;
> + power-domains = <&DIE_NODE(ps_avd_sys)>;
> + resets = <&DIE_NODE(ps_avd_sys)>;
> + };
> +
> DIE_NODE(pmgr_gfx): power-management@408e80000 {
> compatible = "apple,t6031-pmgr", "apple,t8103-pmgr", "syscon", "simple-mfd";
> #address-cells = <1>;
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261020-avd-v3-0-85cbaa2125d8@icloud.com?part=17
prev parent reply other threads:[~2026-10-20 15:02 UTC|newest]
Thread overview: 47+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-20 9:37 [PATCH v3 00/17] media: apple: add avd driver Sofus Forstreuter
2026-10-20 9:37 ` Sofus Forstreuter
2026-10-20 9:37 ` [PATCH v3 01/17] dt-bindings: media: add apple,avd Sofus Forstreuter
2026-10-20 9:37 ` Sofus Forstreuter
2026-10-20 9:37 ` [PATCH v3 02/17] media: v4l2: Add P210 pixel format Sofus Forstreuter
2026-10-20 9:37 ` Sofus Forstreuter
2026-10-20 9:37 ` [PATCH v3 03/17] media: v4l2: Add Apple interchange pixel formats Sofus Forstreuter
2026-10-20 9:37 ` Sofus Forstreuter
2026-10-20 9:56 ` sashiko-bot
2026-10-20 9:37 ` [PATCH v3 04/17] media: v4l2-ctrls: validate av1 tile info Sofus Forstreuter
2026-10-20 9:37 ` Sofus Forstreuter
2026-10-20 10:10 ` sashiko-bot
2026-10-20 9:37 ` [PATCH v3 05/17] media: v4l2-ctrls: validate vp9 tile_rows_log2 Sofus Forstreuter
2026-10-20 9:37 ` Sofus Forstreuter
2026-10-20 9:37 ` [PATCH v3 06/17] media: apple: add avd driver Sofus Forstreuter
2026-10-20 9:37 ` Sofus Forstreuter
2026-10-20 10:34 ` sashiko-bot
2026-10-20 9:37 ` [PATCH v3 07/17] media: apple: avd: add h264 support Sofus Forstreuter
2026-10-20 9:37 ` Sofus Forstreuter
2026-10-20 10:55 ` sashiko-bot
2026-10-20 9:37 ` [PATCH v3 08/17] media: apple: avd: add vp9 support Sofus Forstreuter
2026-10-20 9:37 ` Sofus Forstreuter
2026-10-20 11:22 ` sashiko-bot
2026-10-20 9:37 ` [PATCH v3 09/17] media: apple: avd: add hevc support Sofus Forstreuter
2026-10-20 9:37 ` Sofus Forstreuter
2026-10-20 11:40 ` sashiko-bot
2026-10-20 9:37 ` [PATCH v3 10/17] media: apple: avd: add av1 support Sofus Forstreuter
2026-10-20 9:37 ` Sofus Forstreuter
2026-10-20 12:50 ` sashiko-bot
2026-10-20 9:37 ` [PATCH v3 11/17] arm64: dts: apple: t8103: add avd nodes Sofus Forstreuter
2026-10-20 9:37 ` Sofus Forstreuter
2026-10-20 13:27 ` sashiko-bot
2026-10-20 9:37 ` [PATCH v3 12/17] arm64: dts: apple: t8112: " Sofus Forstreuter
2026-10-20 9:37 ` Sofus Forstreuter
2026-10-20 9:37 ` [PATCH v3 13/17] arm64: dts: apple: t8122: " Sofus Forstreuter
2026-10-20 9:37 ` Sofus Forstreuter
2026-10-20 14:02 ` sashiko-bot
2026-10-20 9:37 ` [PATCH v3 14/17] arm64: dts: apple: t600x: " Sofus Forstreuter
2026-10-20 9:37 ` Sofus Forstreuter
2026-10-20 9:37 ` [PATCH v3 15/17] arm64: dts: apple: t602x: " Sofus Forstreuter
2026-10-20 9:37 ` Sofus Forstreuter
2026-10-20 9:37 ` [PATCH v3 16/17] arm64: dts: apple: t6030: " Sofus Forstreuter
2026-10-20 9:37 ` Sofus Forstreuter
2026-10-20 14:40 ` sashiko-bot
2026-10-20 9:37 ` [PATCH v3 17/17] arm64: dts: apple: t6031: " Sofus Forstreuter
2026-10-20 9:37 ` Sofus Forstreuter
2026-10-20 15:02 ` sashiko-bot [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=sashiko-outbox-179210@kernel.org \
--to=sashiko-bot@kernel.org \
--cc=conor+dt@kernel.org \
--cc=devicetree@vger.kernel.org \
--cc=media-ci@linuxtv.org \
--cc=robh@kernel.org \
--cc=sashiko-reviews@lists.linux.dev \
--cc=sofus.c@icloud.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.