mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH] drm/syncobj: Silence allocation warnings for user-sized arrays
@ 2026-11-03  8:50 Yu, Fei
  2026-11-03  9:46 ` Christian König
  0 siblings, 1 reply; 2+ messages in thread
From: Yu, Fei @ 2026-11-03  8:50 UTC (permalink / raw)
  To: dri-devel
  Cc: Christian König, Maarten Lankhorst, Maxime Ripard,
	Thomas Zimmermann, David Airlie, Simona Vetter, linux-kernel,
	syzbot+95416f957d84e858b377, Madhur Kumar, Fei Yu

From: Fei Yu <fei.yu@intel.com>

The syncobj wait, timeline wait and timeline signal ioctls allocate
several temporary arrays whose size is taken directly from the u32
count_handles provided by userspace:

 - handles and syncobjs in drm_syncobj_array_find()
 - points and entries in drm_syncobj_array_wait_timeout()
 - points and chains in drm_syncobj_timeline_signal_ioctl()

A large enough count makes these allocations exceed KMALLOC_MAX_SIZE
and trips the WARN_ON_ONCE_GFP() in ___kmalloc_large_node():

  WARNING: mm/slub.c:5459 at ___kmalloc_large_node+0x10c/0x170 mm/slub.c:5459
  Call Trace:
   __kmalloc_large_node_noprof+0x18/0x90 mm/slub.c:5502
   __do_kmalloc_node mm/slub.c:5519 [inline]
   __kmalloc_noprof+0x3f6/0x710 mm/slub.c:5556
   _kmalloc_noprof include/linux/slab.h:995 [inline]
   _kmalloc_array_noprof include/linux/slab.h:1211 [inline]
   drm_syncobj_array_find+0x3a/0x440 drivers/gpu/drm/drm_syncobj.c:1241
   drm_syncobj_timeline_wait_ioctl+0x18a/0x640 drivers/gpu/drm/drm_syncobj.c:1356
   drm_ioctl_kernel+0x2df/0x3b0 drivers/gpu/drm/drm_ioctl.c:817
   drm_ioctl+0x70e/0xba0 drivers/gpu/drm/drm_ioctl.c:914

The allocation failure itself is already handled by returning -ENOMEM,
so the only problem is a warning that userspace can trigger at will.

Pass __GFP_NOWARN to all allocations whose size is derived from
count_handles. Guarding only drm_syncobj_array_find() is not enough:
the wait entries are much larger than a handle, so a count that passes
drm_syncobj_array_find() can still trigger the same warning in
drm_syncobj_array_wait_timeout().

No functional change and no new limit on the uAPI.

Fixes: 3e6fb72d6cef ("drm/syncobj: Add a syncobj_array_find helper")
Reported-by: syzbot+95416f957d84e858b377@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=95416f957d84e858b377
Signed-off-by: Fei Yu <fei.yu@intel.com>
---
Testing: on v7.4-rc1 (x86_64, KASAN) the syzbot C reproducer triggers the
___kmalloc_large_node() warning with the same size (0x100000920); with
this patch it runs clean. DRM KUnit: 667/667 passed.

Notes:
 - An earlier attempt [1] added a size check returning -ERANGE, but only
   for the handles array, so the syncobjs array and the much larger wait
   entries could still warn, and it changed the ioctl's error codes.
   This version keeps the existing -ENOMEM behaviour for all six
   allocations.
 - kvmalloc() was not used on purpose: it would let userspace trigger
   multi-GB vmalloc() attempts. A hard upper limit on count_handles
   would be a uAPI change; happy to do that instead if preferred.

[1] https://lore.kernel.org/all/20251227160830.34291-1-madhurkumar004@gmail.com/

 drivers/gpu/drm/drm_syncobj.c | 16 ++++++++++------
 1 file changed, 10 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/drm_syncobj.c b/drivers/gpu/drm/drm_syncobj.c
index f1d4da168..10aede1c0 100644
--- a/drivers/gpu/drm/drm_syncobj.c
+++ b/drivers/gpu/drm/drm_syncobj.c
@@ -1051,7 +1051,8 @@ static signed long drm_syncobj_array_wait_timeout(struct drm_syncobj **syncobjs,
 		lockdep_assert_none_held_once();
 	}
 
-	points = kmalloc_array(count, sizeof(*points), GFP_KERNEL);
+	points = kmalloc_array(count, sizeof(*points),
+			       GFP_KERNEL | __GFP_NOWARN);
 	if (points == NULL)
 		return -ENOMEM;
 
@@ -1064,7 +1065,7 @@ static signed long drm_syncobj_array_wait_timeout(struct drm_syncobj **syncobjs,
 		goto err_free_points;
 	}
 
-	entries = kzalloc_objs(*entries, count);
+	entries = kzalloc_objs(*entries, count, GFP_KERNEL | __GFP_NOWARN);
 	if (!entries) {
 		timeout = -ENOMEM;
 		goto err_free_points;
@@ -1238,7 +1239,8 @@ static int drm_syncobj_array_find(struct drm_file *file_private,
 	struct drm_syncobj **syncobjs;
 	int ret;
 
-	handles = kmalloc_array(count_handles, sizeof(*handles), GFP_KERNEL);
+	handles = kmalloc_array(count_handles, sizeof(*handles),
+				GFP_KERNEL | __GFP_NOWARN);
 	if (handles == NULL)
 		return -ENOMEM;
 
@@ -1248,7 +1250,8 @@ static int drm_syncobj_array_find(struct drm_file *file_private,
 		goto err_free_handles;
 	}
 
-	syncobjs = kmalloc_objs(*syncobjs, count_handles);
+	syncobjs = kmalloc_objs(*syncobjs, count_handles,
+				GFP_KERNEL | __GFP_NOWARN);
 	if (syncobjs == NULL) {
 		ret = -ENOMEM;
 		goto err_free_handles;
@@ -1573,7 +1576,7 @@ drm_syncobj_timeline_signal_ioctl(struct drm_device *dev, void *data,
 		return ret;
 
 	points = kmalloc_array(args->count_handles, sizeof(*points),
-			       GFP_KERNEL);
+			       GFP_KERNEL | __GFP_NOWARN);
 	if (!points) {
 		ret = -ENOMEM;
 		goto out;
@@ -1586,7 +1589,8 @@ drm_syncobj_timeline_signal_ioctl(struct drm_device *dev, void *data,
 		goto err_points;
 	}
 
-	chains = kmalloc_objs(*chains, args->count_handles);
+	chains = kmalloc_objs(*chains, args->count_handles,
+			      GFP_KERNEL | __GFP_NOWARN);
 	if (!chains) {
 		ret = -ENOMEM;
 		goto err_points;

base-commit: 6628e7d4c6b25c8d18f1345e3a20d21829aae7e4
-- 
2.43.0


^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: [PATCH] drm/syncobj: Silence allocation warnings for user-sized arrays
  2026-11-03  8:50 [PATCH] drm/syncobj: Silence allocation warnings for user-sized arrays Yu, Fei
@ 2026-11-03  9:46 ` Christian König
  0 siblings, 0 replies; 2+ messages in thread
From: Christian König @ 2026-11-03  9:46 UTC (permalink / raw)
  To: Yu, Fei, dri-devel
  Cc: Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann,
	David Airlie, Simona Vetter, linux-kernel,
	syzbot+95416f957d84e858b377, Madhur Kumar

On 11/3/26 09:50, Yu, Fei wrote:
> From: Fei Yu <fei.yu@intel.com>
> 
> The syncobj wait, timeline wait and timeline signal ioctls allocate
> several temporary arrays whose size is taken directly from the u32
> count_handles provided by userspace:
> 
>  - handles and syncobjs in drm_syncobj_array_find()
>  - points and entries in drm_syncobj_array_wait_timeout()
>  - points and chains in drm_syncobj_timeline_signal_ioctl()
> 
> A large enough count makes these allocations exceed KMALLOC_MAX_SIZE
> and trips the WARN_ON_ONCE_GFP() in ___kmalloc_large_node():
> 
>   WARNING: mm/slub.c:5459 at ___kmalloc_large_node+0x10c/0x170 mm/slub.c:5459
>   Call Trace:
>    __kmalloc_large_node_noprof+0x18/0x90 mm/slub.c:5502
>    __do_kmalloc_node mm/slub.c:5519 [inline]
>    __kmalloc_noprof+0x3f6/0x710 mm/slub.c:5556
>    _kmalloc_noprof include/linux/slab.h:995 [inline]
>    _kmalloc_array_noprof include/linux/slab.h:1211 [inline]
>    drm_syncobj_array_find+0x3a/0x440 drivers/gpu/drm/drm_syncobj.c:1241
>    drm_syncobj_timeline_wait_ioctl+0x18a/0x640 drivers/gpu/drm/drm_syncobj.c:1356
>    drm_ioctl_kernel+0x2df/0x3b0 drivers/gpu/drm/drm_ioctl.c:817
>    drm_ioctl+0x70e/0xba0 drivers/gpu/drm/drm_ioctl.c:914
> 
> The allocation failure itself is already handled by returning -ENOMEM,
> so the only problem is a warning that userspace can trigger at will.
> 
> Pass __GFP_NOWARN to all allocations whose size is derived from
> count_handles.

That is clearly not a good idea. __GFP_NOWARN should only be used when the allocation is optional and that is really not the case here.

> Guarding only drm_syncobj_array_find() is not enough:
> the wait entries are much larger than a handle, so a count that passes
> drm_syncobj_array_find() can still trigger the same warning in
> drm_syncobj_array_wait_timeout().
> 
> No functional change and no new limit on the uAPI.
> 
> Fixes: 3e6fb72d6cef ("drm/syncobj: Add a syncobj_array_find helper")
> Reported-by: syzbot+95416f957d84e858b377@syzkaller.appspotmail.com
> Closes: https://syzkaller.appspot.com/bug?extid=95416f957d84e858b377
> Signed-off-by: Fei Yu <fei.yu@intel.com>
> ---
> Testing: on v7.4-rc1 (x86_64, KASAN) the syzbot C reproducer triggers the
> ___kmalloc_large_node() warning with the same size (0x100000920); with
> this patch it runs clean. DRM KUnit: 667/667 passed.
> 
> Notes:
>  - An earlier attempt [1] added a size check returning -ERANGE, but only
>    for the handles array, so the syncobjs array and the much larger wait
>    entries could still warn, and it changed the ioctl's error codes.
>    This version keeps the existing -ENOMEM behaviour for all six
>    allocations.
>  - kvmalloc() was not used on purpose: it would let userspace trigger
>    multi-GB vmalloc() attempts. A hard upper limit on count_handles
>    would be a uAPI change; happy to do that instead if preferred.

Yeah that is most likely what we need to do here.

A "reasonable limit" needs to be applied to the number of handles given when that is exceeded -EINVAL returned.

The problem here is to find that "reasonable limit" since this function needs to scale from the tiny embedded device to the largest HPC cluster on the planet.

Considering that using kvmalloc() is probably justified.

Regards,
Christian.

> 
> [1] https://lore.kernel.org/all/20251227160830.34291-1-madhurkumar004@gmail.com/
> 
>  drivers/gpu/drm/drm_syncobj.c | 16 ++++++++++------
>  1 file changed, 10 insertions(+), 6 deletions(-)
> 
> diff --git a/drivers/gpu/drm/drm_syncobj.c b/drivers/gpu/drm/drm_syncobj.c
> index f1d4da168..10aede1c0 100644
> --- a/drivers/gpu/drm/drm_syncobj.c
> +++ b/drivers/gpu/drm/drm_syncobj.c
> @@ -1051,7 +1051,8 @@ static signed long drm_syncobj_array_wait_timeout(struct drm_syncobj **syncobjs,
>                 lockdep_assert_none_held_once();
>         }
> 
> -       points = kmalloc_array(count, sizeof(*points), GFP_KERNEL);
> +       points = kmalloc_array(count, sizeof(*points),
> +                              GFP_KERNEL | __GFP_NOWARN);
>         if (points == NULL)
>                 return -ENOMEM;
> 
> @@ -1064,7 +1065,7 @@ static signed long drm_syncobj_array_wait_timeout(struct drm_syncobj **syncobjs,
>                 goto err_free_points;
>         }
> 
> -       entries = kzalloc_objs(*entries, count);
> +       entries = kzalloc_objs(*entries, count, GFP_KERNEL | __GFP_NOWARN);
>         if (!entries) {
>                 timeout = -ENOMEM;
>                 goto err_free_points;
> @@ -1238,7 +1239,8 @@ static int drm_syncobj_array_find(struct drm_file *file_private,
>         struct drm_syncobj **syncobjs;
>         int ret;
> 
> -       handles = kmalloc_array(count_handles, sizeof(*handles), GFP_KERNEL);
> +       handles = kmalloc_array(count_handles, sizeof(*handles),
> +                               GFP_KERNEL | __GFP_NOWARN);
>         if (handles == NULL)
>                 return -ENOMEM;
> 
> @@ -1248,7 +1250,8 @@ static int drm_syncobj_array_find(struct drm_file *file_private,
>                 goto err_free_handles;
>         }
> 
> -       syncobjs = kmalloc_objs(*syncobjs, count_handles);
> +       syncobjs = kmalloc_objs(*syncobjs, count_handles,
> +                               GFP_KERNEL | __GFP_NOWARN);
>         if (syncobjs == NULL) {
>                 ret = -ENOMEM;
>                 goto err_free_handles;
> @@ -1573,7 +1576,7 @@ drm_syncobj_timeline_signal_ioctl(struct drm_device *dev, void *data,
>                 return ret;
> 
>         points = kmalloc_array(args->count_handles, sizeof(*points),
> -                              GFP_KERNEL);
> +                              GFP_KERNEL | __GFP_NOWARN);
>         if (!points) {
>                 ret = -ENOMEM;
>                 goto out;
> @@ -1586,7 +1589,8 @@ drm_syncobj_timeline_signal_ioctl(struct drm_device *dev, void *data,
>                 goto err_points;
>         }
> 
> -       chains = kmalloc_objs(*chains, args->count_handles);
> +       chains = kmalloc_objs(*chains, args->count_handles,
> +                             GFP_KERNEL | __GFP_NOWARN);
>         if (!chains) {
>                 ret = -ENOMEM;
>                 goto err_points;
> 
> base-commit: 6628e7d4c6b25c8d18f1345e3a20d21829aae7e4
> --
> 2.43.0
> 


^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2026-11-03  9:47 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-11-03  8:50 [PATCH] drm/syncobj: Silence allocation warnings for user-sized arrays Yu, Fei
2026-11-03  9:46 ` Christian König

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®