* [PATCH] drm/v3d: Limit ioctl extension chain depth to prevent infinite loop
@ 2026-04-10 1:39 Ashutosh Desai
2026-04-10 18:16 ` Maíra Canal
` (2 more replies)
0 siblings, 3 replies; 5+ messages in thread
From: Ashutosh Desai @ 2026-04-10 1:39 UTC (permalink / raw)
To: dri-devel; +Cc: mcanal, itoral, stable, Ashutosh Desai
v3d_get_extensions() walks a userspace-provided singly-linked list of
ioctl extensions without any bound on the chain length. A local user
can craft a self-referential extension (ext->next == &ext) with zero
in_sync_count and out_sync_count, which bypasses the existing duplicate-
extension guard:
if (se->in_sync_count || se->out_sync_count)
return -EINVAL;
The guard never fires because v3d_get_multisync_post_deps() returns
immediately when count is zero, leaving both fields at zero on every
iteration. The result is an infinite loop in kernel context, blocking
the calling thread and pegging a CPU core indefinitely.
Both i915 (stackdepth = 512) and xe (MAX_USER_EXTENSIONS = 16) impose
an explicit depth limit on the same pattern. Apply the same defence to
V3D by capping the walk at 16 extensions.
Cc: stable@vger.kernel.org
Signed-off-by: Ashutosh Desai <ashutoshdesai993@gmail.com>
---
drivers/gpu/drm/v3d/v3d_submit.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/drivers/gpu/drm/v3d/v3d_submit.c b/drivers/gpu/drm/v3d/v3d_submit.c
index 18f2bf1fe..491eeb6b3 100644
--- a/drivers/gpu/drm/v3d/v3d_submit.c
+++ b/drivers/gpu/drm/v3d/v3d_submit.c
@@ -802,12 +802,18 @@ v3d_get_extensions(struct drm_file *file_priv,
struct v3d_file_priv *v3d_priv = file_priv->driver_priv;
struct v3d_dev *v3d = v3d_priv->v3d;
struct drm_v3d_extension __user *user_ext;
+ unsigned int ext_count = 0;
int ret;
user_ext = u64_to_user_ptr(ext_handles);
while (user_ext) {
struct drm_v3d_extension ext;
+ if (ext_count++ >= 16) {
+ drm_dbg(&v3d->drm, "Too many V3D ioctl extensions\n");
+ return -E2BIG;
+ }
+
if (copy_from_user(&ext, user_ext, sizeof(ext))) {
drm_dbg(&v3d->drm, "Failed to copy submit extension\n");
return -EFAULT;
--
2.34.1
^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [PATCH] drm/v3d: Limit ioctl extension chain depth to prevent infinite loop
2026-04-10 1:39 [PATCH] drm/v3d: Limit ioctl extension chain depth to prevent infinite loop Ashutosh Desai
@ 2026-04-10 18:16 ` Maíra Canal
2026-04-13 5:52 ` [PATCH v2] " Ashutosh Desai
2026-04-12 0:35 ` Claude review: " Claude Code Review Bot
2026-04-12 0:35 ` Claude Code Review Bot
2 siblings, 1 reply; 5+ messages in thread
From: Maíra Canal @ 2026-04-10 18:16 UTC (permalink / raw)
To: Ashutosh Desai, dri-devel; +Cc: itoral, stable
Hi Ashutosh,
On 09/04/26 22:39, Ashutosh Desai wrote:
> v3d_get_extensions() walks a userspace-provided singly-linked list of
> ioctl extensions without any bound on the chain length. A local user
> can craft a self-referential extension (ext->next == &ext) with zero
> in_sync_count and out_sync_count, which bypasses the existing duplicate-
> extension guard:
>
> if (se->in_sync_count || se->out_sync_count)
> return -EINVAL;
>
> The guard never fires because v3d_get_multisync_post_deps() returns
> immediately when count is zero, leaving both fields at zero on every
> iteration. The result is an infinite loop in kernel context, blocking
> the calling thread and pegging a CPU core indefinitely.
>
> Both i915 (stackdepth = 512) and xe (MAX_USER_EXTENSIONS = 16) impose
> an explicit depth limit on the same pattern. Apply the same defence to
> V3D by capping the walk at 16 extensions.
>
> Cc: stable@vger.kernel.org
> Signed-off-by: Ashutosh Desai <ashutoshdesai993@gmail.com>
As Jani mentioned in a previous e-mail, if this is AI-generated, please
add an AI coding assistant attribution.
That said, I believe this makes a lot of sense. Some comments below.
> ---
> drivers/gpu/drm/v3d/v3d_submit.c | 6 ++++++
> 1 file changed, 6 insertions(+)
>
> diff --git a/drivers/gpu/drm/v3d/v3d_submit.c b/drivers/gpu/drm/v3d/v3d_submit.c
> index 18f2bf1fe..491eeb6b3 100644
> --- a/drivers/gpu/drm/v3d/v3d_submit.c
> +++ b/drivers/gpu/drm/v3d/v3d_submit.c
> @@ -802,12 +802,18 @@ v3d_get_extensions(struct drm_file *file_priv,
> struct v3d_file_priv *v3d_priv = file_priv->driver_priv;
> struct v3d_dev *v3d = v3d_priv->v3d;
> struct drm_v3d_extension __user *user_ext;
> + unsigned int ext_count = 0;
> int ret;
>
> user_ext = u64_to_user_ptr(ext_handles);
> while (user_ext) {
> struct drm_v3d_extension ext;
>
> + if (ext_count++ >= 16) {
I believe we could limit it to 7, which is the number of existing V3D
extensions. Also, we could add this number as a #define, to make things
more clear.
Best regards,
- Maíra
> + drm_dbg(&v3d->drm, "Too many V3D ioctl extensions\n");
> + return -E2BIG;
> + }
> +
> if (copy_from_user(&ext, user_ext, sizeof(ext))) {
> drm_dbg(&v3d->drm, "Failed to copy submit extension\n");
> return -EFAULT;
^ permalink raw reply [flat|nested] 5+ messages in thread
* Claude review: drm/v3d: Limit ioctl extension chain depth to prevent infinite loop
2026-04-10 1:39 [PATCH] drm/v3d: Limit ioctl extension chain depth to prevent infinite loop Ashutosh Desai
2026-04-10 18:16 ` Maíra Canal
@ 2026-04-12 0:35 ` Claude Code Review Bot
2026-04-12 0:35 ` Claude Code Review Bot
2 siblings, 0 replies; 5+ messages in thread
From: Claude Code Review Bot @ 2026-04-12 0:35 UTC (permalink / raw)
To: dri-devel-reviews
Overall Series Review
Subject: drm/v3d: Limit ioctl extension chain depth to prevent infinite loop
Author: Ashutosh Desai <ashutoshdesai993@gmail.com>
Patches: 2
Reviewed: 2026-04-12T10:35:51.967853
---
This is a single-patch fix for a real denial-of-service vulnerability in the V3D DRM driver. A userspace process can craft a self-referential ioctl extension chain (where `ext->next` points back to the extension itself) that causes `v3d_get_extensions()` to loop infinitely in kernel context, permanently pegging a CPU core.
The vulnerability analysis in the commit message is correct. The existing "duplicate guard" in `v3d_get_multisync_submit_deps()` (line 391) only checks `se->in_sync_count || se->out_sync_count`, and `v3d_get_multisync_post_deps()` returns immediately at line 340 when `count` is 0 without ever setting `se->out_sync_count`. So a crafted extension with `DRM_V3D_EXT_ID_MULTI_SYNC`, zero sync counts, and `next` pointing to itself will loop forever.
The fix is sound in principle — adding a depth limit is the standard defense used by both i915 (512) and xe (16). However, there are several issues that should be addressed before merging.
---
Generated by Claude Code Patch Reviewer
^ permalink raw reply [flat|nested] 5+ messages in thread
* Claude review: drm/v3d: Limit ioctl extension chain depth to prevent infinite loop
2026-04-10 1:39 [PATCH] drm/v3d: Limit ioctl extension chain depth to prevent infinite loop Ashutosh Desai
2026-04-10 18:16 ` Maíra Canal
2026-04-12 0:35 ` Claude review: " Claude Code Review Bot
@ 2026-04-12 0:35 ` Claude Code Review Bot
2 siblings, 0 replies; 5+ messages in thread
From: Claude Code Review Bot @ 2026-04-12 0:35 UTC (permalink / raw)
To: dri-devel-reviews
Patch Review
**Positive aspects:**
- The commit message is well-written, clearly explains the vulnerability mechanism and the bypass of the existing guard, and references how other drivers handle this.
- The chosen error code `-E2BIG` is consistent with i915's approach (`i915_user_extensions.c:29`).
- The fix is simple and correct in behavior.
**Issues:**
1. **Missing `Fixes:` tag** (required for stable backport). The patch has `Cc: stable@vger.kernel.org` but no `Fixes:` tag identifying when `v3d_get_extensions()` was introduced. This is required by the stable kernel process for patches targeting stable. The tag should reference the commit that added the vulnerable function.
2. **Magic number — should use a named constant.** Both xe and i915 define named constants for their limits:
```c
// xe (xe_bo.c:3291, xe_exec_queue.c:1128, xe_oa.c:1366):
#define MAX_USER_EXTENSIONS 16
// i915 (i915_user_extensions.c:21):
unsigned int stackdepth = 512;
```
The patch uses a bare `16`:
```c
if (ext_count++ >= 16) {
```
This should be a `#define`, e.g. `#define V3D_MAX_EXTENSIONS 16`, placed near the top of the function or in the file's defines section.
3. **Consider also fixing the weak duplicate guard.** The depth limit is good defense-in-depth, but the underlying duplicate guard in `v3d_get_multisync_submit_deps()` is fundamentally broken for the zero-sync-count case. Line 409 already sets `se->flags |= DRM_V3D_EXT_ID_MULTI_SYNC`, so the duplicate check could simply test the flags:
```c
if (se->flags & DRM_V3D_EXT_ID_MULTI_SYNC) {
drm_dbg(&v3d->drm, "Two multisync extensions...");
return -EINVAL;
}
```
This would be a more robust fix at the source, and the other CPU extension types (`DRM_V3D_EXT_ID_CPU_INDIRECT_CSD`, `DRM_V3D_EXT_ID_CPU_TIMESTAMP_QUERY`, etc.) have **no** duplicate guard at all — a self-referential chain using any of those IDs would also loop, and on each iteration potentially allocate memory or do real work. The depth limit catches all cases, but fixing the guards would be a more complete solution. This could be a follow-up patch in a small series.
4. **Minor style point:** The post-increment in `ext_count++ >= 16` is correct (allows exactly 16 iterations, rejects on the 17th), but a pre-increment `++ext_count > 16` or `++ext_count > V3D_MAX_EXTENSIONS` would be slightly more readable, making it obvious that the first extension is counted as 1, not 0. This is a very minor nit.
**Verdict:** The fix addresses a real vulnerability and the approach is appropriate, but it needs at minimum a `Fixes:` tag and a named constant instead of the magic number `16`. The weak duplicate guard should ideally be fixed as well, either in this patch or as a follow-up.
---
Generated by Claude Code Patch Reviewer
^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH v2] drm/v3d: Limit ioctl extension chain depth to prevent infinite loop
2026-04-10 18:16 ` Maíra Canal
@ 2026-04-13 5:52 ` Ashutosh Desai
0 siblings, 0 replies; 5+ messages in thread
From: Ashutosh Desai @ 2026-04-13 5:52 UTC (permalink / raw)
To: dri-devel; +Cc: mcanal, itoral, stable, Ashutosh Desai
v3d_get_extensions() walks a userspace-provided singly-linked list of
ioctl extensions without any bound on the chain length. A local user
can craft a self-referential extension (ext->next == &ext) with zero
in_sync_count and out_sync_count, which bypasses the existing duplicate-
extension guard:
if (se->in_sync_count || se->out_sync_count)
return -EINVAL;
The guard never fires because v3d_get_multisync_post_deps() returns
immediately when count is zero, leaving both fields at zero on every
iteration. The result is an infinite loop in kernel context, blocking
the calling thread and pegging a CPU core indefinitely.
Both i915 (stackdepth = 512) and xe (MAX_USER_EXTENSIONS = 16) impose
an explicit depth limit on the same pattern. Apply the same defence to
V3D by introducing V3D_MAX_EXTENSIONS and capping the walk at 7, which
matches the number of currently defined V3D extension types.
Cc: stable@vger.kernel.org
Signed-off-by: Ashutosh Desai <ashutoshdesai993@gmail.com>
---
drivers/gpu/drm/v3d/v3d_submit.c | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/drivers/gpu/drm/v3d/v3d_submit.c b/drivers/gpu/drm/v3d/v3d_submit.c
index 18f2bf1fe89f..8951909198c2 100644
--- a/drivers/gpu/drm/v3d/v3d_submit.c
+++ b/drivers/gpu/drm/v3d/v3d_submit.c
@@ -11,6 +11,8 @@
#include "v3d_regs.h"
#include "v3d_trace.h"
+#define V3D_MAX_EXTENSIONS 7
+
/* Takes the reservation lock on all the BOs being referenced, so that
* we can attach fences and update the reservations after pushing the job
* to the queue.
@@ -802,12 +804,18 @@ v3d_get_extensions(struct drm_file *file_priv,
struct v3d_file_priv *v3d_priv = file_priv->driver_priv;
struct v3d_dev *v3d = v3d_priv->v3d;
struct drm_v3d_extension __user *user_ext;
+ unsigned int ext_count = 0;
int ret;
user_ext = u64_to_user_ptr(ext_handles);
while (user_ext) {
struct drm_v3d_extension ext;
+ if (ext_count++ >= V3D_MAX_EXTENSIONS) {
+ drm_dbg(&v3d->drm, "Too many V3D ioctl extensions\n");
+ return -E2BIG;
+ }
+
if (copy_from_user(&ext, user_ext, sizeof(ext))) {
drm_dbg(&v3d->drm, "Failed to copy submit extension\n");
return -EFAULT;
--
2.34.1
^ permalink raw reply related [flat|nested] 5+ messages in thread
end of thread, other threads:[~2026-04-13 5:52 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-04-10 1:39 [PATCH] drm/v3d: Limit ioctl extension chain depth to prevent infinite loop Ashutosh Desai
2026-04-10 18:16 ` Maíra Canal
2026-04-13 5:52 ` [PATCH v2] " Ashutosh Desai
2026-04-12 0:35 ` Claude review: " Claude Code Review Bot
2026-04-12 0:35 ` Claude Code Review Bot
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox