* [PATCH 1/2] drm/nouveau: bound sync and op counts in EXEC and VM_BIND
@ 2026-08-08 11:14 ` Junrui Luo
0 siblings, 0 replies; 14+ messages in thread
From: Junrui Luo @ 2026-08-08 11:14 UTC (permalink / raw)
To: Lyude Paul, Danilo Krummrich, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, David Airlie, Simona Vetter, Dave Airlie
Cc: dri-devel, nouveau, linux-kernel, Junrui Luo, Yuhao Jiang, stable
nouveau_exec_ucopy() and nouveau_uvmm_vm_bind_ucopy() pass user-supplied
u32 counts to u_memcpya(). DRM_IOCTL_NOUVEAU_EXEC bounds only
req->push_count against push_max, leaving req->wait_count and
req->sig_count unchecked; DRM_IOCTL_NOUVEAU_VM_BIND bounds none of
op_count, wait_count or sig_count. u_memcpya() itself only rejects
multiplication overflow, which on 64-bit never triggers for a u32 count
times a small element size.
A wait_count of 0xffffffff therefore becomes a 64 GB vmemdup_user()
request. Since vmemdup_user() allocates with GFP_USER and hence without
__GFP_NOWARN, a size above INT_MAX trips the WARN_ON_ONCE() in
__kvmalloc_node_noprof(); below that the kernel attempts an up to 2 GB
vmalloc that GFP_USER also leaves uncharged to the caller's memcg. Both
ioctls are DRM_RENDER_ALLOW, so any client holding a render node can
issue this.
Reject the oversized counts at the ioctl entry points, the way
nouveau_gem_ioctl_pushbuf() and the existing push_count check already
do, so that the client is told which limit it exceeded. Sync objects get
NOUVEAU_MAX_SYNCS, matching both NOUVEAU_GEM_MAX_BUFFERS and the value
xe settled on for the same field in DRM_XE_MAX_SYNCS. VM_BIND operations
have no comparable semantic limit, so NOUVEAU_VM_BIND_MAX_OPS is set
well above any batch size a client is expected to submit; it exists only
to keep the copy-in allocation finite.
Fixes: b88baab82871 ("drm/nouveau: implement new VM_BIND uAPI")
Reported-by: Yuhao Jiang <danisjiang@gmail.com>
Assisted-by: Claude:claude-opus-5
Cc: stable@vger.kernel.org
Signed-off-by: Junrui Luo <moonafterrain@outlook.com>
---
drivers/gpu/drm/nouveau/nouveau_exec.c | 12 ++++++++++++
drivers/gpu/drm/nouveau/nouveau_uvmm.c | 18 ++++++++++++++++++
include/uapi/drm/nouveau_drm.h | 18 ++++++++++++++++++
3 files changed, 48 insertions(+)
diff --git a/drivers/gpu/drm/nouveau/nouveau_exec.c b/drivers/gpu/drm/nouveau/nouveau_exec.c
index a08ab1cfea9b..7bdccbae53b1 100644
--- a/drivers/gpu/drm/nouveau/nouveau_exec.c
+++ b/drivers/gpu/drm/nouveau/nouveau_exec.c
@@ -389,6 +389,18 @@ nouveau_exec_ioctl_exec(struct drm_device *dev,
return nouveau_abi16_put(abi16, -EINVAL);
}
+ if (unlikely(req->wait_count > NOUVEAU_MAX_SYNCS)) {
+ NV_PRINTK(err, cli, "exec wait count exceeds limit: %d max %d\n",
+ req->wait_count, NOUVEAU_MAX_SYNCS);
+ return nouveau_abi16_put(abi16, -EINVAL);
+ }
+
+ if (unlikely(req->sig_count > NOUVEAU_MAX_SYNCS)) {
+ NV_PRINTK(err, cli, "exec sig count exceeds limit: %d max %d\n",
+ req->sig_count, NOUVEAU_MAX_SYNCS);
+ return nouveau_abi16_put(abi16, -EINVAL);
+ }
+
ret = nouveau_exec_ucopy(&args, req);
if (ret)
goto out;
diff --git a/drivers/gpu/drm/nouveau/nouveau_uvmm.c b/drivers/gpu/drm/nouveau/nouveau_uvmm.c
index f5e4756b4de4..bced1481674e 100644
--- a/drivers/gpu/drm/nouveau/nouveau_uvmm.c
+++ b/drivers/gpu/drm/nouveau/nouveau_uvmm.c
@@ -1807,6 +1807,24 @@ nouveau_uvmm_ioctl_vm_bind(struct drm_device *dev,
if (unlikely(!nouveau_cli_uvmm_locked(cli)))
return -ENOSYS;
+ if (unlikely(req->op_count > NOUVEAU_VM_BIND_MAX_OPS)) {
+ NV_PRINTK(err, cli, "vm_bind op count exceeds limit: %d max %d\n",
+ req->op_count, NOUVEAU_VM_BIND_MAX_OPS);
+ return -EINVAL;
+ }
+
+ if (unlikely(req->wait_count > NOUVEAU_MAX_SYNCS)) {
+ NV_PRINTK(err, cli, "vm_bind wait count exceeds limit: %d max %d\n",
+ req->wait_count, NOUVEAU_MAX_SYNCS);
+ return -EINVAL;
+ }
+
+ if (unlikely(req->sig_count > NOUVEAU_MAX_SYNCS)) {
+ NV_PRINTK(err, cli, "vm_bind sig count exceeds limit: %d max %d\n",
+ req->sig_count, NOUVEAU_MAX_SYNCS);
+ return -EINVAL;
+ }
+
ret = nouveau_uvmm_vm_bind_ucopy(&args, req);
if (ret)
return ret;
diff --git a/include/uapi/drm/nouveau_drm.h b/include/uapi/drm/nouveau_drm.h
index 1fa82fa6af38..35ddf97ca873 100644
--- a/include/uapi/drm/nouveau_drm.h
+++ b/include/uapi/drm/nouveau_drm.h
@@ -220,6 +220,14 @@ struct drm_nouveau_gem_cpu_fini {
__u32 handle;
};
+/*
+ * NOUVEAU_MAX_SYNCS - maximum number of sync objects per ioctl
+ *
+ * The maximum value EXEC and VM_BIND accept in their wait_count and
+ * sig_count fields.
+ */
+#define NOUVEAU_MAX_SYNCS 1024
+
/**
* struct drm_nouveau_sync - sync object
*
@@ -332,6 +340,16 @@ struct drm_nouveau_vm_bind_op {
__u64 range;
};
+/*
+ * NOUVEAU_VM_BIND_MAX_OPS - maximum number of &drm_nouveau_vm_bind_ops
+ *
+ * The maximum value VM_BIND accepts in its op_count field. There is no
+ * semantic limit on the number of operations a bind may carry; this bound
+ * exists only to keep the copy-in allocation finite and is far above any
+ * batch size a client is expected to submit.
+ */
+#define NOUVEAU_VM_BIND_MAX_OPS 65536
+
/**
* struct drm_nouveau_vm_bind - structure for DRM_IOCTL_NOUVEAU_VM_BIND
*/
--
2.51.2
^ permalink raw reply related [flat|nested] 14+ messages in thread* Re: [PATCH 1/2] drm/nouveau: bound sync and op counts in EXEC and VM_BIND
2026-08-08 11:14 ` Junrui Luo
(?)
@ 2026-08-08 11:27 ` sashiko-bot
-1 siblings, 0 replies; 14+ messages in thread
From: sashiko-bot @ 2026-08-08 11:27 UTC (permalink / raw)
To: Junrui Luo; +Cc: dri-devel
Thank you for your contribution! Sashiko AI review found 3 potential issue(s) to consider:
- [Medium] Un-rate-limited error logging creates a potential log-spam DoS vector.
- [Medium] Validation of flag-gated syscall parameters outside their flag scope.
- [Low] Format string specifier mismatch in error logging for __u32 counts.
--
--- Patch [1]: [PATCH 1/2] drm/nouveau: bound sync and op counts in EXEC and VM_BIND ---
commit 6d0adda3ff0dd4a0e4440dc92362fcb0ad993d9a
Author: Junrui Luo <moonafterrain@outlook.com>
Subject: drm/nouveau: bound sync and op counts in EXEC and VM_BIND
This commit introduces upper bounds for sync and op counts in the EXEC and
VM_BIND ioctls. By restricting the size of these counts, it prevents potential
excessive memory allocations that could trigger warnings or exhaust memory.
> diff --git a/drivers/gpu/drm/nouveau/nouveau_exec.c b/drivers/gpu/drm/nouveau/nouveau_exec.c
> index a08ab1cfea9be..7bdccbae53b1d 100644
> --- a/drivers/gpu/drm/nouveau/nouveau_exec.c
> +++ b/drivers/gpu/drm/nouveau/nouveau_exec.c
> @@ -389,6 +389,18 @@ nouveau_exec_ioctl_exec(struct drm_device *dev,
> return nouveau_abi16_put(abi16, -EINVAL);
> }
>
> + if (unlikely(req->wait_count > NOUVEAU_MAX_SYNCS)) {
> + NV_PRINTK(err, cli, "exec wait count exceeds limit: %d max %d\n",
> + req->wait_count, NOUVEAU_MAX_SYNCS);
[Severity: Low]
Are the format string specifiers correct here? The req->wait_count field is
a __u32 type, so using %d will print large values as negative numbers.
[Severity: Medium]
Could this un-rate-limited NV_PRINTK log be intentionally triggered by
userspace to spam the kernel log buffer and hide other messages?
> + return nouveau_abi16_put(abi16, -EINVAL);
> + }
> +
> + if (unlikely(req->sig_count > NOUVEAU_MAX_SYNCS)) {
> + NV_PRINTK(err, cli, "exec sig count exceeds limit: %d max %d\n",
> + req->sig_count, NOUVEAU_MAX_SYNCS);
> + return nouveau_abi16_put(abi16, -EINVAL);
> + }
> +
> ret = nouveau_exec_ucopy(&args, req);
[ ... ]
> diff --git a/drivers/gpu/drm/nouveau/nouveau_uvmm.c b/drivers/gpu/drm/nouveau/nouveau_uvmm.c
> index f5e4756b4de4a..bced1481674e7 100644
> --- a/drivers/gpu/drm/nouveau/nouveau_uvmm.c
> +++ b/drivers/gpu/drm/nouveau/nouveau_uvmm.c
> @@ -1807,6 +1807,24 @@ nouveau_uvmm_ioctl_vm_bind(struct drm_device *dev,
> if (unlikely(!nouveau_cli_uvmm_locked(cli)))
> return -ENOSYS;
>
> + if (unlikely(req->op_count > NOUVEAU_VM_BIND_MAX_OPS)) {
> + NV_PRINTK(err, cli, "vm_bind op count exceeds limit: %d max %d\n",
> + req->op_count, NOUVEAU_VM_BIND_MAX_OPS);
> + return -EINVAL;
> + }
> +
> + if (unlikely(req->wait_count > NOUVEAU_MAX_SYNCS)) {
[Severity: Medium]
According to the userspace API documentation, sync objects are only accepted
when DRM_NOUVEAU_VM_BIND_RUN_ASYNC is set in req->flags. If a user submits a
VM_BIND ioctl without this flag, might wait_count and sig_count contain
uninitialized garbage from userspace stack slots?
If so, is it safe to validate these flag-gated parameters outside the scope
of their flag check, rather than explicitly ignoring or rejecting them when
the flag is absent?
> + NV_PRINTK(err, cli, "vm_bind wait count exceeds limit: %d max %d\n",
> + req->wait_count, NOUVEAU_MAX_SYNCS);
> + return -EINVAL;
> + }
> +
> + if (unlikely(req->sig_count > NOUVEAU_MAX_SYNCS)) {
> + NV_PRINTK(err, cli, "vm_bind sig count exceeds limit: %d max %d\n",
> + req->sig_count, NOUVEAU_MAX_SYNCS);
> + return -EINVAL;
> + }
> +
> ret = nouveau_uvmm_vm_bind_ucopy(&args, req);
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260808-nouveau-fixes-v1-0-c3ebdc17a89c@outlook.com?part=1
^ permalink raw reply [flat|nested] 14+ messages in thread* Re: [PATCH 1/2] drm/nouveau: bound sync and op counts in EXEC and VM_BIND
2026-08-08 11:14 ` Junrui Luo
@ 2026-08-09 22:43 ` David Airlie
-1 siblings, 0 replies; 14+ messages in thread
From: David Airlie @ 2026-08-09 22:43 UTC (permalink / raw)
To: moonafterrain
Cc: Danilo Krummrich, Maarten Lankhorst, Maxime Ripard, Simona Vetter,
dri-devel, nouveau, linux-kernel, Yuhao Jiang, stable
> From: Junrui Luo <moonafterrain@outlook.com>
>
> nouveau_exec_ucopy() and nouveau_uvmm_vm_bind_ucopy() pass user-supplied
> u32 counts to u_memcpya(). DRM_IOCTL_NOUVEAU_EXEC bounds only
> req->push_count against push_max, leaving req->wait_count and
> req->sig_count unchecked; DRM_IOCTL_NOUVEAU_VM_BIND bounds none of
> op_count, wait_count or sig_count. u_memcpya() itself only rejects
> multiplication overflow, which on 64-bit never triggers for a u32 count
> times a small element size.
>
> A wait_count of 0xffffffff therefore becomes a 64 GB vmemdup_user()
> request. Since vmemdup_user() allocates with GFP_USER and hence without
> __GFP_NOWARN, a size above INT_MAX trips the WARN_ON_ONCE() in
> __kvmalloc_node_noprof(); below that the kernel attempts an up to 2 GB
> vmalloc that GFP_USER also leaves uncharged to the caller's memcg. Both
> ioctls are DRM_RENDER_ALLOW, so any client holding a render node can
> issue this.
>
> Reject the oversized counts at the ioctl entry points, the way
> nouveau_gem_ioctl_pushbuf() and the existing push_count check already
> do, so that the client is told which limit it exceeded. Sync objects get
> NOUVEAU_MAX_SYNCS, matching both NOUVEAU_GEM_MAX_BUFFERS and the value
> xe settled on for the same field in DRM_XE_MAX_SYNCS. VM_BIND operations
> have no comparable semantic limit, so NOUVEAU_VM_BIND_MAX_OPS is set
> well above any batch size a client is expected to submit; it exists only
> to keep the copy-in allocation finite.
>
> Fixes: b88baab82871 ("drm/nouveau: implement new VM_BIND uAPI")
> Reported-by: Yuhao Jiang <danisjiang@gmail.com>
> Assisted-by: Claude:claude-opus-5
> Cc: stable@vger.kernel.org
> Signed-off-by: Junrui Luo <moonafterrain@outlook.com>
Have you run a complete Vulkan CTS with NVK across this with no regressions?
I'm weary of those limits being too low, but I think the only app that
might push them beyond CTS would be Forza Horizon 5 or 6.
Dave.
> ---
> drivers/gpu/drm/nouveau/nouveau_exec.c | 12 ++++++++++++
> drivers/gpu/drm/nouveau/nouveau_uvmm.c | 18 ++++++++++++++++++
> include/uapi/drm/nouveau_drm.h | 18 ++++++++++++++++++
> 3 files changed, 48 insertions(+)
>
> diff --git a/drivers/gpu/drm/nouveau/nouveau_exec.c b/drivers/gpu/drm/nouveau/nouveau_exec.c
> index a08ab1cfea9b..7bdccbae53b1 100644
> --- a/drivers/gpu/drm/nouveau/nouveau_exec.c
> +++ b/drivers/gpu/drm/nouveau/nouveau_exec.c
> @@ -389,6 +389,18 @@ nouveau_exec_ioctl_exec(struct drm_device *dev,
> return nouveau_abi16_put(abi16, -EINVAL);
> }
>
> + if (unlikely(req->wait_count > NOUVEAU_MAX_SYNCS)) {
> + NV_PRINTK(err, cli, "exec wait count exceeds limit: %d max %d\n",
> + req->wait_count, NOUVEAU_MAX_SYNCS);
> + return nouveau_abi16_put(abi16, -EINVAL);
> + }
> +
> + if (unlikely(req->sig_count > NOUVEAU_MAX_SYNCS)) {
> + NV_PRINTK(err, cli, "exec sig count exceeds limit: %d max %d\n",
> + req->sig_count, NOUVEAU_MAX_SYNCS);
> + return nouveau_abi16_put(abi16, -EINVAL);
> + }
> +
> ret = nouveau_exec_ucopy(&args, req);
> if (ret)
> goto out;
> diff --git a/drivers/gpu/drm/nouveau/nouveau_uvmm.c b/drivers/gpu/drm/nouveau/nouveau_uvmm.c
> index f5e4756b4de4..bced1481674e 100644
> --- a/drivers/gpu/drm/nouveau/nouveau_uvmm.c
> +++ b/drivers/gpu/drm/nouveau/nouveau_uvmm.c
> @@ -1807,6 +1807,24 @@ nouveau_uvmm_ioctl_vm_bind(struct drm_device *dev,
> if (unlikely(!nouveau_cli_uvmm_locked(cli)))
> return -ENOSYS;
>
> + if (unlikely(req->op_count > NOUVEAU_VM_BIND_MAX_OPS)) {
> + NV_PRINTK(err, cli, "vm_bind op count exceeds limit: %d max %d\n",
> + req->op_count, NOUVEAU_VM_BIND_MAX_OPS);
> + return -EINVAL;
> + }
> +
> + if (unlikely(req->wait_count > NOUVEAU_MAX_SYNCS)) {
> + NV_PRINTK(err, cli, "vm_bind wait count exceeds limit: %d max %d\n",
> + req->wait_count, NOUVEAU_MAX_SYNCS);
> + return -EINVAL;
> + }
> +
> + if (unlikely(req->sig_count > NOUVEAU_MAX_SYNCS)) {
> + NV_PRINTK(err, cli, "vm_bind sig count exceeds limit: %d max %d\n",
> + req->sig_count, NOUVEAU_MAX_SYNCS);
> + return -EINVAL;
> + }
> +
> ret = nouveau_uvmm_vm_bind_ucopy(&args, req);
> if (ret)
> return ret;
> diff --git a/include/uapi/drm/nouveau_drm.h b/include/uapi/drm/nouveau_drm.h
> index 1fa82fa6af38..35ddf97ca873 100644
> --- a/include/uapi/drm/nouveau_drm.h
> +++ b/include/uapi/drm/nouveau_drm.h
> @@ -220,6 +220,14 @@ struct drm_nouveau_gem_cpu_fini {
> __u32 handle;
> };
>
> +/*
> + * NOUVEAU_MAX_SYNCS - maximum number of sync objects per ioctl
> + *
> + * The maximum value EXEC and VM_BIND accept in their wait_count and
> + * sig_count fields.
> + */
> +#define NOUVEAU_MAX_SYNCS 1024
> +
> /**
> * struct drm_nouveau_sync - sync object
> *
> @@ -332,6 +340,16 @@ struct drm_nouveau_vm_bind_op {
> __u64 range;
> };
>
> +/*
> + * NOUVEAU_VM_BIND_MAX_OPS - maximum number of &drm_nouveau_vm_bind_ops
> + *
> + * The maximum value VM_BIND accepts in its op_count field. There is no
> + * semantic limit on the number of operations a bind may carry; this bound
> + * exists only to keep the copy-in allocation finite and is far above any
> + * batch size a client is expected to submit.
> + */
> +#define NOUVEAU_VM_BIND_MAX_OPS 65536
> +
> /**
> * struct drm_nouveau_vm_bind - structure for DRM_IOCTL_NOUVEAU_VM_BIND
> */
>
> --
> 2.51.2
>
>
^ permalink raw reply [flat|nested] 14+ messages in thread* Re: [PATCH 1/2] drm/nouveau: bound sync and op counts in EXEC and VM_BIND
@ 2026-08-09 22:43 ` David Airlie
0 siblings, 0 replies; 14+ messages in thread
From: David Airlie @ 2026-08-09 22:43 UTC (permalink / raw)
To: moonafterrain
Cc: Lyude Paul, Danilo Krummrich, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, David Airlie, Simona Vetter, dri-devel,
nouveau, linux-kernel, Yuhao Jiang, stable
> From: Junrui Luo <moonafterrain@outlook.com>
>
> nouveau_exec_ucopy() and nouveau_uvmm_vm_bind_ucopy() pass user-supplied
> u32 counts to u_memcpya(). DRM_IOCTL_NOUVEAU_EXEC bounds only
> req->push_count against push_max, leaving req->wait_count and
> req->sig_count unchecked; DRM_IOCTL_NOUVEAU_VM_BIND bounds none of
> op_count, wait_count or sig_count. u_memcpya() itself only rejects
> multiplication overflow, which on 64-bit never triggers for a u32 count
> times a small element size.
>
> A wait_count of 0xffffffff therefore becomes a 64 GB vmemdup_user()
> request. Since vmemdup_user() allocates with GFP_USER and hence without
> __GFP_NOWARN, a size above INT_MAX trips the WARN_ON_ONCE() in
> __kvmalloc_node_noprof(); below that the kernel attempts an up to 2 GB
> vmalloc that GFP_USER also leaves uncharged to the caller's memcg. Both
> ioctls are DRM_RENDER_ALLOW, so any client holding a render node can
> issue this.
>
> Reject the oversized counts at the ioctl entry points, the way
> nouveau_gem_ioctl_pushbuf() and the existing push_count check already
> do, so that the client is told which limit it exceeded. Sync objects get
> NOUVEAU_MAX_SYNCS, matching both NOUVEAU_GEM_MAX_BUFFERS and the value
> xe settled on for the same field in DRM_XE_MAX_SYNCS. VM_BIND operations
> have no comparable semantic limit, so NOUVEAU_VM_BIND_MAX_OPS is set
> well above any batch size a client is expected to submit; it exists only
> to keep the copy-in allocation finite.
>
> Fixes: b88baab82871 ("drm/nouveau: implement new VM_BIND uAPI")
> Reported-by: Yuhao Jiang <danisjiang@gmail.com>
> Assisted-by: Claude:claude-opus-5
> Cc: stable@vger.kernel.org
> Signed-off-by: Junrui Luo <moonafterrain@outlook.com>
Have you run a complete Vulkan CTS with NVK across this with no regressions?
I'm weary of those limits being too low, but I think the only app that
might push them beyond CTS would be Forza Horizon 5 or 6.
Dave.
> ---
> drivers/gpu/drm/nouveau/nouveau_exec.c | 12 ++++++++++++
> drivers/gpu/drm/nouveau/nouveau_uvmm.c | 18 ++++++++++++++++++
> include/uapi/drm/nouveau_drm.h | 18 ++++++++++++++++++
> 3 files changed, 48 insertions(+)
>
> diff --git a/drivers/gpu/drm/nouveau/nouveau_exec.c b/drivers/gpu/drm/nouveau/nouveau_exec.c
> index a08ab1cfea9b..7bdccbae53b1 100644
> --- a/drivers/gpu/drm/nouveau/nouveau_exec.c
> +++ b/drivers/gpu/drm/nouveau/nouveau_exec.c
> @@ -389,6 +389,18 @@ nouveau_exec_ioctl_exec(struct drm_device *dev,
> return nouveau_abi16_put(abi16, -EINVAL);
> }
>
> + if (unlikely(req->wait_count > NOUVEAU_MAX_SYNCS)) {
> + NV_PRINTK(err, cli, "exec wait count exceeds limit: %d max %d\n",
> + req->wait_count, NOUVEAU_MAX_SYNCS);
> + return nouveau_abi16_put(abi16, -EINVAL);
> + }
> +
> + if (unlikely(req->sig_count > NOUVEAU_MAX_SYNCS)) {
> + NV_PRINTK(err, cli, "exec sig count exceeds limit: %d max %d\n",
> + req->sig_count, NOUVEAU_MAX_SYNCS);
> + return nouveau_abi16_put(abi16, -EINVAL);
> + }
> +
> ret = nouveau_exec_ucopy(&args, req);
> if (ret)
> goto out;
> diff --git a/drivers/gpu/drm/nouveau/nouveau_uvmm.c b/drivers/gpu/drm/nouveau/nouveau_uvmm.c
> index f5e4756b4de4..bced1481674e 100644
> --- a/drivers/gpu/drm/nouveau/nouveau_uvmm.c
> +++ b/drivers/gpu/drm/nouveau/nouveau_uvmm.c
> @@ -1807,6 +1807,24 @@ nouveau_uvmm_ioctl_vm_bind(struct drm_device *dev,
> if (unlikely(!nouveau_cli_uvmm_locked(cli)))
> return -ENOSYS;
>
> + if (unlikely(req->op_count > NOUVEAU_VM_BIND_MAX_OPS)) {
> + NV_PRINTK(err, cli, "vm_bind op count exceeds limit: %d max %d\n",
> + req->op_count, NOUVEAU_VM_BIND_MAX_OPS);
> + return -EINVAL;
> + }
> +
> + if (unlikely(req->wait_count > NOUVEAU_MAX_SYNCS)) {
> + NV_PRINTK(err, cli, "vm_bind wait count exceeds limit: %d max %d\n",
> + req->wait_count, NOUVEAU_MAX_SYNCS);
> + return -EINVAL;
> + }
> +
> + if (unlikely(req->sig_count > NOUVEAU_MAX_SYNCS)) {
> + NV_PRINTK(err, cli, "vm_bind sig count exceeds limit: %d max %d\n",
> + req->sig_count, NOUVEAU_MAX_SYNCS);
> + return -EINVAL;
> + }
> +
> ret = nouveau_uvmm_vm_bind_ucopy(&args, req);
> if (ret)
> return ret;
> diff --git a/include/uapi/drm/nouveau_drm.h b/include/uapi/drm/nouveau_drm.h
> index 1fa82fa6af38..35ddf97ca873 100644
> --- a/include/uapi/drm/nouveau_drm.h
> +++ b/include/uapi/drm/nouveau_drm.h
> @@ -220,6 +220,14 @@ struct drm_nouveau_gem_cpu_fini {
> __u32 handle;
> };
>
> +/*
> + * NOUVEAU_MAX_SYNCS - maximum number of sync objects per ioctl
> + *
> + * The maximum value EXEC and VM_BIND accept in their wait_count and
> + * sig_count fields.
> + */
> +#define NOUVEAU_MAX_SYNCS 1024
> +
> /**
> * struct drm_nouveau_sync - sync object
> *
> @@ -332,6 +340,16 @@ struct drm_nouveau_vm_bind_op {
> __u64 range;
> };
>
> +/*
> + * NOUVEAU_VM_BIND_MAX_OPS - maximum number of &drm_nouveau_vm_bind_ops
> + *
> + * The maximum value VM_BIND accepts in its op_count field. There is no
> + * semantic limit on the number of operations a bind may carry; this bound
> + * exists only to keep the copy-in allocation finite and is far above any
> + * batch size a client is expected to submit.
> + */
> +#define NOUVEAU_VM_BIND_MAX_OPS 65536
> +
> /**
> * struct drm_nouveau_vm_bind - structure for DRM_IOCTL_NOUVEAU_VM_BIND
> */
>
> --
> 2.51.2
>
>
^ permalink raw reply [flat|nested] 14+ messages in thread* Re: [PATCH 1/2] drm/nouveau: bound sync and op counts in EXEC and VM_BIND
2026-08-09 22:43 ` David Airlie
@ 2026-08-11 4:00 ` Junrui Luo
-1 siblings, 0 replies; 14+ messages in thread
From: Junrui Luo @ 2026-08-11 4:00 UTC (permalink / raw)
To: David Airlie
Cc: Lyude Paul, Danilo Krummrich, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, David Airlie, Simona Vetter,
dri-devel@lists.freedesktop.org, nouveau@lists.freedesktop.org,
linux-kernel@vger.kernel.org, Yuhao Jiang, stable@vger.kernel.org
On Mon, Aug 10, 2026 at 08:43:50AM +1000, David Airlie wrote:
> Have you run a complete Vulkan CTS with NVK across this with no regressions?
>
> I'm weary of those limits being too low, but I think the only app that
> might push them beyond CTS would be Forza Horizon 5 or 6.
No, I have not. I don't currently have the hardware to run NVK, so I can't
offer a CTS run or any other regression test for this.
Is there a better guard that avoids a hard limit here, or does this need
a test before it can go in?
Thanks,
Junrui Luo
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH 1/2] drm/nouveau: bound sync and op counts in EXEC and VM_BIND
@ 2026-08-11 4:00 ` Junrui Luo
0 siblings, 0 replies; 14+ messages in thread
From: Junrui Luo @ 2026-08-11 4:00 UTC (permalink / raw)
To: David Airlie
Cc: Danilo Krummrich, Maarten Lankhorst, Maxime Ripard, Simona Vetter,
dri-devel@lists.freedesktop.org, nouveau@lists.freedesktop.org,
linux-kernel@vger.kernel.org, Yuhao Jiang, stable@vger.kernel.org
On Mon, Aug 10, 2026 at 08:43:50AM +1000, David Airlie wrote:
> Have you run a complete Vulkan CTS with NVK across this with no regressions?
>
> I'm weary of those limits being too low, but I think the only app that
> might push them beyond CTS would be Forza Horizon 5 or 6.
No, I have not. I don't currently have the hardware to run NVK, so I can't
offer a CTS run or any other regression test for this.
Is there a better guard that avoids a hard limit here, or does this need
a test before it can go in?
Thanks,
Junrui Luo
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH 1/2] drm/nouveau: bound sync and op counts in EXEC and VM_BIND
2026-08-11 4:00 ` Junrui Luo
@ 2026-08-11 4:05 ` Dave Airlie
-1 siblings, 0 replies; 14+ messages in thread
From: Dave Airlie @ 2026-08-11 4:05 UTC (permalink / raw)
To: Junrui Luo
Cc: David Airlie, Lyude Paul, Danilo Krummrich, Maarten Lankhorst,
Maxime Ripard, Thomas Zimmermann, Simona Vetter,
dri-devel@lists.freedesktop.org, nouveau@lists.freedesktop.org,
linux-kernel@vger.kernel.org, Yuhao Jiang, stable@vger.kernel.org
On Tue, 11 Aug 2026 at 14:00, Junrui Luo <moonafterrain@outlook.com> wrote:
>
> On Mon, Aug 10, 2026 at 08:43:50AM +1000, David Airlie wrote:
> > Have you run a complete Vulkan CTS with NVK across this with no regressions?
> >
> > I'm weary of those limits being too low, but I think the only app that
> > might push them beyond CTS would be Forza Horizon 5 or 6.
>
> No, I have not. I don't currently have the hardware to run NVK, so I can't
> offer a CTS run or any other regression test for this.
>
> Is there a better guard that avoids a hard limit here, or does this need
> a test before it can go in?
Looking at xe it also has 1024 limit on number of syncs, but it
doesn't have any limit on number of binds,
*bind_ops = kvmalloc_objs(struct drm_xe_vm_bind_op,
args->num_binds,
GFP_KERNEL | __GFP_ACCOUNT |
__GFP_RETRY_MAYFAIL | __GFP_NOWARN);
Maybe nouveau could do the same.
Dave.
>
> Thanks,
> Junrui Luo
^ permalink raw reply [flat|nested] 14+ messages in thread* Re: [PATCH 1/2] drm/nouveau: bound sync and op counts in EXEC and VM_BIND
@ 2026-08-11 4:05 ` Dave Airlie
0 siblings, 0 replies; 14+ messages in thread
From: Dave Airlie @ 2026-08-11 4:05 UTC (permalink / raw)
To: Junrui Luo
Cc: David Airlie, Danilo Krummrich, Maarten Lankhorst, Maxime Ripard,
Simona Vetter, dri-devel@lists.freedesktop.org,
nouveau@lists.freedesktop.org, linux-kernel@vger.kernel.org,
Yuhao Jiang, stable@vger.kernel.org
On Tue, 11 Aug 2026 at 14:00, Junrui Luo <moonafterrain@outlook.com> wrote:
>
> On Mon, Aug 10, 2026 at 08:43:50AM +1000, David Airlie wrote:
> > Have you run a complete Vulkan CTS with NVK across this with no regressions?
> >
> > I'm weary of those limits being too low, but I think the only app that
> > might push them beyond CTS would be Forza Horizon 5 or 6.
>
> No, I have not. I don't currently have the hardware to run NVK, so I can't
> offer a CTS run or any other regression test for this.
>
> Is there a better guard that avoids a hard limit here, or does this need
> a test before it can go in?
Looking at xe it also has 1024 limit on number of syncs, but it
doesn't have any limit on number of binds,
*bind_ops = kvmalloc_objs(struct drm_xe_vm_bind_op,
args->num_binds,
GFP_KERNEL | __GFP_ACCOUNT |
__GFP_RETRY_MAYFAIL | __GFP_NOWARN);
Maybe nouveau could do the same.
Dave.
>
> Thanks,
> Junrui Luo
^ permalink raw reply [flat|nested] 14+ messages in thread