* [PATCH 0/3] drm/vc4: Fix binner overflow-memory corruption and GPU hangs
@ 2026-07-18 17:28 Maíra Canal
2026-07-18 17:28 ` [PATCH 1/3] drm/vc4: Supply the overflow slot size in BPOS, not the whole bin BO size Maíra Canal
` (2 more replies)
0 siblings, 3 replies; 6+ messages in thread
From: Maíra Canal @ 2026-07-18 17:28 UTC (permalink / raw)
To: Jose Maria Casanova Crespo, Iago Toral, Emma Anholt,
Maxime Ripard, Dave Stevenson, Raspberry Pi Kernel Maintenance
Cc: kernel-dev, dri-devel, stable, Maíra Canal
This series fixes a couple of long-standing bugs in the VC4 binner's
out-of-memory (overflow) path. The binner writes each tile's binned
command list into a per-job binner BO that is carved into fixed slots,
and spills into overflow memory whenever a tile's list outgrows its
initial tile-alloc block. Bugs in that path have been reported for years
as GPU hangs, a GPU that stays permanently wedged after the first hang,
userspace heap corruption and occasional full system crashes [1][2].
The three patches address distinct problems and can be reviewed
independently, though they were all found while chasing the same reports.
Patch 1 address an issue in vc4_overflow_mem_work(). The function points
BPOA at a 512KB slot inside the 16MB binner BO but writes the size of the
*whole* BO to BPOS, so on every binner OOM event the hardware is authorized
to DMA tile lists across other in-flight jobs' slots and, for any slot but
the first, past the end of the BO into unrelated CMA memory.
Patch 2 resets the software overflow allocator and the BPOA/BPOS
registers on GPU reset. Today a reset force-completes the RENDER job that
would have consumed the pending overflow slot, so a slot leaks on every
reset and the hardware is left pointing at stale overflow memory that the
re-queued BIN job would consume before raising a fresh OOM.
Patch 3 dynamically sizes the initial tile-alloc block up to the 256-byte
hardware maximum, picking the largest size that still fits the binner
slot for the job's tile count. This keeps more tiles' lists in their
initial block and off the continuation-block chain, which VC4 does not
walk reliably, and takes the reported EmulationStation workload from
storming resets to zero. As explained in that patch, it is a mitigation
for a hardware limitation rather than a complete fix.
[1] https://github.com/raspberrypi/linux/issues/3221
[2] https://github.com/raspberrypi/linux/issues/5780
Best regards,
- Maíra
---
Jose Maria Casanova Crespo (1):
drm/vc4: Supply the overflow slot size in BPOS, not the whole bin BO size
Maíra Canal (2):
drm/vc4: Reset the binner overflow allocator on GPU reset
drm/vc4: Dynamically size the initial tile-alloc block
drivers/gpu/drm/vc4/vc4_drv.h | 5 +++++
drivers/gpu/drm/vc4/vc4_irq.c | 14 +++++++++++++-
drivers/gpu/drm/vc4/vc4_render_cl.c | 3 ++-
drivers/gpu/drm/vc4/vc4_validate.c | 29 ++++++++++++++++++++++++++---
4 files changed, 46 insertions(+), 5 deletions(-)
---
base-commit: 7a4b7122a623e3d57fc15cf843a9d45fbd72c6ab
change-id: 20260718-vc4-bin-oom-fixes-29cf2cce2562
^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH 1/3] drm/vc4: Supply the overflow slot size in BPOS, not the whole bin BO size
2026-07-18 17:28 [PATCH 0/3] drm/vc4: Fix binner overflow-memory corruption and GPU hangs Maíra Canal
@ 2026-07-18 17:28 ` Maíra Canal
2026-07-18 17:28 ` [PATCH 2/3] drm/vc4: Reset the binner overflow allocator on GPU reset Maíra Canal
2026-07-18 17:28 ` [PATCH 3/3] drm/vc4: Dynamically size the initial tile-alloc block Maíra Canal
2 siblings, 0 replies; 6+ messages in thread
From: Maíra Canal @ 2026-07-18 17:28 UTC (permalink / raw)
To: Jose Maria Casanova Crespo, Iago Toral, Emma Anholt,
Maxime Ripard, Dave Stevenson, Raspberry Pi Kernel Maintenance
Cc: kernel-dev, dri-devel, stable, Maíra Canal
From: Jose Maria Casanova Crespo <jmcasanova@igalia.com>
vc4_overflow_mem_work() points BPOA at a 512KB slot inside the 16MB
binner BO, but writes the size of the whole BO to BPOS. On every binner
out-of-memory event the PTB is therefore authorized to write tile lists
across all the other slots (which may hold the tile state, tile alloc and
overflow memory of in-flight jobs) and, for any slot but the first, past
the end of the binner BO into unrelated CMA memory.
Since CMA pages are recycled into page cache and user allocations, this
is arbitrary memory corruption by GPU DMA. In practice it shows up as GPU
hangs with corrupted control list pointers, userspace heap corruption, a
GPU that stays permanently wedged after the first hang, and occasional
full system crashes, whenever a job overflows the initial binner slot.
The bug dates back to the conversion from a dedicated overflow BO (where
writing the full BO size was correct) to the slotted binner BO.
Fixes: 553c942f8b2c ("drm/vc4: Allow using more than 256MB of CMA memory.")
Cc: stable@vger.kernel.org
Assisted-by: Claude:claude-opus-4.8
Signed-off-by: Jose Maria Casanova Crespo <jmcasanova@igalia.com>
Reviewed-by: Maíra Canal <mcanal@igalia.com>
Signed-off-by: Maíra Canal <mcanal@igalia.com>
---
drivers/gpu/drm/vc4/vc4_irq.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/vc4/vc4_irq.c b/drivers/gpu/drm/vc4/vc4_irq.c
index 8e5141bb5075..7877d493d80e 100644
--- a/drivers/gpu/drm/vc4/vc4_irq.c
+++ b/drivers/gpu/drm/vc4/vc4_irq.c
@@ -104,7 +104,7 @@ vc4_overflow_mem_work(struct work_struct *work)
vc4->bin_alloc_overflow = BIT(bin_bo_slot);
V3D_WRITE(V3D_BPOA, bo->base.dma_addr + bin_bo_slot * vc4->bin_alloc_size);
- V3D_WRITE(V3D_BPOS, bo->base.base.size);
+ V3D_WRITE(V3D_BPOS, vc4->bin_alloc_size);
V3D_WRITE(V3D_INTCTL, V3D_INT_OUTOMEM);
V3D_WRITE(V3D_INTENA, V3D_INT_OUTOMEM);
spin_unlock_irqrestore(&vc4->job_lock, irqflags);
--
2.55.0
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH 2/3] drm/vc4: Reset the binner overflow allocator on GPU reset
2026-07-18 17:28 [PATCH 0/3] drm/vc4: Fix binner overflow-memory corruption and GPU hangs Maíra Canal
2026-07-18 17:28 ` [PATCH 1/3] drm/vc4: Supply the overflow slot size in BPOS, not the whole bin BO size Maíra Canal
@ 2026-07-18 17:28 ` Maíra Canal
2026-07-18 17:42 ` sashiko-bot
2026-07-18 17:28 ` [PATCH 3/3] drm/vc4: Dynamically size the initial tile-alloc block Maíra Canal
2 siblings, 1 reply; 6+ messages in thread
From: Maíra Canal @ 2026-07-18 17:28 UTC (permalink / raw)
To: Jose Maria Casanova Crespo, Iago Toral, Emma Anholt,
Maxime Ripard, Dave Stevenson, Raspberry Pi Kernel Maintenance
Cc: kernel-dev, dri-devel, stable, Maíra Canal
Although vc4_irq_reset() tears down the in-flight jobs, it never resets
the software binner-overflow allocator or the HW overflow registers
(BPOA/BPOS).
The current overflow slot is tracked in bin_alloc_overflow and is attached
to a job's bin_slots at the *next* out-of-memory event. On reset, the
RENDER job that would have read it is force-completed, so it is never
attached and never freed: a slot leaks on every reset.
BPOA/BPOS are also left pointing at the stale overflow slot, so the
re-queued BIN job would consume that stale pointer before raising a new
OOM interrupt.
Free the pending overflow slot, clear bin_alloc_overflow, and zero
BPOA/BPOS under job_lock, so the allocator and hardware return to a
clean state before submitting new jobs.
Fixes: 553c942f8b2c ("drm/vc4: Allow using more than 256MB of CMA memory.")
Cc: stable@vger.kernel.org
Signed-off-by: Maíra Canal <mcanal@igalia.com>
---
drivers/gpu/drm/vc4/vc4_irq.c | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/drivers/gpu/drm/vc4/vc4_irq.c b/drivers/gpu/drm/vc4/vc4_irq.c
index 7877d493d80e..9fac1b39e8b9 100644
--- a/drivers/gpu/drm/vc4/vc4_irq.c
+++ b/drivers/gpu/drm/vc4/vc4_irq.c
@@ -344,6 +344,18 @@ void vc4_irq_reset(struct drm_device *dev)
V3D_WRITE(V3D_INTENA, V3D_DRIVER_IRQS);
spin_lock_irqsave(&vc4->job_lock, irqflags);
+
+ /*
+ * The reset wiped the binner's hardware state, and the job that may
+ * have been reading overflow memory is torn down just below. Free the
+ * current overflow slot and clear the overflow registers so the
+ * re-queued BIN job restarts from a clean OOM state.
+ */
+ vc4->bin_alloc_used &= ~vc4->bin_alloc_overflow;
+ vc4->bin_alloc_overflow = 0;
+ V3D_WRITE(V3D_BPOA, 0);
+ V3D_WRITE(V3D_BPOS, 0);
+
vc4_cancel_bin_job(dev);
vc4_irq_finish_render_job(dev);
spin_unlock_irqrestore(&vc4->job_lock, irqflags);
--
2.55.0
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH 3/3] drm/vc4: Dynamically size the initial tile-alloc block
2026-07-18 17:28 [PATCH 0/3] drm/vc4: Fix binner overflow-memory corruption and GPU hangs Maíra Canal
2026-07-18 17:28 ` [PATCH 1/3] drm/vc4: Supply the overflow slot size in BPOS, not the whole bin BO size Maíra Canal
2026-07-18 17:28 ` [PATCH 2/3] drm/vc4: Reset the binner overflow allocator on GPU reset Maíra Canal
@ 2026-07-18 17:28 ` Maíra Canal
2026-07-18 17:44 ` sashiko-bot
2 siblings, 1 reply; 6+ messages in thread
From: Maíra Canal @ 2026-07-18 17:28 UTC (permalink / raw)
To: Jose Maria Casanova Crespo, Iago Toral, Emma Anholt,
Maxime Ripard, Dave Stevenson, Raspberry Pi Kernel Maintenance
Cc: kernel-dev, dri-devel, stable, Maíra Canal
The binner writes each tile's binned command list into an initial
tile-allocation block and, when that list outgrows the block, continues
it into a chain of continuation blocks. On VC4 the hardware does not link
that chain reliably: the render thread that later walks it desyncs -- it
has been seen to fetch an invalid opcode partway through a block (CT1CS
reports CTERR) or to follow the chain into never-written memory and stall
-- and hangcheck then resets the GPU.
The chain is only walked once a tile spills its initial block, so the
problem scales with how small that block is. The continuation-block size
is not the lever: the hang reproduces with both 32- and 128-byte
continuation blocks. Enlarging the *initial* block is what helps, as it
keeps more tiles' lists in that block and off the chain entirely, and 256
bytes is the hardware maximum.
A fixed 256-byte block cannot be used unconditionally, though. The
tile_count initial blocks are laid out contiguously right after the tile
state and must fit within the binner slot, and the render thread reaches
each tile's list by a fixed per-tile stride. If the blocks did not fit,
the later ones would land at a non-contiguous address and that stride
would point at the wrong memory. So pick the largest initial block (256,
128, 64 or 32 bytes) that still fits the slot for the job's tile count,
and program the RCL branch stride to match.
This is a mitigation for a hardware limitation, not a complete fix: a
single tile whose list exceeds even a 256-byte block, or a scene dense
enough to force a smaller initial block, can still reach the chain and
hang. But the case users have reported in EmulationStation's 1080p
transitions between consoles, which previously stormed "Resetting GPU",
now runs with zero resets.
Link: https://github.com/raspberrypi/linux/issues/3221
Link: https://github.com/raspberrypi/linux/issues/5780
Fixes: d5b1a78a772f ("drm/vc4: Add support for drawing 3D frames.")
Cc: stable@vger.kernel.org
Assisted-by: Claude:claude-opus-4.8
Signed-off-by: Maíra Canal <mcanal@igalia.com>
---
drivers/gpu/drm/vc4/vc4_drv.h | 5 +++++
drivers/gpu/drm/vc4/vc4_render_cl.c | 3 ++-
drivers/gpu/drm/vc4/vc4_validate.c | 29 ++++++++++++++++++++++++++---
3 files changed, 33 insertions(+), 4 deletions(-)
diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h
index 0f5958c1e6b6..854204b096b6 100644
--- a/drivers/gpu/drm/vc4/vc4_drv.h
+++ b/drivers/gpu/drm/vc4/vc4_drv.h
@@ -743,6 +743,11 @@ struct vc4_exec_info {
* (where each tile's binned CL will start)
*/
uint32_t tile_alloc_offset;
+ /* Stride between adjacent tiles' initial alloc blocks. Equals the
+ * initial block size programmed in the binning config, and is used
+ * as the per-tile stride when emitting the RCL branches.
+ */
+ u32 tile_alloc_stride;
/* Bitmask of which binner slots are freed when this job completes. */
uint32_t bin_slots;
diff --git a/drivers/gpu/drm/vc4/vc4_render_cl.c b/drivers/gpu/drm/vc4/vc4_render_cl.c
index c264d21bc3fe..be150bad676f 100644
--- a/drivers/gpu/drm/vc4/vc4_render_cl.c
+++ b/drivers/gpu/drm/vc4/vc4_render_cl.c
@@ -184,7 +184,8 @@ static void emit_tile(struct vc4_exec_info *exec,
if (has_bin) {
rcl_u8(setup, VC4_PACKET_BRANCH_TO_SUB_LIST);
rcl_u32(setup, (exec->tile_alloc_offset +
- (y * exec->bin_tiles_x + x) * 32));
+ (y * exec->bin_tiles_x + x) *
+ exec->tile_alloc_stride));
}
if (setup->msaa_color_write) {
diff --git a/drivers/gpu/drm/vc4/vc4_validate.c b/drivers/gpu/drm/vc4/vc4_validate.c
index 7f2fadfde7a8..3961cf38fc2a 100644
--- a/drivers/gpu/drm/vc4/vc4_validate.c
+++ b/drivers/gpu/drm/vc4/vc4_validate.c
@@ -357,8 +357,9 @@ validate_tile_binning_config(VALIDATE_ARGS)
struct drm_device *dev = exec->exec_bo->base.dev;
struct vc4_dev *vc4 = to_vc4_dev(dev);
uint8_t flags;
- uint32_t tile_state_size;
+ u32 tile_state_size, tile_state_aligned;
uint32_t tile_count, bin_addr;
+ u8 init_block;
int bin_slot;
if (exec->found_tile_binning_mode_config_packet) {
@@ -406,13 +407,35 @@ validate_tile_binning_config(VALIDATE_ARGS)
tile_state_size = 48 * tile_count;
/* Since the tile alloc array will follow us, align. */
- exec->tile_alloc_offset = bin_addr + roundup(tile_state_size, 4096);
+ tile_state_aligned = roundup(tile_state_size, 4096);
+ exec->tile_alloc_offset = bin_addr + tile_state_aligned;
+
+ /*
+ * Pick the largest initial tile-alloc block that still fits the slot.
+ * Larger initial blocks keep more tiles' binned lists off the
+ * continuation-block chain, which the binner does not always link
+ * reliably. Denser tile counts fall back to smaller blocks, down to
+ * the 32-byte minimum which always fits.
+ */
+ if (tile_state_aligned + 256 * tile_count <= vc4->bin_alloc_size) {
+ exec->tile_alloc_stride = 256;
+ init_block = VC4_BIN_CONFIG_ALLOC_INIT_BLOCK_SIZE_256;
+ } else if (tile_state_aligned + 128 * tile_count <= vc4->bin_alloc_size) {
+ exec->tile_alloc_stride = 128;
+ init_block = VC4_BIN_CONFIG_ALLOC_INIT_BLOCK_SIZE_128;
+ } else if (tile_state_aligned + 64 * tile_count <= vc4->bin_alloc_size) {
+ exec->tile_alloc_stride = 64;
+ init_block = VC4_BIN_CONFIG_ALLOC_INIT_BLOCK_SIZE_64;
+ } else {
+ exec->tile_alloc_stride = 32;
+ init_block = VC4_BIN_CONFIG_ALLOC_INIT_BLOCK_SIZE_32;
+ }
*(uint8_t *)(validated + 14) =
((flags & ~(VC4_BIN_CONFIG_ALLOC_INIT_BLOCK_SIZE_MASK |
VC4_BIN_CONFIG_ALLOC_BLOCK_SIZE_MASK)) |
VC4_BIN_CONFIG_AUTO_INIT_TSDA |
- VC4_SET_FIELD(VC4_BIN_CONFIG_ALLOC_INIT_BLOCK_SIZE_32,
+ VC4_SET_FIELD(init_block,
VC4_BIN_CONFIG_ALLOC_INIT_BLOCK_SIZE) |
VC4_SET_FIELD(VC4_BIN_CONFIG_ALLOC_BLOCK_SIZE_128,
VC4_BIN_CONFIG_ALLOC_BLOCK_SIZE));
--
2.55.0
^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [PATCH 2/3] drm/vc4: Reset the binner overflow allocator on GPU reset
2026-07-18 17:28 ` [PATCH 2/3] drm/vc4: Reset the binner overflow allocator on GPU reset Maíra Canal
@ 2026-07-18 17:42 ` sashiko-bot
0 siblings, 0 replies; 6+ messages in thread
From: sashiko-bot @ 2026-07-18 17:42 UTC (permalink / raw)
To: Maíra Canal; +Cc: dri-devel
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [High] Blindly freeing `vc4->bin_alloc_overflow` during GPU reset causes a Use-After-Free for queued render jobs that still depend on the binner overflow memory.
--
--- Patch [2]: [PATCH 2/3] drm/vc4: Reset the binner overflow allocator on GPU reset ---
commit 74342beb01de4148c8046f07cd05468691648692
Author: Maíra Canal <mcanal@igalia.com>
drm/vc4: Reset the binner overflow allocator on GPU reset
This commit resets the binner overflow allocator during a GPU reset to
prevent leaking overflow slots. It frees the pending overflow slot and
clears the hardware overflow registers so the re-queued bin job starts
from a clean state.
> diff --git a/drivers/gpu/drm/vc4/vc4_irq.c b/drivers/gpu/drm/vc4/vc4_irq.c
> index 7877d493d80e6..9fac1b39e8b98 100644
> --- a/drivers/gpu/drm/vc4/vc4_irq.c
> +++ b/drivers/gpu/drm/vc4/vc4_irq.c
[ ... ]
> @@ -344,6 +344,18 @@ void vc4_irq_reset(struct drm_device *dev)
> V3D_WRITE(V3D_INTENA, V3D_DRIVER_IRQS);
>
> spin_lock_irqsave(&vc4->job_lock, irqflags);
> +
> + /*
> + * The reset wiped the binner's hardware state, and the job that may
> + * have been reading overflow memory is torn down just below. Free the
> + * current overflow slot and clear the overflow registers so the
> + * re-queued BIN job restarts from a clean OOM state.
> + */
> + vc4->bin_alloc_used &= ~vc4->bin_alloc_overflow;
> + vc4->bin_alloc_overflow = 0;
[Severity: High]
Does clearing the overflow slot here create a use-after-free for render jobs
that have already completed binning and are waiting in the render queue?
If we have the following sequence:
1. Job A is executing on the render thread.
2. Job B finishes binning, using an overflow slot (tracked in
vc4->bin_alloc_overflow), and is placed in the render queue.
3. Job C starts binning, hangs, and triggers a GPU reset.
When vc4_irq_reset() runs, it frees the overflow slot used by Job B. Then
vc4_irq_finish_render_job() completes the active render job (Job A) and
submits Job B to the hardware.
Since Job B's overflow memory was just freed, could a subsequent binning job
encounter an out-of-memory condition, allocate this exact same slot, and
overwrite it while Job B is actively reading from it?
> + V3D_WRITE(V3D_BPOA, 0);
> + V3D_WRITE(V3D_BPOS, 0);
> +
> vc4_cancel_bin_job(dev);
> vc4_irq_finish_render_job(dev);
> spin_unlock_irqrestore(&vc4->job_lock, irqflags);
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260718-vc4-bin-oom-fixes-v1-0-8cba09558c33@igalia.com?part=2
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH 3/3] drm/vc4: Dynamically size the initial tile-alloc block
2026-07-18 17:28 ` [PATCH 3/3] drm/vc4: Dynamically size the initial tile-alloc block Maíra Canal
@ 2026-07-18 17:44 ` sashiko-bot
0 siblings, 0 replies; 6+ messages in thread
From: sashiko-bot @ 2026-07-18 17:44 UTC (permalink / raw)
To: Maíra Canal; +Cc: dri-devel
Thank you for your contribution! Sashiko AI review found 3 potential issue(s) to consider:
Pre-existing issues:
- [Critical] Missing bounds check on user-controlled `bin_tiles_x` and `bin_tiles_y` causes an integer underflow when calculating the `tile alloc size`, leading to massive out-of-bounds writes in GPU memory.
- [Critical] Off-by-one validation check on `max_x_tile` allows out-of-bounds tile rendering, leading to an out-of-bounds physical offset computation.
- [High] Unconditional dereference of `vc4->bin_bo` allows local attackers to trigger a NULL pointer dereference by bypassing the BO allocation.
--
--- Patch [3]: [PATCH 3/3] drm/vc4: Dynamically size the initial tile-alloc block ---
commit 70ba8b264b3becc24aff870ad390492995036867
Author: Maíra Canal <mcanal@igalia.com>
drm/vc4: Dynamically size the initial tile-alloc block
This patch dynamically adjusts the initial tile-allocation block size to fix
hardware hangs caused by unreliable continuation-block chain linking. It
calculates the largest block size that fits within the binner slot for the
job's tile count, and programs the RCL branch stride to match.
Link: https://github.com/raspberrypi/linux/issues/3221
Link: https://github.com/raspberrypi/linux/issues/5780
> diff --git a/drivers/gpu/drm/vc4/vc4_render_cl.c b/drivers/gpu/drm/vc4/vc4_render_cl.c
> index c264d21bc3fe3..be150bad676f6 100644
> --- a/drivers/gpu/drm/vc4/vc4_render_cl.c
> +++ b/drivers/gpu/drm/vc4/vc4_render_cl.c
> @@ -184,7 +184,8 @@ static void emit_tile(struct vc4_exec_info *exec,
> if (has_bin) {
> rcl_u8(setup, VC4_PACKET_BRANCH_TO_SUB_LIST);
> rcl_u32(setup, (exec->tile_alloc_offset +
> - (y * exec->bin_tiles_x + x) * 32));
> + (y * exec->bin_tiles_x + x) *
> + exec->tile_alloc_stride));
[Severity: Critical]
This is a pre-existing issue, but can this out-of-bounds computation occur
here?
If a user specifies args->max_x_tile equal to exec->bin_tiles_x in the render
job ioctl, the check (args->max_x_tile > exec->bin_tiles_x) in vc4_get_rcl()
will pass since it uses > instead of >= for bounds checking.
Would this cause the driver to iterate an extra tile and emit a branch
instruction pointing to an out-of-bounds tile index in the initial tile-alloc
block array, bypassing the command stream validation sandbox?
> diff --git a/drivers/gpu/drm/vc4/vc4_validate.c b/drivers/gpu/drm/vc4/vc4_validate.c
> index 7f2fadfde7a8e..3961cf38fc2a5 100644
> --- a/drivers/gpu/drm/vc4/vc4_validate.c
> +++ b/drivers/gpu/drm/vc4/vc4_validate.c
[ ... ]
> @@ -406,13 +407,35 @@ validate_tile_binning_config(VALIDATE_ARGS)
> tile_state_size = 48 * tile_count;
>
> /* Since the tile alloc array will follow us, align. */
> - exec->tile_alloc_offset = bin_addr + roundup(tile_state_size, 4096);
> + tile_state_aligned = roundup(tile_state_size, 4096);
> + exec->tile_alloc_offset = bin_addr + tile_state_aligned;
[Severity: Critical]
This isn't a bug introduced by this patch, but does the lack of bounds
validation on user-controlled bin_tiles_x and bin_tiles_y cause an integer
underflow later when calculating the tile alloc size?
If bin_tiles_x and bin_tiles_y are set to 255, tile_state_aligned evaluates
to ~3.1MB, which is greater than vc4->bin_alloc_size (512KB). The computation
of (vc4->bin_alloc_size - exec->tile_alloc_offset) would then underflow,
writing a massive positive size to the validated command packet. This could
allow the GPU's binner to overwrite arbitrary physical memory out of bounds.
[Severity: High]
This isn't a bug introduced by this patch, but could the unconditional
dereference of vc4->bin_bo in validate_tile_binning_config() trigger a NULL
pointer dereference?
If an attacker allocates a dumb buffer and submits a command list containing
VC4_PACKET_TILE_BINNING_MODE_CONFIG, vc4_v3d_bin_bo_get() isn't called yet,
and the validator might blindly access vc4->bin_bo->base.dma_addr before
it is guaranteed to be allocated.
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260718-vc4-bin-oom-fixes-v1-0-8cba09558c33@igalia.com?part=3
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2026-07-18 17:44 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-18 17:28 [PATCH 0/3] drm/vc4: Fix binner overflow-memory corruption and GPU hangs Maíra Canal
2026-07-18 17:28 ` [PATCH 1/3] drm/vc4: Supply the overflow slot size in BPOS, not the whole bin BO size Maíra Canal
2026-07-18 17:28 ` [PATCH 2/3] drm/vc4: Reset the binner overflow allocator on GPU reset Maíra Canal
2026-07-18 17:42 ` sashiko-bot
2026-07-18 17:28 ` [PATCH 3/3] drm/vc4: Dynamically size the initial tile-alloc block Maíra Canal
2026-07-18 17:44 ` sashiko-bot
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.