[PATCH RFC] drm/lease: use kvmalloc for user-controlled allocations
"syzbot" <[email protected]>
| Newsgroups | dev.linux.lists.syzbot |
|---|---|
| Message-ID | <[email protected]> |
In drm_mode_create_lease_ioctl(), a user-controlled object_count is used to
allocate memory for object_ids and objects. If a user provides a very large
object_count (e.g., 1,000,000), the kernel attempts to allocate a
contiguous memory chunk that exceeds the maximum allowed size by the slab
allocator (KMALLOC_MAX_SIZE).
For the objects array, kzalloc_objs() is used, which expands to a standard
kzalloc() call without the __GFP_NOWARN flag. When the requested size
exceeds KMALLOC_MAX_SIZE, the SLUB allocator passes the request to the page
allocator, which triggers a WARN_ON_ONCE_GFP because the required page
order is greater than MAX_PAGE_ORDER:
WARNING: mm/page_alloc.c:5197 at __alloc_frozen_pages_noprof+0x2ce/0x380
mm/page_alloc.c:5197
Call Trace:
<TASK>
alloc_pages_mpol+0x212/0x380 mm/mempolicy.c:2490
___kmalloc_large_node+0x4c/0x120 mm/slub.c:5237
__kmalloc_large_node_noprof+0x18/0x90 mm/slub.c:5268
__do_kmalloc_node mm/slub.c:5284 [inline]
__kmalloc_noprof+0x3e4/0x750 mm/slub.c:5308
kmalloc_noprof include/linux/slab.h:954 [inline]
kzalloc_noprof include/linux/slab.h:1188 [inline]
fill_object_idr drivers/gpu/drm/drm_lease.c:389 [inline]
drm_mode_create_lease_ioctl+0x533/0x1ab0 drivers/gpu/drm/drm_lease.c:521
To fix this, replace memdup_array_user() with vmemdup_array_user() and
kzalloc_objs() with kvcalloc(), along with changing their respective
kfree() calls to kvfree(). The kvmalloc family of functions attempts a
kmalloc() first with __GFP_NOWARN applied internally, and gracefully falls
back to vmalloc() for large allocations. This prevents the kernel warning
and makes the allocations more robust against memory fragmentation,
gracefully returning -ENOMEM if the system cannot satisfy the request.
Fixes: 62884cd386b8 ("drm: Add four ioctls for managing drm mode object leases [v7]")
Assisted-by: Gemini:gemini-3.1-pro-preview syzbot
Reported-by: [email protected]
Closes: https://syzkaller.appspot.com/bug?extid=03fb58296859d8dbab4d
Link: https://syzkaller.appspot.com/ai_job?id=73f2715e-0f0e-4924-ad92-d4ef4f06a14f
To: "David Airlie" <[email protected]>
To: <[email protected]>
To: "Maarten Lankhorst" <[email protected]>
To: "Maxime Ripard" <[email protected]>
To: "Simona Vetter" <[email protected]>
To: "Thomas Zimmermann" <[email protected]>
Cc: <[email protected]>
---
diff --git a/drivers/gpu/drm/drm_lease.c b/drivers/gpu/drm/drm_lease.c
index 5d2cf724c..240e0ea6c 100644
--- a/drivers/gpu/drm/drm_lease.c
+++ b/drivers/gpu/drm/drm_lease.c
@@ -386,7 +386,8 @@ static int fill_object_idr(struct drm_device *dev,
int ret;
bool universal_planes = READ_ONCE(lessor_priv->universal_planes);
- objects = kzalloc_objs(struct drm_mode_object *, object_count);
+ objects = kvcalloc(object_count, sizeof(struct drm_mode_object *),
+ GFP_KERNEL);
if (!objects)
return -ENOMEM;
@@ -462,7 +463,7 @@ static int fill_object_idr(struct drm_device *dev,
if (objects[o])
drm_mode_object_put(objects[o]);
}
- kfree(objects);
+ kvfree(objects);
return ret;
}
@@ -509,8 +510,8 @@ int drm_mode_create_lease_ioctl(struct drm_device *dev,
/* Handle leased objects, if any */
idr_init(&leases);
if (object_count != 0) {
- object_ids = memdup_array_user(u64_to_user_ptr(cl->object_ids),
- object_count, sizeof(__u32));
+ object_ids = vmemdup_array_user(u64_to_user_ptr(cl->object_ids),
+ object_count, sizeof(__u32));
if (IS_ERR(object_ids)) {
ret = PTR_ERR(object_ids);
idr_destroy(&leases);
@@ -520,7 +521,7 @@ int drm_mode_create_lease_ioctl(struct drm_device *dev,
/* fill and validate the object idr */
ret = fill_object_idr(dev, lessor_priv, &leases,
object_count, object_ids);
- kfree(object_ids);
+ kvfree(object_ids);
if (ret) {
drm_dbg_lease(dev, "lease object lookup failed: %i\n", ret);
idr_destroy(&leases);
base-commit: 8cd9520d35a6c38db6567e97dd93b1f11f185dc6
--
This is an AI-generated patch subject to moderation.
Reply with '#syz upstream' to Sign-off the patch as a human author
and send it to the upstream kernel mailing lists.
Reply with '#syz reject' to reject it ('#syz unreject' to undo).
See https://goo.gle/syzbot-ai-patches for information about AI-generated patches.
You can comment on the patch as usual, syzbot will try to address
the comments and send a new version of the patch if necessary.
syzbot engineers can be reached at [email protected].