* Forwarded: [PATCH] drm/syncobj: Silence allocation warnings for user-sized arrays
2023-09-06 11:42 [syzbot] [dri?] WARNING in drm_syncobj_array_find syzbot
@ 2026-11-03 8:23 ` syzbot
2026-11-04 2:31 ` Forwarded: [PATCH v2] drm/syncobj: Limit the number of handles and use kvmalloc " syzbot
2026-11-04 2:37 ` syzbot
2 siblings, 0 replies; 4+ messages in thread
From: syzbot @ 2026-11-03 8:23 UTC (permalink / raw)
To: linux-kernel, syzkaller-bugs
For archival purposes, forwarding an incoming command email to
linux-kernel@vger.kernel.org, syzkaller-bugs@googlegroups.com.
***
Subject: [PATCH] drm/syncobj: Silence allocation warnings for user-sized arrays
Author: fei.yu@intel.com
From: Fei Yu <fei.yu@intel.com>
#syz test: git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git master
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] 4+ messages in thread* Forwarded: [PATCH v2] drm/syncobj: Limit the number of handles and use kvmalloc for user-sized arrays
2023-09-06 11:42 [syzbot] [dri?] WARNING in drm_syncobj_array_find syzbot
2026-11-03 8:23 ` Forwarded: [PATCH] drm/syncobj: Silence allocation warnings for user-sized arrays syzbot
@ 2026-11-04 2:31 ` syzbot
2026-11-04 2:37 ` syzbot
2 siblings, 0 replies; 4+ messages in thread
From: syzbot @ 2026-11-04 2:31 UTC (permalink / raw)
To: linux-kernel, syzkaller-bugs
For archival purposes, forwarding an incoming command email to
linux-kernel@vger.kernel.org, syzkaller-bugs@googlegroups.com.
***
Subject: [PATCH v2] drm/syncobj: Limit the number of handles and use kvmalloc for user-sized arrays
Author: fei.yu@intel.com
From: Fei Yu <fei.yu@intel.com>
#syz test: git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git master
The syncobj 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()
These are kmalloc() allocations, so a count above KMALLOC_MAX_SIZE /
element size 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 wait entries are 64 bytes each on 64-bit, so with a 4 MiB
KMALLOC_MAX_SIZE a wait on more than about 64K handles already fails
today, with a warning.
Fix this in two parts:
- Reject more than DRM_SYNCOBJ_MAX_HANDLES handles with -EINVAL in
drm_syncobj_array_find(), which every ioctl taking a handle array goes
through. The limit is derived from the largest per-handle allocation
(the wait entries) and the INT_MAX size limit of kvmalloc(), so none
of the allocations above can exceed it. That is about 33M handles on
64-bit.
- Switch the six allocations to kvmalloc(), so that large but valid
handle counts no longer depend on physically contiguous memory.
Using kvmalloc() alone is not enough: the reproducer asks for more than
INT_MAX bytes, which hits the WARN_ON_ONCE() in __kvmalloc_node_noprof()
instead.
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
Suggested-by: Christian König <christian.koenig@amd.com>
Signed-off-by: Fei Yu <fei.yu@intel.com>
---
v2:
- Drop __GFP_NOWARN (Christian).
- Add DRM_SYNCOBJ_MAX_HANDLES, return -EINVAL above it, and switch all six
arrays to kvmalloc() (Christian).
- v1: https://lore.kernel.org/all/20261103085002.3100723-1-fei.yu@intel.com/
About the limit: INT_MAX / sizeof(struct syncobj_wait_entry) is about 33M
handles on 64-bit. It is the largest count for which every allocation stays
below the kvmalloc() INT_MAX size limit, so it does not add a new policy
number. Today the real limit is much lower: a wait on more than ~64K
handles already fails with -ENOMEM (plus the warning), because the wait
entries are a kmalloc() allocation larger than 4 MiB. If you prefer a lower,
fixed limit (e.g. SZ_1M) or GFP_KERNEL_ACCOUNT for these arrays, I can
change it.
Testing on v7.4-rc1 (x86_64, KASAN, virtio-gpu in QEMU):
- syzbot C reproducer: base warns in ___kmalloc_large_node() (size
0x100000920), patched is clean, ioctl returns -EINVAL.
- wait / timeline_wait / timeline_signal / reset / signal on 200000
signaled syncobjs: base fails wait and timeline_wait with -ENOMEM and
the same warning; patched all succeed.
- count == DRM_SYNCOBJ_MAX_HANDLES gets past the check (-EFAULT from the
short user buffer), count == DRM_SYNCOBJ_MAX_HANDLES + 1 returns -EINVAL
for wait, reset and timeline_signal.
- kmemleak clean, checkpatch --strict clean, W=1 clean,
DRM KUnit 667/667 passed.
- IGT syncobj_basic, syncobj_wait, syncobj_timeline on virtio-gpu:
202/202 subtests pass, same as base.
drivers/gpu/drm/drm_syncobj.c | 40 ++++++++++++++++++++++-------------
1 file changed, 25 insertions(+), 15 deletions(-)
diff --git a/drivers/gpu/drm/drm_syncobj.c b/drivers/gpu/drm/drm_syncobj.c
index f1d4da1685457..c01cf164a4f9e 100644
--- a/drivers/gpu/drm/drm_syncobj.c
+++ b/drivers/gpu/drm/drm_syncobj.c
@@ -220,6 +220,13 @@ struct syncobj_wait_entry {
u64 point;
};
+/*
+ * Upper limit for the number of handles passed to a single ioctl. The
+ * largest per-handle allocation is the wait entry array, keep it below the
+ * INT_MAX size limit of kvmalloc().
+ */
+#define DRM_SYNCOBJ_MAX_HANDLES (INT_MAX / sizeof(struct syncobj_wait_entry))
+
static void syncobj_wait_syncobj_func(struct drm_syncobj *syncobj,
struct syncobj_wait_entry *wait);
@@ -1051,7 +1058,7 @@ 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 = kvmalloc_array(count, sizeof(*points), GFP_KERNEL);
if (points == NULL)
return -ENOMEM;
@@ -1064,7 +1071,7 @@ static signed long drm_syncobj_array_wait_timeout(struct drm_syncobj **syncobjs,
goto err_free_points;
}
- entries = kzalloc_objs(*entries, count);
+ entries = kvzalloc_objs(*entries, count);
if (!entries) {
timeout = -ENOMEM;
goto err_free_points;
@@ -1185,10 +1192,10 @@ static signed long drm_syncobj_array_wait_timeout(struct drm_syncobj **syncobjs,
&entries[i].fence_cb);
dma_fence_put(entries[i].fence);
}
- kfree(entries);
+ kvfree(entries);
err_free_points:
- kfree(points);
+ kvfree(points);
return timeout;
}
@@ -1238,7 +1245,10 @@ 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);
+ if (count_handles > DRM_SYNCOBJ_MAX_HANDLES)
+ return -EINVAL;
+
+ handles = kvmalloc_array(count_handles, sizeof(*handles), GFP_KERNEL);
if (handles == NULL)
return -ENOMEM;
@@ -1248,7 +1258,7 @@ static int drm_syncobj_array_find(struct drm_file *file_private,
goto err_free_handles;
}
- syncobjs = kmalloc_objs(*syncobjs, count_handles);
+ syncobjs = kvmalloc_objs(*syncobjs, count_handles);
if (syncobjs == NULL) {
ret = -ENOMEM;
goto err_free_handles;
@@ -1262,16 +1272,16 @@ static int drm_syncobj_array_find(struct drm_file *file_private,
}
}
- kfree(handles);
+ kvfree(handles);
*syncobjs_out = syncobjs;
return 0;
err_put_syncobjs:
while (i-- > 0)
drm_syncobj_put(syncobjs[i]);
- kfree(syncobjs);
+ kvfree(syncobjs);
err_free_handles:
- kfree(handles);
+ kvfree(handles);
return ret;
}
@@ -1283,7 +1293,7 @@ static void drm_syncobj_array_free(struct drm_syncobj **syncobjs,
for (i = 0; i < count; i++)
drm_syncobj_put(syncobjs[i]);
- kfree(syncobjs);
+ kvfree(syncobjs);
}
int
@@ -1572,8 +1582,8 @@ drm_syncobj_timeline_signal_ioctl(struct drm_device *dev, void *data,
if (ret < 0)
return ret;
- points = kmalloc_array(args->count_handles, sizeof(*points),
- GFP_KERNEL);
+ points = kvmalloc_array(args->count_handles, sizeof(*points),
+ GFP_KERNEL);
if (!points) {
ret = -ENOMEM;
goto out;
@@ -1586,7 +1596,7 @@ drm_syncobj_timeline_signal_ioctl(struct drm_device *dev, void *data,
goto err_points;
}
- chains = kmalloc_objs(*chains, args->count_handles);
+ chains = kvmalloc_objs(*chains, args->count_handles);
if (!chains) {
ret = -ENOMEM;
goto err_points;
@@ -1609,9 +1619,9 @@ drm_syncobj_timeline_signal_ioctl(struct drm_device *dev, void *data,
dma_fence_put(fence);
}
err_chains:
- kfree(chains);
+ kvfree(chains);
err_points:
- kfree(points);
+ kvfree(points);
out:
drm_syncobj_array_free(syncobjs, args->count_handles);
base-commit: 6628e7d4c6b25c8d18f1345e3a20d21829aae7e4
--
2.43.0
^ permalink raw reply [flat|nested] 4+ messages in thread* Forwarded: [PATCH v2] drm/syncobj: Limit the number of handles and use kvmalloc for user-sized arrays
2023-09-06 11:42 [syzbot] [dri?] WARNING in drm_syncobj_array_find syzbot
2026-11-03 8:23 ` Forwarded: [PATCH] drm/syncobj: Silence allocation warnings for user-sized arrays syzbot
2026-11-04 2:31 ` Forwarded: [PATCH v2] drm/syncobj: Limit the number of handles and use kvmalloc " syzbot
@ 2026-11-04 2:37 ` syzbot
2 siblings, 0 replies; 4+ messages in thread
From: syzbot @ 2026-11-04 2:37 UTC (permalink / raw)
To: linux-kernel, syzkaller-bugs
For archival purposes, forwarding an incoming command email to
linux-kernel@vger.kernel.org, syzkaller-bugs@googlegroups.com.
***
Subject: [PATCH v2] drm/syncobj: Limit the number of handles and use kvmalloc for user-sized arrays
Author: fei.yu@intel.com
From: Fei Yu <fei.yu@intel.com>
#syz test: git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git master
The syncobj 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()
These are kmalloc() allocations, so a count above KMALLOC_MAX_SIZE /
element size 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 wait entries are 64 bytes each on 64-bit, so with a 4 MiB
KMALLOC_MAX_SIZE a wait on more than about 64K handles already fails
today, with a warning.
Fix this in two parts:
- Reject more than DRM_SYNCOBJ_MAX_HANDLES handles with -EINVAL in
drm_syncobj_array_find(), which every ioctl taking a handle array goes
through. The limit is derived from the largest per-handle allocation
(the wait entries) and the INT_MAX size limit of kvmalloc(), so none
of the allocations above can exceed it. That is about 33M handles on
64-bit.
- Switch the six allocations to kvmalloc(), so that large but valid
handle counts no longer depend on physically contiguous memory.
Using kvmalloc() alone is not enough: the reproducer asks for more than
INT_MAX bytes, which hits the WARN_ON_ONCE() in __kvmalloc_node_noprof()
instead.
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
Suggested-by: Christian König <christian.koenig@amd.com>
Signed-off-by: Fei Yu <fei.yu@intel.com>
---
v2:
- Drop __GFP_NOWARN (Christian).
- Add DRM_SYNCOBJ_MAX_HANDLES, return -EINVAL above it, and switch all six
arrays to kvmalloc() (Christian).
- v1: https://lore.kernel.org/all/20261103085002.3100723-1-fei.yu@intel.com/
About the limit: INT_MAX / sizeof(struct syncobj_wait_entry) is about 33M
handles on 64-bit. It is the largest count for which every allocation stays
below the kvmalloc() INT_MAX size limit, so it does not add a new policy
number. Today the real limit is much lower: a wait on more than ~64K
handles already fails with -ENOMEM (plus the warning), because the wait
entries are a kmalloc() allocation larger than 4 MiB. If you prefer a lower,
fixed limit (e.g. SZ_1M) or GFP_KERNEL_ACCOUNT for these arrays, I can
change it.
Testing on v7.4-rc1 (x86_64, KASAN, virtio-gpu in QEMU):
- syzbot C reproducer: base warns in ___kmalloc_large_node() (size
0x100000920), patched is clean, ioctl returns -EINVAL.
- wait / timeline_wait / timeline_signal / reset / signal on 200000
signaled syncobjs: base fails wait and timeline_wait with -ENOMEM and
the same warning; patched all succeed.
- count == DRM_SYNCOBJ_MAX_HANDLES gets past the check (-EFAULT from the
short user buffer), count == DRM_SYNCOBJ_MAX_HANDLES + 1 returns -EINVAL
for wait, reset and timeline_signal.
- kmemleak clean, checkpatch --strict clean, W=1 clean,
DRM KUnit 667/667 passed.
- IGT syncobj_basic, syncobj_wait, syncobj_timeline on virtio-gpu:
202/202 subtests pass, same as base.
drivers/gpu/drm/drm_syncobj.c | 40 ++++++++++++++++++++++-------------
1 file changed, 25 insertions(+), 15 deletions(-)
diff --git a/drivers/gpu/drm/drm_syncobj.c b/drivers/gpu/drm/drm_syncobj.c
index f1d4da1685457..c01cf164a4f9e 100644
--- a/drivers/gpu/drm/drm_syncobj.c
+++ b/drivers/gpu/drm/drm_syncobj.c
@@ -220,6 +220,13 @@ struct syncobj_wait_entry {
u64 point;
};
+/*
+ * Upper limit for the number of handles passed to a single ioctl. The
+ * largest per-handle allocation is the wait entry array, keep it below the
+ * INT_MAX size limit of kvmalloc().
+ */
+#define DRM_SYNCOBJ_MAX_HANDLES (INT_MAX / sizeof(struct syncobj_wait_entry))
+
static void syncobj_wait_syncobj_func(struct drm_syncobj *syncobj,
struct syncobj_wait_entry *wait);
@@ -1051,7 +1058,7 @@ 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 = kvmalloc_array(count, sizeof(*points), GFP_KERNEL);
if (points == NULL)
return -ENOMEM;
@@ -1064,7 +1071,7 @@ static signed long drm_syncobj_array_wait_timeout(struct drm_syncobj **syncobjs,
goto err_free_points;
}
- entries = kzalloc_objs(*entries, count);
+ entries = kvzalloc_objs(*entries, count);
if (!entries) {
timeout = -ENOMEM;
goto err_free_points;
@@ -1185,10 +1192,10 @@ static signed long drm_syncobj_array_wait_timeout(struct drm_syncobj **syncobjs,
&entries[i].fence_cb);
dma_fence_put(entries[i].fence);
}
- kfree(entries);
+ kvfree(entries);
err_free_points:
- kfree(points);
+ kvfree(points);
return timeout;
}
@@ -1238,7 +1245,10 @@ 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);
+ if (count_handles > DRM_SYNCOBJ_MAX_HANDLES)
+ return -EINVAL;
+
+ handles = kvmalloc_array(count_handles, sizeof(*handles), GFP_KERNEL);
if (handles == NULL)
return -ENOMEM;
@@ -1248,7 +1258,7 @@ static int drm_syncobj_array_find(struct drm_file *file_private,
goto err_free_handles;
}
- syncobjs = kmalloc_objs(*syncobjs, count_handles);
+ syncobjs = kvmalloc_objs(*syncobjs, count_handles);
if (syncobjs == NULL) {
ret = -ENOMEM;
goto err_free_handles;
@@ -1262,16 +1272,16 @@ static int drm_syncobj_array_find(struct drm_file *file_private,
}
}
- kfree(handles);
+ kvfree(handles);
*syncobjs_out = syncobjs;
return 0;
err_put_syncobjs:
while (i-- > 0)
drm_syncobj_put(syncobjs[i]);
- kfree(syncobjs);
+ kvfree(syncobjs);
err_free_handles:
- kfree(handles);
+ kvfree(handles);
return ret;
}
@@ -1283,7 +1293,7 @@ static void drm_syncobj_array_free(struct drm_syncobj **syncobjs,
for (i = 0; i < count; i++)
drm_syncobj_put(syncobjs[i]);
- kfree(syncobjs);
+ kvfree(syncobjs);
}
int
@@ -1572,8 +1582,8 @@ drm_syncobj_timeline_signal_ioctl(struct drm_device *dev, void *data,
if (ret < 0)
return ret;
- points = kmalloc_array(args->count_handles, sizeof(*points),
- GFP_KERNEL);
+ points = kvmalloc_array(args->count_handles, sizeof(*points),
+ GFP_KERNEL);
if (!points) {
ret = -ENOMEM;
goto out;
@@ -1586,7 +1596,7 @@ drm_syncobj_timeline_signal_ioctl(struct drm_device *dev, void *data,
goto err_points;
}
- chains = kmalloc_objs(*chains, args->count_handles);
+ chains = kvmalloc_objs(*chains, args->count_handles);
if (!chains) {
ret = -ENOMEM;
goto err_points;
@@ -1609,9 +1619,9 @@ drm_syncobj_timeline_signal_ioctl(struct drm_device *dev, void *data,
dma_fence_put(fence);
}
err_chains:
- kfree(chains);
+ kvfree(chains);
err_points:
- kfree(points);
+ kvfree(points);
out:
drm_syncobj_array_free(syncobjs, args->count_handles);
base-commit: 6628e7d4c6b25c8d18f1345e3a20d21829aae7e4
--
2.43.0
^ permalink raw reply [flat|nested] 4+ messages in thread