| 0/0 |
2026/06/15 15:30 |
flow |
patching |
1h08m
Results: map[AckedBy:[] Fixes:map[Hash:62884cd386b876638720ef88374b31a84ca7ee5f Title:drm: Add four ioctls for managing drm mode object leases [v7]] KernelBranch:master KernelCommit:8cd9520d35a6c38db6567e97dd93b1f11f185dc6 KernelRepo:git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git PatchDescription:drm/lease: use kvmalloc for user-controlled allocations
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. PatchDiff: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);
Recipients:[map[Email:airlied@gmail.com Name:David Airlie To:true] map[Email:dri-devel@lists.freedesktop.org Name: To:true] map[Email:linux-kernel@vger.kernel.org Name: To:false] map[Email:maarten.lankhorst@linux.intel.com Name:Maarten Lankhorst To:true] map[Email:mripard@kernel.org Name:Maxime Ripard To:true] map[Email:simona@ffwll.ch Name:Simona Vetter To:true] map[Email:tzimmermann@suse.de Name:Thomas Zimmermann To:true]] ReportedBy:[] ReviewedBy:[] TestedBy:[]]
|
| 1/1 |
2026/06/15 15:30 |
action |
base-commit-picker |
0m
Results: map[KernelBranch:master KernelCommit:8cd9520d35a6c38db6567e97dd93b1f11f185dc6 KernelRepo:git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git]
|
| 2/1 |
2026/06/15 15:31 |
action |
syz-repro-to-c-repro |
0m
Results: map[SimplifiedCRepro:// autogenerated by syzkaller (https://github.com/google/syzkaller)
#define _GNU_SOURCE
#include <endian.h>
#include <fcntl.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mount.h>
#include <sys/stat.h>
#include <sys/syscall.h>
#include <sys/types.h>
#include <unistd.h>
static long syz_open_dev(volatile long a0, volatile long a1, volatile long a2)
{
if (a0 == 0xc || a0 == 0xb) {
char buf[128];
sprintf(buf, "/dev/%s/%d:%d", a0 == 0xc ? "char" : "block", (uint8_t)a1, (uint8_t)a2);
return open(buf, O_RDWR, 0);
} else {
unsigned long nb = a1;
char buf[1024];
char* hash;
strncpy(buf, (char*)a0, sizeof(buf) - 1);
buf[sizeof(buf) - 1] = 0;
while ((hash = strchr(buf, '#'))) {
*hash = '0' + (char)(nb % 10);
nb /= 10;
}
return open(buf, a2 & ~O_CREAT, 0);
}
}
uint64_t r[1] = {0xffffffffffffffff};
int main(void)
{
syscall(__NR_mmap, /*addr=*/0x1ffffffff000ul, /*len=*/0x1000ul, /*prot=*/0ul, /*flags=MAP_FIXED|MAP_ANONYMOUS|MAP_PRIVATE*/0x32ul, /*fd=*/(intptr_t)-1, /*offset=*/0ul);
syscall(__NR_mmap, /*addr=*/0x200000000000ul, /*len=*/0x1000000ul, /*prot=PROT_WRITE|PROT_READ|PROT_EXEC*/7ul, /*flags=MAP_FIXED|MAP_ANONYMOUS|MAP_PRIVATE*/0x32ul, /*fd=*/(intptr_t)-1, /*offset=*/0ul);
syscall(__NR_mmap, /*addr=*/0x200001000000ul, /*len=*/0x1000ul, /*prot=*/0ul, /*flags=MAP_FIXED|MAP_ANONYMOUS|MAP_PRIVATE*/0x32ul, /*fd=*/(intptr_t)-1, /*offset=*/0ul);
const char* reason;
(void)reason;
intptr_t res = 0;
if (write(1, "executing program\n", sizeof("executing program\n") - 1)) {}
// syz_open_dev$dri arguments: [
// dev: ptr[in, buffer] {
// buffer: {2f 64 65 76 2f 64 72 69 2f 63 61 72 64 23 00} (length 0xf)
// }
// id: intptr = 0x1f (8 bytes)
// flags: open_flags = 0x0 (8 bytes)
// ]
// returns fd_dri
memcpy((void*)0x200000000000, "/dev/dri/card#\000", 15);
res = -1;
res = syz_open_dev(/*dev=*/0x200000000000, /*id=*/0x1f, /*flags=*/0);
if (res != -1)
r[0] = res;
// ioctl$DRM_IOCTL_MODE_CREATE_LEASE arguments: [
// fd: fd_dri (resource)
// cmd: const = 0xc01864c6 (4 bytes)
// arg: ptr[inout, drm_mode_create_lease] {
// drm_mode_create_lease {
// object_ids: ptr[in, array[drm_obj_id]] {
// array[drm_obj_id] {
// drm_obj_id (resource)
// }
// }
// object_count: len = 0xf4240 (4 bytes)
// flags: drm_mode_create_lease_flag = 0x0 (4 bytes)
// lessee_id: drm_lessee_id (resource)
// fd: fd (resource)
// }
// }
// ]
*(uint64_t*)0x2000000003c0 = 0x200000000280;
*(uint32_t*)0x200000000280 = 0;
*(uint32_t*)0x2000000003c8 = 0xf4240;
*(uint32_t*)0x2000000003cc = 0;
syscall(__NR_ioctl, /*fd=*/r[0], /*cmd=*/0xc01864c6, /*arg=*/0x2000000003c0ul);
return 0;
}
]
|
| 3/1 |
2026/06/15 15:31 |
action |
kernel-checkouter |
1m
Results: map[KernelSrc:/app/workdir/cache/src/1583fc50e73bc268b47064ec35fa43904fad8ca1]
|
| 4/1 |
2026/06/15 15:32 |
action |
kernel-builder |
14m
Results: map[KernelObj:/app/workdir/cache/build/b53f680cef6f7dd872861412531ef646b7563759]
|
| 5/1 |
2026/06/15 15:47 |
action |
crash-reproducer |
1m
Results: map[OtherCrashReports:<nil> ReproducedBugTitle:WARNING in drm_mode_create_lease_ioctl ReproducedCrashReport:------------[ cut here ]------------
WARNING: mm/page_alloc.c:5197 at __alloc_frozen_pages_noprof+0x2ce/0x380 mm/page_alloc.c:5197, CPU#0: syz.0.17/6137
Modules linked in:
CPU: 0 UID: 0 PID: 6137 Comm: syz.0.17 Not tainted syzkaller #1 PREEMPT(full)
Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.16.3-debian-1.16.3-2 04/01/2014
RIP: 0010:__alloc_frozen_pages_noprof+0x2ce/0x380 mm/page_alloc.c:5197
Code: 74 10 4c 89 e7 89 54 24 0c e8 6e a2 0d 00 8b 54 24 0c 49 83 3c 24 00 0f 85 ab fe ff ff e9 ac fe ff ff c6 05 92 0e b2 0d 01 90 <0f> 0b 90 e9 17 ff ff ff a9 00 00 08 00 48 8b 4c 24 10 4c 8d 44 24
RSP: 0018:ffffc90003aa7800 EFLAGS: 00010246
RAX: ffffc90003aa7800 RBX: 000000000000000b RCX: 0000000000000000
RDX: 0000000000000000 RSI: 0000000000000000 RDI: ffffc90003aa7868
RBP: ffffc90003aa78e8 R08: ffffc90003aa7867 R09: 0000000000000000
R10: ffffc90003aa7840 R11: fffff52000754f0d R12: 0000000000000000
R13: 1ffff92000754f04 R14: 0000000000040dc0 R15: dffffc0000000000
FS: 00007fe037ac16c0(0000) GS:ffff8881a59ad000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 00002000003d0000 CR3: 0000000104ab0000 CR4: 00000000000006f0
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
drm_ioctl_kernel+0x2df/0x3b0 drivers/gpu/drm/drm_ioctl.c:805
drm_ioctl+0x6fa/0xbc0 drivers/gpu/drm/drm_ioctl.c:902
vfs_ioctl fs/ioctl.c:51 [inline]
__do_sys_ioctl fs/ioctl.c:597 [inline]
__se_sys_ioctl+0xfc/0x170 fs/ioctl.c:583
do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
do_syscall_64+0x15f/0x560 arch/x86/entry/syscall_64.c:94
entry_SYSCALL_64_after_hwframe+0x77/0x7f
RIP: 0033:0x7fe036b9ce59
Code: ff c3 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 44 00 00 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 c7 c1 e8 ff ff ff f7 d8 64 89 01 48
RSP: 002b:00007fe037ac1028 EFLAGS: 00000246 ORIG_RAX: 0000000000000010
RAX: ffffffffffffffda RBX: 00007fe036e15fa0 RCX: 00007fe036b9ce59
RDX: 00002000000003c0 RSI: 00000000c01864c6 RDI: 0000000000000003
RBP: 00007fe036c32d6f R08: 0000000000000000 R09: 0000000000000000
R10: 0000000000000000 R11: 0000000000000246 R12: 0000000000000000
R13: 00007fe036e16038 R14: 00007fe036e15fa0 R15: 00007fffcab0e958
</TASK>
ReproducedFaultInjection:]
|
| 6/1 |
2026/06/15 15:48 |
action |
codesearch-prepare |
18m
Results: map[Index:codesearch-index]
|
| 7/1 |
2026/06/15 16:07 |
agent |
debugger |
5m
Model:
Instruction:
You are an experienced Linux kernel developer tasked with debugging a kernel crash root cause.
You need to provide a detailed explanation of the root cause for another developer to be
able to write a fix for the bug based on your explanation. Include all relevant details
into the response: function/struct/field/etc names, code snippets, line numbers,
macro/enum values, etc.
Don't make assumptions about the kernel source code (it may be different from what you assume it is).
Extensively use the provided code access tools (codesearch-*, git-*, grepper, etc)
to examine the actual source code, and confirm any assumptions.
Prefer calling several tools at the same time to save round-trips.
Prompt:
The crash is:
------------[ cut here ]------------
WARNING: mm/page_alloc.c:5197 at __alloc_frozen_pages_noprof+0x2ce/0x380 mm/page_alloc.c:5197, CPU#0: syz.0.17/6137
Modules linked in:
CPU: 0 UID: 0 PID: 6137 Comm: syz.0.17 Not tainted syzkaller #1 PREEMPT(full)
Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.16.3-debian-1.16.3-2 04/01/2014
RIP: 0010:__alloc_frozen_pages_noprof+0x2ce/0x380 mm/page_alloc.c:5197
Code: 74 10 4c 89 e7 89 54 24 0c e8 6e a2 0d 00 8b 54 24 0c 49 83 3c 24 00 0f 85 ab fe ff ff e9 ac fe ff ff c6 05 92 0e b2 0d 01 90 <0f> 0b 90 e9 17 ff ff ff a9 00 00 08 00 48 8b 4c 24 10 4c 8d 44 24
RSP: 0018:ffffc90003aa7800 EFLAGS: 00010246
RAX: ffffc90003aa7800 RBX: 000000000000000b RCX: 0000000000000000
RDX: 0000000000000000 RSI: 0000000000000000 RDI: ffffc90003aa7868
RBP: ffffc90003aa78e8 R08: ffffc90003aa7867 R09: 0000000000000000
R10: ffffc90003aa7840 R11: fffff52000754f0d R12: 0000000000000000
R13: 1ffff92000754f04 R14: 0000000000040dc0 R15: dffffc0000000000
FS: 00007fe037ac16c0(0000) GS:ffff8881a59ad000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 00002000003d0000 CR3: 0000000104ab0000 CR4: 00000000000006f0
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
drm_ioctl_kernel+0x2df/0x3b0 drivers/gpu/drm/drm_ioctl.c:805
drm_ioctl+0x6fa/0xbc0 drivers/gpu/drm/drm_ioctl.c:902
vfs_ioctl fs/ioctl.c:51 [inline]
__do_sys_ioctl fs/ioctl.c:597 [inline]
__se_sys_ioctl+0xfc/0x170 fs/ioctl.c:583
do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
do_syscall_64+0x15f/0x560 arch/x86/entry/syscall_64.c:94
entry_SYSCALL_64_after_hwframe+0x77/0x7f
RIP: 0033:0x7fe036b9ce59
Code: ff c3 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 44 00 00 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 c7 c1 e8 ff ff ff f7 d8 64 89 01 48
RSP: 002b:00007fe037ac1028 EFLAGS: 00000246 ORIG_RAX: 0000000000000010
RAX: ffffffffffffffda RBX: 00007fe036e15fa0 RCX: 00007fe036b9ce59
RDX: 00002000000003c0 RSI: 00000000c01864c6 RDI: 0000000000000003
RBP: 00007fe036c32d6f R08: 0000000000000000 R09: 0000000000000000
R10: 0000000000000000 R11: 0000000000000246 R12: 0000000000000000
R13: 00007fe036e16038 R14: 00007fe036e15fa0 R15: 00007fffcab0e958
</TASK>
The following C code is a draft of the vulnerable syscall sequence. Keep in mind that
it may lack the precise threading, sandboxing, and some arguments of a working reproducer:
// autogenerated by syzkaller (https://github.com/google/syzkaller)
#define _GNU_SOURCE
#include <endian.h>
#include <fcntl.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mount.h>
#include <sys/stat.h>
#include <sys/syscall.h>
#include <sys/types.h>
#include <unistd.h>
static long syz_open_dev(volatile long a0, volatile long a1, volatile long a2)
{
if (a0 == 0xc || a0 == 0xb) {
char buf[128];
sprintf(buf, "/dev/%s/%d:%d", a0 == 0xc ? "char" : "block", (uint8_t)a1, (uint8_t)a2);
return open(buf, O_RDWR, 0);
} else {
unsigned long nb = a1;
char buf[1024];
char* hash;
strncpy(buf, (char*)a0, sizeof(buf) - 1);
buf[sizeof(buf) - 1] = 0;
while ((hash = strchr(buf, '#'))) {
*hash = '0' + (char)(nb % 10);
nb /= 10;
}
return open(buf, a2 & ~O_CREAT, 0);
}
}
uint64_t r[1] = {0xffffffffffffffff};
int main(void)
{
syscall(__NR_mmap, /*addr=*/0x1ffffffff000ul, /*len=*/0x1000ul, /*prot=*/0ul, /*flags=MAP_FIXED|MAP_ANONYMOUS|MAP_PRIVATE*/0x32ul, /*fd=*/(intptr_t)-1, /*offset=*/0ul);
syscall(__NR_mmap, /*addr=*/0x200000000000ul, /*len=*/0x1000000ul, /*prot=PROT_WRITE|PROT_READ|PROT_EXEC*/7ul, /*flags=MAP_FIXED|MAP_ANONYMOUS|MAP_PRIVATE*/0x32ul, /*fd=*/(intptr_t)-1, /*offset=*/0ul);
syscall(__NR_mmap, /*addr=*/0x200001000000ul, /*len=*/0x1000ul, /*prot=*/0ul, /*flags=MAP_FIXED|MAP_ANONYMOUS|MAP_PRIVATE*/0x32ul, /*fd=*/(intptr_t)-1, /*offset=*/0ul);
const char* reason;
(void)reason;
intptr_t res = 0;
if (write(1, "executing program\n", sizeof("executing program\n") - 1)) {}
// syz_open_dev$dri arguments: [
// dev: ptr[in, buffer] {
// buffer: {2f 64 65 76 2f 64 72 69 2f 63 61 72 64 23 00} (length 0xf)
// }
// id: intptr = 0x1f (8 bytes)
// flags: open_flags = 0x0 (8 bytes)
// ]
// returns fd_dri
memcpy((void*)0x200000000000, "/dev/dri/card#\000", 15);
res = -1;
res = syz_open_dev(/*dev=*/0x200000000000, /*id=*/0x1f, /*flags=*/0);
if (res != -1)
r[0] = res;
// ioctl$DRM_IOCTL_MODE_CREATE_LEASE arguments: [
// fd: fd_dri (resource)
// cmd: const = 0xc01864c6 (4 bytes)
// arg: ptr[inout, drm_mode_create_lease] {
// drm_mode_create_lease {
// object_ids: ptr[in, array[drm_obj_id]] {
// array[drm_obj_id] {
// drm_obj_id (resource)
// }
// }
// object_count: len = 0xf4240 (4 bytes)
// flags: drm_mode_create_lease_flag = 0x0 (4 bytes)
// lessee_id: drm_lessee_id (resource)
// fd: fd (resource)
// }
// }
// ]
*(uint64_t*)0x2000000003c0 = 0x200000000280;
*(uint32_t*)0x200000000280 = 0;
*(uint32_t*)0x2000000003c8 = 0xf4240;
*(uint32_t*)0x2000000003cc = 0;
syscall(__NR_ioctl, /*fd=*/r[0], /*cmd=*/0xc01864c6, /*arg=*/0x2000000003c0ul);
return 0;
}
Reply: The root cause of this kernel crash is an unbounded memory allocation based on a user-controlled value, which attempts to allocate a contiguous memory chunk larger than the maximum allowed by the slab allocator (`KMALLOC_MAX_SIZE`), triggering a warning in the page allocator.
### Detailed Root Cause Analysis
1. **User-controlled `object_count`**:
In `drivers/gpu/drm/drm_lease.c`, the `drm_mode_create_lease_ioctl()` function retrieves `object_count` directly from the user-provided `struct drm_mode_create_lease` argument:
```c
object_count = cl->object_count;
```
The syzkaller reproducer sets this value to `0xf4240` (1,000,000).
2. **First Allocation (`memdup_array_user`)**:
The ioctl first allocates an array to hold the object IDs:
```c
object_ids = memdup_array_user(u64_to_user_ptr(cl->object_ids),
object_count, sizeof(__u32));
```
For `1,000,000` objects, this requires `4,000,000` bytes (~3.8 MB). This size is typically just under the `KMALLOC_MAX_SIZE` limit (usually 4 MB on many architectures). Furthermore, `memdup_array_user()` internally uses `memdup_user()`, which allocates memory with the `__GFP_NOWARN` flag. Thus, even if it were to fail, it would gracefully return `-ENOMEM` without triggering a kernel warning.
3. **Second Allocation (`kzalloc_objs`)**:
After successfully allocating `object_ids`, the ioctl calls `fill_object_idr()`:
```c
ret = fill_object_idr(dev, lessor_priv, &leases, object_count, object_ids);
```
Inside `fill_object_idr()`, the kernel attempts to allocate an array of pointers for the objects:
```c
objects = kzalloc_objs(struct drm_mode_object *, object_count);
```
The size of `struct drm_mode_object *` is 8 bytes (on 64-bit systems). For `1,000,000` objects, this requires `8,000,000` bytes (~7.6 MB). This size strictly exceeds the `KMALLOC_MAX_SIZE` limit.
Unlike `memdup_user()`, the `kzalloc_objs()` macro expands to a standard `kzalloc()` call using `GFP_KERNEL | __GFP_ZERO` **without** the `__GFP_NOWARN` flag.
4. **The Crash (Warning)**:
Because the requested size is larger than `KMALLOC_MAX_SIZE`, the SLUB allocator passes the request directly to the page allocator (`___kmalloc_large_node`). The page allocator calculates the required page order (order 11 for 8 MB). Since order 11 is strictly greater than `MAX_PAGE_ORDER` (typically 10), the page allocator hits the following safety check in `__alloc_frozen_pages_noprof()`:
```c
if (WARN_ON_ONCE_GFP(order > MAX_PAGE_ORDER, gfp))
return NULL;
```
Because `__GFP_NOWARN` was not provided, this triggers the `WARN_ON_ONCE_GFP` warning, which syzkaller correctly identifies as a crash.
### Proposed Fix
To fix this issue, both allocations should be updated to use the `kvmalloc` family of functions. These functions automatically fall back to `vmalloc()` for large allocations (avoiding memory fragmentation issues) and internally apply `__GFP_NOWARN` when attempting the initial `kmalloc()`, preventing the page allocator warning.
1. In `drm_mode_create_lease_ioctl()`, replace `memdup_array_user()` with `vmemdup_array_user()`, and change the corresponding `kfree()` to `kvfree()`:
```c
// drivers/gpu/drm/drm_lease.c : ~512
- 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));
// drivers/gpu/drm/drm_lease.c : ~523
- kfree(object_ids);
+ kvfree(object_ids);
```
2. In `fill_object_idr()`, replace `kzalloc_objs()` with `kvcalloc()`, and change the corresponding `kfree()` to `kvfree()`:
```c
// drivers/gpu/drm/drm_lease.c : ~389
- objects = kzalloc_objs(struct drm_mode_object *, object_count);
+ objects = kvcalloc(object_count, sizeof(struct drm_mode_object *), GFP_KERNEL);
// drivers/gpu/drm/drm_lease.c : ~465
- kfree(objects);
+ kvfree(objects);
```
This ensures that userspace cannot trigger a kernel warning by passing an arbitrarily large `object_count`, and the kernel will gracefully return `-ENOMEM` if the system truly cannot satisfy the `vmalloc` request.
|
| 8/2 |
2026/06/15 16:07 |
llm |
debugger |
0m
Model:
Tokens:
input: 6832
output: 44
thoughts: 536
Thoughts: **Kernel Crash Investigation: A Deep Dive**
Okay, so we've got a kernel crash, and the trace points us directly to `mm/page_alloc.c`, specifically the `__alloc_frozen_pages_noprof` function. That's immediately interesting, because `page_alloc.c` is the heart of memory management. The trace shows a call path that looks like:
`drm_mode_create_lease_ioctl` -> `fill_object_idr` -> `kzalloc_noprof` -> `kmalloc_noprof` -> `__kmalloc_large_node_noprof` -> `___kmalloc_large_node` -> `alloc_pages_mpol`.
That indicates a memory allocation issue during a lease creation attempt within the DRM (Direct Rendering Manager) subsystem. `alloc_pages_mpol` suggests it's related to memory policy, probably a NUMA node issue if it is a large allocation. It seems we're requesting a page allocation that's hitting a limit or an error. This kind of error is a pretty common pitfall during lease management, so, let's look at the C reproducer.
The C reproducer is interesting. We're setting up a memory region with a few specific addresses: `0x2000000003c0`, `0x200000000280`, and then we perform an `ioctl` with a specific command code `0xc01864c6`. The key here is that we're setting an `object_count` to 1000000. It looks like we're setting up an `drm_lease` request with a *very* large number of objects. Given that the crash is in `page_alloc.c`, I'm guessing this large allocation request is what's causing the problem. My guess is that memory is being exhausted or there's some kind of integer overflow/underflow error when attempting to allocate the space.
The next thing I need to do is jump into the code for `drm_mode_create_lease_ioctl` and `fill_object_idr`, understand the data structure and look closely at the memory allocation size calculations, and the constraints on the number of objects we can lease at once. This smells like a classic denial-of-service vulnerability due to excessive memory usage. Or, it could just be a coding error. Either way, it's time to dig into the source.
|
| 9/2 |
2026/06/15 16:07 |
tool |
codesearch-definition-source |
0m
Args: map[ContextFile:drivers/gpu/drm/drm_lease.c Name:drm_mode_create_lease_ioctl]
Results: map[SourceCode: 469: /*
470: * The master associated with the specified file will have a lease
471: * created containing the objects specified in the ioctl structure.
472: * A file descriptor will be allocated for that and returned to the
473: * application.
474: */
475: int drm_mode_create_lease_ioctl(struct drm_device *dev,
476: void *data, struct drm_file *lessor_priv)
477: {
478: struct drm_mode_create_lease *cl = data;
479: size_t object_count;
480: int ret = 0;
481: struct idr leases;
482: struct drm_master *lessor;
483: struct drm_master *lessee = NULL;
484: struct file *lessee_file = NULL;
485: struct file *lessor_file = lessor_priv->filp;
486: struct drm_file *lessee_priv;
487: int fd = -1;
488: uint32_t *object_ids;
489:
490: /* Can't lease without MODESET */
491: if (!drm_core_check_feature(dev, DRIVER_MODESET))
492: return -EOPNOTSUPP;
493:
494: if (cl->flags && (cl->flags & ~(O_CLOEXEC | O_NONBLOCK))) {
495: drm_dbg_lease(dev, "invalid flags\n");
496: return -EINVAL;
497: }
498:
499: lessor = drm_file_get_master(lessor_priv);
500: /* Do not allow sub-leases */
501: if (lessor->lessor) {
502: drm_dbg_lease(dev, "recursive leasing not allowed\n");
503: ret = -EINVAL;
504: goto out_lessor;
505: }
506:
507: object_count = cl->object_count;
508:
509: /* Handle leased objects, if any */
510: idr_init(&leases);
511: if (object_count != 0) {
512: object_ids = memdup_array_user(u64_to_user_ptr(cl->object_ids),
513: object_count, sizeof(__u32));
514: if (IS_ERR(object_ids)) {
515: ret = PTR_ERR(object_ids);
516: idr_destroy(&leases);
517: goto out_lessor;
518: }
519:
520: /* fill and validate the object idr */
521: ret = fill_object_idr(dev, lessor_priv, &leases,
522: object_count, object_ids);
523: kfree(object_ids);
524: if (ret) {
525: drm_dbg_lease(dev, "lease object lookup failed: %i\n", ret);
526: idr_destroy(&leases);
527: goto out_lessor;
528: }
529: }
530:
531: /* Allocate a file descriptor for the lease */
532: fd = get_unused_fd_flags(cl->flags & (O_CLOEXEC | O_NONBLOCK));
533: if (fd < 0) {
534: idr_destroy(&leases);
535: ret = fd;
536: goto out_lessor;
537: }
538:
539: drm_dbg_lease(dev, "Creating lease\n");
540: /* lessee will take the ownership of leases */
541: lessee = drm_lease_create(lessor, &leases);
542:
543: if (IS_ERR(lessee)) {
544: ret = PTR_ERR(lessee);
545: idr_destroy(&leases);
546: goto out_leases;
547: }
548:
549: /* Clone the lessor file to create a new file for us */
550: drm_dbg_lease(dev, "Allocating lease file\n");
551: lessee_file = file_clone_open(lessor_file);
552: if (IS_ERR(lessee_file)) {
553: ret = PTR_ERR(lessee_file);
554: goto out_lessee;
555: }
556:
557: lessee_priv = lessee_file->private_data;
558: /* Change the file to a master one */
559: drm_master_put(&lessee_priv->master);
560: lessee_priv->master = lessee;
561: lessee_priv->is_master = 1;
562: lessee_priv->authenticated = 1;
563:
564: /* Pass fd back to userspace */
565: drm_dbg_lease(dev, "Returning fd %d id %d\n", fd, lessee->lessee_id);
566: cl->fd = fd;
567: cl->lessee_id = lessee->lessee_id;
568:
569: /* Hook up the fd */
570: fd_install(fd, lessee_file);
571:
572: drm_master_put(&lessor);
573: drm_dbg_lease(dev, "drm_mode_create_lease_ioctl succeeded\n");
574: return 0;
575:
576: out_lessee:
577: drm_master_put(&lessee);
578:
579: out_leases:
580: put_unused_fd(fd);
581:
582: out_lessor:
583: drm_master_put(&lessor);
584: drm_dbg_lease(dev, "drm_mode_create_lease_ioctl failed: %d\n", ret);
585: return ret;
586: }
SourceFile:drivers/gpu/drm/drm_lease.c]
|
| 10/2 |
2026/06/15 16:07 |
llm |
debugger |
0m
Model:
Tokens:
input: 9773
output: 41
thoughts: 25
Thoughts: Here's a summary of my immediate thought process:
**Diving into the Root Cause**
Okay, so we've got a crash, and the backtrace points directly to `fill_object_idr`. That's our starting point. No need to chase ghosts; we go straight to the source. Time to dig into the `fill_object_idr` function. Let's see what's happening in there. What are its inputs? What's the logic flow? Gotta understand this function intimately to figure out why it's failing and how we can prevent this crash going forward. It's time to put on my debugging hat and get to work.
|
| 11/2 |
2026/06/15 16:08 |
tool |
codesearch-definition-source |
0m
Args: map[ContextFile:drivers/gpu/drm/drm_lease.c Name:fill_object_idr]
Results: map[SourceCode: 378: static int fill_object_idr(struct drm_device *dev,
379: struct drm_file *lessor_priv,
380: struct idr *leases,
381: int object_count,
382: u32 *object_ids)
383: {
384: struct drm_mode_object **objects;
385: u32 o;
386: int ret;
387: bool universal_planes = READ_ONCE(lessor_priv->universal_planes);
388:
389: objects = kzalloc_objs(struct drm_mode_object *, object_count);
390: if (!objects)
391: return -ENOMEM;
392:
393: /* step one - get references to all the mode objects
394: and check for validity. */
395: for (o = 0; o < object_count; o++) {
396: objects[o] = drm_mode_object_find(dev, lessor_priv,
397: object_ids[o],
398: DRM_MODE_OBJECT_ANY);
399: if (!objects[o]) {
400: ret = -ENOENT;
401: goto out_free_objects;
402: }
403:
404: if (!drm_mode_object_lease_required(objects[o]->type)) {
405: DRM_DEBUG_KMS("invalid object for lease\n");
406: ret = -EINVAL;
407: goto out_free_objects;
408: }
409: }
410:
411: ret = validate_lease(dev, object_count, objects, universal_planes);
412: if (ret) {
413: drm_dbg_lease(dev, "lease validation failed\n");
414: goto out_free_objects;
415: }
416:
417: /* add their IDs to the lease request - taking into account
418: universal planes */
419: for (o = 0; o < object_count; o++) {
420: struct drm_mode_object *obj = objects[o];
421: u32 object_id = objects[o]->id;
422:
423: drm_dbg_lease(dev, "Adding object %d to lease\n", object_id);
424:
425: /*
426: * We're using an IDR to hold the set of leased
427: * objects, but we don't need to point at the object's
428: * data structure from the lease as the main object_idr
429: * will be used to actually find that. Instead, all we
430: * really want is a 'leased/not-leased' result, for
431: * which any non-NULL pointer will work fine.
432: */
433: ret = idr_alloc(leases, &drm_lease_idr_object , object_id, object_id + 1, GFP_KERNEL);
434: if (ret < 0) {
435: drm_dbg_lease(dev, "Object %d cannot be inserted into leases (%d)\n",
436: object_id, ret);
437: goto out_free_objects;
438: }
439: if (obj->type == DRM_MODE_OBJECT_CRTC && !universal_planes) {
440: struct drm_crtc *crtc = obj_to_crtc(obj);
441:
442: ret = idr_alloc(leases, &drm_lease_idr_object, crtc->primary->base.id, crtc->primary->base.id + 1, GFP_KERNEL);
443: if (ret < 0) {
444: drm_dbg_lease(dev, "Object primary plane %d cannot be inserted into leases (%d)\n",
445: object_id, ret);
446: goto out_free_objects;
447: }
448: if (crtc->cursor) {
449: ret = idr_alloc(leases, &drm_lease_idr_object, crtc->cursor->base.id, crtc->cursor->base.id + 1, GFP_KERNEL);
450: if (ret < 0) {
451: drm_dbg_lease(dev, "Object cursor plane %d cannot be inserted into leases (%d)\n",
452: object_id, ret);
453: goto out_free_objects;
454: }
455: }
456: }
457: }
458:
459: ret = 0;
460: out_free_objects:
461: for (o = 0; o < object_count; o++) {
462: if (objects[o])
463: drm_mode_object_put(objects[o]);
464: }
465: kfree(objects);
466: return ret;
467: }
SourceFile:drivers/gpu/drm/drm_lease.c]
|
| 12/2 |
2026/06/15 16:08 |
llm |
debugger |
0m
Model:
Tokens:
input: 11476
output: 18
thoughts: 59
Thoughts: **Debugging the Graphics Driver Crash**
Okay, so the kernel is crashing, and the backtrace points directly to `kzalloc_objs(struct drm_mode_object *, object_count);`. That's the key. Now, hold on a minute... `kzalloc_objs` doesn't ring any bells as a standard kernel function. It feels custom. Right, maybe it's a macro. Let's not jump to conclusions about a non-existent function. It's time to fire up the search tools and look for where `kzalloc_objs` is defined. This could be a driver-specific allocation routine, or perhaps even an incorrectly used standard function with an odd name. I need to understand what this macro is doing before I can even begin to understand the crash. Let's see what the source code reveals.
|
| 13/2 |
2026/06/15 16:08 |
tool |
grepper |
0m
Args: map[Expression:kzalloc_objs]
Results: map[Output:
Full output is too long, showing 500 out of 13925 lines.
Use more precise expression if possible.
Documentation/process/deprecated.rst=393=become, respectively::
--
Documentation/process/deprecated.rst-397- ptr = kmalloc_objs(*ptr, count, gfp);
Documentation/process/deprecated.rst:398: ptr = kzalloc_objs(*ptr, count, gfp);
Documentation/process/deprecated.rst-399- ptr = kmalloc_flex(*ptr, flex_member, count, gfp);
--
arch/alpha/kernel/module.c=64=module_frob_arch_sections(Elf64_Ehdr *hdr, Elf64_Shdr *sechdrs,
--
arch/alpha/kernel/module.c-95- nsyms = symtab->sh_size / sizeof(Elf64_Sym);
arch/alpha/kernel/module.c:96: chains = kzalloc_objs(struct got_entry, nsyms);
arch/alpha/kernel/module.c-97- if (!chains) {
--
arch/arm/kernel/vdso.c=169=static int __init vdso_init(void)
--
arch/arm/kernel/vdso.c-181- /* Allocate the VDSO text pagelist */
arch/arm/kernel/vdso.c:182: vdso_text_pagelist = kzalloc_objs(struct page *, text_pages);
arch/arm/kernel/vdso.c-183- if (vdso_text_pagelist == NULL)
--
arch/arm/mach-footbridge/dc21285.c=261=int __init dc21285_setup(int nr, struct pci_sys_data *sys)
--
arch/arm/mach-footbridge/dc21285.c-264-
arch/arm/mach-footbridge/dc21285.c:265: res = kzalloc_objs(struct resource, 2);
arch/arm/mach-footbridge/dc21285.c-266- if (!res) {
--
arch/arm/mach-omap1/mcbsp.c=292=static void omap_mcbsp_register_board_cfg(struct resource *res, int res_count,
--
arch/arm/mach-omap1/mcbsp.c-296-
arch/arm/mach-omap1/mcbsp.c:297: omap_mcbsp_devices = kzalloc_objs(struct platform_device *, size);
arch/arm/mach-omap1/mcbsp.c-298- if (!omap_mcbsp_devices) {
--
arch/arm/mach-omap2/omap_device.c=131=static int omap_device_build_from_dt(struct platform_device *pdev)
--
arch/arm/mach-omap2/omap_device.c-158-
arch/arm/mach-omap2/omap_device.c:159: hwmods = kzalloc_objs(struct omap_hwmod *, oh_cnt);
arch/arm/mach-omap2/omap_device.c-160- if (!hwmods) {
--
arch/arm/mach-omap2/pm33xx-core.c=379=static int __init amx3_idle_init(struct device_node *cpu_node, int cpu)
--
arch/arm/mach-omap2/pm33xx-core.c-412-
arch/arm/mach-omap2/pm33xx-core.c:413: idle_states = kzalloc_objs(*idle_states, state_count);
arch/arm/mach-omap2/pm33xx-core.c-414- if (!idle_states)
--
arch/arm/mach-omap2/sr_device.c=30=static void __init sr_set_nvalues(struct omap_volt_data *volt_data,
--
arch/arm/mach-omap2/sr_device.c-41-
arch/arm/mach-omap2/sr_device.c:42: nvalue_table = kzalloc_objs(*nvalue_table, count);
arch/arm/mach-omap2/sr_device.c-43- if (!nvalue_table)
--
arch/arm/mach-versatile/spc.c=393=static int ve_spc_populate_opps(uint32_t cluster)
--
arch/arm/mach-versatile/spc.c-397-
arch/arm/mach-versatile/spc.c:398: opps = kzalloc_objs(*opps, MAX_OPPS);
arch/arm/mach-versatile/spc.c-399- if (!opps)
--
arch/arm/xen/enlighten.c=316=int __init arch_xen_unpopulated_init(struct resource **res)
--
arch/arm/xen/enlighten.c-343-
arch/arm/xen/enlighten.c:344: regs = kzalloc_objs(*regs, nr_reg);
arch/arm/xen/enlighten.c-345- if (!regs) {
--
arch/arm64/kernel/vdso.c=68=static int __init __vdso_init(enum vdso_abi abi)
--
arch/arm64/kernel/vdso.c-83-
arch/arm64/kernel/vdso.c:84: vdso_pagelist = kzalloc_objs(struct page *, vdso_info[abi].vdso_pages);
arch/arm64/kernel/vdso.c-85- if (vdso_pagelist == NULL)
--
arch/arm64/kvm/vgic/vgic-init.c=207=static int kvm_vgic_dist_init(struct kvm *kvm, unsigned int nr_spis)
--
arch/arm64/kvm/vgic/vgic-init.c-213- dist->active_spis = (atomic_t)ATOMIC_INIT(0);
arch/arm64/kvm/vgic/vgic-init.c:214: dist->spis = kzalloc_objs(struct vgic_irq, nr_spis, GFP_KERNEL_ACCOUNT);
arch/arm64/kvm/vgic/vgic-init.c-215- if (!dist->spis)
--
arch/arm64/kvm/vgic/vgic-init.c=329=static int vgic_allocate_private_irqs_locked(struct kvm_vcpu *vcpu, u32 type)
--
arch/arm64/kvm/vgic/vgic-init.c-344-
arch/arm64/kvm/vgic/vgic-init.c:345: vgic_cpu->private_irqs = kzalloc_objs(struct vgic_irq,
arch/arm64/kvm/vgic/vgic-init.c-346- num_private_irqs,
--
arch/arm64/kvm/vgic/vgic-irqfd.c=136=int kvm_vgic_setup_default_irq_routing(struct kvm *kvm)
--
arch/arm64/kvm/vgic/vgic-irqfd.c-142-
arch/arm64/kvm/vgic/vgic-irqfd.c:143: entries = kzalloc_objs(*entries, nr, GFP_KERNEL_ACCOUNT);
arch/arm64/kvm/vgic/vgic-irqfd.c-144- if (!entries)
--
arch/arm64/kvm/vgic/vgic-v4.c=242=int vgic_v4_init(struct kvm *kvm)
--
arch/arm64/kvm/vgic/vgic-v4.c-258-
arch/arm64/kvm/vgic/vgic-v4.c:259: dist->its_vm.vpes = kzalloc_objs(*dist->its_vm.vpes, nr_vcpus,
arch/arm64/kvm/vgic/vgic-v4.c-260- GFP_KERNEL_ACCOUNT);
--
arch/csky/kernel/vdso.c=17=static int __init vdso_init(void)
--
arch/csky/kernel/vdso.c-22- vdso_pagelist =
arch/csky/kernel/vdso.c:23: kzalloc_objs(struct page *, vdso_pages);
arch/csky/kernel/vdso.c-24- if (unlikely(vdso_pagelist == NULL)) {
--
arch/loongarch/kernel/vdso.c=45=static int __init init_vdso(void)
--
arch/loongarch/kernel/vdso.c-55- vdso_info.code_mapping.pages =
arch/loongarch/kernel/vdso.c:56: kzalloc_objs(struct page *, vdso_info.size / PAGE_SIZE);
arch/loongarch/kernel/vdso.c-57-
--
arch/loongarch/kvm/intc/pch_pic.c=410=static int kvm_setup_default_irq_routing(struct kvm *kvm)
--
arch/loongarch/kvm/intc/pch_pic.c-415-
arch/loongarch/kvm/intc/pch_pic.c:416: entries = kzalloc_objs(*entries, nr);
arch/loongarch/kvm/intc/pch_pic.c-417- if (!entries)
--
arch/mips/alchemy/common/clock.c=754=static int __init alchemy_clk_init_fgens(int ctype)
--
arch/mips/alchemy/common/clock.c-777-
arch/mips/alchemy/common/clock.c:778: a = kzalloc_objs(*a, 6);
arch/mips/alchemy/common/clock.c-779- if (!a)
--
arch/mips/alchemy/common/clock.c=960=static int __init alchemy_clk_setup_imux(int ctype)
--
arch/mips/alchemy/common/clock.c-998-
arch/mips/alchemy/common/clock.c:999: a = kzalloc_objs(*a, 6);
arch/mips/alchemy/common/clock.c-1000- if (!a)
--
arch/mips/alchemy/common/dbdma.c=1056=static int __init dbdma_setup(unsigned int irq, dbdev_tab_t *idtable)
--
arch/mips/alchemy/common/dbdma.c-1059-
arch/mips/alchemy/common/dbdma.c:1060: dbdev_tab = kzalloc_objs(dbdev_tab_t, DBDEV_TAB_SIZE);
arch/mips/alchemy/common/dbdma.c-1061- if (!dbdev_tab)
--
arch/mips/alchemy/common/platform.c=203=static int __init _new_usbres(struct resource **r, struct platform_device **d)
arch/mips/alchemy/common/platform.c-204-{
arch/mips/alchemy/common/platform.c:205: *r = kzalloc_objs(struct resource, 2);
arch/mips/alchemy/common/platform.c-206- if (!*r)
--
arch/mips/alchemy/devboards/platform.c=68=int __init db1x_register_pcmcia_socket(phys_addr_t pcmcia_attr_start,
--
arch/mips/alchemy/devboards/platform.c-89-
arch/mips/alchemy/devboards/platform.c:90: sr = kzalloc_objs(struct resource, cnt);
arch/mips/alchemy/devboards/platform.c-91- if (!sr)
--
arch/mips/alchemy/devboards/platform.c=152=int __init db1x_register_norflash(unsigned long size, int width,
--
arch/mips/alchemy/devboards/platform.c-164- ret = -ENOMEM;
arch/mips/alchemy/devboards/platform.c:165: parts = kzalloc_objs(struct mtd_partition, 5);
arch/mips/alchemy/devboards/platform.c-166- if (!parts)
--
arch/mips/kernel/smp-cps.c=295=static void __init cps_prepare_cpus(unsigned int max_cpus)
--
arch/mips/kernel/smp-cps.c-343- nclusters = mips_cps_numclusters();
arch/mips/kernel/smp-cps.c:344: mips_cps_cluster_bootcfg = kzalloc_objs(*mips_cps_cluster_bootcfg,
arch/mips/kernel/smp-cps.c-345- nclusters);
--
arch/mips/kernel/smp-cps.c-354- ncores = mips_cps_numcores(cl);
arch/mips/kernel/smp-cps.c:355: core_bootcfg = kzalloc_objs(*core_bootcfg, ncores);
arch/mips/kernel/smp-cps.c-356- if (!core_bootcfg)
--
arch/mips/kernel/smp-cps.c-369- core_vpes = core_vpe_count(cl, c);
arch/mips/kernel/smp-cps.c:370: core_bootcfg[c].vpe_config = kzalloc_objs(*core_bootcfg[c].vpe_config,
arch/mips/kernel/smp-cps.c-371- core_vpes);
--
arch/parisc/kernel/vdso.c=99=static struct page ** __init vdso_setup_pages(void *start, void *end)
--
arch/parisc/kernel/vdso.c-104-
arch/parisc/kernel/vdso.c:105: pagelist = kzalloc_objs(struct page *, pages + 1);
arch/parisc/kernel/vdso.c-106- if (!pagelist)
--
arch/parisc/net/bpf_jit_core.c=44=struct bpf_prog *bpf_int_jit_compile(struct bpf_verifier_env *env, struct bpf_prog *prog)
--
arch/parisc/net/bpf_jit_core.c-71- ctx->prog = prog;
arch/parisc/net/bpf_jit_core.c:72: ctx->offset = kzalloc_objs(int, prog->len);
arch/parisc/net/bpf_jit_core.c-73- if (!ctx->offset)
--
arch/powerpc/kernel/smp.c=1113=void __init smp_prepare_cpus(unsigned int max_cpus)
--
arch/powerpc/kernel/smp.c-1174- */
arch/powerpc/kernel/smp.c:1175: chip_id_lookup_table = kzalloc_objs(int, idx);
arch/powerpc/kernel/smp.c-1176- if (chip_id_lookup_table)
--
arch/powerpc/kernel/vdso.c=242=static struct page ** __init vdso_setup_pages(void *start, void *end)
--
arch/powerpc/kernel/vdso.c-247-
arch/powerpc/kernel/vdso.c:248: pagelist = kzalloc_objs(struct page *, pages + 1);
arch/powerpc/kernel/vdso.c-249- if (!pagelist)
--
arch/powerpc/kvm/e500_mmu.c=731=int kvm_vcpu_ioctl_config_tlb(struct kvm_vcpu *vcpu,
--
arch/powerpc/kvm/e500_mmu.c-794-
arch/powerpc/kvm/e500_mmu.c:795: privs[0] = kzalloc_objs(*privs[0], params.tlb_sizes[0]);
arch/powerpc/kvm/e500_mmu.c-796- if (!privs[0]) {
--
arch/powerpc/kvm/e500_mmu.c-800-
arch/powerpc/kvm/e500_mmu.c:801: privs[1] = kzalloc_objs(*privs[1], params.tlb_sizes[1]);
arch/powerpc/kvm/e500_mmu.c-802- if (!privs[1]) {
--
arch/powerpc/kvm/e500_mmu.c=898=int kvmppc_e500_tlb_init(struct kvmppc_vcpu_e500 *vcpu_e500)
--
arch/powerpc/kvm/e500_mmu.c-922-
arch/powerpc/kvm/e500_mmu.c:923: vcpu_e500->gtlb_priv[0] = kzalloc_objs(struct tlbe_priv,
arch/powerpc/kvm/e500_mmu.c-924- vcpu_e500->gtlb_params[0].entries);
--
arch/powerpc/kvm/e500_mmu.c-927-
arch/powerpc/kvm/e500_mmu.c:928: vcpu_e500->gtlb_priv[1] = kzalloc_objs(struct tlbe_priv,
arch/powerpc/kvm/e500_mmu.c-929- vcpu_e500->gtlb_params[1].entries);
--
arch/powerpc/mm/drmem.c=425=static void __init init_drmem_v1_lmbs(const __be32 *prop)
--
arch/powerpc/mm/drmem.c-432-
arch/powerpc/mm/drmem.c:433: drmem_info->lmbs = kzalloc_objs(*lmb, drmem_info->n_lmbs);
arch/powerpc/mm/drmem.c-434- if (!drmem_info->lmbs)
--
arch/powerpc/mm/drmem.c=441=static void __init init_drmem_v2_lmbs(const __be32 *prop)
--
arch/powerpc/mm/drmem.c-459-
arch/powerpc/mm/drmem.c:460: drmem_info->lmbs = kzalloc_objs(*lmb, drmem_info->n_lmbs);
arch/powerpc/mm/drmem.c-461- if (!drmem_info->lmbs)
--
arch/powerpc/perf/imc-pmu.c=221=static int update_events_in_group(struct device_node *node, struct imc_pmu *pmu)
--
arch/powerpc/perf/imc-pmu.c-259- /* Allocate memory for the events */
arch/powerpc/perf/imc-pmu.c:260: pmu->events = kzalloc_objs(struct imc_events, ct);
arch/powerpc/perf/imc-pmu.c-261- if (!pmu->events) {
--
arch/powerpc/perf/imc-pmu.c-290- */
arch/powerpc/perf/imc-pmu.c:291: attrs = kzalloc_objs(struct attribute *, ((ct * 3) + 1));
arch/powerpc/perf/imc-pmu.c-292- if (!attrs) {
--
arch/powerpc/perf/imc-pmu.c=1526=static int init_nest_pmu_ref(void)
--
arch/powerpc/perf/imc-pmu.c-1529-
arch/powerpc/perf/imc-pmu.c:1530: nest_imc_refc = kzalloc_objs(*nest_imc_refc, num_possible_nodes());
arch/powerpc/perf/imc-pmu.c-1531-
--
arch/powerpc/perf/imc-pmu.c=1683=static int imc_mem_init(struct imc_pmu *pmu_ptr, struct device_node *parent,
--
arch/powerpc/perf/imc-pmu.c-1700- if (!per_nest_pmu_arr) {
arch/powerpc/perf/imc-pmu.c:1701: per_nest_pmu_arr = kzalloc_objs(struct imc_pmu *,
arch/powerpc/perf/imc-pmu.c-1702- get_max_nest_dev() + 1);
--
arch/powerpc/perf/imc-pmu.c-1714- nr_cores = DIV_ROUND_UP(num_possible_cpus(), threads_per_core);
arch/powerpc/perf/imc-pmu.c:1715: pmu_ptr->mem_info = kzalloc_objs(struct imc_mem_info, nr_cores);
arch/powerpc/perf/imc-pmu.c-1716-
--
arch/powerpc/perf/imc-pmu.c-1719-
arch/powerpc/perf/imc-pmu.c:1720: core_imc_refc = kzalloc_objs(struct imc_pmu_ref, nr_cores);
arch/powerpc/perf/imc-pmu.c-1721-
--
arch/powerpc/perf/imc-pmu.c-1752- nr_cores = DIV_ROUND_UP(num_possible_cpus(), threads_per_core);
arch/powerpc/perf/imc-pmu.c:1753: trace_imc_refc = kzalloc_objs(struct imc_pmu_ref, nr_cores);
arch/powerpc/perf/imc-pmu.c-1754- if (!trace_imc_refc)
--
arch/powerpc/perf/vpa-dtl.c=508=static void *vpa_dtl_setup_aux(struct perf_event *event, void **pages,
--
arch/powerpc/perf/vpa-dtl.c-525-
arch/powerpc/perf/vpa-dtl.c:526: pglist = kzalloc_objs(*pglist, nr_pages);
arch/powerpc/perf/vpa-dtl.c-527- if (!pglist)
--
arch/powerpc/platforms/44x/pci.c=1307=static int __init ppc4xx_pciex_check_core_init(struct device_node *np)
--
arch/powerpc/platforms/44x/pci.c-1341- ppc4xx_pciex_ports =
arch/powerpc/platforms/44x/pci.c:1342: kzalloc_objs(struct ppc4xx_pciex_port, count);
arch/powerpc/platforms/44x/pci.c-1343- if (ppc4xx_pciex_ports) {
--
arch/powerpc/platforms/powernv/idle.c=1322=static int __init pnv_parse_cpuidle_dt(void)
--
arch/powerpc/platforms/powernv/idle.c-1338-
arch/powerpc/platforms/powernv/idle.c:1339: pnv_idle_states = kzalloc_objs(*pnv_idle_states, nr_idle_states);
arch/powerpc/platforms/powernv/idle.c-1340- temp_u32 = kcalloc(nr_idle_states, sizeof(u32), GFP_KERNEL);
--
arch/powerpc/platforms/powernv/memtrace.c=131=static int memtrace_init_regions_runtime(u64 size)
--
arch/powerpc/platforms/powernv/memtrace.c-135-
arch/powerpc/platforms/powernv/memtrace.c:136: memtrace_array = kzalloc_objs(struct memtrace_entry, num_online_nodes());
arch/powerpc/platforms/powernv/memtrace.c-137- if (!memtrace_array) {
--
arch/powerpc/platforms/powernv/opal-async.c=246=int __init opal_async_comp_init(void)
--
arch/powerpc/platforms/powernv/opal-async.c-267- opal_max_async_tokens = be32_to_cpup(async);
arch/powerpc/platforms/powernv/opal-async.c:268: opal_async_tokens = kzalloc_objs(*opal_async_tokens,
arch/powerpc/platforms/powernv/opal-async.c-269- opal_max_async_tokens);
--
arch/powerpc/platforms/powernv/opal-imc.c=82=static int imc_get_mem_addr_nest(struct device_node *node,
--
arch/powerpc/platforms/powernv/opal-imc.c-110-
arch/powerpc/platforms/powernv/opal-imc.c:111: pmu_ptr->mem_info = kzalloc_objs(*pmu_ptr->mem_info, nr_chips + 1);
arch/powerpc/platforms/powernv/opal-imc.c-112- if (!pmu_ptr->mem_info)
--
arch/powerpc/platforms/powernv/opal-irqchip.c=174=int __init opal_event_init(void)
--
arch/powerpc/platforms/powernv/opal-irqchip.c-223- /* Allocate an IRQ resources array */
arch/powerpc/platforms/powernv/opal-irqchip.c:224: opal_irqs = kzalloc_objs(struct resource, opal_irq_count);
arch/powerpc/platforms/powernv/opal-irqchip.c-225- if (WARN_ON(!opal_irqs)) {
--
arch/powerpc/platforms/powernv/opal-powercap.c=142=void __init opal_powercap_init(void)
--
arch/powerpc/platforms/powernv/opal-powercap.c-152-
arch/powerpc/platforms/powernv/opal-powercap.c:153: pcaps = kzalloc_objs(*pcaps, of_get_child_count(powercap));
arch/powerpc/platforms/powernv/opal-powercap.c-154- if (!pcaps)
--
arch/powerpc/platforms/powernv/opal-powercap.c-183-
arch/powerpc/platforms/powernv/opal-powercap.c:184: pcaps[i].pattrs = kzalloc_objs(struct powercap_attr, j);
arch/powerpc/platforms/powernv/opal-powercap.c-185- if (!pcaps[i].pattrs)
--
arch/powerpc/platforms/powernv/opal-powercap.c-187-
arch/powerpc/platforms/powernv/opal-powercap.c:188: pcaps[i].pg.attrs = kzalloc_objs(struct attribute *, j + 1);
arch/powerpc/platforms/powernv/opal-powercap.c-189- if (!pcaps[i].pg.attrs) {
--
arch/powerpc/platforms/powernv/opal-psr.c=123=void __init opal_psr_init(void)
--
arch/powerpc/platforms/powernv/opal-psr.c-134-
arch/powerpc/platforms/powernv/opal-psr.c:135: psr_attrs = kzalloc_objs(*psr_attrs, of_get_child_count(psr));
arch/powerpc/platforms/powernv/opal-psr.c-136- if (!psr_attrs)
--
arch/powerpc/platforms/powernv/opal-sensor-groups.c=160=void __init opal_sensor_groups_init(void)
--
arch/powerpc/platforms/powernv/opal-sensor-groups.c-170-
arch/powerpc/platforms/powernv/opal-sensor-groups.c:171: sgs = kzalloc_objs(*sgs, of_get_child_count(sg));
arch/powerpc/platforms/powernv/opal-sensor-groups.c-172- if (!sgs)
--
arch/powerpc/platforms/powernv/opal-sensor-groups.c-192-
arch/powerpc/platforms/powernv/opal-sensor-groups.c:193: sgs[i].sgattrs = kzalloc_objs(*sgs[i].sgattrs, nr_attrs);
arch/powerpc/platforms/powernv/opal-sensor-groups.c-194- if (!sgs[i].sgattrs)
--
arch/powerpc/platforms/powernv/opal-sensor-groups.c-196-
arch/powerpc/platforms/powernv/opal-sensor-groups.c:197: sgs[i].sg.attrs = kzalloc_objs(*sgs[i].sg.attrs, nr_attrs + 1);
arch/powerpc/platforms/powernv/opal-sensor-groups.c-198-
--
arch/powerpc/platforms/powernv/opal-sysparam.c=143=void __init opal_sys_param_init(void)
--
arch/powerpc/platforms/powernv/opal-sysparam.c-224-
arch/powerpc/platforms/powernv/opal-sysparam.c:225: attr = kzalloc_objs(*attr, count);
arch/powerpc/platforms/powernv/opal-sysparam.c-226- if (!attr) {
--
arch/powerpc/platforms/pseries/papr_platform_attributes.c=233=static int __init papr_init(void)
--
arch/powerpc/platforms/pseries/papr_platform_attributes.c-297-
arch/powerpc/platforms/pseries/papr_platform_attributes.c:298: papr_groups = kzalloc_objs(*papr_groups, num_attrs);
arch/powerpc/platforms/pseries/papr_platform_attributes.c-299- if (!papr_groups)
--
arch/powerpc/platforms/pseries/papr_platform_attributes.c-315- for (idx = 0; idx < num_attrs; idx++) {
arch/powerpc/platforms/pseries/papr_platform_attributes.c:316: papr_groups[idx].pg.attrs = kzalloc_objs(*papr_groups[idx].pg.attrs,
arch/powerpc/platforms/pseries/papr_platform_attributes.c-317- KOBJ_MAX_ATTRS + 1);
--
arch/powerpc/sysdev/mpic.c=542=static void __init mpic_scan_ht_pics(struct mpic *mpic)
--
arch/powerpc/sysdev/mpic.c-549- /* Allocate fixups array */
arch/powerpc/sysdev/mpic.c:550: mpic->fixups = kzalloc_objs(*mpic->fixups, 128);
arch/powerpc/sysdev/mpic.c-551- BUG_ON(mpic->fixups == NULL);
--
arch/powerpc/sysdev/mpic_msgr.c=167=static int mpic_msgr_probe(struct platform_device *dev)
--
arch/powerpc/sysdev/mpic_msgr.c-190-
arch/powerpc/sysdev/mpic_msgr.c:191: mpic_msgrs = kzalloc_objs(*mpic_msgrs, mpic_msgr_count);
arch/powerpc/sysdev/mpic_msgr.c-192- if (!mpic_msgrs) {
--
arch/powerpc/sysdev/xive/common.c=1118=static int __init xive_init_ipis(void)
--
arch/powerpc/sysdev/xive/common.c-1133-
arch/powerpc/sysdev/xive/common.c:1134: xive_ipis = kzalloc_objs(*xive_ipis, nr_node_ids,
arch/powerpc/sysdev/xive/common.c-1135- GFP_KERNEL | __GFP_NOFAIL);
--
arch/riscv/kernel/tests/kprobes/test-kprobes.c=13=static void test_kprobe_riscv(struct kunit *test)
--
arch/riscv/kernel/tests/kprobes/test-kprobes.c-22-
arch/riscv/kernel/tests/kprobes/test-kprobes.c:23: kp = kzalloc_objs(*kp, num_kprobe);
arch/riscv/kernel/tests/kprobes/test-kprobes.c-24- KUNIT_EXPECT_TRUE(test, kp);
--
arch/riscv/kernel/unaligned_access_speed.c=154=static void __init check_unaligned_access_speed_all_cpus(void)
--
arch/riscv/kernel/unaligned_access_speed.c-157- unsigned int cpu_count = num_possible_cpus();
arch/riscv/kernel/unaligned_access_speed.c:158: struct page **bufs = kzalloc_objs(*bufs, cpu_count);
arch/riscv/kernel/unaligned_access_speed.c-159-
--
arch/riscv/kernel/vdso.c=44=static void __init __vdso_init(struct __vdso_info *vdso_info)
--
arch/riscv/kernel/vdso.c-57-
arch/riscv/kernel/vdso.c:58: vdso_pagelist = kzalloc_objs(struct page *, vdso_info->vdso_pages);
arch/riscv/kernel/vdso.c-59- if (vdso_pagelist == NULL)
--
arch/riscv/kvm/aia_aplic.c=574=int kvm_riscv_aia_aplic_init(struct kvm *kvm)
--
arch/riscv/kvm/aia_aplic.c-591- aplic->nr_words = DIV_ROUND_UP(aplic->nr_irqs, 32);
arch/riscv/kvm/aia_aplic.c:592: aplic->irqs = kzalloc_objs(*aplic->irqs, aplic->nr_irqs);
arch/riscv/kvm/aia_aplic.c-593- if (!aplic->irqs) {
--
arch/riscv/kvm/vcpu_sbi_fwft.c=348=static int kvm_sbi_ext_fwft_init(struct kvm_vcpu *vcpu)
--
arch/riscv/kvm/vcpu_sbi_fwft.c-354-
arch/riscv/kvm/vcpu_sbi_fwft.c:355: fwft->configs = kzalloc_objs(struct kvm_sbi_fwft_config,
arch/riscv/kvm/vcpu_sbi_fwft.c-356- ARRAY_SIZE(features));
--
arch/riscv/kvm/vm.c=93=int kvm_riscv_setup_default_irq_routing(struct kvm *kvm, u32 lines)
--
arch/riscv/kvm/vm.c-97-
arch/riscv/kvm/vm.c:98: ents = kzalloc_objs(*ents, lines);
arch/riscv/kvm/vm.c-99- if (!ents)
--
arch/riscv/net/bpf_jit_comp64.c=1022=static int __arch_prepare_bpf_trampoline(struct bpf_tramp_image *im,
--
arch/riscv/net/bpf_jit_comp64.c-1197- if (fmod_ret->nr_links) {
arch/riscv/net/bpf_jit_comp64.c:1198: branches_off = kzalloc_objs(int, fmod_ret->nr_links);
arch/riscv/net/bpf_jit_comp64.c-1199- if (!branches_off)
--
arch/riscv/net/bpf_jit_core.c=44=struct bpf_prog *bpf_int_jit_compile(struct bpf_verifier_env *env, struct bpf_prog *prog)
--
arch/riscv/net/bpf_jit_core.c-74- ctx->prog = prog;
arch/riscv/net/bpf_jit_core.c:75: ctx->offset = kzalloc_objs(int, prog->len);
arch/riscv/net/bpf_jit_core.c-76- if (!ctx->offset)
--
arch/s390/appldata/appldata_base.c=348=int appldata_register_ops(struct appldata_ops *ops)
--
arch/s390/appldata/appldata_base.c-352-
arch/s390/appldata/appldata_base.c:353: ops->ctl_table = kzalloc_objs(struct ctl_table, 1);
arch/s390/appldata/appldata_base.c-354- if (!ops->ctl_table)
--
arch/s390/include/asm/idals.h=88=static inline int set_normalized_cda(struct ccw1 *ccw, void *vaddr)
--
arch/s390/include/asm/idals.h-96- if (nridaws > 0) {
arch/s390/include/asm/idals.h:97: idal = kzalloc_objs(*idal, nridaws, GFP_ATOMIC | GFP_DMA);
arch/s390/include/asm/idals.h-98- if (!idal)
--
arch/s390/kernel/cert_store.c=315=static int invalidate_keyring_keys(struct key *keyring)
--
arch/s390/kernel/cert_store.c-324- num_keys = keyring_payload_len / sizeof(key_serial_t);
arch/s390/kernel/cert_store.c:325: key_array = kzalloc_objs(key_serial_t, num_keys);
arch/s390/kernel/cert_store.c-326- if (!key_array)
--
arch/s390/kernel/debug.c=220=static debug_info_t *debug_info_alloc(const char *name, int pages_per_area,
--
arch/s390/kernel/debug.c-229- goto fail_malloc_rc;
arch/s390/kernel/debug.c:230: rc->active_entries = kzalloc_objs(int, nr_areas);
arch/s390/kernel/debug.c-231- if (!rc->active_entries)
arch/s390/kernel/debug.c-232- goto fail_malloc_active_entries;
arch/s390/kernel/debug.c:233: rc->active_pages = kzalloc_objs(int, nr_areas);
arch/s390/kernel/debug.c-234- if (!rc->active_pages)
--
arch/s390/kernel/vdso.c=129=static struct page ** __init vdso_setup_pages(void *start, void *end)
--
arch/s390/kernel/vdso.c-134-
arch/s390/kernel/vdso.c:135: pagelist = kzalloc_objs(struct page *, pages + 1);
arch/s390/kernel/vdso.c-136- if (!pagelist)
--
arch/s390/kvm/pci.c=120=int kvm_s390_pci_aen_init(u8 nisc)
--
arch/s390/kvm/pci.c-128- mutex_lock(&aift->aift_lock);
arch/s390/kvm/pci.c:129: aift->kzdev = kzalloc_objs(struct kvm_zdev *, ZPCI_NR_DEVICES);
arch/s390/kvm/pci.c-130- if (!aift->kzdev) {
--
arch/s390/pci/pci.c=1065=static int zpci_mem_init(void)
--
arch/s390/pci/pci.c-1076-
arch/s390/pci/pci.c:1077: zpci_iomap_start = kzalloc_objs(*zpci_iomap_start, ZPCI_IOMAP_ENTRIES);
arch/s390/pci/pci.c-1078- if (!zpci_iomap_start)
--
arch/s390/pci/pci_irq.c=552=static int __init zpci_directed_irq_init(void)
--
arch/s390/pci/pci_irq.c-565-
arch/s390/pci/pci_irq.c:566: zpci_ibv = kzalloc_objs(*zpci_ibv, num_possible_cpus());
arch/s390/pci/pci_irq.c-567- if (!zpci_ibv)
--
arch/s390/pci/pci_irq.c=590=static int __init zpci_floating_irq_init(void)
arch/s390/pci/pci_irq.c-591-{
arch/s390/pci/pci_irq.c:592: zpci_ibv = kzalloc_objs(*zpci_ibv, ZPCI_NR_DEVICES);
arch/s390/pci/pci_irq.c-593- if (!zpci_ibv)
--
arch/sh/drivers/dma/dmabrg.c=151=static int __init dmabrg_init(void)
--
arch/sh/drivers/dma/dmabrg.c-155-
arch/sh/drivers/dma/dmabrg.c:156: dmabrg_handlers = kzalloc_objs(struct dmabrg_handler, 10);
arch/sh/drivers/dma/dmabrg.c-157- if (!dmabrg_handlers)
--
arch/sh/drivers/pci/pcie-sh7786.c=545=static int __init sh7786_pcie_init(void)
--
arch/sh/drivers/pci/pcie-sh7786.c-560-
arch/sh/drivers/pci/pcie-sh7786.c:561: sh7786_pcie_ports = kzalloc_objs(struct sh7786_pcie_port, nr_ports);
arch/sh/drivers/pci/pcie-sh7786.c-562- if (unlikely(!sh7786_pcie_ports))
--
arch/sparc/kernel/sys_sparc_64.c=625=SYSCALL_DEFINE5(utrap_install, utrap_entry_t, type,
--
arch/sparc/kernel/sys_sparc_64.c-649- current_thread_info()->utraps =
arch/sparc/kernel/sys_sparc_64.c:650: kzalloc_objs(long, UT_TRAP_INSTRUCTION_31 + 1);
arch/sparc/kernel/sys_sparc_64.c-651- if (!current_thread_info()->utraps)
--
arch/sparc/vdso/vma.c=46=static int __init init_vdso_image(const struct vdso_image *image,
--
arch/sparc/vdso/vma.c-60-
arch/sparc/vdso/vma.c:61: cpp = kzalloc_objs(struct page *, cnpages);
arch/sparc/vdso/vma.c-62- vdso_mapping->pages = cpp;
--
arch/x86/events/amd/iommu.c=382=static __init int _init_events_attrs(void)
--
arch/x86/events/amd/iommu.c-389-
arch/x86/events/amd/iommu.c:390: attrs = kzalloc_objs(*attrs, i + 1);
arch/x86/events/amd/iommu.c-391- if (!attrs)
--
arch/x86/events/intel/core.c=7420=static __always_inline int intel_pmu_init_hybrid(enum hybrid_pmu_type pmus)
--
arch/x86/events/intel/core.c-7426- x86_pmu.num_hybrid_pmus = hweight_long(pmus_mask);
arch/x86/events/intel/core.c:7427: x86_pmu.hybrid_pmu = kzalloc_objs(struct x86_hybrid_pmu,
arch/x86/events/intel/core.c-7428- x86_pmu.num_hybrid_pmus);
--
arch/x86/events/intel/uncore.c=988=static int __init uncore_type_init(struct intel_uncore_type *type)
--
arch/x86/events/intel/uncore.c-993-
]
|
| 14/2 |
2026/06/15 16:08 |
llm |
debugger |
0m
Model:
Tokens:
input: 23590
output: 20
thoughts: 124
Thoughts: **Investigating an Unfamiliar Allocation Macro**
Okay, so I've come across this `kzalloc_objs` thing. My first instinct, being familiar with the kernel's memory management, is to quickly check where it's defined. My first thought is to look in the standard slab headers, `include/linux/slab.h` or maybe the related `include/linux/slab_def.h`. Hmm, that's not quite right. `kzalloc_objs` doesn't immediately ring a bell. Is it a non-standard name? I think the proper approach would be to use `kcalloc` or `kmalloc_array`.
Wait... is `kzalloc_objs` not even showing up when I search for its definition? That's odd. Let me double-check the immediate output related to `kzalloc_objs`. Still nothing. Okay, perhaps it's defined in `include/linux/slab.h` after all, despite it not seeming like the most standard of allocations. Let me run a search for `#define kzalloc_objs` or something similar, just to be absolutely sure. This is an unusual allocation construct, I need to figure out where it comes from.
|
| 15/2 |
2026/06/15 16:08 |
tool |
grepper |
0m
Args: map[Expression:#define kzalloc_objs]
Results: map[Output:include/linux/slab.h=958=void *kmalloc_nolock_noprof(size_t size, gfp_t gfp_flags, int node);
--
include/linux/slab.h-1040- __alloc_objs(kzalloc, default_gfp(__VA_ARGS__), typeof(P), 1)
include/linux/slab.h:1041:#define kzalloc_objs(P, COUNT, ...) \
include/linux/slab.h-1042- __alloc_objs(kzalloc, default_gfp(__VA_ARGS__), typeof(P), COUNT)
]
|
| 16/2 |
2026/06/15 16:08 |
llm |
debugger |
1m
Model:
Tokens:
input: 24151
output: 41
thoughts: 510
Thoughts: **Analyzing a Potential Memory Allocation Issue**
Okay, so I'm looking at this `kzalloc_objs` function, which appears to allocate an array of `drm_mode_object` pointers. The core of it seems to be calling `kzalloc`, which makes me immediately think of memory allocation limits. Let's see, `object_count` is a hefty `0xf4240` (1,000,000). And since a `drm_mode_object *` is 8 bytes, the total size of the allocation is a substantial 8MB.
Now, alarm bells are going off. While `kzalloc` is generally safe, it relies on `kmalloc` underneath, and `kmalloc` *definitely* has size limits. So, allocating an 8MB block directly with `kzalloc` (or, by extension, `kmalloc`) is making me a bit nervous. I need to be sure this is handled correctly.
Let me refresh my memory and examine the crash again. The backtrace shows a warning from `mm/page_alloc.c:5197`, a clear red flag. That's a strong hint that the underlying memory allocation isn't happening properly. Let's dig into that specific line of code in `mm/page_alloc.c` and figure out why it's complaining. It's time to understand exactly where the allocation is failing and why the kernel's memory management is issuing a warning. We need to prevent such allocations from crashing the system.
|
| 17/2 |
2026/06/15 16:09 |
tool |
codesearch-definition-source |
0m
Args: map[ContextFile:mm/page_alloc.c Name:__alloc_frozen_pages_noprof]
Results: map[SourceCode:5182: /*
5183: * This is the 'heart' of the zoned buddy allocator.
5184: */
5185: struct page *__alloc_frozen_pages_noprof(gfp_t gfp, unsigned int order,
5186: int preferred_nid, nodemask_t *nodemask)
5187: {
5188: struct page *page;
5189: unsigned int alloc_flags = ALLOC_WMARK_LOW;
5190: gfp_t alloc_gfp; /* The gfp_t that was actually used for allocation */
5191: struct alloc_context ac = { };
5192:
5193: /*
5194: * There are several places where we assume that the order value is sane
5195: * so bail out early if the request is out of bound.
5196: */
5197: if (WARN_ON_ONCE_GFP(order > MAX_PAGE_ORDER, gfp))
5198: return NULL;
5199:
5200: gfp &= gfp_allowed_mask;
5201: /*
5202: * Apply scoped allocation constraints. This is mainly about GFP_NOFS
5203: * resp. GFP_NOIO which has to be inherited for all allocation requests
5204: * from a particular context which has been marked by
5205: * memalloc_no{fs,io}_{save,restore}. And PF_MEMALLOC_PIN which ensures
5206: * movable zones are not used during allocation.
5207: */
5208: gfp = current_gfp_context(gfp);
5209: alloc_gfp = gfp;
5210: if (!prepare_alloc_pages(gfp, order, preferred_nid, nodemask, &ac,
5211: &alloc_gfp, &alloc_flags))
5212: return NULL;
5213:
5214: /*
5215: * Forbid the first pass from falling back to types that fragment
5216: * memory until all local zones are considered.
5217: */
5218: alloc_flags |= alloc_flags_nofragment(zonelist_zone(ac.preferred_zoneref), gfp);
5219:
5220: /* First allocation attempt */
5221: page = get_page_from_freelist(alloc_gfp, order, alloc_flags, &ac);
5222: if (likely(page))
5223: goto out;
5224:
5225: alloc_gfp = gfp;
5226: ac.spread_dirty_pages = false;
5227:
5228: /*
5229: * Restore the original nodemask if it was potentially replaced with
5230: * &cpuset_current_mems_allowed to optimize the fast-path attempt.
5231: */
5232: ac.nodemask = nodemask;
5233:
5234: page = __alloc_pages_slowpath(alloc_gfp, order, &ac);
5235:
5236: out:
5237: if (memcg_kmem_online() && (gfp & __GFP_ACCOUNT) && page &&
5238: unlikely(__memcg_kmem_charge_page(page, gfp, order) != 0)) {
5239: free_frozen_pages(page, order);
5240: page = NULL;
5241: }
5242:
5243: trace_mm_page_alloc(page, order, alloc_gfp, ac.migratetype);
5244: kmsan_alloc_page(page, order, alloc_gfp);
5245:
5246: return page;
5247: }
SourceFile:mm/page_alloc.c]
|
| 18/2 |
2026/06/15 16:09 |
llm |
debugger |
0m
Model:
Tokens:
input: 26103
output: 35
thoughts: 266
Thoughts: **Analyzing a Potential Memory Allocation Issue**
Okay, so I'm looking at this warning: `WARN_ON_ONCE_GFP(order > MAX_PAGE_ORDER, gfp)`. My initial thought is to figure out when this condition is met. I know `MAX_PAGE_ORDER` is typically 10 or 11. Let's work through an example. If we have an `object_count` of 1,000,000, and assuming a size of 8 bytes per object (just making an assumption here, but I need a representative value), then the total allocation size is 8MB. Converting that to pages gives us roughly 1953 pages. Now, 1953 pages corresponds to an order of 11. So, if `MAX_PAGE_ORDER` is set to 10, then yes, this *would* trigger the warning because 11 is greater than 10. That makes perfect sense.
But wait a minute... where is this memory being allocated? Ah, the `drm_mode_create_lease_ioctl` function calls `memdup_array_user` to copy the `object_ids` array:
```c
if (object_count != 0) {
object_ids = memdup_array_user(u64_to_user_ptr(cl->object_ids),
object_count, sizeof(__u32));
if (IS_ERR(object_ids)) {
```
Okay, so the `object_ids` are allocated using `memdup_array_user`. I need to look closely at that. Is it using the standard kernel allocators, or does it have its own mechanisms? I need to understand how the user-space data is being copied, the allocation size, and the potential for abuse (i.e., user-provided `object_count` being too large.)
|
| 19/2 |
2026/06/15 16:09 |
tool |
codesearch-definition-source |
0m
Args: map[ContextFile:mm/util.c Name:memdup_array_user]
Results: map[SourceCode: 22: /**
23: * memdup_array_user - duplicate array from user space
24: * @src: source address in user space
25: * @n: number of array members to copy
26: * @size: size of one array member
27: *
28: * Return: an ERR_PTR() on failure. Result is physically
29: * contiguous, to be freed by kfree().
30: */
31: static inline __realloc_size(2, 3)
32: void *memdup_array_user(const void __user *src, size_t n, size_t size)
33: {
34: size_t nbytes;
35:
36: if (check_mul_overflow(n, size, &nbytes))
37: return ERR_PTR(-EOVERFLOW);
38:
39: return memdup_user(src, nbytes);
40: }
SourceFile:include/linux/string.h]
|
| 20/2 |
2026/06/15 16:09 |
llm |
debugger |
0m
Model:
Tokens:
input: 27116
output: 33
thoughts: 29
Thoughts: Here's my thought process, as if I were considering this myself:
**Investigating `memdup_user` and Memory Allocation**
Okay, so I'm dealing with `memdup_user` again. Hmm, I need to refresh my memory on the underlying memory allocation used by this function. I seem to recall it being one of the kernel's memory allocators, but I need to be precise. Does it use `kvmalloc` or the more general `kmalloc`? Time to dig into the implementation of `memdup_user` itself. Let's get to the source and verify how it handles its memory allocation. I need to be certain about this before I proceed.
|
| 21/2 |
2026/06/15 16:10 |
tool |
codesearch-definition-source |
0m
Args: map[ContextFile:mm/util.c Name:memdup_user]
Results: map[SourceCode: 208: /**
209: * memdup_user - duplicate memory region from user space
210: *
211: * @src: source address in user space
212: * @len: number of bytes to copy
213: *
214: * Return: an ERR_PTR() on failure. Result is physically
215: * contiguous, to be freed by kfree().
216: */
217: void *memdup_user(const void __user *src, size_t len)
218: {
219: void *p;
220:
221: p = kmem_buckets_alloc_track_caller(user_buckets, len, GFP_USER | __GFP_NOWARN);
222: if (!p)
223: return ERR_PTR(-ENOMEM);
224:
225: if (copy_from_user(p, src, len)) {
226: kfree(p);
227: return ERR_PTR(-EFAULT);
228: }
229:
230: return p;
231: }
SourceFile:mm/util.c]
|
| 22/2 |
2026/06/15 16:10 |
llm |
debugger |
0m
Model:
Tokens:
input: 27678
output: 35
thoughts: 272
Thoughts: **My Analysis of a Memory Allocation Pattern**
Okay, so I'm looking at `memdup_user` here. It seems to be using `kmem_buckets_alloc_track_caller` with `GFP_USER | __GFP_NOWARN`. Hmm, the `__GFP_NOWARN` flag... that means it's *not* going to complain if the memory allocation fails. That's a red flag. But wait, `fill_object_idr` uses `kzalloc_objs(struct drm_mode_object *, object_count)` which appears as:
```c
objects = kzalloc_objs(struct drm_mode_object *, object_count);
```
Right, but `kzalloc_objs` expands, which is where things get interesting: `__alloc_objs(kzalloc, default_gfp(__VA_ARGS__), typeof(P), COUNT)`. `kzalloc_objs` is using `kzalloc`. And *that* uses `kmalloc` with `GFP_KERNEL | __GFP_ZERO`. Crucially, `kzalloc` doesn't have the `__GFP_NOWARN` flag.
So, here's the problem. If `object_count` is large, `kzalloc` is going to attempt to allocate a *large* chunk of physically contiguous memory. This will likely trigger `WARN_ON_ONCE_GFP(order > MAX_PAGE_ORDER, gfp)` within `__alloc_frozen_pages_noprof`. I need to review `kzalloc_objs` to be certain.
|
| 23/2 |
2026/06/15 16:10 |
tool |
codesearch-definition-source |
0m
Error:
Args: map[ContextFile:include/linux/slab.h Name:kzalloc_objs]
Results: map[SourceCode: SourceFile:]
|
| 24/2 |
2026/06/15 16:10 |
llm |
debugger |
0m
Model:
Tokens:
input: 28345
output: 43
thoughts: 196
Thoughts: **Analyzing a Potential Vulnerability in the DRM Lease Creation IOCTL**
Okay, so I'm looking at this macro, `kzalloc_objs`, found in `include/linux/slab.h`. It looks like it's a wrapper for `kzalloc`, and I see the definition:
```c
#define kzalloc_objs(P, COUNT, ...) \
__alloc_objs(kzalloc, default_gfp(__VA_ARGS__), typeof(P), COUNT)
```
The key thing here is `kzalloc`. That means it's allocating memory, and if `COUNT` gets big, it'll allocate a really big chunk. Hmmm, the next thing I see, a user controls `object_count`. This is in the `drm_mode_create_lease_ioctl` function:
```c
object_count = cl->object_count;
```
Okay, `cl` is a `struct drm_mode_create_lease *cl = data;` so that's where `object_count` comes from. This `cl->object_count` is passed directly into the `kzalloc_objs` macro. But wait a minute, `object_count` itself is `size_t` but, `cl->object_count` is `__u32` according to the struct. Time to verify what `struct drm_mode_create_lease` holds. This is interesting... this could be a classic integer overflow vulnerability right here.
|
| 25/2 |
2026/06/15 16:10 |
tool |
codesearch-definition-source |
0m
Args: map[ContextFile:include/uapi/drm/drm_mode.h Name:drm_mode_create_lease]
Results: map[SourceCode:1441: /**
1442: * struct drm_mode_create_lease - Create lease
1443: *
1444: * Lease mode resources, creating another drm_master.
1445: *
1446: * The @object_ids array must reference at least one CRTC, one connector and
1447: * one plane if &DRM_CLIENT_CAP_UNIVERSAL_PLANES is enabled. Alternatively,
1448: * the lease can be completely empty.
1449: */
1450: struct drm_mode_create_lease {
1451: /** @object_ids: Pointer to array of object ids (__u32) */
1452: __u64 object_ids;
1453: /** @object_count: Number of object ids */
1454: __u32 object_count;
1455: /** @flags: flags for new FD (O_CLOEXEC, etc) */
1456: __u32 flags;
1457:
1458: /** @lessee_id: Return: unique identifier for lessee. */
1459: __u32 lessee_id;
1460: /** @fd: Return: file descriptor to new drm_master file */
1461: __u32 fd;
1462: };
SourceFile:include/uapi/drm/drm_mode.h]
|
| 26/2 |
2026/06/15 16:10 |
llm |
debugger |
0m
Model:
Tokens:
input: 29291
output: 37
thoughts: 620
Thoughts: **Analyzing a Potential Vulnerability in DRM Lease Creation**
Okay, so I'm looking at this `drm_mode_create_lease_ioctl` function, specifically the section dealing with object IDs. I see `object_count` is a `__u32`, which is important for the potential size of the array. The code uses `memdup_array_user` to copy these IDs from userspace, and that's where things get interesting.
`memdup_array_user` ultimately calls `memdup_user`, which uses `kmem_buckets_alloc_track_caller`. That's basically a `kmalloc` under the hood. Now, if `object_count` is a substantial number like 1,000,000 (0xf4240), then the size of the allocation is `4 * 1,000,000 = 4,000,000` bytes, since each ID is a `__u32`. I need to think about potential integer overflows here, but I don't see anything obvious that indicates that is a problem here.
I see that `kmem_buckets_alloc_track_caller` with `__GFP_NOWARN` means it'll silently fail if the allocation is too big. That's a good first check. If `KMALLOC_MAX_SIZE` is, say, 4MB, then the 4MB allocation *succeeds*, because it's exactly the same size. That's fine, so far.
The code then calls `fill_object_idr`. Within that function, `kzalloc_objs` is called which is simply `kzalloc` with a suffix. This attempts to allocate an array of `struct drm_mode_object *` entries. With `object_count` at 1,000,000, and the size of a pointer (let's assume 8 bytes), that's an allocation of `8 * 1,000,000 = 8,000,000` bytes, or 8MB.
Now, if `KMALLOC_MAX_SIZE` is only 4MB, this allocation is *too large* for `kmalloc`. It looks like `kzalloc` will use `kmalloc`, which then would use `kmalloc_large`. I need to double-check that `kmalloc_large` or `__kmalloc_large_node` is not subject to a size limit that could be bypassed. I suspect, as a large allocation, we might see it try to allocate a large contiguous region. I'll check how that allocation works to look for potential flaws.
|
| 27/2 |
2026/06/15 16:10 |
tool |
codesearch-definition-source |
0m
Error:
Args: map[ContextFile:mm/slub.c Name:__kmalloc_large_node]
Results: map[SourceCode: SourceFile:]
|
| 28/2 |
2026/06/15 16:10 |
llm |
debugger |
0m
Model:
Tokens:
input: 30549
output: 41
thoughts: 17
Thoughts: Okay, here's my attempt at summarizing that thought process, keeping in mind I'm speaking to a fellow expert:
**Diving into `__kmalloc_large_node_noprof`**
Alright, time to get my hands dirty. Let's start with a look at `__kmalloc_large_node_noprof`. It's a key function in the memory management realm, specifically dealing with the allocation of larger memory chunks. Given the "large" and "node" elements, I'm already anticipating considerations related to NUMA architectures and potentially the complexities of allocating memory across different nodes in the system. The "noprof" suffix is particularly interesting. That strongly suggests that we're dealing with an uninstrumented version, possibly for performance-critical path. This usually means that any debugging will require extreme care! I should quickly check the surrounding context to understand what the larger code is intending to achieve, or where it's called from. I need to understand its relationship to things like `slab` and `buddy` allocators, and how it handles potential fragmentation issues or different memory policies. Time to see what the code has to say.
|
| 29/2 |
2026/06/15 16:10 |
tool |
codesearch-definition-source |
0m
Args: map[ContextFile:mm/slub.c Name:__kmalloc_large_node_noprof]
Results: map[SourceCode:5266: void *__kmalloc_large_node_noprof(size_t size, gfp_t flags, int node)
5267: {
5268: void *ret = ___kmalloc_large_node(size, flags, node);
5269:
5270: trace_kmalloc(_RET_IP_, ret, size, PAGE_SIZE << get_order(size),
5271: flags, node);
5272: return ret;
5273: }
SourceFile:mm/slub.c]
|
| 30/2 |
2026/06/15 16:10 |
llm |
debugger |
0m
Model:
Tokens:
input: 31016
output: 37
thoughts: 13
Thoughts: Okay, here's my take on those thoughts, tailored for an expert audience, presented in the first person:
**Diving into `kmalloc_large_node`**
Alright, time to get my hands dirty. Let's see what's happening with `___kmalloc_large_node`. I need to understand its behavior and potential edge cases within the broader memory allocation landscape. I’m thinking specifically about how it interacts with NUMA, and what sort of performance implications its large-node focus carries. I should probably be considering things like fragmentation risks within that particular node and how it handles allocation failures, especially when dealing with large requests, and if there are considerations regarding the size of the request relative to available memory. I’ll need to make sure to look at how it interacts with other memory allocation schemes as well, making sure there are no unexpected conflicts. I'm also curious about its interplay with any slab or page allocation internals. Let's see if this is handling prefetching properly too. The devil is always in the details, so I need to dig deep into the implementation.
|
| 31/2 |
2026/06/15 16:10 |
tool |
codesearch-definition-source |
0m
Args: map[ContextFile:mm/slub.c Name:___kmalloc_large_node]
Results: map[SourceCode:5220: /*
5221: * To avoid unnecessary overhead, we pass through large allocation requests
5222: * directly to the page allocator. We use __GFP_COMP, because we will need to
5223: * know the allocation order to free the pages properly in kfree.
5224: */
5225: static void *___kmalloc_large_node(size_t size, gfp_t flags, int node)
5226: {
5227: struct page *page;
5228: void *ptr = NULL;
5229: unsigned int order = get_order(size);
5230:
5231: if (unlikely(flags & GFP_SLAB_BUG_MASK))
5232: flags = kmalloc_fix_flags(flags);
5233:
5234: flags |= __GFP_COMP;
5235:
5236: if (node == NUMA_NO_NODE)
5237: page = alloc_frozen_pages_noprof(flags, order);
5238: else
5239: page = __alloc_frozen_pages_noprof(flags, order, node, NULL);
5240:
5241: if (page) {
5242: ptr = page_address(page);
5243: mod_lruvec_page_state(page, NR_SLAB_UNRECLAIMABLE_B,
5244: PAGE_SIZE << order);
5245: __SetPageLargeKmalloc(page);
5246: }
5247:
5248: ptr = kasan_kmalloc_large(ptr, size, flags);
5249: /* As ptr might get tagged, call kmemleak hook after KASAN. */
5250: kmemleak_alloc(ptr, size, 1, flags);
5251: kmsan_kmalloc_large(ptr, size, flags);
5252:
5253: return ptr;
5254: }
SourceFile:mm/slub.c]
|
| 32/2 |
2026/06/15 16:10 |
llm |
debugger |
0m
Model:
Tokens:
input: 31866
output: 34
thoughts: 470
Thoughts: **Analyzing Potential Memory Allocation Issues**
Okay, so I'm following the code path, starting with `___kmalloc_large_node`, which leads me to `alloc_frozen_pages_noprof` called with the `order` parameter. Right, so if the size is 8MB, the order is 11, which is important. Now, here's where it gets interesting: if `MAX_PAGE_ORDER` is set to 10, then `__alloc_frozen_pages_noprof` is going to trigger `WARN_ON_ONCE_GFP(order > MAX_PAGE_ORDER, gfp)`.
I'm making sure I have this right. The `kzalloc_objs` function, it relies on `kzalloc`, which in turn uses `kmalloc` with `GFP_KERNEL | __GFP_ZERO`. And wait, `kmalloc` here *doesn't* have `__GFP_NOWARN` set, which is crucial. So, since the `order` is 11 and `MAX_PAGE_ORDER` is 10, the `WARN_ON_ONCE_GFP` will indeed be triggered because that `__GFP_NOWARN` flag isn't there to suppress the warning.
Now, I'm thinking about the contrast... I know that `memdup_array_user` *does* have `__GFP_NOWARN` inside `memdup_user`, so that specific call doesn't generate a warning on failure. But hold on, `memdup_array_user` allocates `object_count * 4` bytes. Let's say, just hypothetically, `object_count` is 1,000,000, then we get 4,000,000 bytes, which is 976 pages. 976 pages translates to an order of 10. And if `MAX_PAGE_ORDER` is 10, then order 10 is fine because it is less than or equal to `MAX_PAGE_ORDER`, so `memdup_user` succeeds, no warning.
Now the problem is clear, `kzalloc_objs` *then* allocates `object_count * 8` bytes. With the same `object_count` of 1,000,000, that’s 8,000,000 bytes. This is 1953 pages, order 11, which exceeds our `MAX_PAGE_ORDER` of 10. So *that's* why `kzalloc_objs` is triggering the warning!
The question now becomes, why does `fill_object_idr` use `kzalloc_objs` instead of something like `kvzalloc` or even the array version, `kvmalloc_array`? If `object_count` can potentially be large, it seems like `kvmalloc_array` would be much better, or at least a hard limit on `object_count`. I need to see if there's any kind of protection or limitations on how large `object_count` can be. I'll need to check the code for any bounds checks.
|
| 33/2 |
2026/06/15 16:10 |
tool |
grepper |
0m
Args: map[Expression:object_count PathPrefix:drivers/gpu/drm/drm_lease.c]
Results: map[Output:drivers/gpu/drm/drm_lease.c=346=static int validate_lease(struct drm_device *dev,
drivers/gpu/drm/drm_lease.c:347: int object_count,
drivers/gpu/drm/drm_lease.c-348- struct drm_mode_object **objects,
--
drivers/gpu/drm/drm_lease.c-358-
drivers/gpu/drm/drm_lease.c:359: for (o = 0; o < object_count; o++) {
drivers/gpu/drm/drm_lease.c-360- if (objects[o]->type == DRM_MODE_OBJECT_CRTC && has_crtc == -1) {
--
drivers/gpu/drm/drm_lease.c=378=static int fill_object_idr(struct drm_device *dev,
--
drivers/gpu/drm/drm_lease.c-380- struct idr *leases,
drivers/gpu/drm/drm_lease.c:381: int object_count,
drivers/gpu/drm/drm_lease.c-382- u32 *object_ids)
--
drivers/gpu/drm/drm_lease.c-388-
drivers/gpu/drm/drm_lease.c:389: objects = kzalloc_objs(struct drm_mode_object *, object_count);
drivers/gpu/drm/drm_lease.c-390- if (!objects)
--
drivers/gpu/drm/drm_lease.c-394- and check for validity. */
drivers/gpu/drm/drm_lease.c:395: for (o = 0; o < object_count; o++) {
drivers/gpu/drm/drm_lease.c-396- objects[o] = drm_mode_object_find(dev, lessor_priv,
--
drivers/gpu/drm/drm_lease.c-410-
drivers/gpu/drm/drm_lease.c:411: ret = validate_lease(dev, object_count, objects, universal_planes);
drivers/gpu/drm/drm_lease.c-412- if (ret) {
--
drivers/gpu/drm/drm_lease.c-418- universal planes */
drivers/gpu/drm/drm_lease.c:419: for (o = 0; o < object_count; o++) {
drivers/gpu/drm/drm_lease.c-420- struct drm_mode_object *obj = objects[o];
--
drivers/gpu/drm/drm_lease.c-460-out_free_objects:
drivers/gpu/drm/drm_lease.c:461: for (o = 0; o < object_count; o++) {
drivers/gpu/drm/drm_lease.c-462- if (objects[o])
--
drivers/gpu/drm/drm_lease.c=475=int drm_mode_create_lease_ioctl(struct drm_device *dev,
--
drivers/gpu/drm/drm_lease.c-478- struct drm_mode_create_lease *cl = data;
drivers/gpu/drm/drm_lease.c:479: size_t object_count;
drivers/gpu/drm/drm_lease.c-480- int ret = 0;
--
drivers/gpu/drm/drm_lease.c-506-
drivers/gpu/drm/drm_lease.c:507: object_count = cl->object_count;
drivers/gpu/drm/drm_lease.c-508-
--
drivers/gpu/drm/drm_lease.c-510- idr_init(&leases);
drivers/gpu/drm/drm_lease.c:511: if (object_count != 0) {
drivers/gpu/drm/drm_lease.c-512- object_ids = memdup_array_user(u64_to_user_ptr(cl->object_ids),
drivers/gpu/drm/drm_lease.c:513: object_count, sizeof(__u32));
drivers/gpu/drm/drm_lease.c-514- if (IS_ERR(object_ids)) {
--
drivers/gpu/drm/drm_lease.c-521- ret = fill_object_idr(dev, lessor_priv, &leases,
drivers/gpu/drm/drm_lease.c:522: object_count, object_ids);
drivers/gpu/drm/drm_lease.c-523- kfree(object_ids);
]
|
| 34/2 |
2026/06/15 16:10 |
llm |
debugger |
0m
Model:
Tokens:
input: 34217
output: 19
thoughts: 997
Thoughts: **Analyzing a Potential Kernel Crash in drm_mode_create_lease_ioctl**
Okay, so I'm looking at this `drm_mode_create_lease_ioctl` function, and it seems there's a potential vulnerability due to how it handles the `object_count` parameter from userspace. There's no inherent limit enforced on this `object_count`, which immediately raises a red flag. Let's see what happens if a user passes a large value, like `0xf4240` (1000000).
The `memdup_array_user` function is called, which allocates memory based on `object_count`. With the given example, it will try to allocate `1000000 * 4 = 4000000` bytes. Now, this is where it gets interesting: is this allocation size valid? I know `KMALLOC_MAX_SIZE` can be crucial here. On many systems, this is 4MB, sometimes 8MB. Let me check the math. `KMALLOC_MAX_SIZE` is defined as `PAGE_SIZE << MAX_PAGE_ORDER`. Assuming a standard 4096-byte page size and `MAX_PAGE_ORDER` of 10, that makes it `4096 << 10 = 4194304` bytes (4MB). So, the `memdup_array_user` allocation *succeeds* because 4MB is less than 4MB, I have to be careful with my words!
However, the problem comes next. The code then calls `fill_object_idr`, which calls `kzalloc_objs` to allocate memory for the objects. The allocation size here is `1000000 * 8 = 8000000` bytes. 8MB is larger than the 4MB `KMALLOC_MAX_SIZE`.
`kzalloc_objs` uses `kmalloc` without `__GFP_NOWARN`. This means it *will* trigger a warning from the page allocator when it tries to allocate memory larger than allowed. This isn't just a potential performance issue, this is a kernel crash! Syzkaller treats warnings as crashes, so this is a serious problem.
Let's drill down: `kzalloc_objs` is just a wrapper for `kzalloc`, which, in turn, uses `kmalloc` with the `__GFP_ZERO` flag. Now, if the requested size exceeds `KMALLOC_MAX_SIZE`, `kmalloc` calls `kmalloc_large`. `kmalloc_large` calls `alloc_pages` with an order exceeding `MAX_PAGE_ORDER`. And `alloc_pages` *has* a `WARN_ON_ONCE_GFP` check for this condition! It prints a warning and returns NULL, which then cascades up to `kzalloc`, which returns NULL. Then `fill_object_idr` returns `-ENOMEM`. The core of the problem here is the warning that gets triggered due to the `kmalloc` with a size greater than `KMALLOC_MAX_SIZE`.
So, the immediate fix? I need to look at using `kvmalloc_array` or `kvzalloc` for the `objects` allocation.
Also, let's revisit `memdup_array_user`: It uses `memdup_user`, which uses `kmalloc` with `GFP_USER | __GFP_NOWARN`. If `object_count` were even *larger*, say 2000000, `memdup_array_user` would try to allocate 8MB. Because of `__GFP_NOWARN`, it would *fail* and return `-ENOMEM` silently, which is better than a kernel panic, but still not ideal.
But if `object_count` is large enough to pass the first allocation, but small enough to fail on the second, we still have a problem. Let's say `object_count` is 1000000, `memdup_array_user` allocates successfully (4MB), and `kzalloc_objs` fails (8MB).
I'm starting to think that `memdup_array_user` should also consider `kvmalloc` for larger arrays, even though it currently just uses `kmalloc`. It's defined in `include/linux/string.h` and uses `memdup_user`, which in turn, uses `kmalloc`. If a user wants a huge array, `memdup_user` fails because it exceeds the `4MB` limit. Is there something like `vmemdup_user`?
|
| 35/2 |
2026/06/15 16:11 |
tool |
grepper |
0m
Args: map[Expression:vmemdup_user]
Results: map[Output:Documentation/core-api/kernel-api.rst=30=String Manipulation
--
Documentation/core-api/kernel-api.rst-43- :functions: kstrdup kstrdup_const kstrndup kmemdup kmemdup_nul memdup_user
Documentation/core-api/kernel-api.rst:44: vmemdup_user strndup_user memdup_user_nul
Documentation/core-api/kernel-api.rst-45-
--
drivers/cxl/core/mbox.c=359=static int cxl_mbox_cmd_ctor(struct cxl_mbox_cmd *mbox_cmd,
--
drivers/cxl/core/mbox.c-368- if (in_size) {
drivers/cxl/core/mbox.c:369: mbox_cmd->payload_in = vmemdup_user(u64_to_user_ptr(in_payload),
drivers/cxl/core/mbox.c-370- in_size);
--
drivers/gpu/drm/nouveau/nouveau_drv.h=194=u_memcpya(uint64_t user, unsigned int nmemb, unsigned int size)
--
drivers/gpu/drm/nouveau/nouveau_drv.h-200- return ERR_PTR(-EOVERFLOW);
drivers/gpu/drm/nouveau/nouveau_drv.h:201: return vmemdup_user(userptr, bytes);
drivers/gpu/drm/nouveau/nouveau_drv.h-202-}
--
drivers/gpu/drm/tegra/submit.c=161=static void *alloc_copy_user_array(void __user *from, size_t count, size_t size)
--
drivers/gpu/drm/tegra/submit.c-171-
drivers/gpu/drm/tegra/submit.c:172: data = vmemdup_user(from, copy_len);
drivers/gpu/drm/tegra/submit.c-173- if (IS_ERR(data))
--
drivers/gpu/drm/virtio/virtgpu_submit.c=369=static int virtio_gpu_init_submit(struct virtio_gpu_submit *submit,
--
drivers/gpu/drm/virtio/virtgpu_submit.c-417-
drivers/gpu/drm/virtio/virtgpu_submit.c:418: submit->buf = vmemdup_user(u64_to_user_ptr(exbuf->command), exbuf->size);
drivers/gpu/drm/virtio/virtgpu_submit.c-419- if (IS_ERR(submit->buf))
--
drivers/gpu/drm/xe/xe_exec_queue.c=796=static int exec_queue_set_hang_replay_state(struct xe_device *xe,
--
drivers/gpu/drm/xe/xe_exec_queue.c-803-
drivers/gpu/drm/xe/xe_exec_queue.c:804: ptr = vmemdup_user(address, size);
drivers/gpu/drm/xe/xe_exec_queue.c-805- if (XE_IOCTL_DBG(xe, IS_ERR(ptr)))
--
drivers/hv/mshv_root_main.c=1571=mshv_partition_ioctl_set_msi_routing(struct mshv_partition *partition,
--
drivers/hv/mshv_root_main.c-1587-
drivers/hv/mshv_root_main.c:1588: entries = vmemdup_user(urouting->entries,
drivers/hv/mshv_root_main.c-1589- array_size(sizeof(*entries),
--
drivers/staging/axis-fifo/axis-fifo.c=213=static ssize_t axis_fifo_write(struct file *f, const char __user *buf,
--
drivers/staging/axis-fifo/axis-fifo.c-253-
drivers/staging/axis-fifo/axis-fifo.c:254: txbuf = vmemdup_user(buf, len);
drivers/staging/axis-fifo/axis-fifo.c-255- if (IS_ERR(txbuf)) {
--
drivers/vdpa/vdpa_user/vduse_dev.c=2142=static long vduse_ioctl(struct file *file, unsigned int cmd,
--
drivers/vdpa/vdpa_user/vduse_dev.c-2185-
drivers/vdpa/vdpa_user/vduse_dev.c:2186: buf = vmemdup_user(argp + size, config.config_size);
drivers/vdpa/vdpa_user/vduse_dev.c-2187- if (IS_ERR(buf)) {
--
drivers/vhost/vdpa.c=382=static long vhost_vdpa_set_config(struct vhost_vdpa *v,
--
drivers/vhost/vdpa.c-394-
drivers/vhost/vdpa.c:395: buf = vmemdup_user(c->buf, config.len);
drivers/vhost/vdpa.c-396- if (IS_ERR(buf))
--
fs/coda/psdev.c=91=static ssize_t coda_psdev_write(struct file *file, const char __user *buf,
--
fs/coda/psdev.c-125-
fs/coda/psdev.c:126: dcbuf = vmemdup_user(buf, nbytes);
fs/coda/psdev.c-127- if (IS_ERR(dcbuf)) {
--
fs/nilfs2/ioctl.c=834=static int nilfs_ioctl_clean_segments(struct inode *inode, struct file *filp,
--
fs/nilfs2/ioctl.c-895-
fs/nilfs2/ioctl.c:896: kbufs[n] = vmemdup_user(u64_to_user_ptr(argv[n].v_base), len);
fs/nilfs2/ioctl.c-897- if (IS_ERR(kbufs[n])) {
--
fs/nilfs2/ioctl.c=1176=static int nilfs_ioctl_set_suinfo(struct inode *inode, struct file *filp,
--
fs/nilfs2/ioctl.c-1212-
fs/nilfs2/ioctl.c:1213: kbuf = vmemdup_user(u64_to_user_ptr(argv.v_base), len);
fs/nilfs2/ioctl.c-1214- if (IS_ERR(kbuf)) {
--
fs/pstore/platform.c=436=static int pstore_write_user_compat(struct pstore_record *record,
--
fs/pstore/platform.c-443-
fs/pstore/platform.c:444: record->buf = vmemdup_user(buf, record->size);
fs/pstore/platform.c-445- if (IS_ERR(record->buf)) {
--
fs/xattr.c=622=int setxattr_copy(const char __user *name, struct kernel_xattr_ctx *ctx)
--
fs/xattr.c-636-
fs/xattr.c:637: ctx->kvalue = vmemdup_user(ctx->cvalue, ctx->size);
fs/xattr.c-638- if (IS_ERR(ctx->kvalue)) {
--
include/linux/string.h=18=extern void *memdup_user(const void __user *, size_t) __realloc_size(2);
include/linux/string.h:19:extern void *vmemdup_user(const void __user *, size_t) __realloc_size(2);
include/linux/string.h-20-extern void *memdup_user_nul(const void __user *, size_t);
--
include/linux/string.h=52=void *vmemdup_array_user(const void __user *src, size_t n, size_t size)
--
include/linux/string.h-58-
include/linux/string.h:59: return vmemdup_user(src, nbytes);
include/linux/string.h-60-}
--
kernel/bpf/syscall.c=1679=static void *__bpf_copy_key(void __user *ukey, u64 key_size)
--
kernel/bpf/syscall.c-1681- if (key_size)
kernel/bpf/syscall.c:1682: return vmemdup_user(ukey, key_size);
kernel/bpf/syscall.c-1683-
--
mm/util.c=232=EXPORT_SYMBOL(memdup_user);
--
mm/util.c-234-/**
mm/util.c:235: * vmemdup_user - duplicate memory region from user space
mm/util.c-236- *
--
mm/util.c-242- */
mm/util.c:243:void *vmemdup_user(const void __user *src, size_t len)
mm/util.c-244-{
--
mm/util.c-257-}
mm/util.c:258:EXPORT_SYMBOL(vmemdup_user);
mm/util.c-259-
--
scripts/coccinelle/api/memdup_user.cocci=16=virtual report
--
scripts/coccinelle/api/memdup_user.cocci-19-@@
scripts/coccinelle/api/memdup_user.cocci:20:filter = frozenset(['memdup_user', 'vmemdup_user'])
scripts/coccinelle/api/memdup_user.cocci-21-
--
scripts/coccinelle/api/memdup_user.cocci=53=position p : script:python() { relevant(p) };
--
scripts/coccinelle/api/memdup_user.cocci-56-- to = \(kvmalloc@p\|kvzalloc@p\)(size,\(GFP_KERNEL\|GFP_USER\));
scripts/coccinelle/api/memdup_user.cocci:57:+ to = vmemdup_user(from,size);
scripts/coccinelle/api/memdup_user.cocci-58- if (
--
scripts/coccinelle/api/memdup_user.cocci=110=p << rv.p;
--
scripts/coccinelle/api/memdup_user.cocci-112-
scripts/coccinelle/api/memdup_user.cocci:113:coccilib.org.print_todo(p[0], "WARNING opportunity for vmemdup_user")
scripts/coccinelle/api/memdup_user.cocci-114-
--
scripts/coccinelle/api/memdup_user.cocci=116=p << rv.p;
--
scripts/coccinelle/api/memdup_user.cocci-118-
scripts/coccinelle/api/memdup_user.cocci:119:coccilib.report.print_report(p[0], "WARNING opportunity for vmemdup_user")
--
sound/core/control.c=1549=static int replace_user_tlv(struct snd_kcontrol *kctl, unsigned int __user *buf,
--
sound/core/control.c-1566-
sound/core/control.c:1567: container = vmemdup_user(buf, size);
sound/core/control.c-1568- if (IS_ERR(container))
--
sound/core/control.c=1629=static int snd_ctl_elem_init_enum_names(struct user_element *ue)
--
sound/core/control.c-1643- return -ENOMEM;
sound/core/control.c:1644: names = vmemdup_user((const void __user *)user_ptrval, buf_len);
sound/core/control.c-1645- if (IS_ERR(names))
--
sound/soc/codecs/wm_adsp.c=425=static int wm_coeff_tlv_put(struct snd_kcontrol *kctl,
--
sound/soc/codecs/wm_adsp.c-431- struct cs_dsp_coeff_ctl *cs_ctl = ctl->cs_ctl;
sound/soc/codecs/wm_adsp.c:432: void *scratch __free(kvfree) = vmemdup_user(bytes, size);
sound/soc/codecs/wm_adsp.c-433-
]
|
| 36/2 |
2026/06/15 16:11 |
llm |
debugger |
0m
Model:
Tokens:
input: 39470
output: 19
thoughts: 553
Thoughts: **Refactoring Memory Allocation in `fill_object_idr`**
Okay, so I see `vmemdup_array_user` exists, that's good to know. But I'm looking at `fill_object_idr` and it's using `kzalloc_objs` which in turn calls `kmalloc`. Hmm, if I remember correctly, there are warnings associated with the page allocator with kmalloc. I wonder if I can replace it with `kvmalloc_array` or `kvzalloc`?
Hold on... `kzalloc_objs` isn't a standard function; it's a macro. Let me check... Ah, right, I remember now, I grepped for it and it's defined in `include/linux/slab.h`. Let's see what this macro expands to... Okay, so it's expanding to `kzalloc(sizeof(struct drm_mode_object *) * object_count, GFP_KERNEL)`. Got it.
So, `kzalloc_objs` is basically just allocating memory. But `objects` here is an array of *pointers*, a classic case of allocating the array of pointers with `kzalloc`. So then, why *not* use `kvmalloc_array`? I think this would be cleaner:
```c
objects = kvmalloc_array(object_count, sizeof(struct drm_mode_object *), GFP_KERNEL | __GFP_ZERO);
```
Yes, that makes sense. Using `kvmalloc_array` or even `kvzalloc` would sidestep those potential page allocator warnings because `kvmalloc` will fall back to `vmalloc` if `kmalloc` fails and `vmalloc` can handle larger chunks, and avoid the warnings! Just to clarify, `kvmalloc` first tries `kmalloc` with `__GFP_NOWARN` for larger sizes and falls back to `vmalloc` if it fails.
So, `kvmalloc_array` is definitely the right choice in this scenario.
Let's look at that `fill_object_idr` code again:
```c
objects = kzalloc_objs(struct drm_mode_object *, object_count);
if (!objects)
return -ENOMEM;
```
If I change that to:
```c
objects = kvmalloc_array(object_count, sizeof(struct drm_mode_object *), GFP_KERNEL | __GFP_ZERO);
```
Wait a second... isn't `kzalloc_objs` a macro that expands to `kzalloc` with `__GFP_ZERO`? I wonder if there is a `kvzalloc_objs` macro defined somewhere? Let me quickly check...
|
| 37/2 |
2026/06/15 16:11 |
tool |
grepper |
0m
Args: map[Expression:kvzalloc_objs]
Results: map[Output:
Full output is too long, showing 500 out of 993 lines.
Use more precise expression if possible.
arch/arm64/net/bpf_jit_comp.c=2006=struct bpf_prog *bpf_int_jit_compile(struct bpf_verifier_env *env, struct bpf_prog *prog)
--
arch/arm64/net/bpf_jit_comp.c-2060-
arch/arm64/net/bpf_jit_comp.c:2061: ctx.offset = kvzalloc_objs(int, prog->len + 1);
arch/arm64/net/bpf_jit_comp.c-2062- if (ctx.offset == NULL)
--
arch/x86/kvm/cpuid.c=1977=int kvm_dev_ioctl_get_cpuid(struct kvm_cpuid2 *cpuid,
--
arch/x86/kvm/cpuid.c-1997-
arch/x86/kvm/cpuid.c:1998: array.entries = kvzalloc_objs(struct kvm_cpuid_entry2, cpuid->nent);
arch/x86/kvm/cpuid.c-1999- if (!array.entries)
--
arch/x86/kvm/mmu/mmu.c=3991=static int kvm_mmu_alloc_page_hash(struct kvm *kvm)
--
arch/x86/kvm/mmu/mmu.c-3997-
arch/x86/kvm/mmu/mmu.c:3998: h = kvzalloc_objs(*h, KVM_NUM_MMU_PAGES, GFP_KERNEL_ACCOUNT);
arch/x86/kvm/mmu/mmu.c-3999- if (!h)
--
arch/x86/kvm/svm/sev.c=723=static struct page **sev_pin_memory(struct kvm *kvm, unsigned long uaddr,
--
arch/x86/kvm/svm/sev.c-762- */
arch/x86/kvm/svm/sev.c:763: pages = kvzalloc_objs(*pages, npages, GFP_KERNEL_ACCOUNT | __GFP_NOWARN);
arch/x86/kvm/svm/sev.c-764- if (!pages)
--
block/blk-crypto-profile.c=74=int blk_crypto_profile_init(struct blk_crypto_profile *profile,
--
block/blk-crypto-profile.c-95-
block/blk-crypto-profile.c:96: profile->slots = kvzalloc_objs(profile->slots[0], num_slots);
block/blk-crypto-profile.c-97- if (!profile->slots)
--
drivers/accel/amdxdna/amdxdna_gem.c=287=static int amdxdna_hmm_register(struct amdxdna_gem_obj *abo,
--
drivers/accel/amdxdna/amdxdna_gem.c-304- nr_pages = (PAGE_ALIGN(addr + len) - (addr & PAGE_MASK)) >> PAGE_SHIFT;
drivers/accel/amdxdna/amdxdna_gem.c:305: mapp->range.hmm_pfns = kvzalloc_objs(*mapp->range.hmm_pfns, nr_pages);
drivers/accel/amdxdna/amdxdna_gem.c-306- if (!mapp->range.hmm_pfns) {
--
drivers/accel/amdxdna/amdxdna_ubuf.c=78=struct dma_buf *amdxdna_get_ubuf(struct drm_device *dev,
--
drivers/accel/amdxdna/amdxdna_ubuf.c-99-
drivers/accel/amdxdna/amdxdna_ubuf.c:100: va_ent = kvzalloc_objs(*va_ent, num_entries);
drivers/accel/amdxdna/amdxdna_ubuf.c-101- if (!va_ent) {
--
drivers/accel/habanalabs/common/mmu/mmu.c=824=int hl_mmu_hr_init(struct hl_device *hdev, struct hl_mmu_hr_priv *hr_priv, u32 hop_table_size,
--
drivers/accel/habanalabs/common/mmu/mmu.c-845-
drivers/accel/habanalabs/common/mmu/mmu.c:846: hr_priv->mmu_asid_hop0 = kvzalloc_objs(struct pgt_info, prop->max_asid);
drivers/accel/habanalabs/common/mmu/mmu.c-847- if (ZERO_OR_NULL_PTR(hr_priv->mmu_asid_hop0)) {
--
drivers/accel/qaic/qaic_data.c=391=static int qaic_map_one_slice(struct qaic_device *qdev, struct qaic_bo *bo,
--
drivers/accel/qaic/qaic_data.c-407-
drivers/accel/qaic/qaic_data.c:408: slice->reqs = kvzalloc_objs(*slice->reqs, sgt->nents);
drivers/accel/qaic/qaic_data.c-409- if (!slice->reqs) {
--
drivers/android/binder_alloc.c=894=int binder_alloc_mmap_handler(struct binder_alloc *alloc,
--
drivers/android/binder_alloc.c-918-
drivers/android/binder_alloc.c:919: alloc->pages = kvzalloc_objs(alloc->pages[0],
drivers/android/binder_alloc.c-920- alloc->buffer_size / PAGE_SIZE);
--
drivers/block/xen-blkfront.c=2161=static int blkfront_setup_indirect(struct blkfront_ring_info *rinfo)
--
drivers/block/xen-blkfront.c-2209- rinfo->shadow[i].grants_used =
drivers/block/xen-blkfront.c:2210: kvzalloc_objs(rinfo->shadow[i].grants_used[0], grants);
drivers/block/xen-blkfront.c:2211: rinfo->shadow[i].sg = kvzalloc_objs(rinfo->shadow[i].sg[0],
drivers/block/xen-blkfront.c-2212- psegs);
--
drivers/block/xen-blkfront.c-2214- rinfo->shadow[i].indirect_grants =
drivers/block/xen-blkfront.c:2215: kvzalloc_objs(rinfo->shadow[i].indirect_grants[0],
drivers/block/xen-blkfront.c-2216- INDIRECT_GREFS(grants));
--
drivers/dma-buf/udmabuf.c=208=static __always_inline int init_udmabuf(struct udmabuf *ubuf, pgoff_t pgcnt)
--
drivers/dma-buf/udmabuf.c-213-
drivers/dma-buf/udmabuf.c:214: ubuf->offsets = kvzalloc_objs(*ubuf->offsets, pgcnt);
drivers/dma-buf/udmabuf.c-215- if (!ubuf->offsets)
--
drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c=1166=int amdgpu_gem_list_handles_ioctl(struct drm_device *dev, void *data,
--
drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c-1190-
drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c:1191: bo_entries = kvzalloc_objs(*bo_entries, num_bos);
drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c-1192- if (!bo_entries)
--
drivers/gpu/drm/amd/amdkfd/kfd_svm.c=160=svm_range_dma_map_dev(struct amdgpu_device *adev, struct svm_range *prange,
--
drivers/gpu/drm/amd/amdkfd/kfd_svm.c-170- if (!addr) {
drivers/gpu/drm/amd/amdkfd/kfd_svm.c:171: addr = kvzalloc_objs(*addr, prange->npages);
drivers/gpu/drm/amd/amdkfd/kfd_svm.c-172- if (!addr)
--
drivers/gpu/drm/amd/display/modules/color/color_gamma.c=1672=bool mod_color_calculate_degamma_params(struct dc_color_caps *dc_caps,
--
drivers/gpu/drm/amd/display/modules/color/color_gamma.c-1718- if (map_user_ramp && ramp && ramp->type == GAMMA_RGB_256) {
drivers/gpu/drm/amd/display/modules/color/color_gamma.c:1719: rgb_user = kvzalloc_objs(*rgb_user,
drivers/gpu/drm/amd/display/modules/color/color_gamma.c-1720- ramp->num_entries + _EXTRA_POINTS);
--
drivers/gpu/drm/amd/display/modules/color/color_gamma.c-1723-
drivers/gpu/drm/amd/display/modules/color/color_gamma.c:1724: axis_x = kvzalloc_objs(*axis_x,
drivers/gpu/drm/amd/display/modules/color/color_gamma.c-1725- ramp->num_entries + _EXTRA_POINTS);
--
drivers/gpu/drm/amd/display/modules/color/color_gamma.c-1740-
drivers/gpu/drm/amd/display/modules/color/color_gamma.c:1741: curve = kvzalloc_objs(*curve, MAX_HW_POINTS + _EXTRA_POINTS);
drivers/gpu/drm/amd/display/modules/color/color_gamma.c-1742- if (!curve)
--
drivers/gpu/drm/amd/display/modules/color/color_gamma.c-1744-
drivers/gpu/drm/amd/display/modules/color/color_gamma.c:1745: coeff = kvzalloc_objs(*coeff, MAX_HW_POINTS + _EXTRA_POINTS);
drivers/gpu/drm/amd/display/modules/color/color_gamma.c-1746- if (!coeff)
--
drivers/gpu/drm/amd/display/modules/color/color_gamma.c=1907=bool mod_color_calculate_regamma_params(struct dc_transfer_func *output_tf,
--
drivers/gpu/drm/amd/display/modules/color/color_gamma.c-1941- (map_user_ramp || ramp->type != GAMMA_RGB_256)) {
drivers/gpu/drm/amd/display/modules/color/color_gamma.c:1942: rgb_user = kvzalloc_objs(*rgb_user,
drivers/gpu/drm/amd/display/modules/color/color_gamma.c-1943- ramp->num_entries + _EXTRA_POINTS);
--
drivers/gpu/drm/amd/display/modules/color/color_gamma.c-1946-
drivers/gpu/drm/amd/display/modules/color/color_gamma.c:1947: axis_x = kvzalloc_objs(*axis_x, ramp->num_entries + 3);
drivers/gpu/drm/amd/display/modules/color/color_gamma.c-1948- if (!axis_x)
--
drivers/gpu/drm/amd/display/modules/color/color_gamma.c-1965-
drivers/gpu/drm/amd/display/modules/color/color_gamma.c:1966: rgb_regamma = kvzalloc_objs(*rgb_regamma, MAX_HW_POINTS + _EXTRA_POINTS);
drivers/gpu/drm/amd/display/modules/color/color_gamma.c-1967- if (!rgb_regamma)
--
drivers/gpu/drm/amd/display/modules/color/color_gamma.c-1969-
drivers/gpu/drm/amd/display/modules/color/color_gamma.c:1970: coeff = kvzalloc_objs(*coeff, MAX_HW_POINTS + _EXTRA_POINTS);
drivers/gpu/drm/amd/display/modules/color/color_gamma.c-1971- if (!coeff)
--
drivers/gpu/drm/nouveau/nouveau_dmem.c=475=nouveau_dmem_evict_chunk(struct nouveau_dmem_chunk *chunk)
--
drivers/gpu/drm/nouveau/nouveau_dmem.c-483- dst_pfns = kvcalloc(npages, sizeof(*dst_pfns), GFP_KERNEL | __GFP_NOFAIL);
drivers/gpu/drm/nouveau/nouveau_dmem.c:484: dma_info = kvzalloc_objs(*dma_info, npages, GFP_KERNEL | __GFP_NOFAIL);
drivers/gpu/drm/nouveau/nouveau_dmem.c-485-
--
drivers/gpu/drm/nouveau/nouveau_svm.c=985=nouveau_svm_fault_buffer_ctor(struct nouveau_svm *svm, s32 oclass, int id)
--
drivers/gpu/drm/nouveau/nouveau_svm.c-1012-
drivers/gpu/drm/nouveau/nouveau_svm.c:1013: buffer->fault = kvzalloc_objs(*buffer->fault, buffer->entries);
drivers/gpu/drm/nouveau/nouveau_svm.c-1014- if (!buffer->fault)
--
drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmm.c=40=nvkm_vmm_pt_new(const struct nvkm_vmm_desc *desc, bool sparse,
--
drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmm.c-61- if (desc->type == PGD) {
drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmm.c:62: pgt->pde = kvzalloc_objs(*pgt->pde, pten);
drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmm.c-63- if (!pgt->pde) {
--
drivers/gpu/drm/radeon/radeon_cs.c=81=static int radeon_cs_parser_relocs(struct radeon_cs_parser *p)
--
drivers/gpu/drm/radeon/radeon_cs.c-95- p->nrelocs = chunk->length_dw / 4;
drivers/gpu/drm/radeon/radeon_cs.c:96: p->relocs = kvzalloc_objs(struct radeon_bo_list, p->nrelocs);
drivers/gpu/drm/radeon/radeon_cs.c-97- if (p->relocs == NULL) {
--
drivers/gpu/drm/radeon/radeon_cs.c=264=int radeon_cs_parser_init(struct radeon_cs_parser *p, void *data)
--
drivers/gpu/drm/radeon/radeon_cs.c-298- p->nchunks = cs->num_chunks;
drivers/gpu/drm/radeon/radeon_cs.c:299: p->chunks = kvzalloc_objs(struct radeon_cs_chunk, p->nchunks);
drivers/gpu/drm/radeon/radeon_cs.c-300- if (p->chunks == NULL) {
--
drivers/gpu/drm/ttm/ttm_tt.c=138=static int ttm_sg_tt_alloc_page_directory(struct ttm_tt *ttm)
drivers/gpu/drm/ttm/ttm_tt.c-139-{
drivers/gpu/drm/ttm/ttm_tt.c:140: ttm->dma_address = kvzalloc_objs(*ttm->dma_address, ttm->num_pages);
drivers/gpu/drm/ttm/ttm_tt.c-141- if (!ttm->dma_address)
--
drivers/gpu/drm/virtio/virtgpu_submit.c=91=virtio_gpu_parse_deps(struct virtio_gpu_submit *submit)
--
drivers/gpu/drm/virtio/virtgpu_submit.c-108- */
drivers/gpu/drm/virtio/virtgpu_submit.c:109: syncobjs = kvzalloc_objs(*syncobjs, num_in_syncobjs);
drivers/gpu/drm/virtio/virtgpu_submit.c-110- if (!syncobjs)
--
drivers/gpu/drm/virtio/virtgpu_submit.c=188=static int virtio_gpu_parse_post_deps(struct virtio_gpu_submit *submit)
--
drivers/gpu/drm/virtio/virtgpu_submit.c-199-
drivers/gpu/drm/virtio/virtgpu_submit.c:200: post_deps = kvzalloc_objs(*post_deps, num_out_syncobjs);
drivers/gpu/drm/virtio/virtgpu_submit.c-201- if (!post_deps)
--
drivers/gpu/drm/xe/xe_vm.c=3854=int xe_vm_bind_ioctl(struct drm_device *dev, void *data, struct drm_file *file)
--
drivers/gpu/drm/xe/xe_vm.c-3921- if (args->num_binds) {
drivers/gpu/drm/xe/xe_vm.c:3922: bos = kvzalloc_objs(*bos, args->num_binds,
drivers/gpu/drm/xe/xe_vm.c-3923- GFP_KERNEL | __GFP_ACCOUNT | __GFP_RETRY_MAYFAIL | __GFP_NOWARN);
--
drivers/gpu/drm/xe/xe_vm.c-3928-
drivers/gpu/drm/xe/xe_vm.c:3929: ops = kvzalloc_objs(*ops, args->num_binds,
drivers/gpu/drm/xe/xe_vm.c-3930- GFP_KERNEL | __GFP_ACCOUNT | __GFP_RETRY_MAYFAIL | __GFP_NOWARN);
--
drivers/infiniband/hw/hns/hns_roce_main.c=1154=static int hns_roce_alloc_dfx_cnt(struct hns_roce_dev *hr_dev)
drivers/infiniband/hw/hns/hns_roce_main.c-1155-{
drivers/infiniband/hw/hns/hns_roce_main.c:1156: hr_dev->dfx_cnt = kvzalloc_objs(atomic64_t, HNS_ROCE_DFX_CNT_TOTAL);
drivers/infiniband/hw/hns/hns_roce_main.c-1157- if (!hr_dev->dfx_cnt)
--
drivers/infiniband/hw/hns/hns_roce_mr.c=449=int hns_roce_map_mr_sg(struct ib_mr *ibmr, struct scatterlist *sg, int sg_nents,
--
drivers/infiniband/hw/hns/hns_roce_mr.c-464- mr->npages = 0;
drivers/infiniband/hw/hns/hns_roce_mr.c:465: mr->page_list = kvzalloc_objs(dma_addr_t,
drivers/infiniband/hw/hns/hns_roce_mr.c-466- mr->pbl_mtr.hem_cfg.buf_pg_count);
--
drivers/infiniband/hw/hns/hns_roce_mr.c=645=static int mtr_map_bufs(struct hns_roce_dev *hr_dev, struct hns_roce_mtr *mtr)
--
drivers/infiniband/hw/hns/hns_roce_mr.c-656- /* alloc a tmp array to store buffer's dma address */
drivers/infiniband/hw/hns/hns_roce_mr.c:657: pages = kvzalloc_objs(dma_addr_t, page_count);
drivers/infiniband/hw/hns/hns_roce_mr.c-658- if (!pages)
--
drivers/infiniband/ulp/ipoib/ipoib_main.c=1589=static int ipoib_neigh_hash_init(struct ipoib_dev_priv *priv)
--
drivers/infiniband/ulp/ipoib/ipoib_main.c-1601- size = roundup_pow_of_two(arp_tbl.gc_thresh3);
drivers/infiniband/ulp/ipoib/ipoib_main.c:1602: buckets = kvzalloc_objs(*buckets, size);
drivers/infiniband/ulp/ipoib/ipoib_main.c-1603- if (!buckets) {
--
drivers/iommu/amd/init.c=663=static inline int __init alloc_rlookup_table(struct amd_iommu_pci_seg *pci_seg)
drivers/iommu/amd/init.c-664-{
drivers/iommu/amd/init.c:665: pci_seg->rlookup_table = kvzalloc_objs(*pci_seg->rlookup_table,
drivers/iommu/amd/init.c-666- pci_seg->last_bdf + 1);
--
drivers/iommu/amd/init.c=679=static inline int __init alloc_irq_lookup_table(struct amd_iommu_pci_seg *pci_seg)
drivers/iommu/amd/init.c-680-{
drivers/iommu/amd/init.c:681: pci_seg->irq_lookup_table = kvzalloc_objs(*pci_seg->irq_lookup_table,
drivers/iommu/amd/init.c-682- pci_seg->last_bdf + 1);
--
drivers/iommu/dma-iommu.c=884=static struct page **__iommu_dma_alloc_pages(struct device *dev,
--
drivers/iommu/dma-iommu.c-893-
drivers/iommu/dma-iommu.c:894: pages = kvzalloc_objs(*pages, count);
drivers/iommu/dma-iommu.c-895- if (!pages)
--
drivers/iommu/iommufd/selftest.c=1529=static int iommufd_test_access_pages(struct iommufd_ucmd *ucmd,
--
drivers/iommu/iommufd/selftest.c-1563- PAGE_SIZE;
drivers/iommu/iommufd/selftest.c:1564: pages = kvzalloc_objs(*pages, npages, GFP_KERNEL_ACCOUNT);
drivers/iommu/iommufd/selftest.c-1565- if (!pages) {
--
drivers/iommu/iommufd/viommu.c=290=iommufd_hw_queue_alloc_phys(struct iommu_hw_queue_alloc *cmd,
--
drivers/iommu/iommufd/viommu.c-314- */
drivers/iommu/iommufd/viommu.c:315: pages = kvzalloc_objs(*pages, max_npages, GFP_KERNEL | __GFP_NOWARN);
drivers/iommu/iommufd/viommu.c-316- if (!pages)
--
drivers/md/dm-pcache/cache.c=134=static int cache_init(struct dm_pcache *pcache)
--
drivers/md/dm-pcache/cache.c-140-
drivers/md/dm-pcache/cache.c:141: cache->segments = kvzalloc_objs(struct pcache_cache_segment,
drivers/md/dm-pcache/cache.c-142- cache_dev->seg_num);
--
drivers/md/dm-pcache/cache_key.c=823=int cache_tree_init(struct pcache_cache *cache, struct pcache_cache_tree *cache_tree, u32 n_subtrees)
--
drivers/md/dm-pcache/cache_key.c-839- */
drivers/md/dm-pcache/cache_key.c:840: cache_tree->subtrees = kvzalloc_objs(struct pcache_cache_subtree,
drivers/md/dm-pcache/cache_key.c-841- cache_tree->n_subtrees);
--
drivers/md/dm-snap-persistent.c=609=static int persistent_read_metadata(struct dm_exception_store *store,
--
drivers/md/dm-snap-persistent.c-628- sizeof(struct disk_exception);
drivers/md/dm-snap-persistent.c:629: ps->callbacks = kvzalloc_objs(*ps->callbacks, ps->exceptions_per_area);
drivers/md/dm-snap-persistent.c-630- if (!ps->callbacks)
--
drivers/md/raid0.c=65=static int create_strip_zones(struct mddev *mddev, struct r0conf **private_conf)
--
drivers/md/raid0.c-145- err = -ENOMEM;
drivers/md/raid0.c:146: conf->strip_zone = kvzalloc_objs(struct strip_zone, conf->nr_strip_zones);
drivers/md/raid0.c-147- if (!conf->strip_zone)
--
drivers/media/common/videobuf2/videobuf2-dma-sg.c=101=static void *vb2_dma_sg_alloc(struct vb2_buffer *vb, struct device *dev,
--
drivers/media/common/videobuf2/videobuf2-dma-sg.c-128- */
drivers/media/common/videobuf2/videobuf2-dma-sg.c:129: buf->pages = kvzalloc_objs(struct page *, buf->num_pages);
drivers/media/common/videobuf2/videobuf2-dma-sg.c-130- if (!buf->pages)
--
drivers/media/v4l2-core/v4l2-ctrls-core.c=1718=int v4l2_ctrl_handler_init_class(struct v4l2_ctrl_handler *hdl,
--
drivers/media/v4l2-core/v4l2-ctrls-core.c-1727- hdl->nr_of_buckets = 1 + nr_of_controls_hint / 8;
drivers/media/v4l2-core/v4l2-ctrls-core.c:1728: hdl->buckets = kvzalloc_objs(hdl->buckets[0], hdl->nr_of_buckets);
drivers/media/v4l2-core/v4l2-ctrls-core.c-1729- hdl->error = hdl->buckets ? 0 : -ENOMEM;
--
drivers/media/v4l2-core/v4l2-subdev.c=1603=__v4l2_subdev_state_alloc(struct v4l2_subdev *sd, const char *lock_name,
--
drivers/media/v4l2-core/v4l2-subdev.c-1622- if (!(sd->flags & V4L2_SUBDEV_FL_STREAMS) && sd->entity.num_pads) {
drivers/media/v4l2-core/v4l2-subdev.c:1623: state->pads = kvzalloc_objs(*state->pads, sd->entity.num_pads);
drivers/media/v4l2-core/v4l2-subdev.c-1624- if (!state->pads) {
--
drivers/media/v4l2-core/v4l2-subdev.c=1875=v4l2_subdev_init_stream_configs(struct v4l2_subdev_stream_configs *stream_configs,
--
drivers/media/v4l2-core/v4l2-subdev.c-1890- if (new_configs.num_configs) {
drivers/media/v4l2-core/v4l2-subdev.c:1891: new_configs.configs = kvzalloc_objs(*new_configs.configs,
drivers/media/v4l2-core/v4l2-subdev.c-1892- new_configs.num_configs);
--
drivers/net/ethernet/broadcom/cnic.c=4100=static int cnic_cm_alloc_mem(struct cnic_dev *dev)
--
drivers/net/ethernet/broadcom/cnic.c-4105-
drivers/net/ethernet/broadcom/cnic.c:4106: cp->csk_tbl = kvzalloc_objs(struct cnic_sock, MAX_CM_SK_TBL_SZ);
drivers/net/ethernet/broadcom/cnic.c-4107- if (!cp->csk_tbl)
--
drivers/net/ethernet/chelsio/cxgb4/clip_tbl.c=276=struct clip_tbl *t4_init_clip_tbl(unsigned int clipt_start,
--
drivers/net/ethernet/chelsio/cxgb4/clip_tbl.c-303-
drivers/net/ethernet/chelsio/cxgb4/clip_tbl.c:304: cl_list = kvzalloc_objs(struct clip_entry, clipt_size);
drivers/net/ethernet/chelsio/cxgb4/clip_tbl.c-305- if (!cl_list) {
--
drivers/net/ethernet/fungible/funcore/fun_dev.c=209=static int fun_init_cmd_ctx(struct fun_dev *fdev, unsigned int ntags)
--
drivers/net/ethernet/fungible/funcore/fun_dev.c-212-
drivers/net/ethernet/fungible/funcore/fun_dev.c:213: fdev->cmd_ctx = kvzalloc_objs(*fdev->cmd_ctx, ntags);
drivers/net/ethernet/fungible/funcore/fun_dev.c-214- if (!fdev->cmd_ctx)
--
drivers/net/ethernet/fungible/funeth/funeth_main.c=1173=static int fun_init_vports(struct fun_ethdev *ed, unsigned int n)
--
drivers/net/ethernet/fungible/funeth/funeth_main.c-1177-
drivers/net/ethernet/fungible/funeth/funeth_main.c:1178: ed->vport_info = kvzalloc_objs(*ed->vport_info, n);
drivers/net/ethernet/fungible/funeth/funeth_main.c-1179- if (!ed->vport_info)
--
drivers/net/ethernet/google/gve/gve_main.c=146=static int gve_alloc_flow_rule_caches(struct gve_priv *priv)
--
drivers/net/ethernet/google/gve/gve_main.c-154- flow_rules_cache->rules_cache =
drivers/net/ethernet/google/gve/gve_main.c:155: kvzalloc_objs(*flow_rules_cache->rules_cache,
drivers/net/ethernet/google/gve/gve_main.c-156- GVE_FLOW_RULES_CACHE_SIZE);
--
drivers/net/ethernet/google/gve/gve_main.c=480=static int gve_alloc_notify_blocks(struct gve_priv *priv)
--
drivers/net/ethernet/google/gve/gve_main.c-488-
drivers/net/ethernet/google/gve/gve_main.c:489: priv->msix_vectors = kvzalloc_objs(*priv->msix_vectors,
drivers/net/ethernet/google/gve/gve_main.c-490- num_vecs_requested);
--
drivers/net/ethernet/google/gve/gve_main.c=1123=struct gve_queue_page_list *gve_alloc_queue_page_list(struct gve_priv *priv,
--
drivers/net/ethernet/google/gve/gve_main.c-1135- qpl->num_entries = 0;
drivers/net/ethernet/google/gve/gve_main.c:1136: qpl->pages = kvzalloc_objs(*qpl->pages, pages);
drivers/net/ethernet/google/gve/gve_main.c-1137- if (!qpl->pages)
--
drivers/net/ethernet/google/gve/gve_main.c-1139-
drivers/net/ethernet/google/gve/gve_main.c:1140: qpl->page_buses = kvzalloc_objs(*qpl->page_buses, pages);
drivers/net/ethernet/google/gve/gve_main.c-1141- if (!qpl->page_buses)
--
drivers/net/ethernet/google/gve/gve_rx.c=383=int gve_rx_alloc_rings_gqi(struct gve_priv *priv,
--
drivers/net/ethernet/google/gve/gve_rx.c-389-
drivers/net/ethernet/google/gve/gve_rx.c:390: rx = kvzalloc_objs(struct gve_rx_ring, cfg->qcfg_rx->max_queues);
drivers/net/ethernet/google/gve/gve_rx.c-391- if (!rx)
--
drivers/net/ethernet/google/gve/gve_rx_dqo.c=314=int gve_rx_alloc_rings_dqo(struct gve_priv *priv,
--
drivers/net/ethernet/google/gve/gve_rx_dqo.c-320-
drivers/net/ethernet/google/gve/gve_rx_dqo.c:321: rx = kvzalloc_objs(struct gve_rx_ring, cfg->qcfg_rx->max_queues);
drivers/net/ethernet/google/gve/gve_rx_dqo.c-322- if (!rx)
--
drivers/net/ethernet/google/gve/gve_tx.c=330=int gve_tx_alloc_rings_gqi(struct gve_priv *priv,
--
drivers/net/ethernet/google/gve/gve_tx.c-344-
drivers/net/ethernet/google/gve/gve_tx.c:345: tx = kvzalloc_objs(struct gve_tx_ring, cfg->qcfg->max_queues);
drivers/net/ethernet/google/gve/gve_tx.c-346- if (!tx)
--
drivers/net/ethernet/google/gve/gve_tx_dqo.c=273=static int gve_tx_qpl_buf_init(struct gve_tx_ring *tx)
--
drivers/net/ethernet/google/gve/gve_tx_dqo.c-278-
drivers/net/ethernet/google/gve/gve_tx_dqo.c:279: tx->dqo.tx_qpl_buf_next = kvzalloc_objs(tx->dqo.tx_qpl_buf_next[0],
drivers/net/ethernet/google/gve/gve_tx_dqo.c-280- num_tx_qpl_bufs);
--
drivers/net/ethernet/google/gve/gve_tx_dqo.c=307=static int gve_tx_alloc_ring_dqo(struct gve_priv *priv,
--
drivers/net/ethernet/google/gve/gve_tx_dqo.c-347- tx->dqo.num_pending_packets = min_t(int, num_pending_packets, S16_MAX);
drivers/net/ethernet/google/gve/gve_tx_dqo.c:348: tx->dqo.pending_packets = kvzalloc_objs(tx->dqo.pending_packets[0],
drivers/net/ethernet/google/gve/gve_tx_dqo.c-349- tx->dqo.num_pending_packets);
--
drivers/net/ethernet/google/gve/gve_tx_dqo.c=411=int gve_tx_alloc_rings_dqo(struct gve_priv *priv,
--
drivers/net/ethernet/google/gve/gve_tx_dqo.c-425-
drivers/net/ethernet/google/gve/gve_tx_dqo.c:426: tx = kvzalloc_objs(struct gve_tx_ring, cfg->qcfg->max_queues);
drivers/net/ethernet/google/gve/gve_tx_dqo.c-427- if (!tx)
--
drivers/net/ethernet/intel/idpf/xdp.c=152=int idpf_xdpsqs_get(const struct idpf_vport *vport)
--
drivers/net/ethernet/intel/idpf/xdp.c-160-
drivers/net/ethernet/intel/idpf/xdp.c:161: timers = kvzalloc_objs(*timers, vport->num_xdp_txq);
drivers/net/ethernet/intel/idpf/xdp.c-162- if (!timers)
--
drivers/net/ethernet/mellanox/mlx4/icm.c=414=int mlx4_init_icm_table(struct mlx4_dev *dev, struct mlx4_icm_table *table,
--
drivers/net/ethernet/mellanox/mlx4/icm.c-428-
drivers/net/ethernet/mellanox/mlx4/icm.c:429: table->icm = kvzalloc_objs(*table->icm, num_icm);
drivers/net/ethernet/mellanox/mlx4/icm.c-430- if (!table->icm)
--
drivers/net/ethernet/mellanox/mlx5/core/en/qos.c=69=int mlx5e_open_qos_sq(struct mlx5e_priv *priv, struct mlx5e_channels *chs,
--
drivers/net/ethernet/mellanox/mlx5/core/en/qos.c-89-
drivers/net/ethernet/mellanox/mlx5/core/en/qos.c:90: stats_list = kvzalloc_objs(*stats_list,
drivers/net/ethernet/mellanox/mlx5/core/en/qos.c-91- mlx5e_qos_max_leaf_nodes(priv->mdev));
--
drivers/net/ethernet/mellanox/mlx5/core/en/qos.c=269=int mlx5e_qos_alloc_queues(struct mlx5e_priv *priv, struct mlx5e_channels *chs)
--
drivers/net/ethernet/mellanox/mlx5/core/en/qos.c-278-
drivers/net/ethernet/mellanox/mlx5/core/en/qos.c:279: sqs = kvzalloc_objs(struct mlx5e_txqsq *, qos_sqs_size);
drivers/net/ethernet/mellanox/mlx5/core/en/qos.c-280- if (!sqs)
--
drivers/net/ethernet/mellanox/mlx5/core/en/rx_res.c=350=static int mlx5e_rx_res_channels_init(struct mlx5e_rx_res *res)
--
drivers/net/ethernet/mellanox/mlx5/core/en/rx_res.c-361-
drivers/net/ethernet/mellanox/mlx5/core/en/rx_res.c:362: res->channels = kvzalloc_objs(*res->channels, res->max_nch);
drivers/net/ethernet/mellanox/mlx5/core/en/rx_res.c-363- if (!res->channels) {
--
drivers/net/ethernet/mellanox/mlx5/core/esw/bridge_mcast.c=53=mlx5_esw_bridge_mdb_flow_create(u16 esw_owner_vhca_id, struct mlx5_esw_bridge_mdb_entry *entry,
--
drivers/net/ethernet/mellanox/mlx5/core/esw/bridge_mcast.c-71-
drivers/net/ethernet/mellanox/mlx5/core/esw/bridge_mcast.c:72: dests = kvzalloc_objs(*dests, num_dests);
drivers/net/ethernet/mellanox/mlx5/core/esw/bridge_mcast.c-73- if (!dests) {
--
drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c=1183=static int esw_add_fdb_peer_miss_rules(struct mlx5_eswitch *esw,
--
drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c-1206-
drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c:1207: flows = kvzalloc_objs(*flows, peer_esw->total_vports);
drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c-1208- if (!flows) {
--
drivers/net/ethernet/mellanox/mlx5/core/fpga/conn.c=510=static int mlx5_fpga_conn_create_qp(struct mlx5_fpga_conn *conn,
--
drivers/net/ethernet/mellanox/mlx5/core/fpga/conn.c-533-
drivers/net/ethernet/mellanox/mlx5/core/fpga/conn.c:534: conn->qp.rq.bufs = kvzalloc_objs(conn->qp.rq.bufs[0], conn->qp.rq.size);
drivers/net/ethernet/mellanox/mlx5/core/fpga/conn.c-535- if (!conn->qp.rq.bufs) {
--
drivers/net/ethernet/mellanox/mlx5/core/fpga/conn.c-539-
drivers/net/ethernet/mellanox/mlx5/core/fpga/conn.c:540: conn->qp.sq.bufs = kvzalloc_objs(conn->qp.sq.bufs[0], conn->qp.sq.size);
drivers/net/ethernet/mellanox/mlx5/core/fpga/conn.c-541- if (!conn->qp.sq.bufs) {
--
drivers/net/ethernet/mellanox/mlx5/core/steering/hws/matcher.c=1072=hws_matcher_set_templates(struct mlx5hws_matcher *matcher,
--
drivers/net/ethernet/mellanox/mlx5/core/steering/hws/matcher.c-1092- num_of_at + matcher->attr.max_num_of_at_attach;
drivers/net/ethernet/mellanox/mlx5/core/steering/hws/matcher.c:1093: matcher->at = kvzalloc_objs(*matcher->at, matcher->size_of_at_array);
drivers/net/ethernet/mellanox/mlx5/core/steering/hws/matcher.c-1094- if (!matcher->at) {
--
drivers/net/ethernet/mellanox/mlx5/core/steering/sws/dr_icm_pool.c=225=static int dr_icm_buddy_init_ste_cache(struct mlx5dr_icm_buddy_mem *buddy)
--
drivers/net/ethernet/mellanox/mlx5/core/steering/sws/dr_icm_pool.c-229-
drivers/net/ethernet/mellanox/mlx5/core/steering/sws/dr_icm_pool.c:230: buddy->ste_arr = kvzalloc_objs(struct mlx5dr_ste, num_of_entries);
drivers/net/ethernet/mellanox/mlx5/core/steering/sws/dr_icm_pool.c-231- if (!buddy->ste_arr)
--
drivers/net/ethernet/mellanox/mlx5/core/steering/sws/dr_icm_pool.c=504=struct mlx5dr_icm_pool *mlx5dr_icm_pool_create(struct mlx5dr_domain *dmn,
--
drivers/net/ethernet/mellanox/mlx5/core/steering/sws/dr_icm_pool.c-549-
drivers/net/ethernet/mellanox/mlx5/core/steering/sws/dr_icm_pool.c:550: pool->hot_chunks_arr = kvzalloc_objs(struct mlx5dr_icm_hot_chunk,
drivers/net/ethernet/mellanox/mlx5/core/steering/sws/dr_icm_pool.c-551- num_of_chunks);
--
drivers/net/ethernet/netronome/nfp/nfd3/rings.c=127=nfp_nfd3_tx_ring_alloc(struct nfp_net_dp *dp, struct nfp_net_tx_ring *tx_ring)
--
drivers/net/ethernet/netronome/nfp/nfd3/rings.c-142-
drivers/net/ethernet/netronome/nfp/nfd3/rings.c:143: tx_ring->txbufs = kvzalloc_objs(*tx_ring->txbufs, tx_ring->cnt);
drivers/net/ethernet/netronome/nfp/nfd3/rings.c-144- if (!tx_ring->txbufs)
--
drivers/net/ethernet/netronome/nfp/nfdk/rings.c=93=nfp_nfdk_tx_ring_alloc(struct nfp_net_dp *dp, struct nfp_net_tx_ring *tx_ring)
--
drivers/net/ethernet/netronome/nfp/nfdk/rings.c-107-
drivers/net/ethernet/netronome/nfp/nfdk/rings.c:108: tx_ring->ktxbufs = kvzalloc_objs(*tx_ring->ktxbufs, tx_ring->cnt);
drivers/net/ethernet/netronome/nfp/nfdk/rings.c-109- if (!tx_ring->ktxbufs)
--
drivers/net/veth.c=1433=static int veth_alloc_queues(struct net_device *dev)
--
drivers/net/veth.c-1437-
drivers/net/veth.c:1438: priv->rq = kvzalloc_objs(*priv->rq, dev->num_rx_queues,
drivers/net/veth.c-1439- GFP_KERNEL_ACCOUNT | __GFP_RETRY_MAYFAIL);
--
drivers/net/virtio_net.c=5879=static int virtnet_xsk_pool_enable(struct net_device *dev,
--
drivers/net/virtio_net.c-5920-
drivers/net/virtio_net.c:5921: rq->xsk_buffs = kvzalloc_objs(*rq->xsk_buffs, size);
drivers/net/virtio_net.c-5922- if (!rq->xsk_buffs)
--
drivers/net/wireguard/ratelimiter.c=158=int wg_ratelimiter_init(void)
--
drivers/net/wireguard/ratelimiter.c-178-
drivers/net/wireguard/ratelimiter.c:179: table_v4 = kvzalloc_objs(*table_v4, table_size);
drivers/net/wireguard/ratelimiter.c-180- if (unlikely(!table_v4))
--
drivers/net/wireguard/ratelimiter.c-183-#if IS_ENABLED(CONFIG_IPV6)
drivers/net/wireguard/ratelimiter.c:184: table_v6 = kvzalloc_objs(*table_v6, table_size);
drivers/net/wireguard/ratelimiter.c-185- if (unlikely(!table_v6)) {
--
drivers/nvme/host/auth.c=1015=int nvme_auth_init_ctrl(struct nvme_ctrl *ctrl)
--
drivers/nvme/host/auth.c-1034-
drivers/nvme/host/auth.c:1035: ctrl->dhchap_ctxs = kvzalloc_objs(*chap, ctrl_max_dhchaps(ctrl));
drivers/nvme/host/auth.c-1036- if (!ctrl->dhchap_ctxs) {
--
drivers/nvme/target/rdma.c=364=nvmet_rdma_alloc_cmds(struct nvmet_rdma_device *ndev,
--
drivers/nvme/target/rdma.c-369-
drivers/nvme/target/rdma.c:370: cmds = kvzalloc_objs(struct nvmet_rdma_cmd, nr_cmds);
drivers/nvme/target/rdma.c-371- if (!cmds)
--
drivers/nvme/target/rdma.c=448=nvmet_rdma_alloc_rsps(struct nvmet_rdma_queue *queue)
--
drivers/nvme/target/rdma.c-457-
drivers/nvme/target/rdma.c:458: queue->rsps = kvzalloc_objs(struct nvmet_rdma_rsp, nr_rsps);
drivers/nvme/target/rdma.c-459- if (!queue->rsps)
--
drivers/nvme/target/tcp.c=1523=static int nvmet_tcp_alloc_cmds(struct nvmet_tcp_queue *queue)
--
drivers/nvme/target/tcp.c-1527-
drivers/nvme/target/tcp.c:1528: cmds = kvzalloc_objs(struct nvmet_tcp_cmd, nr_cmds);
drivers/nvme/target/tcp.c-1529- if (!cmds)
--
drivers/s390/crypto/zcrypt_api.c=1597=static long zcrypt_unlocked_ioctl(struct file *filp, unsigned int cmd,
--
drivers/s390/crypto/zcrypt_api.c-1621-
drivers/s390/crypto/zcrypt_api.c:1622: device_status = kvzalloc_objs(struct zcrypt_device_status_ext,
drivers/s390/crypto/zcrypt_api.c-1623- MAX_ZDEV_ENTRIES_EXT);
--
drivers/staging/media/atomisp/pci/isp/kernels/sdis/sdis_1.0/ia_css_sdis.host.c=299=ia_css_isp_dvs_statistics_allocate(
--
drivers/staging/media/atomisp/pci/isp/kernels/sdis/sdis_1.0/ia_css_sdis.host.c-311-
]
|
| 38/2 |
2026/06/15 16:11 |
llm |
debugger |
0m
Model:
Tokens:
input: 54080
output: 29
thoughts: 1154
Thoughts: **Memory Allocation Review: Refining Object Handling**
Okay, so I'm looking at memory allocation, specifically around these `drm_mode_object` structures. Initially, I saw mentions of `kvzalloc_objs`, but a quick check reveals it's not directly defined in the standard include files. That's a bit odd, I thought I'd seen it around. Grepping for it was inconclusive too. The standard approach seems to be `kvmalloc_array`, which I'm familiar with, and it's used here:
```c
objects = kvmalloc_array(object_count, sizeof(struct drm_mode_object *), GFP_KERNEL | __GFP_ZERO);
```
`kvmalloc_array` is preferred because it handles potential integer overflows in the size calculation, and it's quite safe to use. Alternatively I can use `kvzalloc` which is equivalent but, `kvmalloc_array` is safer due to overflow checking. I see that `kvmalloc_array` is implemented using `kvmalloc`, with a size check. This then led me to `kvcalloc`, which is essentially `kvmalloc_array` with `__GFP_ZERO`. Perfect! I think `kvcalloc` is the best replacement in this case.
Next, I'm checking the `fill_object_idr` function, where I want to replace the macro `kzalloc_objs`. This macro expands to `__alloc_objs`, using `kzalloc` which will use `kmalloc` and, on large allocations, it might trigger the page allocator warning. Replacing it with `kvcalloc` should allocate memory via `kvmalloc`, which can fallback to `vmalloc` for larger sizes, avoiding the warning. This seems like a straightforward and good improvement.
Then I moved to `drm_mode_create_lease_ioctl`, where `object_count` is used with `memdup_array_user`:
```c
if (object_count != 0) {
object_ids = memdup_array_user(u64_to_user_ptr(cl->object_ids),
object_count, sizeof(__u32));
if (IS_ERR(object_ids)) {
```
Now, `memdup_array_user` ultimately uses `memdup_user` which uses `kmem_buckets_alloc_track_caller` which, internally, uses `kmalloc` with `__GFP_NOWARN`. So an extremely large `object_count` will be caught by `check_mul_overflow` in `memdup_array_user`. Even if the numbers don't overflow, but create a large allocation, `kmalloc` will return `NULL` (or `ERR_PTR(-ENOMEM)`) due to `__GFP_NOWARN` so there won't be a warning. This is ok from a safety perspective.
However, if `memdup_array_user` fails for a large, but not absurd, `object_count` (like 1,000,000 - 4MB), the user just gets `-ENOMEM`. That's normal, but the kmalloc might succeed or fail depending on fragmentation. So that got me thinking, if we want to support these edge cases, should we use `vmemdup_array_user`? I saw that `vmemdup_array_user` exists. If `object_count` is large, it would use `vmalloc`. The question then becomes, is `object_count = 1000000` a valid use case? It seems absurd for a DRM device, which typically has only a few dozen objects. So, `object_count` should be small. Should we just limit `object_count` in this ioctl? Maybe I should check if there's similar limits on object counts in other DRM ioctls.
|
| 39/2 |
2026/06/15 16:11 |
tool |
grepper |
0m
Args: map[Expression:object_count PathPrefix:drivers/gpu/drm/]
Results: map[Output:drivers/gpu/drm/drm_lease.c=346=static int validate_lease(struct drm_device *dev,
drivers/gpu/drm/drm_lease.c:347: int object_count,
drivers/gpu/drm/drm_lease.c-348- struct drm_mode_object **objects,
--
drivers/gpu/drm/drm_lease.c-358-
drivers/gpu/drm/drm_lease.c:359: for (o = 0; o < object_count; o++) {
drivers/gpu/drm/drm_lease.c-360- if (objects[o]->type == DRM_MODE_OBJECT_CRTC && has_crtc == -1) {
--
drivers/gpu/drm/drm_lease.c=378=static int fill_object_idr(struct drm_device *dev,
--
drivers/gpu/drm/drm_lease.c-380- struct idr *leases,
drivers/gpu/drm/drm_lease.c:381: int object_count,
drivers/gpu/drm/drm_lease.c-382- u32 *object_ids)
--
drivers/gpu/drm/drm_lease.c-388-
drivers/gpu/drm/drm_lease.c:389: objects = kzalloc_objs(struct drm_mode_object *, object_count);
drivers/gpu/drm/drm_lease.c-390- if (!objects)
--
drivers/gpu/drm/drm_lease.c-394- and check for validity. */
drivers/gpu/drm/drm_lease.c:395: for (o = 0; o < object_count; o++) {
drivers/gpu/drm/drm_lease.c-396- objects[o] = drm_mode_object_find(dev, lessor_priv,
--
drivers/gpu/drm/drm_lease.c-410-
drivers/gpu/drm/drm_lease.c:411: ret = validate_lease(dev, object_count, objects, universal_planes);
drivers/gpu/drm/drm_lease.c-412- if (ret) {
--
drivers/gpu/drm/drm_lease.c-418- universal planes */
drivers/gpu/drm/drm_lease.c:419: for (o = 0; o < object_count; o++) {
drivers/gpu/drm/drm_lease.c-420- struct drm_mode_object *obj = objects[o];
--
drivers/gpu/drm/drm_lease.c-460-out_free_objects:
drivers/gpu/drm/drm_lease.c:461: for (o = 0; o < object_count; o++) {
drivers/gpu/drm/drm_lease.c-462- if (objects[o])
--
drivers/gpu/drm/drm_lease.c=475=int drm_mode_create_lease_ioctl(struct drm_device *dev,
--
drivers/gpu/drm/drm_lease.c-478- struct drm_mode_create_lease *cl = data;
drivers/gpu/drm/drm_lease.c:479: size_t object_count;
drivers/gpu/drm/drm_lease.c-480- int ret = 0;
--
drivers/gpu/drm/drm_lease.c-506-
drivers/gpu/drm/drm_lease.c:507: object_count = cl->object_count;
drivers/gpu/drm/drm_lease.c-508-
--
drivers/gpu/drm/drm_lease.c-510- idr_init(&leases);
drivers/gpu/drm/drm_lease.c:511: if (object_count != 0) {
drivers/gpu/drm/drm_lease.c-512- object_ids = memdup_array_user(u64_to_user_ptr(cl->object_ids),
drivers/gpu/drm/drm_lease.c:513: object_count, sizeof(__u32));
drivers/gpu/drm/drm_lease.c-514- if (IS_ERR(object_ids)) {
--
drivers/gpu/drm/drm_lease.c-521- ret = fill_object_idr(dev, lessor_priv, &leases,
drivers/gpu/drm/drm_lease.c:522: object_count, object_ids);
drivers/gpu/drm/drm_lease.c-523- kfree(object_ids);
]
|
| 40/2 |
2026/06/15 16:11 |
llm |
debugger |
0m
Model:
Tokens:
input: 57261
output: 17
thoughts: 920
Thoughts: **Analyzing Potential Memory Allocation Issues in the DRM Lease Implementation**
Okay, let's break this down. I see that `object_count`, passed from the `drm_mode_create_lease_ioctl` ioctl to `fill_object_idr`, is a potential area for abuse. Specifically, `cl->object_count` from the user-space structure is a `__u32`, while the same variable is an `int` within `fill_object_idr`. That jump in types has my attention.
My immediate thought is, if `cl->object_count` is large, say `0x80000000`, the `memdup_array_user` call, using `size_t object_count`, will attempt an 8GB allocation because of that multiplication. However, `kmalloc`, which `memdup_array_user` uses internally, isn't going to handle an 8GB allocation. It should fail with `-ENOMEM`. We can't let that become an unhandled resource exhaustion.
But even a smaller allocation, like 1GB (`0x40000000`), is a problem because `kmalloc` has a limit. It's typically capped at 4MB or 8MB, or similar. So, `memdup_array_user` is going to fail for anything significantly above 4MB. That means `object_count` has a strict upper bound. Doing the math, with 4MB as the limit, it looks like `object_count` can be at most 1,048,576.
Let's assume that it's 1,000,000. Then `memdup_array_user` will allocate 4MB, which is fine. But when we call `fill_object_idr` with that value, the function's integer `object_count` is fine since it's a valid integer value. The problem comes in the next allocation. `kzalloc_objs` is going to allocate 8MB, and that's *greater* than the expected max of 4MB. It will trigger a warning.
I also want to consider the case where `object_count` is `0xffffffff`. The multiplication in `memdup_array_user` will overflow, but the check for that overflow correctly detects the problem. It will try to allocate an enormous amount and fail, but in this case, the `kmalloc` will return `-ENOMEM`, so that's handled. So, that's not the critical issue.
The real problem lies in the window where `object_count * 4 <= KMALLOC_MAX_SIZE`, but `object_count * 8 > KMALLOC_MAX_SIZE`. Let's say `KMALLOC_MAX_SIZE` is 4MB. Then this happens when `object_count` is between 524,288 and 1,048,576. With 8MB, that range shifts to between 1,048,576 and 2,097,152. This is the scenario that needs a fix, so that the allocation does not fail later.
The fix I'm thinking of is to use a different allocator in `fill_object_idr`, specifically `kvmalloc_array` instead of `kzalloc_objs`, since `kvmalloc` can handle larger allocations. But, wait, `kzalloc_objs` is a macro! I need to replace the macro with a call to a function. I could use `kvzalloc` or `kvmalloc_array`. But `kvmalloc_array` doesn't zero the memory. So, I need to use either `kvcalloc` or `kvmalloc_array` with `GFP_KERNEL | __GFP_ZERO`. Now, the important question is: is `kvcalloc` available for this? Let's check.
|
| 41/2 |
2026/06/15 16:11 |
tool |
grepper |
0m
Args:
Results: map[Output:
Full output is too long, showing 500 out of 572 lines.
Use more precise expression if possible.
arch/arm64/kvm/nested.c=68=int kvm_vcpu_init_nested(struct kvm_vcpu *vcpu)
--
arch/arm64/kvm/nested.c-93- if (num_mmus > kvm->arch.nested_mmus_size) {
arch/arm64/kvm/nested.c:94: tmp = kvcalloc(num_mmus, sizeof(*tmp), GFP_KERNEL_ACCOUNT);
arch/arm64/kvm/nested.c-95- if (!tmp)
--
arch/loongarch/net/bpf_jit.c=2169=struct bpf_prog *bpf_int_jit_compile(struct bpf_verifier_env *env, struct bpf_prog *prog)
--
arch/loongarch/net/bpf_jit.c-2208-
arch/loongarch/net/bpf_jit.c:2209: ctx.offset = kvcalloc(prog->len + 1, sizeof(u32), GFP_KERNEL);
arch/loongarch/net/bpf_jit.c-2210- if (ctx.offset == NULL)
--
arch/s390/net/bpf_jit_comp.c=2315=struct bpf_prog *bpf_int_jit_compile(struct bpf_verifier_env *env, struct bpf_prog *fp)
--
arch/s390/net/bpf_jit_comp.c-2341- memset(&jit, 0, sizeof(jit));
arch/s390/net/bpf_jit_comp.c:2342: jit.addrs = kvcalloc(fp->len + 1, sizeof(*jit.addrs), GFP_KERNEL);
arch/s390/net/bpf_jit_comp.c-2343- if (jit.addrs == NULL)
--
drivers/accel/habanalabs/common/mmu/mmu.c=1380=int hl_mmu_dr_init(struct hl_device *hdev)
--
drivers/accel/habanalabs/common/mmu/mmu.c-1401-
drivers/accel/habanalabs/common/mmu/mmu.c:1402: hdev->mmu_priv.dr.mmu_shadow_hop0 = kvcalloc(prop->max_asid,
drivers/accel/habanalabs/common/mmu/mmu.c-1403- prop->dmmu.hop_table_size, GFP_KERNEL);
--
drivers/accel/habanalabs/gaudi2/gaudi2.c=10669=static int gaudi2_memset_device_memory(struct hl_device *hdev, u64 addr, u64 size, u64 val)
--
drivers/accel/habanalabs/gaudi2/gaudi2.c-10709-
drivers/accel/habanalabs/gaudi2/gaudi2.c:10710: lin_dma_pkts_arr = kvcalloc(num_of_pkts, pkt_size, GFP_KERNEL);
drivers/accel/habanalabs/gaudi2/gaudi2.c-10711- if (!lin_dma_pkts_arr)
--
drivers/block/xen-blkfront.c=1894=static int negotiate_mq(struct blkfront_info *info)
--
drivers/block/xen-blkfront.c-1911- BLK_RING_SIZE(info));
drivers/block/xen-blkfront.c:1912: info->rinfo = kvcalloc(info->nr_rings, info->rinfo_size, GFP_KERNEL);
drivers/block/xen-blkfront.c-1913- if (!info->rinfo) {
--
drivers/crypto/intel/qat/qat_common/qat_comp_algs.c=40=static void *qat_zstd_alloc_scratch(void)
--
drivers/crypto/intel/qat/qat_common/qat_comp_algs.c-61-
drivers/crypto/intel/qat/qat_common/qat_comp_algs.c:62: scratch->out_seqs = kvcalloc(QAT_MAX_SEQUENCES, sizeof(ZSTD_Sequence),
drivers/crypto/intel/qat/qat_common/qat_comp_algs.c-63- GFP_KERNEL);
--
drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c=1005=int amdgpu_gem_op_ioctl(struct drm_device *dev, void *data,
--
drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c-1100-
drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c:1101: vm_entries = kvcalloc(args->num_entries, sizeof(*vm_entries), GFP_KERNEL);
drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c-1102- if (!vm_entries) {
--
drivers/gpu/drm/amd/amdkfd/kfd_migrate.c=393=svm_migrate_vma_to_vram(struct kfd_node *node, struct svm_range *prange,
--
drivers/gpu/drm/amd/amdkfd/kfd_migrate.c-415-
drivers/gpu/drm/amd/amdkfd/kfd_migrate.c:416: buf = kvcalloc(npages,
drivers/gpu/drm/amd/amdkfd/kfd_migrate.c-417- 2 * sizeof(*migrate.src) + sizeof(u64) + sizeof(dma_addr_t),
--
drivers/gpu/drm/amd/amdkfd/kfd_migrate.c=692=svm_migrate_vma_to_ram(struct kfd_node *node, struct svm_range *prange,
--
drivers/gpu/drm/amd/amdkfd/kfd_migrate.c-717-
drivers/gpu/drm/amd/amdkfd/kfd_migrate.c:718: buf = kvcalloc(npages,
drivers/gpu/drm/amd/amdkfd/kfd_migrate.c-719- 2 * sizeof(*migrate.src) + sizeof(u64) + sizeof(dma_addr_t),
--
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c=480=void dm_dtn_log_append_v(struct dc_context *ctx,
--
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c-513- if (total > log_ctx->size) {
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c:514: char *buf = kvcalloc(total, sizeof(char), GFP_KERNEL);
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c-515-
--
drivers/gpu/drm/drm_pagemap.c=517=int drm_pagemap_migrate_to_devmem(struct drm_pagemap_devmem *devmem_allocation,
--
drivers/gpu/drm/drm_pagemap.c-563-
drivers/gpu/drm/drm_pagemap.c:564: buf = kvcalloc(npages, 2 * sizeof(*migrate.src) + sizeof(*pagemap_addr) +
drivers/gpu/drm/drm_pagemap.c-565- sizeof(*pages), GFP_KERNEL);
--
drivers/gpu/drm/drm_pagemap.c=1012=int drm_pagemap_evict_to_ram(struct drm_pagemap_devmem *devmem_allocation)
--
drivers/gpu/drm/drm_pagemap.c-1029-
drivers/gpu/drm/drm_pagemap.c:1030: buf = kvcalloc(npages, 2 * sizeof(*src) + sizeof(*pagemap_addr) +
drivers/gpu/drm/drm_pagemap.c-1031- sizeof(*pages), GFP_KERNEL);
--
drivers/gpu/drm/drm_pagemap.c=1113=static int __drm_pagemap_migrate_to_ram(struct vm_area_struct *vas,
--
drivers/gpu/drm/drm_pagemap.c-1153-
drivers/gpu/drm/drm_pagemap.c:1154: buf = kvcalloc(npages, 2 * sizeof(*migrate.src) + sizeof(*pagemap_addr) +
drivers/gpu/drm/drm_pagemap.c-1155- sizeof(*pages), GFP_KERNEL);
--
drivers/gpu/drm/lima/lima_drv.c=102=static int lima_ioctl_gem_submit(struct drm_device *dev, void *data, struct drm_file *file)
--
drivers/gpu/drm/lima/lima_drv.c-124-
drivers/gpu/drm/lima/lima_drv.c:125: bos = kvcalloc(args->nr_bos, sizeof(*submit.bos) + sizeof(*submit.lbos), GFP_KERNEL);
drivers/gpu/drm/lima/lima_drv.c-126- if (!bos)
--
drivers/gpu/drm/nouveau/nouveau_dmem.c=475=nouveau_dmem_evict_chunk(struct nouveau_dmem_chunk *chunk)
--
drivers/gpu/drm/nouveau/nouveau_dmem.c-481-
drivers/gpu/drm/nouveau/nouveau_dmem.c:482: src_pfns = kvcalloc(npages, sizeof(*src_pfns), GFP_KERNEL | __GFP_NOFAIL);
drivers/gpu/drm/nouveau/nouveau_dmem.c:483: dst_pfns = kvcalloc(npages, sizeof(*dst_pfns), GFP_KERNEL | __GFP_NOFAIL);
drivers/gpu/drm/nouveau/nouveau_dmem.c-484- dma_info = kvzalloc_objs(*dma_info, npages, GFP_KERNEL | __GFP_NOFAIL);
--
drivers/gpu/drm/ttm/ttm_tt.c=118=static int ttm_tt_alloc_page_directory(struct ttm_tt *ttm)
drivers/gpu/drm/ttm/ttm_tt.c-119-{
drivers/gpu/drm/ttm/ttm_tt.c:120: ttm->pages = kvcalloc(ttm->num_pages, sizeof(void*), GFP_KERNEL);
drivers/gpu/drm/ttm/ttm_tt.c-121- if (!ttm->pages)
--
drivers/gpu/drm/ttm/ttm_tt.c=127=static int ttm_dma_tt_alloc_page_directory(struct ttm_tt *ttm)
drivers/gpu/drm/ttm/ttm_tt.c-128-{
drivers/gpu/drm/ttm/ttm_tt.c:129: ttm->pages = kvcalloc(ttm->num_pages, sizeof(*ttm->pages) +
drivers/gpu/drm/ttm/ttm_tt.c-130- sizeof(*ttm->dma_address), GFP_KERNEL);
--
drivers/infiniband/core/umem_odp.c=58=static int ib_init_umem_odp(struct ib_umem_odp *umem_odp,
--
drivers/infiniband/core/umem_odp.c-96- if (ib_uses_virt_dma(dev)) {
drivers/infiniband/core/umem_odp.c:97: map->pfn_list = kvcalloc(nr_entries, sizeof(*map->pfn_list),
drivers/infiniband/core/umem_odp.c-98- GFP_KERNEL | __GFP_NOWARN);
--
drivers/infiniband/hw/mlx5/srq.c=96=static int create_srq_kernel(struct mlx5_ib_dev *dev, struct mlx5_ib_srq *srq,
--
drivers/infiniband/hw/mlx5/srq.c-129- mlx5_ib_dbg(dev, "srq->buf.page_shift = %d\n", srq->buf.page_shift);
drivers/infiniband/hw/mlx5/srq.c:130: in->pas = kvcalloc(srq->buf.npages, sizeof(*in->pas), GFP_KERNEL);
drivers/infiniband/hw/mlx5/srq.c-131- if (!in->pas) {
--
drivers/iommu/iommufd/viommu.c=290=iommufd_hw_queue_alloc_phys(struct iommu_hw_queue_alloc *cmd,
--
drivers/iommu/iommufd/viommu.c-311- /*
drivers/iommu/iommufd/viommu.c:312: * Use kvcalloc() to avoid memory fragmentation for a large page array.
drivers/iommu/iommufd/viommu.c-313- * Set __GFP_NOWARN to avoid syzkaller blowups
--
drivers/md/dm-pcache/cache.c=134=static int cache_init(struct dm_pcache *pcache)
--
drivers/md/dm-pcache/cache.c-147-
drivers/md/dm-pcache/cache.c:148: cache->seg_map = kvcalloc(BITS_TO_LONGS(cache_dev->seg_num), sizeof(unsigned long), GFP_KERNEL);
drivers/md/dm-pcache/cache.c-149- if (!cache->seg_map) {
--
drivers/md/dm-pcache/cache.c=281=static int cache_init_req_keys(struct pcache_cache *cache, u32 n_paral)
--
drivers/md/dm-pcache/cache.c-294- cache->n_ksets = n_paral;
drivers/md/dm-pcache/cache.c:295: cache->ksets = kvcalloc(cache->n_ksets, PCACHE_KSET_SIZE, GFP_KERNEL);
drivers/md/dm-pcache/cache.c-296- if (!cache->ksets) {
--
drivers/md/dm-pcache/cache_dev.c=217=static int cache_dev_init(struct pcache_cache_dev *cache_dev, u32 seg_num)
--
drivers/md/dm-pcache/cache_dev.c-219- cache_dev->seg_num = seg_num;
drivers/md/dm-pcache/cache_dev.c:220: cache_dev->seg_bitmap = kvcalloc(BITS_TO_LONGS(cache_dev->seg_num), sizeof(unsigned long), GFP_KERNEL);
drivers/md/dm-pcache/cache_dev.c-221- if (!cache_dev->seg_bitmap)
--
drivers/md/dm-table.c=104=static int alloc_targets(struct dm_table *t, unsigned int num)
--
drivers/md/dm-table.c-111- */
drivers/md/dm-table.c:112: n_highs = kvcalloc(num, sizeof(struct dm_target) + sizeof(sector_t),
drivers/md/dm-table.c-113- GFP_KERNEL);
--
drivers/md/dm-table.c=1089=static int setup_indexes(struct dm_table *t)
--
drivers/md/dm-table.c-1100-
drivers/md/dm-table.c:1101: indexes = kvcalloc(total, NODE_SIZE, GFP_KERNEL);
drivers/md/dm-table.c-1102- if (!indexes)
--
drivers/md/dm-verity-target.c=1103=static int verity_alloc_most_once(struct dm_verity *v)
--
drivers/md/dm-verity-target.c-1115-
drivers/md/dm-verity-target.c:1116: v->validated_blocks = kvcalloc(BITS_TO_LONGS(v->data_blocks),
drivers/md/dm-verity-target.c-1117- sizeof(unsigned long),
--
drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_u32.c=495=struct cxgb4_tc_u32_table *cxgb4_init_tc_u32(struct adapter *adap)
--
drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_u32.c-514- bmap_size = BITS_TO_LONGS(max_tids);
drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_u32.c:515: link->tid_map = kvcalloc(bmap_size, sizeof(unsigned long),
drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_u32.c-516- GFP_KERNEL);
--
drivers/net/ethernet/google/gve/gve_main.c=146=static int gve_alloc_flow_rule_caches(struct gve_priv *priv)
--
drivers/net/ethernet/google/gve/gve_main.c-162- flow_rules_cache->rule_ids_cache =
drivers/net/ethernet/google/gve/gve_main.c:163: kvcalloc(GVE_FLOW_RULE_IDS_CACHE_SIZE, sizeof(*flow_rules_cache->rule_ids_cache),
drivers/net/ethernet/google/gve/gve_main.c-164- GFP_KERNEL);
--
drivers/net/ethernet/google/gve/gve_rx.c=181=static int gve_rx_prefill_pages(struct gve_rx_ring *rx,
--
drivers/net/ethernet/google/gve/gve_rx.c-194-
drivers/net/ethernet/google/gve/gve_rx.c:195: rx->data.page_info = kvcalloc_node(slots, sizeof(*rx->data.page_info),
drivers/net/ethernet/google/gve/gve_rx.c-196- GFP_KERNEL, priv->numa_node);
--
drivers/net/ethernet/google/gve/gve_rx.c=273=int gve_rx_alloc_ring_gqi(struct gve_priv *priv,
--
drivers/net/ethernet/google/gve/gve_rx.c-305- rx->qpl_copy_pool_head = 0;
drivers/net/ethernet/google/gve/gve_rx.c:306: rx->qpl_copy_pool = kvcalloc_node(rx->qpl_copy_pool_mask + 1,
drivers/net/ethernet/google/gve/gve_rx.c-307- sizeof(rx->qpl_copy_pool[0]),
--
drivers/net/ethernet/google/gve/gve_rx_dqo.c=214=int gve_rx_alloc_ring_dqo(struct gve_priv *priv,
--
drivers/net/ethernet/google/gve/gve_rx_dqo.c-248- cfg->pages_per_qpl;
drivers/net/ethernet/google/gve/gve_rx_dqo.c:249: rx->dqo.buf_states = kvcalloc_node(rx->dqo.num_buf_states,
drivers/net/ethernet/google/gve/gve_rx_dqo.c-250- sizeof(rx->dqo.buf_states[0]),
--
drivers/net/ethernet/google/gve/gve_tx_dqo.c=307=static int gve_tx_alloc_ring_dqo(struct gve_priv *priv,
--
drivers/net/ethernet/google/gve/gve_tx_dqo.c-362- tx->dqo.xsk_reorder_queue =
drivers/net/ethernet/google/gve/gve_tx_dqo.c:363: kvcalloc(tx->dqo.complq_mask + 1,
drivers/net/ethernet/google/gve/gve_tx_dqo.c-364- sizeof(tx->dqo.xsk_reorder_queue[0]),
--
drivers/net/ethernet/intel/libeth/rx.c=152=int libeth_rx_fq_create(struct libeth_fq *fq, struct napi_struct *napi)
--
drivers/net/ethernet/intel/libeth/rx.c-179-
drivers/net/ethernet/intel/libeth/rx.c:180: fqes = kvcalloc_node(fq->count, sizeof(*fqes), GFP_KERNEL, fq->nid);
drivers/net/ethernet/intel/libeth/rx.c-181- if (!fqes) {
--
drivers/net/ethernet/intel/libeth/xsk.c=160=int libeth_xskfq_create(struct libeth_xskfq *fq)
drivers/net/ethernet/intel/libeth/xsk.c-161-{
drivers/net/ethernet/intel/libeth/xsk.c:162: fq->fqes = kvcalloc_node(fq->count, sizeof(*fq->fqes), GFP_KERNEL,
drivers/net/ethernet/intel/libeth/xsk.c-163- fq->nid);
--
drivers/net/ethernet/mellanox/mlx5/core/en/qos.c=471=int mlx5e_mqprio_rl_init(struct mlx5e_mqprio_rl *rl, struct mlx5_core_dev *mdev, u8 num_tc,
--
drivers/net/ethernet/mellanox/mlx5/core/en/qos.c-485- rl->num_tc = num_tc;
drivers/net/ethernet/mellanox/mlx5/core/en/qos.c:486: rl->leaves_id = kvcalloc(num_tc, sizeof(*rl->leaves_id), GFP_KERNEL);
drivers/net/ethernet/mellanox/mlx5/core/en/qos.c-487- if (!rl->leaves_id)
--
drivers/net/ethernet/mellanox/mlx5/core/en/rx_res.c=323=static struct mlx5e_rx_res *mlx5e_rx_res_alloc(struct mlx5_core_dev *mdev, unsigned int max_nch,
--
drivers/net/ethernet/mellanox/mlx5/core/en/rx_res.c-331-
drivers/net/ethernet/mellanox/mlx5/core/en/rx_res.c:332: rx_res->rss_rqns = kvcalloc(max_nch, sizeof(*rx_res->rss_rqns), GFP_KERNEL);
drivers/net/ethernet/mellanox/mlx5/core/en/rx_res.c-333- if (!rx_res->rss_rqns) {
--
drivers/net/ethernet/mellanox/mlx5/core/en/rx_res.c-338- if (multi_vhca) {
drivers/net/ethernet/mellanox/mlx5/core/en/rx_res.c:339: rx_res->rss_vhca_ids = kvcalloc(max_nch, sizeof(*rx_res->rss_vhca_ids), GFP_KERNEL);
drivers/net/ethernet/mellanox/mlx5/core/en/rx_res.c-340- if (!rx_res->rss_vhca_ids) {
--
drivers/net/ethernet/mellanox/mlx5/core/en_fs.c=169=static int mlx5e_vport_context_update_vlans(struct mlx5e_flow_steering *fs)
--
drivers/net/ethernet/mellanox/mlx5/core/en_fs.c-189-
drivers/net/ethernet/mellanox/mlx5/core/en_fs.c:190: vlans = kvcalloc(list_size, sizeof(*vlans), GFP_KERNEL);
drivers/net/ethernet/mellanox/mlx5/core/en_fs.c-191- if (!vlans)
--
drivers/net/ethernet/mellanox/mlx5/core/en_rep.c=569=mlx5e_add_sqs_fwd_rules(struct mlx5e_priv *priv)
--
drivers/net/ethernet/mellanox/mlx5/core/en_rep.c-590-
drivers/net/ethernet/mellanox/mlx5/core/en_rep.c:591: sqs = kvcalloc(nch * sqs_per_channel, sizeof(*sqs), GFP_KERNEL);
drivers/net/ethernet/mellanox/mlx5/core/en_rep.c-592- if (!sqs)
--
drivers/net/ethernet/mellanox/mlx5/core/fs_pool.c=7=int mlx5_fs_bulk_bitmap_alloc(struct mlx5_core_dev *dev,
--
drivers/net/ethernet/mellanox/mlx5/core/fs_pool.c-11-
drivers/net/ethernet/mellanox/mlx5/core/fs_pool.c:12: fs_bulk->bitmask = kvcalloc(BITS_TO_LONGS(fs_bulk->bulk_len),
drivers/net/ethernet/mellanox/mlx5/core/fs_pool.c-13- sizeof(unsigned long), GFP_KERNEL);
--
drivers/net/ethernet/mellanox/mlx5/core/steering/sws/dr_icm_pool.c=225=static int dr_icm_buddy_init_ste_cache(struct mlx5dr_icm_buddy_mem *buddy)
--
drivers/net/ethernet/mellanox/mlx5/core/steering/sws/dr_icm_pool.c-236- */
drivers/net/ethernet/mellanox/mlx5/core/steering/sws/dr_icm_pool.c:237: buddy->hw_ste_arr = kvcalloc(num_of_entries,
drivers/net/ethernet/mellanox/mlx5/core/steering/sws/dr_icm_pool.c-238- dr_icm_buddy_get_ste_size(buddy), GFP_KERNEL);
--
drivers/net/ethernet/netronome/nfp/abm/main.c=443=static int nfp_abm_init(struct nfp_app *app)
--
drivers/net/ethernet/netronome/nfp/abm/main.c-479-
drivers/net/ethernet/netronome/nfp/abm/main.c:480: abm->thresholds = kvcalloc(abm->num_thresholds,
drivers/net/ethernet/netronome/nfp/abm/main.c-481- sizeof(*abm->thresholds), GFP_KERNEL);
--
drivers/net/ethernet/netronome/nfp/abm/main.c-484-
drivers/net/ethernet/netronome/nfp/abm/main.c:485: abm->actions = kvcalloc(abm->num_thresholds, sizeof(*abm->actions),
drivers/net/ethernet/netronome/nfp/abm/main.c-486- GFP_KERNEL);
--
drivers/net/ethernet/netronome/nfp/nfp_net_dp.c=283=nfp_net_rx_ring_alloc(struct nfp_net_dp *dp, struct nfp_net_rx_ring *rx_ring)
--
drivers/net/ethernet/netronome/nfp/nfp_net_dp.c-319- if (nfp_net_has_xsk_pool_slow(dp, rx_ring->idx)) {
drivers/net/ethernet/netronome/nfp/nfp_net_dp.c:320: rx_ring->xsk_rxbufs = kvcalloc(rx_ring->cnt, rxbuf_sw_desc_sz,
drivers/net/ethernet/netronome/nfp/nfp_net_dp.c-321- GFP_KERNEL);
--
drivers/net/ethernet/netronome/nfp/nfp_net_dp.c-324- } else {
drivers/net/ethernet/netronome/nfp/nfp_net_dp.c:325: rx_ring->rxbufs = kvcalloc(rx_ring->cnt, rxbuf_sw_desc_sz,
drivers/net/ethernet/netronome/nfp/nfp_net_dp.c-326- GFP_KERNEL);
--
drivers/platform/x86/hp/hp-bioscfg/enum-attributes.c=92=int hp_alloc_enumeration_data(void)
--
drivers/platform/x86/hp/hp-bioscfg/enum-attributes.c-98- return -EINVAL;
drivers/platform/x86/hp/hp-bioscfg/enum-attributes.c:99: bioscfg_drv.enumeration_data = kvcalloc(bioscfg_drv.enumeration_instances_count,
drivers/platform/x86/hp/hp-bioscfg/enum-attributes.c-100- sizeof(*bioscfg_drv.enumeration_data), GFP_KERNEL);
--
drivers/scsi/libiscsi.c=2771=iscsi_pool_init(struct iscsi_pool *q, int max, void ***items, int item_size)
--
drivers/scsi/libiscsi.c-2782- num_arrays++;
drivers/scsi/libiscsi.c:2783: q->pool = kvcalloc(num_arrays * max, sizeof(void *), GFP_KERNEL);
drivers/scsi/libiscsi.c-2784- if (q->pool == NULL)
--
drivers/staging/media/atomisp/pci/runtime/isp_param/src/isp_param.c=97=ia_css_isp_param_allocate_isp_parameters(
--
drivers/staging/media/atomisp/pci/runtime/isp_param/src/isp_param.c-116- if (size) {
drivers/staging/media/atomisp/pci/runtime/isp_param/src/isp_param.c:117: mem_params->params[pclass][mem].address = kvcalloc(1,
drivers/staging/media/atomisp/pci/runtime/isp_param/src/isp_param.c-118- size,
--
drivers/target/target_core_transport.c=313=int transport_alloc_session_tags(struct se_session *se_sess,
--
drivers/target/target_core_transport.c-317-
drivers/target/target_core_transport.c:318: se_sess->sess_cmd_map = kvcalloc(tag_size, tag_num,
drivers/target/target_core_transport.c-319- GFP_KERNEL | __GFP_RETRY_MAYFAIL);
--
drivers/vdpa/mlx5/core/mr.c=211=static int create_direct_keys(struct mlx5_vdpa_dev *mvdev, struct mlx5_vdpa_mr *mr)
--
drivers/vdpa/mlx5/core/mr.c-227- mttcount = mttlen / sizeof(cmd_mem->mtt[0]);
drivers/vdpa/mlx5/core/mr.c:228: cmd_mem = kvcalloc(1, struct_size(cmd_mem, mtt, mttcount), GFP_KERNEL);
drivers/vdpa/mlx5/core/mr.c-229- if (!cmd_mem) {
--
fs/btrfs/file-item.c=346=int btrfs_lookup_bio_sums(struct btrfs_bio *bbio)
--
fs/btrfs/file-item.c-381- if (nblocks * csum_size > BTRFS_BIO_INLINE_CSUM_SIZE) {
fs/btrfs/file-item.c:382: bbio->csum = kvcalloc(nblocks, csum_size, GFP_NOFS);
fs/btrfs/file-item.c-383- if (!bbio->csum)
--
fs/exfat/nls.c=647=static int exfat_load_upcase_table(struct super_block *sb,
--
fs/exfat/nls.c-657-
fs/exfat/nls.c:658: upcase_table = kvcalloc(UTBL_COUNT, sizeof(unsigned short), GFP_KERNEL);
fs/exfat/nls.c-659- if (!upcase_table)
--
fs/exfat/nls.c=702=static int exfat_load_default_upcase_table(struct super_block *sb)
--
fs/exfat/nls.c-709-
fs/exfat/nls.c:710: upcase_table = kvcalloc(UTBL_COUNT, sizeof(unsigned short), GFP_KERNEL);
fs/exfat/nls.c-711- if (!upcase_table)
--
fs/ntfs/runlist.c=1676=struct runlist_element *ntfs_rl_insert_range(struct runlist_element *dst_rl, int dst_cnt,
--
fs/ntfs/runlist.c-1750- new_cnt += dst_rl_split.lcn >= LCN_HOLE ? 1 : 0;
fs/ntfs/runlist.c:1751: new_rl = kvcalloc(new_cnt, sizeof(*new_rl), GFP_NOFS);
fs/ntfs/runlist.c-1752- if (!new_rl)
--
fs/ntfs/runlist.c=1796=struct runlist_element *ntfs_rl_punch_hole(struct runlist_element *dst_rl, int dst_cnt,
--
fs/ntfs/runlist.c-1834-
fs/ntfs/runlist.c:1835: *punch_rl = kvcalloc(punch_cnt + 1, sizeof(struct runlist_element),
fs/ntfs/runlist.c-1836- GFP_NOFS);
--
fs/ntfs/runlist.c-1840- new_cnt = dst_cnt - (int)(e_rl - s_rl + 1) + 3;
fs/ntfs/runlist.c:1841: new_rl = kvcalloc(new_cnt, sizeof(struct runlist_element), GFP_NOFS);
fs/ntfs/runlist.c-1842- if (!new_rl) {
--
fs/ntfs/runlist.c=1947=struct runlist_element *ntfs_rl_collapse_range(struct runlist_element *dst_rl, int dst_cnt,
--
fs/ntfs/runlist.c-1984- punch_cnt = (int)(e_rl - s_rl) + 1;
fs/ntfs/runlist.c:1985: *punch_rl = kvcalloc(punch_cnt + 1, sizeof(struct runlist_element),
fs/ntfs/runlist.c-1986- GFP_NOFS);
--
fs/ntfs/runlist.c-1990- new_cnt = dst_cnt - (int)(e_rl - s_rl + 1) + 3;
fs/ntfs/runlist.c:1991: new_rl = kvcalloc(new_cnt, sizeof(struct runlist_element), GFP_NOFS);
fs/ntfs/runlist.c-1992- if (!new_rl) {
--
fs/ntfs/upcase.c=11=__le16 *generate_default_upcase(void)
--
fs/ntfs/upcase.c-54-
fs/ntfs/upcase.c:55: uc = kvcalloc(default_upcase_len, sizeof(__le16), GFP_NOFS);
fs/ntfs/upcase.c-56- if (!uc)
--
fs/smb/client/compress/lz77.c=218=noinline int lz77_compress(const void *src, const u32 slen, void *dst, u32 *dlen)
--
fs/smb/client/compress/lz77.c-236-
fs/smb/client/compress/lz77.c:237: htable = kvcalloc(LZ77_HASH_SIZE, sizeof(*htable), GFP_KERNEL);
fs/smb/client/compress/lz77.c-238- if (!htable)
--
fs/verity/open.c=186=struct fsverity_info *fsverity_create_info(struct inode *inode,
--
fs/verity/open.c-235-
fs/verity/open.c:236: vi->hash_block_verified = kvcalloc(BITS_TO_LONGS(num_bits),
fs/verity/open.c-237- sizeof(unsigned long),
--
include/linux/bpf.h=2665=void *bpf_map_kzalloc(const struct bpf_map *map, size_t size, gfp_t flags);
include/linux/bpf.h:2666:void *bpf_map_kvcalloc(struct bpf_map *map, size_t n, size_t size,
include/linux/bpf.h-2667- gfp_t flags);
include/linux/bpf.h=2668=void __percpu *bpf_map_alloc_percpu(const struct bpf_map *map, size_t size,
--
include/linux/bpf.h-2680- kzalloc(_size, _flags)
include/linux/bpf.h:2681:#define bpf_map_kvcalloc(_map, _n, _size, _flags) \
include/linux/bpf.h:2682: kvcalloc(_n, _size, _flags)
include/linux/bpf.h-2683-#define bpf_map_alloc_percpu(_map, _size, _align, _flags) \
--
include/linux/slab.h=1209=kvmalloc_array_node_noprof(size_t n, size_t size, gfp_t flags, int node)
--
include/linux/slab.h-1219-#define kvmalloc_array_noprof(...) kvmalloc_array_node_noprof(__VA_ARGS__, NUMA_NO_NODE)
include/linux/slab.h:1220:#define kvcalloc_node_noprof(_n,_s,_f,_node) kvmalloc_array_node_noprof(_n,_s,(_f)|__GFP_ZERO,_node)
include/linux/slab.h:1221:#define kvcalloc_noprof(...) kvcalloc_node_noprof(__VA_ARGS__, NUMA_NO_NODE)
include/linux/slab.h-1222-
include/linux/slab.h-1223-#define kvmalloc_array(...) alloc_hooks(kvmalloc_array_noprof(__VA_ARGS__))
include/linux/slab.h:1224:#define kvcalloc_node(...) alloc_hooks(kvcalloc_node_noprof(__VA_ARGS__))
include/linux/slab.h:1225:#define kvcalloc(...) alloc_hooks(kvcalloc_noprof(__VA_ARGS__))
include/linux/slab.h-1226-
--
kernel/bpf/bpf_local_storage.c=773=bpf_local_storage_map_alloc(union bpf_attr *attr,
--
kernel/bpf/bpf_local_storage.c-790-
kernel/bpf/bpf_local_storage.c:791: smap->buckets = bpf_map_kvcalloc(&smap->map, nbuckets,
kernel/bpf/bpf_local_storage.c-792- sizeof(*smap->buckets), GFP_USER | __GFP_NOWARN);
--
kernel/bpf/btf.c=1926=static int env_resolve_init(struct btf_verifier_env *env)
--
kernel/bpf/btf.c-1933-
kernel/bpf/btf.c:1934: resolved_sizes = kvcalloc(nr_types, sizeof(*resolved_sizes),
kernel/bpf/btf.c-1935- GFP_KERNEL | __GFP_NOWARN);
--
kernel/bpf/btf.c-1938-
kernel/bpf/btf.c:1939: resolved_ids = kvcalloc(nr_types, sizeof(*resolved_ids),
kernel/bpf/btf.c-1940- GFP_KERNEL | __GFP_NOWARN);
--
kernel/bpf/btf.c-1943-
kernel/bpf/btf.c:1944: visit_states = kvcalloc(nr_types, sizeof(*visit_states),
kernel/bpf/btf.c-1945- GFP_KERNEL | __GFP_NOWARN);
--
kernel/bpf/cfg.c=248=static struct bpf_iarray *jt_from_map(struct bpf_map *map)
--
kernel/bpf/cfg.c-276- * Find and collect all maps which fit in the subprog. Return the result as one
kernel/bpf/cfg.c:277: * combined jump table in jt->items (allocated with kvcalloc)
kernel/bpf/cfg.c-278- */
--
kernel/bpf/cfg.c=708=int bpf_compute_scc(struct bpf_verifier_env *env)
--
kernel/bpf/cfg.c-729- */
kernel/bpf/cfg.c:730: stack = kvcalloc(insn_cnt, sizeof(int), GFP_KERNEL_ACCOUNT);
kernel/bpf/cfg.c:731: pre = kvcalloc(insn_cnt, sizeof(int), GFP_KERNEL_ACCOUNT);
kernel/bpf/cfg.c:732: low = kvcalloc(insn_cnt, sizeof(int), GFP_KERNEL_ACCOUNT);
kernel/bpf/cfg.c:733: dfs = kvcalloc(insn_cnt, sizeof(*dfs), GFP_KERNEL_ACCOUNT);
kernel/bpf/cfg.c-734- if (!stack || !pre || !low || !dfs) {
--
kernel/bpf/check_btf.c=31=static int check_btf_func_early(struct bpf_verifier_env *env,
--
kernel/bpf/check_btf.c-65-
kernel/bpf/check_btf.c:66: krecord = kvcalloc(nfuncs, krec_size, GFP_KERNEL_ACCOUNT | __GFP_NOWARN);
kernel/bpf/check_btf.c-67- if (!krecord)
--
kernel/bpf/syscall.c=551=void *bpf_map_kzalloc(const struct bpf_map *map, size_t size, gfp_t flags)
--
kernel/bpf/syscall.c-562-
kernel/bpf/syscall.c:563:void *bpf_map_kvcalloc(struct bpf_map *map, size_t n, size_t size,
kernel/bpf/syscall.c-564- gfp_t flags)
--
kernel/bpf/syscall.c-569- bpf_map_memcg_enter(map, &old_memcg, &memcg);
kernel/bpf/syscall.c:570: ptr = kvcalloc(n, size, flags | __GFP_ACCOUNT);
kernel/bpf/syscall.c-571- bpf_map_memcg_exit(old_memcg, memcg);
--
kernel/bpf/verifier.c=5504=static int check_max_stack_depth(struct bpf_verifier_env *env)
--
kernel/bpf/verifier.c-5511-
kernel/bpf/verifier.c:5512: dinfo = kvcalloc(env->subprog_cnt, sizeof(*dinfo), GFP_KERNEL_ACCOUNT);
kernel/bpf/verifier.c-5513- if (!dinfo)
--
lib/stackdepot.c=150=int __init stack_depot_early_init(void)
--
lib/stackdepot.c-226-
lib/stackdepot.c:227:/* Allocates a hash table via kvcalloc. Can be used after boot. */
lib/stackdepot.c-228-int stack_depot_init(void)
--
lib/stackdepot.c-261-
lib/stackdepot.c:262: pr_info("allocating hash table of %lu entries via kvcalloc\n", entries);
lib/stackdepot.c-263- stack_table = kvzalloc_objs(struct list_head, entries);
--
lib/stackdepot.c-272-
lib/stackdepot.c:273: pr_info("allocating space for %u stack pools via kvcalloc\n",
lib/stackdepot.c-274- stack_max_pools);
lib/stackdepot.c:275: stack_pools = kvcalloc(stack_max_pools, sizeof(void *), GFP_KERNEL);
lib/stackdepot.c-276- if (!stack_pools) {
--
lib/test_hmm.c=188=static void dmirror_device_evict_chunk(struct dmirror_chunk *chunk)
--
lib/test_hmm.c-197-
lib/test_hmm.c:198: src_pfns = kvcalloc(npages, sizeof(*src_pfns), GFP_KERNEL | __GFP_NOFAIL);
lib/test_hmm.c:199: dst_pfns = kvcalloc(npages, sizeof(*dst_pfns), GFP_KERNEL | __GFP_NOFAIL);
lib/test_hmm.c-200-
--
lib/test_hmm.c=1101=static int dmirror_migrate_to_system(struct dmirror *dmirror,
--
lib/test_hmm.c-1113-
lib/test_hmm.c:1114: src_pfns = kvcalloc(PTRS_PER_PTE, sizeof(*src_pfns), GFP_KERNEL | __GFP_NOFAIL);
lib/test_hmm.c:1115: dst_pfns = kvcalloc(PTRS_PER_PTE, sizeof(*dst_pfns), GFP_KERNEL | __GFP_NOFAIL);
lib/test_hmm.c-1116-
--
lib/test_hmm.c=1166=static int dmirror_migrate_to_device(struct dmirror *dmirror,
--
lib/test_hmm.c-1189- ret = -ENOMEM;
lib/test_hmm.c:1190: src_pfns = kvcalloc(PTRS_PER_PTE, sizeof(*src_pfns),
lib/test_hmm.c-1191- GFP_KERNEL | __GFP_NOFAIL);
--
lib/test_hmm.c-1194-
lib/test_hmm.c:1195: dst_pfns = kvcalloc(PTRS_PER_PTE, sizeof(*dst_pfns),
lib/test_hmm.c-1196- GFP_KERNEL | __GFP_NOFAIL);
--
lib/tests/fortify_kunit.c=289=DEFINE_ALLOC_SIZE_TEST_PAIR(vmalloc)
--
lib/tests/fortify_kunit.c-309- checker((expected_pages) * PAGE_SIZE, \
lib/tests/fortify_kunit.c:310: kvcalloc(1, (alloc_pages) * PAGE_SIZE, gfp), \
lib/tests/fortify_kunit.c-311- kvfree(p)); \
lib/tests/fortify_kunit.c-312- checker((expected_pages) * PAGE_SIZE, \
lib/tests/fortify_kunit.c:313: kvcalloc((alloc_pages) * PAGE_SIZE, 1, gfp), \
lib/tests/fortify_kunit.c-314- kvfree(p)); \
--
mm/gup_test.c=101=static int __gup_test_ioctl(unsigned int cmd,
--
mm/gup_test.c-115- nr_pages = gup->size / PAGE_SIZE;
mm/gup_test.c:116: pages = kvcalloc(nr_pages, sizeof(void *), GFP_KERNEL);
mm/gup_test.c-117- if (!pages)
--
mm/gup_test.c=223=static inline int pin_longterm_test_start(unsigned long arg)
--
mm/gup_test.c-248-
mm/gup_test.c:249: pages = kvcalloc(nr_pages, sizeof(void *), GFP_KERNEL);
mm/gup_test.c-250- if (!pages)
--
mm/hmm.c=698=int hmm_dma_map_alloc(struct device *dev, struct hmm_dma_map *map,
]
|
| 42/2 |
2026/06/15 16:11 |
llm |
debugger |
0m
Model:
Tokens:
input: 71899
output: 21
thoughts: 2898
Thoughts: **Analysis of DRM Lease Integer Overflow Vulnerability and Proposed Fix**
Alright, let's break this down. First, `kvcalloc` *is* a common utility, but so is `kvmalloc_array`. My gut tells me using `kvcalloc` instead of `kzalloc_objs` in `fill_object_idr` is the right move to address that warning. Digging into it, `kzalloc_objs` is just a macro wrapping `__alloc_objs`, which in turn, simply calls `alloc`, that means `kzalloc` is the ultimate allocator used.
Okay, so `kzalloc_objs` expands to `kzalloc` with a size derived from `sizeof(struct drm_mode_object *) * (object_count)`. Aha! Now we're getting somewhere. `kzalloc` doesn't protect against integer overflow, and `object_count` is passed as an `int`. Size of the pointer is 8 bytes, so `8 * object_count` can overflow, especially on 32-bit architectures.
Yes, indeed, on a 32-bit system, a large `object_count` results in the multiplication overflowing, and the allocation request is smaller than expected. That leads to a buffer overflow during `fill_object_idr` when it writes outside the allocated memory region. The integer overflow occurs on 32-bit because `8 * 0x7fffffff` overflows the 32-bit size type. It's a textbook buffer overflow condition!
The `object_count` comes from userspace as a `__u32` value, so it can be manipulated by users. In `drm_mode_create_lease_ioctl`, the `object_count` value is directly used. However, `memdup_array_user` is then called. It appears to check for overflow with `check_mul_overflow(n, size, &nbytes)`. Good! That check will detect the potential overflow of `object_count * sizeof(__u32)` and return an error code, which should prevent the vulnerability, right?
Wait, even if the multiplication in `memdup_array_user` overflows, `check_mul_overflow` is safe, so it will return true. `memdup_array_user` will return `-EOVERFLOW` and we do not reach the vulnerable `fill_object_idr` code. Then, `memdup_array_user` allocates via `kmalloc`, and its maximum is 4MB. Because it won't allocate more than 4MB, it's safe. Therefore, there's no actual overflow vulnerability, but we should address the warning in the kernel log.
The primary issue stems from `kzalloc_objs` allocating 8MB which triggers `WARN_ON_ONCE_GFP`. Okay, so `memdup_array_user` has `__GFP_NOWARN`, which means if `object_count` is greater than a certain size, it'll fail without warning. But `fill_object_idr` calls `kzalloc_objs` with potentially very large sizes and *will* trigger a warning.
The solution is to use `kvmalloc_array` or `kvcalloc` in `fill_object_idr` as a replacement for `kzalloc_objs`. Since `kvcalloc` uses `kvmalloc_array` which calls `kvmalloc`, this approach uses the `vmalloc` fallback for large allocations to avoid the warning. The size will be large, but it can avoid the warning. We must also change `kfree` to `kvfree` for the freed memory.
Let's double-check that the `objects` is always freed at the end of `fill_object_idr`. Good, the pointer array is temporary, used to hold object pointers. We can safely change the allocation and deallocation to use `kvcalloc` and `kvfree` respectively.
Looking again at the crash report, the reproducer sets `object_count` to 1,000,000, which confirms our understanding. The allocation size is `1000000 * 8 = 8,000,000`, matching our analysis perfectly.
Now, let's explore if other allocations within `drm_mode_create_lease_ioctl` are affected.
Yes, `memdup_array_user`'s size depends on `object_count` too. If we pass a large enough number to `object_count`, `memdup_array_user` fails because it is using `kmalloc`. It's possible that a large number will fail. Is there an legitimate use case where a user would ask for more than one million objects? No, this is likely because of
|
| 43/2 |
2026/06/15 16:12 |
tool |
grepper |
0m
Args: map[Expression:vmemdup_array_user]
Results: map[Output:arch/x86/kvm/cpuid.c=589=int kvm_vcpu_ioctl_set_cpuid(struct kvm_vcpu *vcpu,
--
arch/x86/kvm/cpuid.c-600- if (cpuid->nent) {
arch/x86/kvm/cpuid.c:601: e = vmemdup_array_user(entries, cpuid->nent, sizeof(*e));
arch/x86/kvm/cpuid.c-602- if (IS_ERR(e))
--
arch/x86/kvm/cpuid.c=634=int kvm_vcpu_ioctl_set_cpuid2(struct kvm_vcpu *vcpu,
--
arch/x86/kvm/cpuid.c-644- if (cpuid->nent) {
arch/x86/kvm/cpuid.c:645: e2 = vmemdup_array_user(entries, cpuid->nent, sizeof(*e2));
arch/x86/kvm/cpuid.c-646- if (IS_ERR(e2))
--
drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.c=183=int amdgpu_bo_create_list_entry_array(struct drm_amdgpu_bo_list_in *in,
--
drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.c-196- if (likely(info_size == bo_info_size)) {
drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.c:197: info = vmemdup_array_user(uptr, bo_number, info_size);
drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.c-198- if (IS_ERR(info))
--
drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c=169=static int amdgpu_cs_pass1(struct amdgpu_cs_parser *p,
--
drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c-209-
drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c:210: p->chunks[i].kdata = vmemdup_array_user(u64_to_user_ptr(user_chunk.chunk_data),
drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c-211- size,
--
drivers/gpu/drm/drm_gem.c=833=int drm_gem_objects_lookup(struct drm_file *filp, void __user *bo_handles,
--
drivers/gpu/drm/drm_gem.c-848-
drivers/gpu/drm/drm_gem.c:849: handles = vmemdup_array_user(bo_handles, count, sizeof(u32));
drivers/gpu/drm/drm_gem.c-850- if (IS_ERR(handles)) {
--
drivers/tty/vt/consolemap.c=632=int con_set_unimap(struct vc_data *vc, ushort ct, struct unipair __user *list)
--
drivers/tty/vt/consolemap.c-640-
drivers/tty/vt/consolemap.c:641: struct unipair *unilist __free(kvfree) = vmemdup_array_user(list, ct, sizeof(*unilist));
drivers/tty/vt/consolemap.c-642- if (IS_ERR(unilist))
--
include/linux/string.h=32=void *memdup_array_user(const void __user *src, size_t n, size_t size)
--
include/linux/string.h-42-/**
include/linux/string.h:43: * vmemdup_array_user - duplicate array from user space
include/linux/string.h-44- * @src: source address in user space
--
include/linux/string.h=51=static inline __realloc_size(2, 3)
include/linux/string.h:52:void *vmemdup_array_user(const void __user *src, size_t n, size_t size)
include/linux/string.h-53-{
--
virt/kvm/kvm_main.c=5148=static long kvm_vm_ioctl(struct file *filp,
--
virt/kvm/kvm_main.c-5315- urouting = argp;
virt/kvm/kvm_main.c:5316: entries = vmemdup_array_user(urouting->entries,
virt/kvm/kvm_main.c-5317- routing.nr, sizeof(*entries));
]
|
| 44/2 |
2026/06/15 16:12 |
llm |
debugger |
0m
Model:
Tokens:
input: 77069
output: 35
thoughts: 436
Thoughts: **Refactoring drm_lease.c for Improved Memory Management**
Okay, so `vmemdup_array_user` *does* exist! That's excellent news. My immediate thought is to replace the existing `memdup_array_user` calls with `vmemdup_array_user` and the corresponding `kfree(object_ids)` calls with `kvfree(object_ids)`. That should make things more robust against fragmentation, right? Let me see... yes, in `drm_mode_create_lease_ioctl`, there it is!
```c
object_ids = memdup_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);
goto out_lessor;
}
/* fill and validate the object idr */
ret = fill_object_idr(dev, lessor_priv, &leases,
object_count, object_ids);
kfree(object_ids);
```
So I'll change that to `vmemdup_array_user` and `kvfree` as planned. Moving on to `fill_object_idr`:
```c
objects = kzalloc_objs(struct drm_mode_object *, object_count);
```
Alright, here, I can switch this over to `kvcalloc`:
```c
objects = kvcalloc(object_count, sizeof(struct drm_mode_object *), GFP_KERNEL);
```
And of course, change the corresponding `kfree(objects)` to `kvfree(objects)`.
Wait, just to be thorough, I should double check what that `objects` pointer is used for. Ah, in `validate_lease`:
```c
ret = validate_lease(dev, object_count, objects, universal_planes);
```
It takes a `struct drm_mode_object **objects` as an argument. The function just iterates over this array, which means `kvcalloc` is perfectly appropriate and safe to use here. Great!
Okay, one last check: I should quickly grep the rest of `drm_lease.c` to make sure there are no other instances of `kzalloc_objs` that need attention.
|
| 45/2 |
2026/06/15 16:12 |
tool |
grepper |
0m
Args: map[Expression:kzalloc_objs PathPrefix:drivers/gpu/drm/drm_lease.c]
Results: map[Output:drivers/gpu/drm/drm_lease.c=378=static int fill_object_idr(struct drm_device *dev,
--
drivers/gpu/drm/drm_lease.c-388-
drivers/gpu/drm/drm_lease.c:389: objects = kzalloc_objs(struct drm_mode_object *, object_count);
drivers/gpu/drm/drm_lease.c-390- if (!objects)
]
|
| 46/2 |
2026/06/15 16:12 |
llm |
debugger |
0m
Model:
Tokens:
input: 78194
output: 37
thoughts: 31
Thoughts: Okay, here's my interpretation of those thoughts, presented as a first-person summary, keeping in mind my expertise:
**Single Focus and Immediate Verification**
Right, only one instance of what I'm looking for. I need to be absolutely certain though, given the potential implications of this function, `memdup_array_user`, within `drm_lease.c`. Let's perform a quick, thorough scan of the code within that file to ensure there isn't another hidden instance, perhaps under a slightly different name or context, that I've missed. Confirmation is key here before proceeding further.
|
| 47/2 |
2026/06/15 16:12 |
tool |
grepper |
0m
Args: map[Expression:memdup_array_user PathPrefix:drivers/gpu/drm/drm_lease.c]
Results: map[Output:drivers/gpu/drm/drm_lease.c=475=int drm_mode_create_lease_ioctl(struct drm_device *dev,
--
drivers/gpu/drm/drm_lease.c-511- if (object_count != 0) {
drivers/gpu/drm/drm_lease.c:512: object_ids = memdup_array_user(u64_to_user_ptr(cl->object_ids),
drivers/gpu/drm/drm_lease.c-513- object_count, sizeof(__u32));
]
|
| 48/2 |
2026/06/15 16:12 |
llm |
debugger |
0m
Model:
Tokens:
input: 78541
output: 1277
thoughts: 2010
Thoughts: **Analysis of the drm_mode_create_lease_ioctl Crash**
Okay, so here's the breakdown of this crash situation. It seems the core problem lies within `drm_mode_create_lease_ioctl`. The issue is that it accepts a user-provided `object_count`, which directly influences memory allocation sizes. Specifically, it uses `drm_mode_create_lease_ioctl` and `fill_object_idr`.
Here's the sequence:
1. **Uncontrolled Allocation Size:** The ioctl takes a `cl->object_count` from userspace, which is then used to determine the size of two memory allocations.
2. **Initial memdup_array_user**: First, `memdup_array_user` is called to allocate `object_ids`. This function allocates memory using `kmalloc` with the `__GFP_NOWARN` flag. This flag is important because it means that even if `kmalloc` can't directly satisfy the request, it won't immediately trigger a warning. If `object_count` is large (say, 1,000,000), `memdup_array_user` requests 4MB. Because it's within `KMALLOC_MAX_SIZE`, it *succeeds*, but sets the stage for a later failure.
3. **The Fatal kzalloc_objs Call:** The function then calls `fill_object_idr`, which, in turn, allocates an array of pointers, `objects`, using `kzalloc_objs`. `kzalloc_objs` expands into `kzalloc`, which calls `kmalloc` without `__GFP_NOWARN`. This means that if the allocation size is problematic, the kernel *will* issue a warning.
4. **Exceeding KMALLOC_MAX_SIZE**: In this case, `object_count` is still 1,000,000. Each element of the array `objects` is a pointer (8 bytes on 64-bit systems), leading to a total allocation size of 8MB. This exceeds the typical `KMALLOC_MAX_SIZE` (usually 4MB), which is linked to `MAX_PAGE_ORDER`.
5. **Page Allocator Panic**: Because the `kmalloc` call now needs to allocate pages larger than `MAX_PAGE_ORDER`, it falls back to the page allocator. But `kzalloc` doesn't suppress the warning. The page allocator then triggers a `WARN_ON_ONCE_GFP(order > MAX_PAGE_ORDER, gfp)` warning in `__alloc_frozen_pages_noprof` (or `alloc_pages`). Syzkaller detects this warning as a crash.
The key is that the initial `kmalloc` in `memdup_array_user` is *masked* by `__GFP_NOWARN`, while the second `kmalloc` triggered by `kzalloc` in `fill_object_idr` isn't, so that's where the problem manifests.
**The Fix:**
The solution is straightforward and involves switching to memory allocators that gracefully handle large requests:
1. **Use vmemdup_array_user for object_ids**: In `drm_mode_create_lease_ioctl`, replace `memdup_array_user` with `vmemdup_array_user`. This new function will use `vmalloc` if necessary, which is designed for allocating large, contiguous regions of virtual memory and avoiding the `KMALLOC_MAX_SIZE` limitation. This also means updating `kfree(object_ids)` to `kvfree(object_ids)`.
2. **Use kvcalloc for objects**: In `fill_object_idr`, replace `kzalloc_objs` (which expands to `kzalloc`) with `kvcalloc`. The `kvcalloc` function is similar to `kzalloc`, but uses `kvmalloc`, which also gracefully falls back to `vmalloc` when necessary, *and* doesn't trigger warnings for large allocations. This also means updating `kfree(objects)` to `kvfree(objects)`.
**Safety Checks:**
The `vmemdup_array_user` function includes an overflow check, returning `-EOVERFLOW` if the multiplication of size and count results in an overflow. This helps to prevent problems where extremely large values are passed as inputs. In addition, if `vmalloc` fails, `vmemdup_array_user` will return -ENOMEM, which is a recoverable error.
This approach ensures that the ioctl function handles large allocations safely and without triggering kernel warnings, preventing the identified crash.
|
| 49/1 |
2026/06/15 16:13 |
action |
kernel-scratch-checkouter |
0m
Results: map[KernelScratchSrc:/app/workdir/cache/tmp/tmp2222411375]
|
| 50/1 |
2026/06/15 16:13 |
loop |
|
23m
|
| 51/2 |
2026/06/15 16:13 |
iteration |
0 |
23m
|
| 52/3 |
2026/06/15 16:13 |
agent |
patch-generator |
1m
Model:
Instruction:
You are an experienced Linux kernel developer tasked with creating a fix for a kernel bug.
You will be given a crash report, and an initial explanation of the root cause done by another
kernel expert.
Use the codeeditor tool to do code edits.
Note: you will not see your changes when looking at the code using codesearch tools.
Use the patch-diff tool to review the modifications you applied.
Your final reply should contain explanation of what you did in the patch and why
(details not present in the initial explanation of the bug).
Your fix must not just prevent the given crash, but also be the best fix for the underlying
root cause from the software engineering point of view. There can be several ways to fix the
same bug. Consider alternatives, and pick the best one. For example, additional checks may be
added at different locations/functions, it's usually better to place them earlier in the
execution to avoid multiple checks at various locations later.
Frequently the same coding mistake is done in several locations in the source code.
Check if your fix should be extended/applied to similar cases around to fix other similar bugs.
But don't go too wide, don't try to fix problems kernel-wide, fix similar issues
in the same file only.
If you are changing post-conditions of a function, consider all callers of the functions,
and if they need to be updated to handle new post-conditions. For example, if you make
a function that previously never returned a NULL, return NULL, consider if callers
need to be updated to handle NULL return value.
If you will end up removing the WARN_ON macro because the condition can legitimately happen,
add a pr_err/dev_err/... (whatever is the macro for printing runtime errors used in the file)
call that logs that the unlikely condition has happened. The pr_err/dev_err/... message
must not include "WARNING" nor "BUG" strings.
Prefer calling several tools at the same time to save round-trips.
Prompt:
The crash that corresponds to the bug is:
------------[ cut here ]------------
WARNING: mm/page_alloc.c:5197 at __alloc_frozen_pages_noprof+0x2ce/0x380 mm/page_alloc.c:5197, CPU#0: syz.0.17/6137
Modules linked in:
CPU: 0 UID: 0 PID: 6137 Comm: syz.0.17 Not tainted syzkaller #1 PREEMPT(full)
Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.16.3-debian-1.16.3-2 04/01/2014
RIP: 0010:__alloc_frozen_pages_noprof+0x2ce/0x380 mm/page_alloc.c:5197
Code: 74 10 4c 89 e7 89 54 24 0c e8 6e a2 0d 00 8b 54 24 0c 49 83 3c 24 00 0f 85 ab fe ff ff e9 ac fe ff ff c6 05 92 0e b2 0d 01 90 <0f> 0b 90 e9 17 ff ff ff a9 00 00 08 00 48 8b 4c 24 10 4c 8d 44 24
RSP: 0018:ffffc90003aa7800 EFLAGS: 00010246
RAX: ffffc90003aa7800 RBX: 000000000000000b RCX: 0000000000000000
RDX: 0000000000000000 RSI: 0000000000000000 RDI: ffffc90003aa7868
RBP: ffffc90003aa78e8 R08: ffffc90003aa7867 R09: 0000000000000000
R10: ffffc90003aa7840 R11: fffff52000754f0d R12: 0000000000000000
R13: 1ffff92000754f04 R14: 0000000000040dc0 R15: dffffc0000000000
FS: 00007fe037ac16c0(0000) GS:ffff8881a59ad000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 00002000003d0000 CR3: 0000000104ab0000 CR4: 00000000000006f0
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
drm_ioctl_kernel+0x2df/0x3b0 drivers/gpu/drm/drm_ioctl.c:805
drm_ioctl+0x6fa/0xbc0 drivers/gpu/drm/drm_ioctl.c:902
vfs_ioctl fs/ioctl.c:51 [inline]
__do_sys_ioctl fs/ioctl.c:597 [inline]
__se_sys_ioctl+0xfc/0x170 fs/ioctl.c:583
do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
do_syscall_64+0x15f/0x560 arch/x86/entry/syscall_64.c:94
entry_SYSCALL_64_after_hwframe+0x77/0x7f
RIP: 0033:0x7fe036b9ce59
Code: ff c3 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 44 00 00 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 c7 c1 e8 ff ff ff f7 d8 64 89 01 48
RSP: 002b:00007fe037ac1028 EFLAGS: 00000246 ORIG_RAX: 0000000000000010
RAX: ffffffffffffffda RBX: 00007fe036e15fa0 RCX: 00007fe036b9ce59
RDX: 00002000000003c0 RSI: 00000000c01864c6 RDI: 0000000000000003
RBP: 00007fe036c32d6f R08: 0000000000000000 R09: 0000000000000000
R10: 0000000000000000 R11: 0000000000000246 R12: 0000000000000000
R13: 00007fe036e16038 R14: 00007fe036e15fa0 R15: 00007fffcab0e958
</TASK>
The explanation of the root cause of the bug is:
The root cause of this kernel crash is an unbounded memory allocation based on a user-controlled value, which attempts to allocate a contiguous memory chunk larger than the maximum allowed by the slab allocator (`KMALLOC_MAX_SIZE`), triggering a warning in the page allocator.
### Detailed Root Cause Analysis
1. **User-controlled `object_count`**:
In `drivers/gpu/drm/drm_lease.c`, the `drm_mode_create_lease_ioctl()` function retrieves `object_count` directly from the user-provided `struct drm_mode_create_lease` argument:
```c
object_count = cl->object_count;
```
The syzkaller reproducer sets this value to `0xf4240` (1,000,000).
2. **First Allocation (`memdup_array_user`)**:
The ioctl first allocates an array to hold the object IDs:
```c
object_ids = memdup_array_user(u64_to_user_ptr(cl->object_ids),
object_count, sizeof(__u32));
```
For `1,000,000` objects, this requires `4,000,000` bytes (~3.8 MB). This size is typically just under the `KMALLOC_MAX_SIZE` limit (usually 4 MB on many architectures). Furthermore, `memdup_array_user()` internally uses `memdup_user()`, which allocates memory with the `__GFP_NOWARN` flag. Thus, even if it were to fail, it would gracefully return `-ENOMEM` without triggering a kernel warning.
3. **Second Allocation (`kzalloc_objs`)**:
After successfully allocating `object_ids`, the ioctl calls `fill_object_idr()`:
```c
ret = fill_object_idr(dev, lessor_priv, &leases, object_count, object_ids);
```
Inside `fill_object_idr()`, the kernel attempts to allocate an array of pointers for the objects:
```c
objects = kzalloc_objs(struct drm_mode_object *, object_count);
```
The size of `struct drm_mode_object *` is 8 bytes (on 64-bit systems). For `1,000,000` objects, this requires `8,000,000` bytes (~7.6 MB). This size strictly exceeds the `KMALLOC_MAX_SIZE` limit.
Unlike `memdup_user()`, the `kzalloc_objs()` macro expands to a standard `kzalloc()` call using `GFP_KERNEL | __GFP_ZERO` **without** the `__GFP_NOWARN` flag.
4. **The Crash (Warning)**:
Because the requested size is larger than `KMALLOC_MAX_SIZE`, the SLUB allocator passes the request directly to the page allocator (`___kmalloc_large_node`). The page allocator calculates the required page order (order 11 for 8 MB). Since order 11 is strictly greater than `MAX_PAGE_ORDER` (typically 10), the page allocator hits the following safety check in `__alloc_frozen_pages_noprof()`:
```c
if (WARN_ON_ONCE_GFP(order > MAX_PAGE_ORDER, gfp))
return NULL;
```
Because `__GFP_NOWARN` was not provided, this triggers the `WARN_ON_ONCE_GFP` warning, which syzkaller correctly identifies as a crash.
### Proposed Fix
To fix this issue, both allocations should be updated to use the `kvmalloc` family of functions. These functions automatically fall back to `vmalloc()` for large allocations (avoiding memory fragmentation issues) and internally apply `__GFP_NOWARN` when attempting the initial `kmalloc()`, preventing the page allocator warning.
1. In `drm_mode_create_lease_ioctl()`, replace `memdup_array_user()` with `vmemdup_array_user()`, and change the corresponding `kfree()` to `kvfree()`:
```c
// drivers/gpu/drm/drm_lease.c : ~512
- 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));
// drivers/gpu/drm/drm_lease.c : ~523
- kfree(object_ids);
+ kvfree(object_ids);
```
2. In `fill_object_idr()`, replace `kzalloc_objs()` with `kvcalloc()`, and change the corresponding `kfree()` to `kvfree()`:
```c
// drivers/gpu/drm/drm_lease.c : ~389
- objects = kzalloc_objs(struct drm_mode_object *, object_count);
+ objects = kvcalloc(object_count, sizeof(struct drm_mode_object *), GFP_KERNEL);
// drivers/gpu/drm/drm_lease.c : ~465
- kfree(objects);
+ kvfree(objects);
```
This ensures that userspace cannot trigger a kernel warning by passing an arbitrarily large `object_count`, and the kernel will gracefully return `-ENOMEM` if the system truly cannot satisfy the `vmalloc` request.
Reply: I have implemented the proposed fix.
### Explanation of the Fix
The crash is caused by an unbounded memory allocation in `drm_mode_create_lease_ioctl()` where the `object_count` is directly controlled by the user. A malicious or buggy userspace program can pass a very large `object_count` (e.g., 1,000,000), causing the kernel to attempt allocating a contiguous memory chunk that exceeds the maximum allowed size by the slab allocator (`KMALLOC_MAX_SIZE`).
There are two allocations involved:
1. **`object_ids` array**: Allocated using `memdup_array_user()`. While this doesn't trigger a warning because `memdup_user()` internally uses `__GFP_NOWARN`, it still attempts a large contiguous allocation (up to ~4MB) which can fail due to memory fragmentation.
2. **`objects` array**: Allocated using `kzalloc_objs()` in `fill_object_idr()`. This macro expands to a standard `kzalloc()` call without the `__GFP_NOWARN` flag. For 1,000,000 objects, this requires ~8MB of memory. Since this 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`.
To fix this, I replaced both allocations with their `kvmalloc` family equivalents:
- In `drm_mode_create_lease_ioctl()`, `memdup_array_user()` was replaced with `vmemdup_array_user()`, and the corresponding `kfree()` was changed to `kvfree()`.
- In `fill_object_idr()`, `kzalloc_objs()` was replaced with `kvcalloc()`, and the corresponding `kfree()` was changed to `kvfree()`.
The `kvmalloc` family of functions attempts a `kmalloc()` first (with `__GFP_NOWARN` applied internally to prevent warnings if it fails), and gracefully falls back to `vmalloc()` for large allocations. This not only prevents the kernel warning but also makes the allocations more robust against memory fragmentation, as `vmalloc()` can satisfy large requests using non-contiguous physical pages. If the system truly cannot satisfy the request, it will gracefully return `-ENOMEM` to userspace.
|
| 53/4 |
2026/06/15 16:13 |
llm |
patch-generator |
0m
Model:
Tokens:
input: 7361
output: 44
thoughts: 215
Thoughts: **Analyzing a Bug Report: Large Allocation in DRM Lease Creation**
Okay, so I've got this bug report about a warning popping up in `__alloc_frozen_pages_noprof`. It seems the warning is triggered by an excessively large allocation within `fill_object_idr`, which itself is being called from `drm_mode_create_lease_ioctl`. Right away, the alarm bells are ringing; anytime I see a warning about large allocations, especially coming from a user-space interaction like this, I get concerned.
Digging deeper, the root cause appears to be that the `object_count` variable, which determines the allocation size, is sourced from user space. The report mentions it can reach a substantial value, up to `0xf4240`, or 1,000,000. That's immediately problematic. One million objects, each taking 8 bytes, leads to an 8MB allocation. And that's where the problem arises: this exceeds `KMALLOC_MAX_SIZE`, which in turn triggers the warning because `kzalloc_objs` is utilizing `kzalloc` directly, without the safety net of `__GFP_NOWARN`. This means we are falling into a known trap and should use the more flexible `kvmalloc` family of functions.
The proposed solution seems sensible. The fix involves swapping out `memdup_array_user` for `vmemdup_array_user` and `kzalloc_objs` for `kvcalloc`. These are all logical replacements, and would likely resolve the size limitations. I'll need to confirm that this change is appropriate and doesn't introduce any new regressions.
First, I need to check the exact code in `drivers/gpu/drm/drm_lease.c` to understand the flow and context of these allocations. It looks like it is going to be a straightforward fix.
|
| 54/4 |
2026/06/15 16:14 |
tool |
codesearch-definition-source |
0m
Args: map[ContextFile:drivers/gpu/drm/drm_lease.c Name:drm_mode_create_lease_ioctl]
Results: map[SourceCode: 469: /*
470: * The master associated with the specified file will have a lease
471: * created containing the objects specified in the ioctl structure.
472: * A file descriptor will be allocated for that and returned to the
473: * application.
474: */
475: int drm_mode_create_lease_ioctl(struct drm_device *dev,
476: void *data, struct drm_file *lessor_priv)
477: {
478: struct drm_mode_create_lease *cl = data;
479: size_t object_count;
480: int ret = 0;
481: struct idr leases;
482: struct drm_master *lessor;
483: struct drm_master *lessee = NULL;
484: struct file *lessee_file = NULL;
485: struct file *lessor_file = lessor_priv->filp;
486: struct drm_file *lessee_priv;
487: int fd = -1;
488: uint32_t *object_ids;
489:
490: /* Can't lease without MODESET */
491: if (!drm_core_check_feature(dev, DRIVER_MODESET))
492: return -EOPNOTSUPP;
493:
494: if (cl->flags && (cl->flags & ~(O_CLOEXEC | O_NONBLOCK))) {
495: drm_dbg_lease(dev, "invalid flags\n");
496: return -EINVAL;
497: }
498:
499: lessor = drm_file_get_master(lessor_priv);
500: /* Do not allow sub-leases */
501: if (lessor->lessor) {
502: drm_dbg_lease(dev, "recursive leasing not allowed\n");
503: ret = -EINVAL;
504: goto out_lessor;
505: }
506:
507: object_count = cl->object_count;
508:
509: /* Handle leased objects, if any */
510: idr_init(&leases);
511: if (object_count != 0) {
512: object_ids = memdup_array_user(u64_to_user_ptr(cl->object_ids),
513: object_count, sizeof(__u32));
514: if (IS_ERR(object_ids)) {
515: ret = PTR_ERR(object_ids);
516: idr_destroy(&leases);
517: goto out_lessor;
518: }
519:
520: /* fill and validate the object idr */
521: ret = fill_object_idr(dev, lessor_priv, &leases,
522: object_count, object_ids);
523: kfree(object_ids);
524: if (ret) {
525: drm_dbg_lease(dev, "lease object lookup failed: %i\n", ret);
526: idr_destroy(&leases);
527: goto out_lessor;
528: }
529: }
530:
531: /* Allocate a file descriptor for the lease */
532: fd = get_unused_fd_flags(cl->flags & (O_CLOEXEC | O_NONBLOCK));
533: if (fd < 0) {
534: idr_destroy(&leases);
535: ret = fd;
536: goto out_lessor;
537: }
538:
539: drm_dbg_lease(dev, "Creating lease\n");
540: /* lessee will take the ownership of leases */
541: lessee = drm_lease_create(lessor, &leases);
542:
543: if (IS_ERR(lessee)) {
544: ret = PTR_ERR(lessee);
545: idr_destroy(&leases);
546: goto out_leases;
547: }
548:
549: /* Clone the lessor file to create a new file for us */
550: drm_dbg_lease(dev, "Allocating lease file\n");
551: lessee_file = file_clone_open(lessor_file);
552: if (IS_ERR(lessee_file)) {
553: ret = PTR_ERR(lessee_file);
554: goto out_lessee;
555: }
556:
557: lessee_priv = lessee_file->private_data;
558: /* Change the file to a master one */
559: drm_master_put(&lessee_priv->master);
560: lessee_priv->master = lessee;
561: lessee_priv->is_master = 1;
562: lessee_priv->authenticated = 1;
563:
564: /* Pass fd back to userspace */
565: drm_dbg_lease(dev, "Returning fd %d id %d\n", fd, lessee->lessee_id);
566: cl->fd = fd;
567: cl->lessee_id = lessee->lessee_id;
568:
569: /* Hook up the fd */
570: fd_install(fd, lessee_file);
571:
572: drm_master_put(&lessor);
573: drm_dbg_lease(dev, "drm_mode_create_lease_ioctl succeeded\n");
574: return 0;
575:
576: out_lessee:
577: drm_master_put(&lessee);
578:
579: out_leases:
580: put_unused_fd(fd);
581:
582: out_lessor:
583: drm_master_put(&lessor);
584: drm_dbg_lease(dev, "drm_mode_create_lease_ioctl failed: %d\n", ret);
585: return ret;
586: }
SourceFile:drivers/gpu/drm/drm_lease.c]
|
| 55/4 |
2026/06/15 16:14 |
llm |
patch-generator |
0m
Model:
Tokens:
input: 9839
output: 41
thoughts: 12
Thoughts: Okay, here's my attempt at summarizing that thought process, keeping in mind I'm speaking to a fellow expert:
**Investigating `fill_object_idr`**
Alright, time to dive in. *Let's check `fill_object_idr`*. Given the context, my initial thought is, what specifically needs to be assessed within this function? I'm already mentally running through the typical areas I'd look at for a routine with that name: data validation, edge case handling, potential for race conditions or concurrent access issues if it's operating on shared resources, performance bottlenecks related to memory allocation or object creation, and of course, the logical correctness of the filling algorithm itself. Is there a specific use-case I'm interested in, or am I running a general review? Either way, let's start with a systematic examination of the code and its dependencies.
|
| 56/4 |
2026/06/15 16:14 |
tool |
codesearch-definition-source |
0m
Args: map[ContextFile:drivers/gpu/drm/drm_lease.c Name:fill_object_idr]
Results: map[SourceCode: 378: static int fill_object_idr(struct drm_device *dev,
379: struct drm_file *lessor_priv,
380: struct idr *leases,
381: int object_count,
382: u32 *object_ids)
383: {
384: struct drm_mode_object **objects;
385: u32 o;
386: int ret;
387: bool universal_planes = READ_ONCE(lessor_priv->universal_planes);
388:
389: objects = kzalloc_objs(struct drm_mode_object *, object_count);
390: if (!objects)
391: return -ENOMEM;
392:
393: /* step one - get references to all the mode objects
394: and check for validity. */
395: for (o = 0; o < object_count; o++) {
396: objects[o] = drm_mode_object_find(dev, lessor_priv,
397: object_ids[o],
398: DRM_MODE_OBJECT_ANY);
399: if (!objects[o]) {
400: ret = -ENOENT;
401: goto out_free_objects;
402: }
403:
404: if (!drm_mode_object_lease_required(objects[o]->type)) {
405: DRM_DEBUG_KMS("invalid object for lease\n");
406: ret = -EINVAL;
407: goto out_free_objects;
408: }
409: }
410:
411: ret = validate_lease(dev, object_count, objects, universal_planes);
412: if (ret) {
413: drm_dbg_lease(dev, "lease validation failed\n");
414: goto out_free_objects;
415: }
416:
417: /* add their IDs to the lease request - taking into account
418: universal planes */
419: for (o = 0; o < object_count; o++) {
420: struct drm_mode_object *obj = objects[o];
421: u32 object_id = objects[o]->id;
422:
423: drm_dbg_lease(dev, "Adding object %d to lease\n", object_id);
424:
425: /*
426: * We're using an IDR to hold the set of leased
427: * objects, but we don't need to point at the object's
428: * data structure from the lease as the main object_idr
429: * will be used to actually find that. Instead, all we
430: * really want is a 'leased/not-leased' result, for
431: * which any non-NULL pointer will work fine.
432: */
433: ret = idr_alloc(leases, &drm_lease_idr_object , object_id, object_id + 1, GFP_KERNEL);
434: if (ret < 0) {
435: drm_dbg_lease(dev, "Object %d cannot be inserted into leases (%d)\n",
436: object_id, ret);
437: goto out_free_objects;
438: }
439: if (obj->type == DRM_MODE_OBJECT_CRTC && !universal_planes) {
440: struct drm_crtc *crtc = obj_to_crtc(obj);
441:
442: ret = idr_alloc(leases, &drm_lease_idr_object, crtc->primary->base.id, crtc->primary->base.id + 1, GFP_KERNEL);
443: if (ret < 0) {
444: drm_dbg_lease(dev, "Object primary plane %d cannot be inserted into leases (%d)\n",
445: object_id, ret);
446: goto out_free_objects;
447: }
448: if (crtc->cursor) {
449: ret = idr_alloc(leases, &drm_lease_idr_object, crtc->cursor->base.id, crtc->cursor->base.id + 1, GFP_KERNEL);
450: if (ret < 0) {
451: drm_dbg_lease(dev, "Object cursor plane %d cannot be inserted into leases (%d)\n",
452: object_id, ret);
453: goto out_free_objects;
454: }
455: }
456: }
457: }
458:
459: ret = 0;
460: out_free_objects:
461: for (o = 0; o < object_count; o++) {
462: if (objects[o])
463: drm_mode_object_put(objects[o]);
464: }
465: kfree(objects);
466: return ret;
467: }
SourceFile:drivers/gpu/drm/drm_lease.c]
|
| 57/4 |
2026/06/15 16:14 |
llm |
patch-generator |
0m
Model:
Tokens:
input: 11574
output: 39
thoughts: 96
Thoughts: **Refactoring for Enhanced Memory Management**
Okay, let's get down to some code optimization. My plan is to swap out some of the memory allocation and deallocation functions in the kernel. Specifically, I'm going to leverage the `codeeditor` tool to make a few targeted changes within the `drm_mode_create_lease_ioctl` function. I'll replace instances of `memdup_array_user` with `vmemdup_array_user`, and, crucially, substitute `kfree` with `kvfree` there.
Then I'm going to move on to `fill_object_idr`. I'll update the function to use `kvcalloc` instead of `kzalloc_objs`, and, again, switch `kfree` to `kvfree`.
Before I commit to these substitutions, I want to take a quick look at the `kzalloc_objs` definition just to refresh my memory and make sure this is the correct move, ensuring I understand its exact behavior to confidently replace it.
|
| 58/4 |
2026/06/15 16:14 |
tool |
codesearch-definition-source |
0m
Error:
Args: map[ContextFile:drivers/gpu/drm/drm_lease.c Name:kzalloc_objs]
Results: map[SourceCode: SourceFile:]
|
| 59/4 |
2026/06/15 16:14 |
llm |
patch-generator |
0m
Model:
Tokens:
input: 11949
output: 18
thoughts: 20
Thoughts: Here's my attempt at summarizing the thought process, tailored for an expert audience:
**Investigating a Possible Macro**
Okay, so I've encountered `kzalloc_objs` in the code, and my initial hunch is that it's likely a macro. Given the naming convention and context, that's the most probable scenario. To confirm and understand its expansion, I'm going to quickly grep through the codebase. I'll need to locate its definition to see what it's doing under the hood, any potential side effects, and what context its used in. Time to fire up the grep command and see what we can dig up. Hopefully, it's not buried in some header file three directories deep.
|
| 60/4 |
2026/06/15 16:14 |
tool |
grepper |
0m
Args: map[Expression:kzalloc_objs]
Results: map[Output:
Full output is too long, showing 500 out of 13925 lines.
Use more precise expression if possible.
Documentation/process/deprecated.rst=393=become, respectively::
--
Documentation/process/deprecated.rst-397- ptr = kmalloc_objs(*ptr, count, gfp);
Documentation/process/deprecated.rst:398: ptr = kzalloc_objs(*ptr, count, gfp);
Documentation/process/deprecated.rst-399- ptr = kmalloc_flex(*ptr, flex_member, count, gfp);
--
arch/alpha/kernel/module.c=64=module_frob_arch_sections(Elf64_Ehdr *hdr, Elf64_Shdr *sechdrs,
--
arch/alpha/kernel/module.c-95- nsyms = symtab->sh_size / sizeof(Elf64_Sym);
arch/alpha/kernel/module.c:96: chains = kzalloc_objs(struct got_entry, nsyms);
arch/alpha/kernel/module.c-97- if (!chains) {
--
arch/arm/kernel/vdso.c=169=static int __init vdso_init(void)
--
arch/arm/kernel/vdso.c-181- /* Allocate the VDSO text pagelist */
arch/arm/kernel/vdso.c:182: vdso_text_pagelist = kzalloc_objs(struct page *, text_pages);
arch/arm/kernel/vdso.c-183- if (vdso_text_pagelist == NULL)
--
arch/arm/mach-footbridge/dc21285.c=261=int __init dc21285_setup(int nr, struct pci_sys_data *sys)
--
arch/arm/mach-footbridge/dc21285.c-264-
arch/arm/mach-footbridge/dc21285.c:265: res = kzalloc_objs(struct resource, 2);
arch/arm/mach-footbridge/dc21285.c-266- if (!res) {
--
arch/arm/mach-omap1/mcbsp.c=292=static void omap_mcbsp_register_board_cfg(struct resource *res, int res_count,
--
arch/arm/mach-omap1/mcbsp.c-296-
arch/arm/mach-omap1/mcbsp.c:297: omap_mcbsp_devices = kzalloc_objs(struct platform_device *, size);
arch/arm/mach-omap1/mcbsp.c-298- if (!omap_mcbsp_devices) {
--
arch/arm/mach-omap2/omap_device.c=131=static int omap_device_build_from_dt(struct platform_device *pdev)
--
arch/arm/mach-omap2/omap_device.c-158-
arch/arm/mach-omap2/omap_device.c:159: hwmods = kzalloc_objs(struct omap_hwmod *, oh_cnt);
arch/arm/mach-omap2/omap_device.c-160- if (!hwmods) {
--
arch/arm/mach-omap2/pm33xx-core.c=379=static int __init amx3_idle_init(struct device_node *cpu_node, int cpu)
--
arch/arm/mach-omap2/pm33xx-core.c-412-
arch/arm/mach-omap2/pm33xx-core.c:413: idle_states = kzalloc_objs(*idle_states, state_count);
arch/arm/mach-omap2/pm33xx-core.c-414- if (!idle_states)
--
arch/arm/mach-omap2/sr_device.c=30=static void __init sr_set_nvalues(struct omap_volt_data *volt_data,
--
arch/arm/mach-omap2/sr_device.c-41-
arch/arm/mach-omap2/sr_device.c:42: nvalue_table = kzalloc_objs(*nvalue_table, count);
arch/arm/mach-omap2/sr_device.c-43- if (!nvalue_table)
--
arch/arm/mach-versatile/spc.c=393=static int ve_spc_populate_opps(uint32_t cluster)
--
arch/arm/mach-versatile/spc.c-397-
arch/arm/mach-versatile/spc.c:398: opps = kzalloc_objs(*opps, MAX_OPPS);
arch/arm/mach-versatile/spc.c-399- if (!opps)
--
arch/arm/xen/enlighten.c=316=int __init arch_xen_unpopulated_init(struct resource **res)
--
arch/arm/xen/enlighten.c-343-
arch/arm/xen/enlighten.c:344: regs = kzalloc_objs(*regs, nr_reg);
arch/arm/xen/enlighten.c-345- if (!regs) {
--
arch/arm64/kernel/vdso.c=68=static int __init __vdso_init(enum vdso_abi abi)
--
arch/arm64/kernel/vdso.c-83-
arch/arm64/kernel/vdso.c:84: vdso_pagelist = kzalloc_objs(struct page *, vdso_info[abi].vdso_pages);
arch/arm64/kernel/vdso.c-85- if (vdso_pagelist == NULL)
--
arch/arm64/kvm/vgic/vgic-init.c=207=static int kvm_vgic_dist_init(struct kvm *kvm, unsigned int nr_spis)
--
arch/arm64/kvm/vgic/vgic-init.c-213- dist->active_spis = (atomic_t)ATOMIC_INIT(0);
arch/arm64/kvm/vgic/vgic-init.c:214: dist->spis = kzalloc_objs(struct vgic_irq, nr_spis, GFP_KERNEL_ACCOUNT);
arch/arm64/kvm/vgic/vgic-init.c-215- if (!dist->spis)
--
arch/arm64/kvm/vgic/vgic-init.c=329=static int vgic_allocate_private_irqs_locked(struct kvm_vcpu *vcpu, u32 type)
--
arch/arm64/kvm/vgic/vgic-init.c-344-
arch/arm64/kvm/vgic/vgic-init.c:345: vgic_cpu->private_irqs = kzalloc_objs(struct vgic_irq,
arch/arm64/kvm/vgic/vgic-init.c-346- num_private_irqs,
--
arch/arm64/kvm/vgic/vgic-irqfd.c=136=int kvm_vgic_setup_default_irq_routing(struct kvm *kvm)
--
arch/arm64/kvm/vgic/vgic-irqfd.c-142-
arch/arm64/kvm/vgic/vgic-irqfd.c:143: entries = kzalloc_objs(*entries, nr, GFP_KERNEL_ACCOUNT);
arch/arm64/kvm/vgic/vgic-irqfd.c-144- if (!entries)
--
arch/arm64/kvm/vgic/vgic-v4.c=242=int vgic_v4_init(struct kvm *kvm)
--
arch/arm64/kvm/vgic/vgic-v4.c-258-
arch/arm64/kvm/vgic/vgic-v4.c:259: dist->its_vm.vpes = kzalloc_objs(*dist->its_vm.vpes, nr_vcpus,
arch/arm64/kvm/vgic/vgic-v4.c-260- GFP_KERNEL_ACCOUNT);
--
arch/csky/kernel/vdso.c=17=static int __init vdso_init(void)
--
arch/csky/kernel/vdso.c-22- vdso_pagelist =
arch/csky/kernel/vdso.c:23: kzalloc_objs(struct page *, vdso_pages);
arch/csky/kernel/vdso.c-24- if (unlikely(vdso_pagelist == NULL)) {
--
arch/loongarch/kernel/vdso.c=45=static int __init init_vdso(void)
--
arch/loongarch/kernel/vdso.c-55- vdso_info.code_mapping.pages =
arch/loongarch/kernel/vdso.c:56: kzalloc_objs(struct page *, vdso_info.size / PAGE_SIZE);
arch/loongarch/kernel/vdso.c-57-
--
arch/loongarch/kvm/intc/pch_pic.c=410=static int kvm_setup_default_irq_routing(struct kvm *kvm)
--
arch/loongarch/kvm/intc/pch_pic.c-415-
arch/loongarch/kvm/intc/pch_pic.c:416: entries = kzalloc_objs(*entries, nr);
arch/loongarch/kvm/intc/pch_pic.c-417- if (!entries)
--
arch/mips/alchemy/common/clock.c=754=static int __init alchemy_clk_init_fgens(int ctype)
--
arch/mips/alchemy/common/clock.c-777-
arch/mips/alchemy/common/clock.c:778: a = kzalloc_objs(*a, 6);
arch/mips/alchemy/common/clock.c-779- if (!a)
--
arch/mips/alchemy/common/clock.c=960=static int __init alchemy_clk_setup_imux(int ctype)
--
arch/mips/alchemy/common/clock.c-998-
arch/mips/alchemy/common/clock.c:999: a = kzalloc_objs(*a, 6);
arch/mips/alchemy/common/clock.c-1000- if (!a)
--
arch/mips/alchemy/common/dbdma.c=1056=static int __init dbdma_setup(unsigned int irq, dbdev_tab_t *idtable)
--
arch/mips/alchemy/common/dbdma.c-1059-
arch/mips/alchemy/common/dbdma.c:1060: dbdev_tab = kzalloc_objs(dbdev_tab_t, DBDEV_TAB_SIZE);
arch/mips/alchemy/common/dbdma.c-1061- if (!dbdev_tab)
--
arch/mips/alchemy/common/platform.c=203=static int __init _new_usbres(struct resource **r, struct platform_device **d)
arch/mips/alchemy/common/platform.c-204-{
arch/mips/alchemy/common/platform.c:205: *r = kzalloc_objs(struct resource, 2);
arch/mips/alchemy/common/platform.c-206- if (!*r)
--
arch/mips/alchemy/devboards/platform.c=68=int __init db1x_register_pcmcia_socket(phys_addr_t pcmcia_attr_start,
--
arch/mips/alchemy/devboards/platform.c-89-
arch/mips/alchemy/devboards/platform.c:90: sr = kzalloc_objs(struct resource, cnt);
arch/mips/alchemy/devboards/platform.c-91- if (!sr)
--
arch/mips/alchemy/devboards/platform.c=152=int __init db1x_register_norflash(unsigned long size, int width,
--
arch/mips/alchemy/devboards/platform.c-164- ret = -ENOMEM;
arch/mips/alchemy/devboards/platform.c:165: parts = kzalloc_objs(struct mtd_partition, 5);
arch/mips/alchemy/devboards/platform.c-166- if (!parts)
--
arch/mips/kernel/smp-cps.c=295=static void __init cps_prepare_cpus(unsigned int max_cpus)
--
arch/mips/kernel/smp-cps.c-343- nclusters = mips_cps_numclusters();
arch/mips/kernel/smp-cps.c:344: mips_cps_cluster_bootcfg = kzalloc_objs(*mips_cps_cluster_bootcfg,
arch/mips/kernel/smp-cps.c-345- nclusters);
--
arch/mips/kernel/smp-cps.c-354- ncores = mips_cps_numcores(cl);
arch/mips/kernel/smp-cps.c:355: core_bootcfg = kzalloc_objs(*core_bootcfg, ncores);
arch/mips/kernel/smp-cps.c-356- if (!core_bootcfg)
--
arch/mips/kernel/smp-cps.c-369- core_vpes = core_vpe_count(cl, c);
arch/mips/kernel/smp-cps.c:370: core_bootcfg[c].vpe_config = kzalloc_objs(*core_bootcfg[c].vpe_config,
arch/mips/kernel/smp-cps.c-371- core_vpes);
--
arch/parisc/kernel/vdso.c=99=static struct page ** __init vdso_setup_pages(void *start, void *end)
--
arch/parisc/kernel/vdso.c-104-
arch/parisc/kernel/vdso.c:105: pagelist = kzalloc_objs(struct page *, pages + 1);
arch/parisc/kernel/vdso.c-106- if (!pagelist)
--
arch/parisc/net/bpf_jit_core.c=44=struct bpf_prog *bpf_int_jit_compile(struct bpf_verifier_env *env, struct bpf_prog *prog)
--
arch/parisc/net/bpf_jit_core.c-71- ctx->prog = prog;
arch/parisc/net/bpf_jit_core.c:72: ctx->offset = kzalloc_objs(int, prog->len);
arch/parisc/net/bpf_jit_core.c-73- if (!ctx->offset)
--
arch/powerpc/kernel/smp.c=1113=void __init smp_prepare_cpus(unsigned int max_cpus)
--
arch/powerpc/kernel/smp.c-1174- */
arch/powerpc/kernel/smp.c:1175: chip_id_lookup_table = kzalloc_objs(int, idx);
arch/powerpc/kernel/smp.c-1176- if (chip_id_lookup_table)
--
arch/powerpc/kernel/vdso.c=242=static struct page ** __init vdso_setup_pages(void *start, void *end)
--
arch/powerpc/kernel/vdso.c-247-
arch/powerpc/kernel/vdso.c:248: pagelist = kzalloc_objs(struct page *, pages + 1);
arch/powerpc/kernel/vdso.c-249- if (!pagelist)
--
arch/powerpc/kvm/e500_mmu.c=731=int kvm_vcpu_ioctl_config_tlb(struct kvm_vcpu *vcpu,
--
arch/powerpc/kvm/e500_mmu.c-794-
arch/powerpc/kvm/e500_mmu.c:795: privs[0] = kzalloc_objs(*privs[0], params.tlb_sizes[0]);
arch/powerpc/kvm/e500_mmu.c-796- if (!privs[0]) {
--
arch/powerpc/kvm/e500_mmu.c-800-
arch/powerpc/kvm/e500_mmu.c:801: privs[1] = kzalloc_objs(*privs[1], params.tlb_sizes[1]);
arch/powerpc/kvm/e500_mmu.c-802- if (!privs[1]) {
--
arch/powerpc/kvm/e500_mmu.c=898=int kvmppc_e500_tlb_init(struct kvmppc_vcpu_e500 *vcpu_e500)
--
arch/powerpc/kvm/e500_mmu.c-922-
arch/powerpc/kvm/e500_mmu.c:923: vcpu_e500->gtlb_priv[0] = kzalloc_objs(struct tlbe_priv,
arch/powerpc/kvm/e500_mmu.c-924- vcpu_e500->gtlb_params[0].entries);
--
arch/powerpc/kvm/e500_mmu.c-927-
arch/powerpc/kvm/e500_mmu.c:928: vcpu_e500->gtlb_priv[1] = kzalloc_objs(struct tlbe_priv,
arch/powerpc/kvm/e500_mmu.c-929- vcpu_e500->gtlb_params[1].entries);
--
arch/powerpc/mm/drmem.c=425=static void __init init_drmem_v1_lmbs(const __be32 *prop)
--
arch/powerpc/mm/drmem.c-432-
arch/powerpc/mm/drmem.c:433: drmem_info->lmbs = kzalloc_objs(*lmb, drmem_info->n_lmbs);
arch/powerpc/mm/drmem.c-434- if (!drmem_info->lmbs)
--
arch/powerpc/mm/drmem.c=441=static void __init init_drmem_v2_lmbs(const __be32 *prop)
--
arch/powerpc/mm/drmem.c-459-
arch/powerpc/mm/drmem.c:460: drmem_info->lmbs = kzalloc_objs(*lmb, drmem_info->n_lmbs);
arch/powerpc/mm/drmem.c-461- if (!drmem_info->lmbs)
--
arch/powerpc/perf/imc-pmu.c=221=static int update_events_in_group(struct device_node *node, struct imc_pmu *pmu)
--
arch/powerpc/perf/imc-pmu.c-259- /* Allocate memory for the events */
arch/powerpc/perf/imc-pmu.c:260: pmu->events = kzalloc_objs(struct imc_events, ct);
arch/powerpc/perf/imc-pmu.c-261- if (!pmu->events) {
--
arch/powerpc/perf/imc-pmu.c-290- */
arch/powerpc/perf/imc-pmu.c:291: attrs = kzalloc_objs(struct attribute *, ((ct * 3) + 1));
arch/powerpc/perf/imc-pmu.c-292- if (!attrs) {
--
arch/powerpc/perf/imc-pmu.c=1526=static int init_nest_pmu_ref(void)
--
arch/powerpc/perf/imc-pmu.c-1529-
arch/powerpc/perf/imc-pmu.c:1530: nest_imc_refc = kzalloc_objs(*nest_imc_refc, num_possible_nodes());
arch/powerpc/perf/imc-pmu.c-1531-
--
arch/powerpc/perf/imc-pmu.c=1683=static int imc_mem_init(struct imc_pmu *pmu_ptr, struct device_node *parent,
--
arch/powerpc/perf/imc-pmu.c-1700- if (!per_nest_pmu_arr) {
arch/powerpc/perf/imc-pmu.c:1701: per_nest_pmu_arr = kzalloc_objs(struct imc_pmu *,
arch/powerpc/perf/imc-pmu.c-1702- get_max_nest_dev() + 1);
--
arch/powerpc/perf/imc-pmu.c-1714- nr_cores = DIV_ROUND_UP(num_possible_cpus(), threads_per_core);
arch/powerpc/perf/imc-pmu.c:1715: pmu_ptr->mem_info = kzalloc_objs(struct imc_mem_info, nr_cores);
arch/powerpc/perf/imc-pmu.c-1716-
--
arch/powerpc/perf/imc-pmu.c-1719-
arch/powerpc/perf/imc-pmu.c:1720: core_imc_refc = kzalloc_objs(struct imc_pmu_ref, nr_cores);
arch/powerpc/perf/imc-pmu.c-1721-
--
arch/powerpc/perf/imc-pmu.c-1752- nr_cores = DIV_ROUND_UP(num_possible_cpus(), threads_per_core);
arch/powerpc/perf/imc-pmu.c:1753: trace_imc_refc = kzalloc_objs(struct imc_pmu_ref, nr_cores);
arch/powerpc/perf/imc-pmu.c-1754- if (!trace_imc_refc)
--
arch/powerpc/perf/vpa-dtl.c=508=static void *vpa_dtl_setup_aux(struct perf_event *event, void **pages,
--
arch/powerpc/perf/vpa-dtl.c-525-
arch/powerpc/perf/vpa-dtl.c:526: pglist = kzalloc_objs(*pglist, nr_pages);
arch/powerpc/perf/vpa-dtl.c-527- if (!pglist)
--
arch/powerpc/platforms/44x/pci.c=1307=static int __init ppc4xx_pciex_check_core_init(struct device_node *np)
--
arch/powerpc/platforms/44x/pci.c-1341- ppc4xx_pciex_ports =
arch/powerpc/platforms/44x/pci.c:1342: kzalloc_objs(struct ppc4xx_pciex_port, count);
arch/powerpc/platforms/44x/pci.c-1343- if (ppc4xx_pciex_ports) {
--
arch/powerpc/platforms/powernv/idle.c=1322=static int __init pnv_parse_cpuidle_dt(void)
--
arch/powerpc/platforms/powernv/idle.c-1338-
arch/powerpc/platforms/powernv/idle.c:1339: pnv_idle_states = kzalloc_objs(*pnv_idle_states, nr_idle_states);
arch/powerpc/platforms/powernv/idle.c-1340- temp_u32 = kcalloc(nr_idle_states, sizeof(u32), GFP_KERNEL);
--
arch/powerpc/platforms/powernv/memtrace.c=131=static int memtrace_init_regions_runtime(u64 size)
--
arch/powerpc/platforms/powernv/memtrace.c-135-
arch/powerpc/platforms/powernv/memtrace.c:136: memtrace_array = kzalloc_objs(struct memtrace_entry, num_online_nodes());
arch/powerpc/platforms/powernv/memtrace.c-137- if (!memtrace_array) {
--
arch/powerpc/platforms/powernv/opal-async.c=246=int __init opal_async_comp_init(void)
--
arch/powerpc/platforms/powernv/opal-async.c-267- opal_max_async_tokens = be32_to_cpup(async);
arch/powerpc/platforms/powernv/opal-async.c:268: opal_async_tokens = kzalloc_objs(*opal_async_tokens,
arch/powerpc/platforms/powernv/opal-async.c-269- opal_max_async_tokens);
--
arch/powerpc/platforms/powernv/opal-imc.c=82=static int imc_get_mem_addr_nest(struct device_node *node,
--
arch/powerpc/platforms/powernv/opal-imc.c-110-
arch/powerpc/platforms/powernv/opal-imc.c:111: pmu_ptr->mem_info = kzalloc_objs(*pmu_ptr->mem_info, nr_chips + 1);
arch/powerpc/platforms/powernv/opal-imc.c-112- if (!pmu_ptr->mem_info)
--
arch/powerpc/platforms/powernv/opal-irqchip.c=174=int __init opal_event_init(void)
--
arch/powerpc/platforms/powernv/opal-irqchip.c-223- /* Allocate an IRQ resources array */
arch/powerpc/platforms/powernv/opal-irqchip.c:224: opal_irqs = kzalloc_objs(struct resource, opal_irq_count);
arch/powerpc/platforms/powernv/opal-irqchip.c-225- if (WARN_ON(!opal_irqs)) {
--
arch/powerpc/platforms/powernv/opal-powercap.c=142=void __init opal_powercap_init(void)
--
arch/powerpc/platforms/powernv/opal-powercap.c-152-
arch/powerpc/platforms/powernv/opal-powercap.c:153: pcaps = kzalloc_objs(*pcaps, of_get_child_count(powercap));
arch/powerpc/platforms/powernv/opal-powercap.c-154- if (!pcaps)
--
arch/powerpc/platforms/powernv/opal-powercap.c-183-
arch/powerpc/platforms/powernv/opal-powercap.c:184: pcaps[i].pattrs = kzalloc_objs(struct powercap_attr, j);
arch/powerpc/platforms/powernv/opal-powercap.c-185- if (!pcaps[i].pattrs)
--
arch/powerpc/platforms/powernv/opal-powercap.c-187-
arch/powerpc/platforms/powernv/opal-powercap.c:188: pcaps[i].pg.attrs = kzalloc_objs(struct attribute *, j + 1);
arch/powerpc/platforms/powernv/opal-powercap.c-189- if (!pcaps[i].pg.attrs) {
--
arch/powerpc/platforms/powernv/opal-psr.c=123=void __init opal_psr_init(void)
--
arch/powerpc/platforms/powernv/opal-psr.c-134-
arch/powerpc/platforms/powernv/opal-psr.c:135: psr_attrs = kzalloc_objs(*psr_attrs, of_get_child_count(psr));
arch/powerpc/platforms/powernv/opal-psr.c-136- if (!psr_attrs)
--
arch/powerpc/platforms/powernv/opal-sensor-groups.c=160=void __init opal_sensor_groups_init(void)
--
arch/powerpc/platforms/powernv/opal-sensor-groups.c-170-
arch/powerpc/platforms/powernv/opal-sensor-groups.c:171: sgs = kzalloc_objs(*sgs, of_get_child_count(sg));
arch/powerpc/platforms/powernv/opal-sensor-groups.c-172- if (!sgs)
--
arch/powerpc/platforms/powernv/opal-sensor-groups.c-192-
arch/powerpc/platforms/powernv/opal-sensor-groups.c:193: sgs[i].sgattrs = kzalloc_objs(*sgs[i].sgattrs, nr_attrs);
arch/powerpc/platforms/powernv/opal-sensor-groups.c-194- if (!sgs[i].sgattrs)
--
arch/powerpc/platforms/powernv/opal-sensor-groups.c-196-
arch/powerpc/platforms/powernv/opal-sensor-groups.c:197: sgs[i].sg.attrs = kzalloc_objs(*sgs[i].sg.attrs, nr_attrs + 1);
arch/powerpc/platforms/powernv/opal-sensor-groups.c-198-
--
arch/powerpc/platforms/powernv/opal-sysparam.c=143=void __init opal_sys_param_init(void)
--
arch/powerpc/platforms/powernv/opal-sysparam.c-224-
arch/powerpc/platforms/powernv/opal-sysparam.c:225: attr = kzalloc_objs(*attr, count);
arch/powerpc/platforms/powernv/opal-sysparam.c-226- if (!attr) {
--
arch/powerpc/platforms/pseries/papr_platform_attributes.c=233=static int __init papr_init(void)
--
arch/powerpc/platforms/pseries/papr_platform_attributes.c-297-
arch/powerpc/platforms/pseries/papr_platform_attributes.c:298: papr_groups = kzalloc_objs(*papr_groups, num_attrs);
arch/powerpc/platforms/pseries/papr_platform_attributes.c-299- if (!papr_groups)
--
arch/powerpc/platforms/pseries/papr_platform_attributes.c-315- for (idx = 0; idx < num_attrs; idx++) {
arch/powerpc/platforms/pseries/papr_platform_attributes.c:316: papr_groups[idx].pg.attrs = kzalloc_objs(*papr_groups[idx].pg.attrs,
arch/powerpc/platforms/pseries/papr_platform_attributes.c-317- KOBJ_MAX_ATTRS + 1);
--
arch/powerpc/sysdev/mpic.c=542=static void __init mpic_scan_ht_pics(struct mpic *mpic)
--
arch/powerpc/sysdev/mpic.c-549- /* Allocate fixups array */
arch/powerpc/sysdev/mpic.c:550: mpic->fixups = kzalloc_objs(*mpic->fixups, 128);
arch/powerpc/sysdev/mpic.c-551- BUG_ON(mpic->fixups == NULL);
--
arch/powerpc/sysdev/mpic_msgr.c=167=static int mpic_msgr_probe(struct platform_device *dev)
--
arch/powerpc/sysdev/mpic_msgr.c-190-
arch/powerpc/sysdev/mpic_msgr.c:191: mpic_msgrs = kzalloc_objs(*mpic_msgrs, mpic_msgr_count);
arch/powerpc/sysdev/mpic_msgr.c-192- if (!mpic_msgrs) {
--
arch/powerpc/sysdev/xive/common.c=1118=static int __init xive_init_ipis(void)
--
arch/powerpc/sysdev/xive/common.c-1133-
arch/powerpc/sysdev/xive/common.c:1134: xive_ipis = kzalloc_objs(*xive_ipis, nr_node_ids,
arch/powerpc/sysdev/xive/common.c-1135- GFP_KERNEL | __GFP_NOFAIL);
--
arch/riscv/kernel/tests/kprobes/test-kprobes.c=13=static void test_kprobe_riscv(struct kunit *test)
--
arch/riscv/kernel/tests/kprobes/test-kprobes.c-22-
arch/riscv/kernel/tests/kprobes/test-kprobes.c:23: kp = kzalloc_objs(*kp, num_kprobe);
arch/riscv/kernel/tests/kprobes/test-kprobes.c-24- KUNIT_EXPECT_TRUE(test, kp);
--
arch/riscv/kernel/unaligned_access_speed.c=154=static void __init check_unaligned_access_speed_all_cpus(void)
--
arch/riscv/kernel/unaligned_access_speed.c-157- unsigned int cpu_count = num_possible_cpus();
arch/riscv/kernel/unaligned_access_speed.c:158: struct page **bufs = kzalloc_objs(*bufs, cpu_count);
arch/riscv/kernel/unaligned_access_speed.c-159-
--
arch/riscv/kernel/vdso.c=44=static void __init __vdso_init(struct __vdso_info *vdso_info)
--
arch/riscv/kernel/vdso.c-57-
arch/riscv/kernel/vdso.c:58: vdso_pagelist = kzalloc_objs(struct page *, vdso_info->vdso_pages);
arch/riscv/kernel/vdso.c-59- if (vdso_pagelist == NULL)
--
arch/riscv/kvm/aia_aplic.c=574=int kvm_riscv_aia_aplic_init(struct kvm *kvm)
--
arch/riscv/kvm/aia_aplic.c-591- aplic->nr_words = DIV_ROUND_UP(aplic->nr_irqs, 32);
arch/riscv/kvm/aia_aplic.c:592: aplic->irqs = kzalloc_objs(*aplic->irqs, aplic->nr_irqs);
arch/riscv/kvm/aia_aplic.c-593- if (!aplic->irqs) {
--
arch/riscv/kvm/vcpu_sbi_fwft.c=348=static int kvm_sbi_ext_fwft_init(struct kvm_vcpu *vcpu)
--
arch/riscv/kvm/vcpu_sbi_fwft.c-354-
arch/riscv/kvm/vcpu_sbi_fwft.c:355: fwft->configs = kzalloc_objs(struct kvm_sbi_fwft_config,
arch/riscv/kvm/vcpu_sbi_fwft.c-356- ARRAY_SIZE(features));
--
arch/riscv/kvm/vm.c=93=int kvm_riscv_setup_default_irq_routing(struct kvm *kvm, u32 lines)
--
arch/riscv/kvm/vm.c-97-
arch/riscv/kvm/vm.c:98: ents = kzalloc_objs(*ents, lines);
arch/riscv/kvm/vm.c-99- if (!ents)
--
arch/riscv/net/bpf_jit_comp64.c=1022=static int __arch_prepare_bpf_trampoline(struct bpf_tramp_image *im,
--
arch/riscv/net/bpf_jit_comp64.c-1197- if (fmod_ret->nr_links) {
arch/riscv/net/bpf_jit_comp64.c:1198: branches_off = kzalloc_objs(int, fmod_ret->nr_links);
arch/riscv/net/bpf_jit_comp64.c-1199- if (!branches_off)
--
arch/riscv/net/bpf_jit_core.c=44=struct bpf_prog *bpf_int_jit_compile(struct bpf_verifier_env *env, struct bpf_prog *prog)
--
arch/riscv/net/bpf_jit_core.c-74- ctx->prog = prog;
arch/riscv/net/bpf_jit_core.c:75: ctx->offset = kzalloc_objs(int, prog->len);
arch/riscv/net/bpf_jit_core.c-76- if (!ctx->offset)
--
arch/s390/appldata/appldata_base.c=348=int appldata_register_ops(struct appldata_ops *ops)
--
arch/s390/appldata/appldata_base.c-352-
arch/s390/appldata/appldata_base.c:353: ops->ctl_table = kzalloc_objs(struct ctl_table, 1);
arch/s390/appldata/appldata_base.c-354- if (!ops->ctl_table)
--
arch/s390/include/asm/idals.h=88=static inline int set_normalized_cda(struct ccw1 *ccw, void *vaddr)
--
arch/s390/include/asm/idals.h-96- if (nridaws > 0) {
arch/s390/include/asm/idals.h:97: idal = kzalloc_objs(*idal, nridaws, GFP_ATOMIC | GFP_DMA);
arch/s390/include/asm/idals.h-98- if (!idal)
--
arch/s390/kernel/cert_store.c=315=static int invalidate_keyring_keys(struct key *keyring)
--
arch/s390/kernel/cert_store.c-324- num_keys = keyring_payload_len / sizeof(key_serial_t);
arch/s390/kernel/cert_store.c:325: key_array = kzalloc_objs(key_serial_t, num_keys);
arch/s390/kernel/cert_store.c-326- if (!key_array)
--
arch/s390/kernel/debug.c=220=static debug_info_t *debug_info_alloc(const char *name, int pages_per_area,
--
arch/s390/kernel/debug.c-229- goto fail_malloc_rc;
arch/s390/kernel/debug.c:230: rc->active_entries = kzalloc_objs(int, nr_areas);
arch/s390/kernel/debug.c-231- if (!rc->active_entries)
arch/s390/kernel/debug.c-232- goto fail_malloc_active_entries;
arch/s390/kernel/debug.c:233: rc->active_pages = kzalloc_objs(int, nr_areas);
arch/s390/kernel/debug.c-234- if (!rc->active_pages)
--
arch/s390/kernel/vdso.c=129=static struct page ** __init vdso_setup_pages(void *start, void *end)
--
arch/s390/kernel/vdso.c-134-
arch/s390/kernel/vdso.c:135: pagelist = kzalloc_objs(struct page *, pages + 1);
arch/s390/kernel/vdso.c-136- if (!pagelist)
--
arch/s390/kvm/pci.c=120=int kvm_s390_pci_aen_init(u8 nisc)
--
arch/s390/kvm/pci.c-128- mutex_lock(&aift->aift_lock);
arch/s390/kvm/pci.c:129: aift->kzdev = kzalloc_objs(struct kvm_zdev *, ZPCI_NR_DEVICES);
arch/s390/kvm/pci.c-130- if (!aift->kzdev) {
--
arch/s390/pci/pci.c=1065=static int zpci_mem_init(void)
--
arch/s390/pci/pci.c-1076-
arch/s390/pci/pci.c:1077: zpci_iomap_start = kzalloc_objs(*zpci_iomap_start, ZPCI_IOMAP_ENTRIES);
arch/s390/pci/pci.c-1078- if (!zpci_iomap_start)
--
arch/s390/pci/pci_irq.c=552=static int __init zpci_directed_irq_init(void)
--
arch/s390/pci/pci_irq.c-565-
arch/s390/pci/pci_irq.c:566: zpci_ibv = kzalloc_objs(*zpci_ibv, num_possible_cpus());
arch/s390/pci/pci_irq.c-567- if (!zpci_ibv)
--
arch/s390/pci/pci_irq.c=590=static int __init zpci_floating_irq_init(void)
arch/s390/pci/pci_irq.c-591-{
arch/s390/pci/pci_irq.c:592: zpci_ibv = kzalloc_objs(*zpci_ibv, ZPCI_NR_DEVICES);
arch/s390/pci/pci_irq.c-593- if (!zpci_ibv)
--
arch/sh/drivers/dma/dmabrg.c=151=static int __init dmabrg_init(void)
--
arch/sh/drivers/dma/dmabrg.c-155-
arch/sh/drivers/dma/dmabrg.c:156: dmabrg_handlers = kzalloc_objs(struct dmabrg_handler, 10);
arch/sh/drivers/dma/dmabrg.c-157- if (!dmabrg_handlers)
--
arch/sh/drivers/pci/pcie-sh7786.c=545=static int __init sh7786_pcie_init(void)
--
arch/sh/drivers/pci/pcie-sh7786.c-560-
arch/sh/drivers/pci/pcie-sh7786.c:561: sh7786_pcie_ports = kzalloc_objs(struct sh7786_pcie_port, nr_ports);
arch/sh/drivers/pci/pcie-sh7786.c-562- if (unlikely(!sh7786_pcie_ports))
--
arch/sparc/kernel/sys_sparc_64.c=625=SYSCALL_DEFINE5(utrap_install, utrap_entry_t, type,
--
arch/sparc/kernel/sys_sparc_64.c-649- current_thread_info()->utraps =
arch/sparc/kernel/sys_sparc_64.c:650: kzalloc_objs(long, UT_TRAP_INSTRUCTION_31 + 1);
arch/sparc/kernel/sys_sparc_64.c-651- if (!current_thread_info()->utraps)
--
arch/sparc/vdso/vma.c=46=static int __init init_vdso_image(const struct vdso_image *image,
--
arch/sparc/vdso/vma.c-60-
arch/sparc/vdso/vma.c:61: cpp = kzalloc_objs(struct page *, cnpages);
arch/sparc/vdso/vma.c-62- vdso_mapping->pages = cpp;
--
arch/x86/events/amd/iommu.c=382=static __init int _init_events_attrs(void)
--
arch/x86/events/amd/iommu.c-389-
arch/x86/events/amd/iommu.c:390: attrs = kzalloc_objs(*attrs, i + 1);
arch/x86/events/amd/iommu.c-391- if (!attrs)
--
arch/x86/events/intel/core.c=7420=static __always_inline int intel_pmu_init_hybrid(enum hybrid_pmu_type pmus)
--
arch/x86/events/intel/core.c-7426- x86_pmu.num_hybrid_pmus = hweight_long(pmus_mask);
arch/x86/events/intel/core.c:7427: x86_pmu.hybrid_pmu = kzalloc_objs(struct x86_hybrid_pmu,
arch/x86/events/intel/core.c-7428- x86_pmu.num_hybrid_pmus);
--
arch/x86/events/intel/uncore.c=988=static int __init uncore_type_init(struct intel_uncore_type *type)
--
arch/x86/events/intel/uncore.c-993-
]
|
| 61/4 |
2026/06/15 16:14 |
llm |
patch-generator |
0m
Model:
Tokens:
input: 24000
output: 351
thoughts: 44
Thoughts: Okay, here's my take on those thoughts, as if they were my own:
**Replacing `kzalloc_objs` with `kvcalloc`**
Right, `kzalloc_objs`... a macro. No need to delve into its inner workings right now; all I really need is to swap it out for `kvcalloc`. That should be a straightforward substitution. Time to get this done.
|
| 62/4 |
2026/06/15 16:14 |
tool |
codeeditor |
0m
Args: map[CurrentCode: if (object_count != 0) {
object_ids = memdup_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);
goto out_lessor;
}
/* fill and validate the object idr */
ret = fill_object_idr(dev, lessor_priv, &leases,
object_count, object_ids);
kfree(object_ids);
if (ret) { NewCode: if (object_count != 0) {
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);
goto out_lessor;
}
/* fill and validate the object idr */
ret = fill_object_idr(dev, lessor_priv, &leases,
object_count, object_ids);
kvfree(object_ids);
if (ret) { SourceFile:drivers/gpu/drm/drm_lease.c]
Results:
|
| 63/4 |
2026/06/15 16:14 |
llm |
patch-generator |
0m
Model:
Tokens:
input: 24489
output: 344
thoughts: 13
Thoughts: Okay, here's my take on those thoughts, tailored for an expert audience, presented in the first person:
**Editing `fill_object_idr` Functionality**
Alright, time to get into the weeds with `fill_object_idr`. I'm going to need to carefully review the current implementation. We're dealing with potentially sensitive data or complex object relationships here, so any changes need to be thoroughly vetted. My primary concern is maintaining data integrity and ensuring the IDR fill process doesn't introduce any unforeseen side effects or performance bottlenecks. I need to keep in mind any dependencies this function might have. I'll need to consider how it interacts with other related modules or systems. I'll approach this with the assumption that I am already familiar with the codebase.
|
| 64/4 |
2026/06/15 16:14 |
tool |
codeeditor |
0m
Args: map[CurrentCode:static int fill_object_idr(struct drm_device *dev,
struct drm_file *lessor_priv,
struct idr *leases,
int object_count,
u32 *object_ids)
{
struct drm_mode_object **objects;
u32 o;
int ret;
bool universal_planes = READ_ONCE(lessor_priv->universal_planes);
objects = kzalloc_objs(struct drm_mode_object *, object_count);
if (!objects)
return -ENOMEM;
/* step one - get references to all the mode objects NewCode:static int fill_object_idr(struct drm_device *dev,
struct drm_file *lessor_priv,
struct idr *leases,
int object_count,
u32 *object_ids)
{
struct drm_mode_object **objects;
u32 o;
int ret;
bool universal_planes = READ_ONCE(lessor_priv->universal_planes);
objects = kvcalloc(object_count, sizeof(struct drm_mode_object *), GFP_KERNEL);
if (!objects)
return -ENOMEM;
/* step one - get references to all the mode objects SourceFile:drivers/gpu/drm/drm_lease.c]
Results:
|
| 65/4 |
2026/06/15 16:14 |
llm |
patch-generator |
0m
Model:
Tokens:
input: 25017
output: 178
thoughts: 15
Thoughts: Okay, here's my interpretation of that thought process, assuming I'm already deep in the weeds of kernel development:
**Kfree and the Object IDR**
Right, so I'm thinking about `fill_object_idr`. What's nagging at me is that `kfree` call in that function. It's a key spot. I need to ensure that the memory freed in the context of `fill_object_idr` is handled correctly. This part of the code is responsible for populating the object IDR, likely associating IDs with specific kernel objects or data structures. I'm wondering if there's any potential for a double free, or a use-after-free scenario. Is the memory being freed safely after it's been used? Is there any chance that the freed memory is still referenced or could be later, which could introduce subtle and hard-to-debug memory corruption problems? I need to analyze the whole call stack and all possible return paths from the function. I also need to make sure the free is conditional and correct for all possible circumstances. If I don't look closely, it's very easy to miss a crucial detail here.
|
| 66/4 |
2026/06/15 16:14 |
tool |
codeeditor |
0m
Args: map[CurrentCode: ret = 0;
out_free_objects:
for (o = 0; o < object_count; o++) {
if (objects[o])
drm_mode_object_put(objects[o]);
}
kfree(objects);
return ret;
} NewCode: ret = 0;
out_free_objects:
for (o = 0; o < object_count; o++) {
if (objects[o])
drm_mode_object_put(objects[o]);
}
kvfree(objects);
return ret;
} SourceFile:drivers/gpu/drm/drm_lease.c]
Results:
|
| 67/4 |
2026/06/15 16:14 |
llm |
patch-generator |
0m
Model:
Tokens:
input: 25465
output: 26
thoughts: 7
Thoughts: Okay, I'm ready to dive into that diff. Let's get this done.
***
**Analyzing the Changes**
Alright, first things first: let's get a good look at the diff. I need to understand exactly what's changed and the scope of these modifications. I'm focusing on the delta here - pinpointing what's been added, deleted, or modified. My mind's already ticking through possible implications, considering the impact on existing systems and potential areas that might break or interact in unexpected ways. Are these isolated changes, or do they ripple out? Are there dependencies I need to flag immediately? I need to quickly assess the context: what project are we working on? What components? What was the previous state? From that, I will understand what this means. I'm already asking myself, 'is this change as straightforward as it appears?'. The goal is a clear understanding. Let's dig in.
|
| 68/4 |
2026/06/15 16:14 |
tool |
patch-diff |
0m
Args: map[File:drivers/gpu/drm/drm_lease.c]
Results: map[Output:diff --git a/drivers/gpu/drm/drm_lease.c b/drivers/gpu/drm/drm_lease.c
index 5d2cf724c..1666dba7b 100644
--- a/drivers/gpu/drm/drm_lease.c
+++ b/drivers/gpu/drm/drm_lease.c
@@ -378,209 +378,209 @@ static int validate_lease(struct drm_device *dev,
static int fill_object_idr(struct drm_device *dev,
struct drm_file *lessor_priv,
struct idr *leases,
int object_count,
u32 *object_ids)
{
struct drm_mode_object **objects;
u32 o;
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;
/* step one - get references to all the mode objects
and check for validity. */
for (o = 0; o < object_count; o++) {
objects[o] = drm_mode_object_find(dev, lessor_priv,
object_ids[o],
DRM_MODE_OBJECT_ANY);
if (!objects[o]) {
ret = -ENOENT;
goto out_free_objects;
}
if (!drm_mode_object_lease_required(objects[o]->type)) {
DRM_DEBUG_KMS("invalid object for lease\n");
ret = -EINVAL;
goto out_free_objects;
}
}
ret = validate_lease(dev, object_count, objects, universal_planes);
if (ret) {
drm_dbg_lease(dev, "lease validation failed\n");
goto out_free_objects;
}
/* add their IDs to the lease request - taking into account
universal planes */
for (o = 0; o < object_count; o++) {
struct drm_mode_object *obj = objects[o];
u32 object_id = objects[o]->id;
drm_dbg_lease(dev, "Adding object %d to lease\n", object_id);
/*
* We're using an IDR to hold the set of leased
* objects, but we don't need to point at the object's
* data structure from the lease as the main object_idr
* will be used to actually find that. Instead, all we
* really want is a 'leased/not-leased' result, for
* which any non-NULL pointer will work fine.
*/
ret = idr_alloc(leases, &drm_lease_idr_object , object_id, object_id + 1, GFP_KERNEL);
if (ret < 0) {
drm_dbg_lease(dev, "Object %d cannot be inserted into leases (%d)\n",
object_id, ret);
goto out_free_objects;
}
if (obj->type == DRM_MODE_OBJECT_CRTC && !universal_planes) {
struct drm_crtc *crtc = obj_to_crtc(obj);
ret = idr_alloc(leases, &drm_lease_idr_object, crtc->primary->base.id, crtc->primary->base.id + 1, GFP_KERNEL);
if (ret < 0) {
drm_dbg_lease(dev, "Object primary plane %d cannot be inserted into leases (%d)\n",
object_id, ret);
goto out_free_objects;
}
if (crtc->cursor) {
ret = idr_alloc(leases, &drm_lease_idr_object, crtc->cursor->base.id, crtc->cursor->base.id + 1, GFP_KERNEL);
if (ret < 0) {
drm_dbg_lease(dev, "Object cursor plane %d cannot be inserted into leases (%d)\n",
object_id, ret);
goto out_free_objects;
}
}
}
}
ret = 0;
out_free_objects:
for (o = 0; o < object_count; o++) {
if (objects[o])
drm_mode_object_put(objects[o]);
}
- kfree(objects);
+ kvfree(objects);
return ret;
}
/*
* The master associated with the specified file will have a lease
* created containing the objects specified in the ioctl structure.
* A file descriptor will be allocated for that and returned to the
* application.
*/
int drm_mode_create_lease_ioctl(struct drm_device *dev,
void *data, struct drm_file *lessor_priv)
{
struct drm_mode_create_lease *cl = data;
size_t object_count;
int ret = 0;
struct idr leases;
struct drm_master *lessor;
struct drm_master *lessee = NULL;
struct file *lessee_file = NULL;
struct file *lessor_file = lessor_priv->filp;
struct drm_file *lessee_priv;
int fd = -1;
uint32_t *object_ids;
/* Can't lease without MODESET */
if (!drm_core_check_feature(dev, DRIVER_MODESET))
return -EOPNOTSUPP;
if (cl->flags && (cl->flags & ~(O_CLOEXEC | O_NONBLOCK))) {
drm_dbg_lease(dev, "invalid flags\n");
return -EINVAL;
}
lessor = drm_file_get_master(lessor_priv);
/* Do not allow sub-leases */
if (lessor->lessor) {
drm_dbg_lease(dev, "recursive leasing not allowed\n");
ret = -EINVAL;
goto out_lessor;
}
object_count = cl->object_count;
/* 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_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);
goto out_lessor;
}
/* 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);
goto out_lessor;
}
}
/* Allocate a file descriptor for the lease */
fd = get_unused_fd_flags(cl->flags & (O_CLOEXEC | O_NONBLOCK));
if (fd < 0) {
idr_destroy(&leases);
ret = fd;
goto out_lessor;
}
drm_dbg_lease(dev, "Creating lease\n");
/* lessee will take the ownership of leases */
lessee = drm_lease_create(lessor, &leases);
if (IS_ERR(lessee)) {
ret = PTR_ERR(lessee);
idr_destroy(&leases);
goto out_leases;
}
/* Clone the lessor file to create a new file for us */
drm_dbg_lease(dev, "Allocating lease file\n");
lessee_file = file_clone_open(lessor_file);
if (IS_ERR(lessee_file)) {
ret = PTR_ERR(lessee_file);
goto out_lessee;
}
lessee_priv = lessee_file->private_data;
/* Change the file to a master one */
drm_master_put(&lessee_priv->master);
lessee_priv->master = lessee;
lessee_priv->is_master = 1;
lessee_priv->authenticated = 1;
/* Pass fd back to userspace */
drm_dbg_lease(dev, "Returning fd %d id %d\n", fd, lessee->lessee_id);
cl->fd = fd;
cl->lessee_id = lessee->lessee_id;
/* Hook up the fd */
fd_install(fd, lessee_file);
drm_master_put(&lessor);
drm_dbg_lease(dev, "drm_mode_create_lease_ioctl succeeded\n");
return 0;
out_lessee:
drm_master_put(&lessee);
out_leases:
put_unused_fd(fd);
out_lessor:
drm_master_put(&lessor);
drm_dbg_lease(dev, "drm_mode_create_lease_ioctl failed: %d\n", ret);
return ret;
}
]
|
| 69/4 |
2026/06/15 16:14 |
llm |
patch-generator |
0m
Model:
Tokens:
input: 28265
output: 520
thoughts: 287
Thoughts: **Analyzing the Memory Allocation in `drm_mode_create_lease_ioctl`**
Okay, the diff seems spot on, lining up perfectly with the fix they're proposing. The core issue is this `drm_mode_create_lease_ioctl` function. It's accepting this `object_count` value from userspace, and that value could be as high as a million. That's the problem.
My first thought is, this is where it gets tricky. That initial `memdup_array_user` call… it's allocating `object_count * sizeof(__u32)` bytes. That could be up to 4MB, which is substantial. And the thing is, internally it's using `memdup_user`, which in turn uses `kmalloc` with `__GFP_NOWARN`. So, it won’t throw up a warning if the memory allocation fails. That's not ideal. Using `vmemdup_array_user` makes much more sense. It can fall back to `vmalloc` if `kmalloc` can’t find a contiguous chunk. This circumvents potential fragmentation issues, making the allocation more resilient to failures when contiguous memory isn't available. Good thinking.
The next allocation, `kzalloc_objs`, that’s the real kicker. That’s allocating `object_count * sizeof(struct drm_mode_object *)` bytes, potentially up to 8MB. And it's using a plain `kzalloc`. No `__GFP_NOWARN` in sight. That means we're going to get a warning from the page allocator if the requested size exceeds `KMALLOC_MAX_SIZE`. The proposed solution, using `kvcalloc`, is elegant. That'll switch to `vmalloc` when dealing with big allocations, while also applying `__GFP_NOWARN` to the initial `kmalloc` attempt. It’s the right way to fix this, no doubt.
Alright, I'm ready to craft the final response. I'll summarize these changes concisely and explain why this is a good improvement.
|
| 70/3 |
2026/06/15 16:15 |
action |
test-patch |
21m
Results: map[PatchDiff: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);
TestError:]
|
| 71/1 |
2026/06/15 16:36 |
agent |
fixes-finder |
2m
Model:
Results: map[FixesHash:62884cd386b876638720ef88374b31a84ca7ee5f]
Instruction:
You are an experienced Linux kernel developer tasked with identifying the commit
that introduced the bug being fixed. Identifying the correct buggy commit is crucial
for proper kernel maintenance (backporting to stable trees, etc.).
Your investigation strategy:
1. Examine the patch that fixes the bug. Use git tools (like git-log or git-blame)
to trace the history of the lines or functions modified by the patch.
2. Analyze the stack trace in the crash report. Identify the key files and functions
involved in the crash and investigate their history to see when the problematic
logic was introduced.
3. Compare the bug explanation with the commit history to find the point where
the described logic error first appeared.
A bug is typically introduced when a piece of code is first written, or when
a refactoring changed its logic in a way that introduced the bug.
Trace the history of relevant symbols or find when specific code patterns were introduced/removed.
You must provide exactly one bug-introducing commit hash.
If you are unable to confidently determine the bug-introducing commit after investigation,
return an empty string rather than guessing.
Prefer calling several tools at the same time to save round-trips.
Use set-results tool to provide results of the analysis.
It must be called exactly once before the final reply.
Ignore results of this tool.
Prompt:
The crash is:
------------[ cut here ]------------
WARNING: mm/page_alloc.c:5197 at __alloc_frozen_pages_noprof+0x2ce/0x380 mm/page_alloc.c:5197, CPU#0: syz.0.17/6137
Modules linked in:
CPU: 0 UID: 0 PID: 6137 Comm: syz.0.17 Not tainted syzkaller #1 PREEMPT(full)
Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.16.3-debian-1.16.3-2 04/01/2014
RIP: 0010:__alloc_frozen_pages_noprof+0x2ce/0x380 mm/page_alloc.c:5197
Code: 74 10 4c 89 e7 89 54 24 0c e8 6e a2 0d 00 8b 54 24 0c 49 83 3c 24 00 0f 85 ab fe ff ff e9 ac fe ff ff c6 05 92 0e b2 0d 01 90 <0f> 0b 90 e9 17 ff ff ff a9 00 00 08 00 48 8b 4c 24 10 4c 8d 44 24
RSP: 0018:ffffc90003aa7800 EFLAGS: 00010246
RAX: ffffc90003aa7800 RBX: 000000000000000b RCX: 0000000000000000
RDX: 0000000000000000 RSI: 0000000000000000 RDI: ffffc90003aa7868
RBP: ffffc90003aa78e8 R08: ffffc90003aa7867 R09: 0000000000000000
R10: ffffc90003aa7840 R11: fffff52000754f0d R12: 0000000000000000
R13: 1ffff92000754f04 R14: 0000000000040dc0 R15: dffffc0000000000
FS: 00007fe037ac16c0(0000) GS:ffff8881a59ad000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 00002000003d0000 CR3: 0000000104ab0000 CR4: 00000000000006f0
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
drm_ioctl_kernel+0x2df/0x3b0 drivers/gpu/drm/drm_ioctl.c:805
drm_ioctl+0x6fa/0xbc0 drivers/gpu/drm/drm_ioctl.c:902
vfs_ioctl fs/ioctl.c:51 [inline]
__do_sys_ioctl fs/ioctl.c:597 [inline]
__se_sys_ioctl+0xfc/0x170 fs/ioctl.c:583
do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
do_syscall_64+0x15f/0x560 arch/x86/entry/syscall_64.c:94
entry_SYSCALL_64_after_hwframe+0x77/0x7f
RIP: 0033:0x7fe036b9ce59
Code: ff c3 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 44 00 00 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 c7 c1 e8 ff ff ff f7 d8 64 89 01 48
RSP: 002b:00007fe037ac1028 EFLAGS: 00000246 ORIG_RAX: 0000000000000010
RAX: ffffffffffffffda RBX: 00007fe036e15fa0 RCX: 00007fe036b9ce59
RDX: 00002000000003c0 RSI: 00000000c01864c6 RDI: 0000000000000003
RBP: 00007fe036c32d6f R08: 0000000000000000 R09: 0000000000000000
R10: 0000000000000000 R11: 0000000000000246 R12: 0000000000000000
R13: 00007fe036e16038 R14: 00007fe036e15fa0 R15: 00007fffcab0e958
</TASK>
The explanation of the root cause is:
The root cause of this kernel crash is an unbounded memory allocation based on a user-controlled value, which attempts to allocate a contiguous memory chunk larger than the maximum allowed by the slab allocator (`KMALLOC_MAX_SIZE`), triggering a warning in the page allocator.
### Detailed Root Cause Analysis
1. **User-controlled `object_count`**:
In `drivers/gpu/drm/drm_lease.c`, the `drm_mode_create_lease_ioctl()` function retrieves `object_count` directly from the user-provided `struct drm_mode_create_lease` argument:
```c
object_count = cl->object_count;
```
The syzkaller reproducer sets this value to `0xf4240` (1,000,000).
2. **First Allocation (`memdup_array_user`)**:
The ioctl first allocates an array to hold the object IDs:
```c
object_ids = memdup_array_user(u64_to_user_ptr(cl->object_ids),
object_count, sizeof(__u32));
```
For `1,000,000` objects, this requires `4,000,000` bytes (~3.8 MB). This size is typically just under the `KMALLOC_MAX_SIZE` limit (usually 4 MB on many architectures). Furthermore, `memdup_array_user()` internally uses `memdup_user()`, which allocates memory with the `__GFP_NOWARN` flag. Thus, even if it were to fail, it would gracefully return `-ENOMEM` without triggering a kernel warning.
3. **Second Allocation (`kzalloc_objs`)**:
After successfully allocating `object_ids`, the ioctl calls `fill_object_idr()`:
```c
ret = fill_object_idr(dev, lessor_priv, &leases, object_count, object_ids);
```
Inside `fill_object_idr()`, the kernel attempts to allocate an array of pointers for the objects:
```c
objects = kzalloc_objs(struct drm_mode_object *, object_count);
```
The size of `struct drm_mode_object *` is 8 bytes (on 64-bit systems). For `1,000,000` objects, this requires `8,000,000` bytes (~7.6 MB). This size strictly exceeds the `KMALLOC_MAX_SIZE` limit.
Unlike `memdup_user()`, the `kzalloc_objs()` macro expands to a standard `kzalloc()` call using `GFP_KERNEL | __GFP_ZERO` **without** the `__GFP_NOWARN` flag.
4. **The Crash (Warning)**:
Because the requested size is larger than `KMALLOC_MAX_SIZE`, the SLUB allocator passes the request directly to the page allocator (`___kmalloc_large_node`). The page allocator calculates the required page order (order 11 for 8 MB). Since order 11 is strictly greater than `MAX_PAGE_ORDER` (typically 10), the page allocator hits the following safety check in `__alloc_frozen_pages_noprof()`:
```c
if (WARN_ON_ONCE_GFP(order > MAX_PAGE_ORDER, gfp))
return NULL;
```
Because `__GFP_NOWARN` was not provided, this triggers the `WARN_ON_ONCE_GFP` warning, which syzkaller correctly identifies as a crash.
### Proposed Fix
To fix this issue, both allocations should be updated to use the `kvmalloc` family of functions. These functions automatically fall back to `vmalloc()` for large allocations (avoiding memory fragmentation issues) and internally apply `__GFP_NOWARN` when attempting the initial `kmalloc()`, preventing the page allocator warning.
1. In `drm_mode_create_lease_ioctl()`, replace `memdup_array_user()` with `vmemdup_array_user()`, and change the corresponding `kfree()` to `kvfree()`:
```c
// drivers/gpu/drm/drm_lease.c : ~512
- 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));
// drivers/gpu/drm/drm_lease.c : ~523
- kfree(object_ids);
+ kvfree(object_ids);
```
2. In `fill_object_idr()`, replace `kzalloc_objs()` with `kvcalloc()`, and change the corresponding `kfree()` to `kvfree()`:
```c
// drivers/gpu/drm/drm_lease.c : ~389
- objects = kzalloc_objs(struct drm_mode_object *, object_count);
+ objects = kvcalloc(object_count, sizeof(struct drm_mode_object *), GFP_KERNEL);
// drivers/gpu/drm/drm_lease.c : ~465
- kfree(objects);
+ kvfree(objects);
```
This ensures that userspace cannot trigger a kernel warning by passing an arbitrarily large `object_count`, and the kernel will gracefully return `-ENOMEM` if the system truly cannot satisfy the `vmalloc` request.
The patch that fixes the bug is:
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);
Search for the commit(s) that introduced this bug.
|
| 72/2 |
2026/06/15 16:36 |
llm |
fixes-finder |
0m
Model:
Tokens:
input: 7608
output: 54
thoughts: 205
Thoughts: **Analyzing a Potential Memory Allocation Bug in drm_lease.c**
Okay, so I'm looking at a potential unbounded memory allocation issue in the DRM subsystem, specifically in `drivers/gpu/drm/drm_lease.c`. The core problem seems to be linked to `fill_object_idr()` and `drm_mode_create_lease_ioctl()`. The vulnerability stems from the use of `kzalloc_objs(struct drm_mode_object *, object_count)` and `memdup_array_user(..., object_count, ...)` which are clearly the culprits.
The proposed patch is smart; it's suggesting we replace `kzalloc_objs` with `kvcalloc` and `memdup_array_user` with `vmemdup_array_user`. That substitution looks like a solid approach to mitigate the risk. The replacement seems reasonable at face value, but I need to dive deeper.
To fully grasp the context and potential implications, I'm going to trace the history of these functions. I'll leverage `git log` to meticulously investigate when `fill_object_idr` and `drm_mode_create_lease_ioctl` were introduced into the code base, and more importantly, when the vulnerable allocation routines were implemented. Understanding the timeline and the commit messages will reveal the rationale behind their introduction and any potential oversight. I'll need to pay close attention to the parameter `object_count` to understand the origin of the potential unboundness. I'll also double-check the other function.
|
| 73/2 |
2026/06/15 16:36 |
tool |
git-log |
0m
Args: map[CodeRegexp:kzalloc_objs.*object_count SourcePath:drivers/gpu/drm/drm_lease.c SymbolName:fill_object_idr]
Results: map[Output:32a92f8c8932 Convert more 'alloc_obj' cases to default GFP_KERNEL arguments
69050f8d6d07 treewide: Replace kmalloc with kmalloc_obj for non-scalar types
7bd224b6625a drm/drm_lease: Remove usage of deprecated DRM_DEBUG_LEASE
676f11b5a4a0 drm: clean up unused kerneldoc in drm_lease.c
948de84233d3 drm : Insert blank lines after declarations.
e40b76428842 drm/leases: Drop object_id validation for negative ids
b5f06893c499 drm: Rename crtc_idr as object_idr to KMS cleanups
968029057192 drm/lease: look at ->universal_planes only once
a0c1af46e9d7 drm/lease: debug output for lease creation
7591844c197c drm: Fix kerneldoc warnings for drm_lease
]
|
| 74/2 |
2026/06/15 16:37 |
llm |
fixes-finder |
0m
Model:
Tokens:
input: 8462
output: 44
thoughts: 16
Thoughts: Okay, let's dive into this code.
**Investigating the Implementation of `fill_object_idr`**
Alright, I need to understand this new `fill_object_idr` function. The first thing I'll do is trace back its introduction in the codebase. I need to pinpoint the commit that brought it in – that's often where the original motivation and initial design choices are documented. Knowing *why* it was added will give me a huge head start in understanding *how* it's intended to work and, potentially, where its limitations might lie. The commit message itself is key. I'm expecting to see a clear explanation of the problem this function solves or the optimization it provides, along with any relevant design considerations. I'm hoping I can easily see how it fits into the broader architecture. Let's start digging.
|
| 75/2 |
2026/06/15 16:37 |
tool |
git-log |
0m
Args: map[Count:10 SourcePath:drivers/gpu/drm/drm_lease.c SymbolName:fill_object_idr]
Results: map[Output:32a92f8c8932 Convert more 'alloc_obj' cases to default GFP_KERNEL arguments
69050f8d6d07 treewide: Replace kmalloc with kmalloc_obj for non-scalar types
7bd224b6625a drm/drm_lease: Remove usage of deprecated DRM_DEBUG_LEASE
676f11b5a4a0 drm: clean up unused kerneldoc in drm_lease.c
948de84233d3 drm : Insert blank lines after declarations.
e40b76428842 drm/leases: Drop object_id validation for negative ids
b5f06893c499 drm: Rename crtc_idr as object_idr to KMS cleanups
968029057192 drm/lease: look at ->universal_planes only once
a0c1af46e9d7 drm/lease: debug output for lease creation
7591844c197c drm: Fix kerneldoc warnings for drm_lease
]
|
| 76/2 |
2026/06/15 16:37 |
llm |
fixes-finder |
0m
Model:
Tokens:
input: 8971
output: 33
thoughts: 50
Thoughts: Okay, let's see...
**Checking the Origins of `fill_object_idr`**
Hmm, I have a hunch that this `fill_object_idr` function might be a relatively recent addition. My gut says it showed up around the time we brought in the display lease core changes, specifically the commit with the ID `62884cd386b8` (drm: Add display lease core). Best practice is to verify my assumptions, so I'll go ahead and dig into the history of `drm_lease.c` to confirm or disprove my suspicion. A quick check of the commit history should give me the answer pretty quickly.
|
| 77/2 |
2026/06/15 16:37 |
tool |
git-log |
0m
Args: map[Count:100 PathPrefix:drivers/gpu/drm/drm_lease.c]
Results: map[Output:32a92f8c8932 Convert more 'alloc_obj' cases to default GFP_KERNEL arguments
69050f8d6d07 treewide: Replace kmalloc with kmalloc_obj for non-scalar types
f37d63e219c3 drm_lease.c: copy user-array safely
cde3d37b19df drm: Remove unnecessary include statements for drm_crtc_helper.h
7bd224b6625a drm/drm_lease: Remove usage of deprecated DRM_DEBUG_LEASE
4bb2d367a5a2 drm/lease: allow empty leases
676f11b5a4a0 drm: clean up unused kerneldoc in drm_lease.c
d793b8f732d6 drm: clarify usage of drm leases
56f0729a510f drm: protect drm_master pointers in drm_lease.c
7988fdf5f0a3 drm: Don't include drm_legacy.h in drm_lease.c
948de84233d3 drm : Insert blank lines after declarations.
b216a8e7908c drm/lease: fix WARNING in idr_destroy
c942fddf8793 treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 157
0500c04ea14a drm: drop use of drmP.h in drm/*
46b757780dfe drm/lease: Check for lessor outside of locks
ae9d6c076c0d drm/lease: Drop recursive leads checks
e40b76428842 drm/leases: Drop object_id validation for negative ids
69ef943dbc14 drm: Use array_size() when creating lease
b5f06893c499 drm: Rename crtc_idr as object_idr to KMS cleanups
ce85882860f0 drm/lease: Send a distinct uevent
968029057192 drm/lease: look at ->universal_planes only once
a0c1af46e9d7 drm/lease: debug output for lease creation
6caec6a04717 drm/lease: drop EXPORT_SYMBOL
918d89bb1a63 gpu: drm/lease: fix spelling mistake, EACCESS -> EACCES
12d43deb1ee6 drm: fix use-after-free read in drm_mode_create_lease_ioctl()
69fdf4206a8b drm: Differentiate the lack of an interface from invalid parameter
19f391eb05b8 turn filp_clone_open() into inline wrapper for dentry_open()
b4e7a7a88b5d drm_mode_create_lease_ioctl(): fix open-coded filp_clone_open()
aec06c7606be gpu: drm/lease:: Use list_{next/prev}_entry instead of list_entry
7591844c197c drm: Fix kerneldoc warnings for drm_lease
d2a48e52541c drm: move lease init after validation in drm_lease_create
bd36d3bab2e3 drm/drm_lease: Prevent deadlock in case drm_lease_create() fails
62884cd386b8 drm: Add four ioctls for managing drm mode object leases [v7]
2ed077e467ee drm: Add drm_object lease infrastructure [v5]
]
|
| 78/2 |
2026/06/15 16:37 |
llm |
fixes-finder |
0m
Model:
Tokens:
input: 10069
output: 26
thoughts: 30
Thoughts: Here's my attempt at summarizing the thought process, tailored for an expert audience:
**Analyzing Potential Commit IDs**
Okay, time to get down to it. Let's start by digging into `62884cd386b8` and `2ed077e467ee`. Based on these commit IDs, I'm expecting this analysis to involve a specific code change investigation or log review; likely related to a recent bug report or integration issue. Knowing the context will heavily influence the direction of this analysis. I'll need to pull up the repo and examine the changesets these IDs represent. From there, I'll compare timestamps, delve into the file modifications, and begin debugging or evaluating from a code review perspective. My immediate objective is to ascertain the function, scope, and impact, and determine its potential effect on the system as a whole.
|
| 79/2 |
2026/06/15 16:37 |
tool |
git-show |
0m
Args:
Results: map[Output:commit 62884cd386b876638720ef88374b31a84ca7ee5f
Author: Keith Packard <keithp@keithp.com>
Date: Thu Mar 16 17:56:28 2017 -0700
drm: Add four ioctls for managing drm mode object leases [v7]
drm_mode_create_lease
Creates a lease for a list of drm mode objects, returning an
fd for the new drm_master and a 64-bit identifier for the lessee
drm_mode_list_lesees
List the identifiers of the lessees for a master file
drm_mode_get_lease
List the leased objects for a master file
drm_mode_revoke_lease
Erase the set of objects managed by a lease.
This should suffice to at least create and query leases.
Changes for v2 as suggested by Daniel Vetter <daniel.vetter@ffwll.ch>:
* query ioctls only query the master associated with
the provided file.
* 'mask_lease' value has been removed
* change ioctl has been removed.
Changes for v3 suggested in part by Dave Airlie <airlied@gmail.com>
* Add revoke ioctl.
Changes for v4 suggested by Dave Airlie <airlied@gmail.com>
* Expand on the comment about the magic use of &drm_lease_idr_object
* Pad lease ioctl structures to align on 64-bit boundaries
Changes for v5 suggested by Dave Airlie <airlied@gmail.com>
* Check for non-negative object_id in create_lease to avoid debug
output from the kernel.
Changes for v6 provided by Dave Airlie <airlied@gmail.com>
* For non-universal planes add primary/cursor planes to lease
If we aren't exposing universal planes to this userspace client,
and it requests a lease on a crtc, we should implicitly export the
primary and cursor planes for the crtc.
If the lessee doesn't request universal planes, it will just see
the crtc, but if it does request them it will then see the plane
objects as well.
This also moves the object look ups earlier as a side effect, so
we'd exit the ioctl quicker for non-existant objects.
* Restrict leases to crtc/connector/planes.
This only allows leasing for objects we wish to allow.
Changes for v7 provided by Dave Airlie <airlied@gmail.com>
* Check pad args are 0
* Check create flags and object count are valid.
* Check return from fd allocation
* Refactor lease idr setup and add some simple validation
* Use idr_mutex uniformly (Keith)
Signed-off-by: Keith Packard <keithp@keithp.com>
Signed-off-by: Dave Airlie <airlied@redhat.com>
diff --git a/drivers/gpu/drm/drm_ioctl.c b/drivers/gpu/drm/drm_ioctl.c
index 9c435a4c0c82..4aafe4802099 100644
--- a/drivers/gpu/drm/drm_ioctl.c
+++ b/drivers/gpu/drm/drm_ioctl.c
@@ -665,6 +665,10 @@ static const struct drm_ioctl_desc drm_ioctls[] = {
DRM_UNLOCKED|DRM_RENDER_ALLOW),
DRM_IOCTL_DEF(DRM_IOCTL_CRTC_GET_SEQUENCE, drm_crtc_get_sequence_ioctl, DRM_UNLOCKED),
DRM_IOCTL_DEF(DRM_IOCTL_CRTC_QUEUE_SEQUENCE, drm_crtc_queue_sequence_ioctl, DRM_UNLOCKED),
+ DRM_IOCTL_DEF(DRM_IOCTL_MODE_CREATE_LEASE, drm_mode_create_lease_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+ DRM_IOCTL_DEF(DRM_IOCTL_MODE_LIST_LESSEES, drm_mode_list_lessees_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+ DRM_IOCTL_DEF(DRM_IOCTL_MODE_GET_LEASE, drm_mode_get_lease_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+ DRM_IOCTL_DEF(DRM_IOCTL_MODE_REVOKE_LEASE, drm_mode_revoke_lease_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
};
#define DRM_CORE_IOCTL_COUNT ARRAY_SIZE( drm_ioctls )
diff --git a/drivers/gpu/drm/drm_lease.c b/drivers/gpu/drm/drm_lease.c
index 030db1170570..d1eb56a1eff4 100644
--- a/drivers/gpu/drm/drm_lease.c
+++ b/drivers/gpu/drm/drm_lease.c
@@ -23,6 +23,8 @@
#define drm_for_each_lessee(lessee, lessor) \
list_for_each_entry((lessee), &(lessor)->lessees, lessee_list)
+static uint64_t drm_lease_idr_object;
+
/**
* drm_lease_owner - return ancestor owner drm_master
* @master: drm_master somewhere within tree of lessees and lessors
@@ -353,3 +355,413 @@ void drm_lease_revoke(struct drm_master *top)
_drm_lease_revoke(top);
mutex_unlock(&top->dev->mode_config.idr_mutex);
}
+
+static int validate_lease(struct drm_device *dev,
+ struct drm_file *lessor_priv,
+ int object_count,
+ struct drm_mode_object **objects)
+{
+ int o;
+ int has_crtc = -1;
+ int has_connector = -1;
+ int has_plane = -1;
+
+ /* we want to confirm that there is at least one crtc, plane
+ connector object. */
+
+ for (o = 0; o < object_count; o++) {
+ if (objects[o]->type == DRM_MODE_OBJECT_CRTC && has_crtc == -1) {
+ has_crtc = o;
+ }
+ if (objects[o]->type == DRM_MODE_OBJECT_CONNECTOR && has_connector == -1)
+ has_connector = o;
+
+ if (lessor_priv->universal_planes) {
+ if (objects[o]->type == DRM_MODE_OBJECT_PLANE && has_plane == -1)
+ has_plane = o;
+ }
+ }
+ if (has_crtc == -1 || has_connector == -1)
+ return -EINVAL;
+ if (lessor_priv->universal_planes && has_plane == -1)
+ return -EINVAL;
+ return 0;
+}
+
+static int fill_object_idr(struct drm_device *dev,
+ struct drm_file *lessor_priv,
+ struct idr *leases,
+ int object_count,
+ u32 *object_ids)
+{
+ struct drm_mode_object **objects;
+ u32 o;
+ int ret;
+ objects = kcalloc(object_count, sizeof(struct drm_mode_object *),
+ GFP_KERNEL);
+ if (!objects)
+ return -ENOMEM;
+
+ /* step one - get references to all the mode objects
+ and check for validity. */
+ for (o = 0; o < object_count; o++) {
+ if ((int) object_ids[o] < 0) {
+ ret = -EINVAL;
+ goto out_free_objects;
+ }
+
+ objects[o] = drm_mode_object_find(dev, lessor_priv,
+ object_ids[o],
+ DRM_MODE_OBJECT_ANY);
+ if (!objects[o]) {
+ ret = -ENOENT;
+ goto out_free_objects;
+ }
+
+ if (!drm_mode_object_lease_required(objects[o]->type)) {
+ ret = -EINVAL;
+ goto out_free_objects;
+ }
+ }
+
+ ret = validate_lease(dev, lessor_priv, object_count, objects);
+ if (ret)
+ goto out_free_objects;
+
+ /* add their IDs to the lease request - taking into account
+ universal planes */
+ for (o = 0; o < object_count; o++) {
+ struct drm_mode_object *obj = objects[o];
+ u32 object_id = objects[o]->id;
+ DRM_DEBUG_LEASE("Adding object %d to lease\n", object_id);
+
+ /*
+ * We're using an IDR to hold the set of leased
+ * objects, but we don't need to point at the object's
+ * data structure from the lease as the main crtc_idr
+ * will be used to actually find that. Instead, all we
+ * really want is a 'leased/not-leased' result, for
+ * which any non-NULL pointer will work fine.
+ */
+ ret = idr_alloc(leases, &drm_lease_idr_object , object_id, object_id + 1, GFP_KERNEL);
+ if (ret < 0) {
+ DRM_DEBUG_LEASE("Object %d cannot be inserted into leases (%d)\n",
+ object_id, ret);
+ goto out_free_objects;
+ }
+ if (obj->type == DRM_MODE_OBJECT_CRTC && !lessor_priv->universal_planes) {
+ struct drm_crtc *crtc = obj_to_crtc(obj);
+ ret = idr_alloc(leases, &drm_lease_idr_object, crtc->primary->base.id, crtc->primary->base.id + 1, GFP_KERNEL);
+ if (ret < 0) {
+ DRM_DEBUG_LEASE("Object primary plane %d cannot be inserted into leases (%d)\n",
+ object_id, ret);
+ goto out_free_objects;
+ }
+ if (crtc->cursor) {
+ ret = idr_alloc(leases, &drm_lease_idr_object, crtc->cursor->base.id, crtc->cursor->base.id + 1, GFP_KERNEL);
+ if (ret < 0) {
+ DRM_DEBUG_LEASE("Object cursor plane %d cannot be inserted into leases (%d)\n",
+ object_id, ret);
+ goto out_free_objects;
+ }
+ }
+ }
+ }
+
+ ret = 0;
+out_free_objects:
+ for (o = 0; o < object_count; o++) {
+ if (objects[o])
+ drm_mode_object_put(objects[o]);
+ }
+ kfree(objects);
+ return ret;
+}
+
+/**
+ * drm_mode_create_lease_ioctl - create a new lease
+ * @dev: the drm device
+ * @data: pointer to struct drm_mode_create_lease
+ * @file_priv: the file being manipulated
+ *
+ * The master associated with the specified file will have a lease
+ * created containing the objects specified in the ioctl structure.
+ * A file descriptor will be allocated for that and returned to the
+ * application.
+ */
+int drm_mode_create_lease_ioctl(struct drm_device *dev,
+ void *data, struct drm_file *lessor_priv)
+{
+ struct drm_mode_create_lease *cl = data;
+ size_t object_count;
+ int ret = 0;
+ struct idr leases;
+ struct drm_master *lessor = lessor_priv->master;
+ struct drm_master *lessee = NULL;
+ struct file *lessee_file = NULL;
+ struct file *lessor_file = lessor_priv->filp;
+ struct drm_file *lessee_priv;
+ int fd = -1;
+ uint32_t *object_ids;
+
+ /* Can't lease without MODESET */
+ if (!drm_core_check_feature(dev, DRIVER_MODESET))
+ return -EINVAL;
+
+ /* Do not allow sub-leases */
+ if (lessor->lessor)
+ return -EINVAL;
+
+ /* need some objects */
+ if (cl->object_count == 0)
+ return -EINVAL;
+
+ if (cl->flags && (cl->flags & ~(O_CLOEXEC | O_NONBLOCK)))
+ return -EINVAL;
+
+ object_count = cl->object_count;
+
+ object_ids = memdup_user(u64_to_user_ptr(cl->object_ids), object_count * sizeof(__u32));
+ if (IS_ERR(object_ids))
+ return PTR_ERR(object_ids);
+
+ idr_init(&leases);
+
+ /* fill and validate the object idr */
+ ret = fill_object_idr(dev, lessor_priv, &leases,
+ object_count, object_ids);
+ kfree(object_ids);
+ if (ret) {
+ idr_destroy(&leases);
+ return ret;
+ }
+
+ /* Allocate a file descriptor for the lease */
+ fd = get_unused_fd_flags(cl->flags & (O_CLOEXEC | O_NONBLOCK));
+ if (fd < 0) {
+ idr_destroy(&leases);
+ return fd;
+ }
+
+ DRM_DEBUG_LEASE("Creating lease\n");
+ lessee = drm_lease_create(lessor, &leases);
+
+ if (IS_ERR(lessee)) {
+ ret = PTR_ERR(lessee);
+ goto out_leases;
+ }
+
+ /* Clone the lessor file to create a new file for us */
+ DRM_DEBUG_LEASE("Allocating lease file\n");
+ path_get(&lessor_file->f_path);
+ lessee_file = alloc_file(&lessor_file->f_path,
+ lessor_file->f_mode,
+ fops_get(lessor_file->f_inode->i_fop));
+
+ if (IS_ERR(lessee_file)) {
+ ret = PTR_ERR(lessee_file);
+ goto out_lessee;
+ }
+
+ /* Initialize the new file for DRM */
+ DRM_DEBUG_LEASE("Initializing the file with %p\n", lessee_file->f_op->open);
+ ret = lessee_file->f_op->open(lessee_file->f_inode, lessee_file);
+ if (ret)
+ goto out_lessee_file;
+
+ lessee_priv = lessee_file->private_data;
+
+ /* Change the file to a master one */
+ drm_master_put(&lessee_priv->master);
+ lessee_priv->master = lessee;
+ lessee_priv->is_master = 1;
+ lessee_priv->authenticated = 1;
+
+ /* Hook up the fd */
+ fd_install(fd, lessee_file);
+
+ /* Pass fd back to userspace */
+ DRM_DEBUG_LEASE("Returning fd %d id %d\n", fd, lessee->lessee_id);
+ cl->fd = fd;
+ cl->lessee_id = lessee->lessee_id;
+
+ DRM_DEBUG_LEASE("drm_mode_create_lease_ioctl succeeded\n");
+ return 0;
+
+out_lessee_file:
+ fput(lessee_file);
+
+out_lessee:
+ drm_master_put(&lessee);
+
+out_leases:
+ put_unused_fd(fd);
+ idr_destroy(&leases);
+
+ DRM_DEBUG_LEASE("drm_mode_create_lease_ioctl failed: %d\n", ret);
+ return ret;
+}
+
+/**
+ * drm_mode_list_lessees_ioctl - list lessee ids
+ * @dev: the drm device
+ * @data: pointer to struct drm_mode_list_lessees
+ * @lessor_priv: the file being manipulated
+ *
+ * Starting from the master associated with the specified file,
+ * the master with the provided lessee_id is found, and then
+ * an array of lessee ids associated with leases from that master
+ * are returned.
+ */
+
+int drm_mode_list_lessees_ioctl(struct drm_device *dev,
+ void *data, struct drm_file *lessor_priv)
+{
+ struct drm_mode_list_lessees *arg = data;
+ __u32 __user *lessee_ids = (__u32 __user *) (uintptr_t) (arg->lessees_ptr);
+ __u32 count_lessees = arg->count_lessees;
+ struct drm_master *lessor = lessor_priv->master, *lessee;
+ int count;
+ int ret = 0;
+
+ if (arg->pad)
+ return -EINVAL;
+
+ /* Can't lease without MODESET */
+ if (!drm_core_check_feature(dev, DRIVER_MODESET))
+ return -EINVAL;
+
+ DRM_DEBUG_LEASE("List lessees for %d\n", lessor->lessee_id);
+
+ mutex_lock(&dev->mode_config.idr_mutex);
+
+ count = 0;
+ drm_for_each_lessee(lessee, lessor) {
+ /* Only list un-revoked leases */
+ if (!idr_is_empty(&lessee->leases)) {
+ if (count_lessees > count) {
+ DRM_DEBUG_LEASE("Add lessee %d\n", lessee->lessee_id);
+ ret = put_user(lessee->lessee_id, lessee_ids + count);
+ if (ret)
+ break;
+ }
+ count++;
+ }
+ }
+
+ DRM_DEBUG_LEASE("Lessor leases to %d\n", count);
+ if (ret == 0)
+ arg->count_lessees = count;
+
+ mutex_unlock(&dev->mode_config.idr_mutex);
+
+ return ret;
+}
+
+/**
+ * drm_mode_get_lease_ioctl - list leased objects
+ * @dev: the drm device
+ * @data: pointer to struct drm_mode_get_lease
+ * @file_priv: the file being manipulated
+ *
+ * Return the list of leased objects for the specified lessee
+ */
+
+int drm_mode_get_lease_ioctl(struct drm_device *dev,
+ void *data, struct drm_file *lessee_priv)
+{
+ struct drm_mode_get_lease *arg = data;
+ __u32 __user *object_ids = (__u32 __user *) (uintptr_t) (arg->objects_ptr);
+ __u32 count_objects = arg->count_objects;
+ struct drm_master *lessee = lessee_priv->master;
+ struct idr *object_idr;
+ int count;
+ void *entry;
+ int object;
+ int ret = 0;
+
+ if (arg->pad)
+ return -EINVAL;
+
+ /* Can't lease without MODESET */
+ if (!drm_core_check_feature(dev, DRIVER_MODESET))
+ return -EINVAL;
+
+ DRM_DEBUG_LEASE("get lease for %d\n", lessee->lessee_id);
+
+ mutex_lock(&dev->mode_config.idr_mutex);
+
+ if (lessee->lessor == NULL)
+ /* owner can use all objects */
+ object_idr = &lessee->dev->mode_config.crtc_idr;
+ else
+ /* lessee can only use allowed object */
+ object_idr = &lessee->leases;
+
+ count = 0;
+ idr_for_each_entry(object_idr, entry, object) {
+ if (count_objects > count) {
+ DRM_DEBUG_LEASE("adding object %d\n", object);
+ ret = put_user(object, object_ids + count);
+ if (ret)
+ break;
+ }
+ count++;
+ }
+
+ DRM_DEBUG("lease holds %d objects\n", count);
+ if (ret == 0)
+ arg->count_objects = count;
+
+ mutex_unlock(&dev->mode_config.idr_mutex);
+
+ return ret;
+}
+
+/**
+ * drm_mode_revoke_lease_ioctl - revoke lease
+ * @dev: the drm device
+ * @data: pointer to struct drm_mode_revoke_lease
+ * @file_priv: the file being manipulated
+ *
+ * This removes all of the objects from the lease without
+ * actually getting rid of the lease itself; that way all
+ * references to it still work correctly
+ */
+int drm_mode_revoke_lease_ioctl(struct drm_device *dev,
+ void *data, struct drm_file *lessor_priv)
+{
+ struct drm_mode_revoke_lease *arg = data;
+ struct drm_master *lessor = lessor_priv->master;
+ struct drm_master *lessee;
+ int ret = 0;
+
+ DRM_DEBUG_LEASE("revoke lease for %d\n", arg->lessee_id);
+
+ /* Can't lease without MODESET */
+ if (!drm_core_check_feature(dev, DRIVER_MODESET))
+ return -EINVAL;
+
+ mutex_lock(&dev->mode_config.idr_mutex);
+
+ lessee = _drm_find_lessee(lessor, arg->lessee_id);
+
+ /* No such lessee */
+ if (!lessee) {
+ ret = -ENOENT;
+ goto fail;
+ }
+
+ /* Lease is not held by lessor */
+ if (lessee->lessor != lessor) {
+ ret = -EACCES;
+ goto fail;
+ }
+
+ _drm_lease_revoke(lessee);
+
+fail:
+ mutex_unlock(&dev->mode_config.idr_mutex);
+
+ return ret;
+}
diff --git a/drivers/gpu/drm/drm_mode_object.c b/drivers/gpu/drm/drm_mode_object.c
index d1599f36b605..7c8b2698c6a7 100644
--- a/drivers/gpu/drm/drm_mode_object.c
+++ b/drivers/gpu/drm/drm_mode_object.c
@@ -111,7 +111,7 @@ void drm_mode_object_unregister(struct drm_device *dev,
* Returns whether the provided type of drm_mode_object must
* be owned or leased to be used by a process.
*/
-static bool drm_lease_required(uint32_t type)
+bool drm_mode_object_lease_required(uint32_t type)
{
switch(type) {
case DRM_MODE_OBJECT_CRTC:
@@ -136,7 +136,8 @@ struct drm_mode_object *__drm_mode_object_find(struct drm_device *dev,
if (obj && obj->id != id)
obj = NULL;
- if (obj && drm_lease_required(obj->type) && !_drm_lease_held(file_priv, obj->id))
+ if (obj && drm_mode_object_lease_required(obj->type) &&
+ !_drm_lease_held(file_priv, obj->id))
obj = NULL;
if (obj && obj->free_cb) {
diff --git a/include/drm/drm_lease.h b/include/drm/drm_lease.h
index 6149e56ddbf3..fbc0ab54855b 100644
--- a/include/drm/drm_lease.h
+++ b/include/drm/drm_lease.h
@@ -31,4 +31,16 @@ void drm_lease_revoke(struct drm_master *master);
uint32_t drm_lease_filter_crtcs(struct drm_file *file_priv, uint32_t crtcs);
+int drm_mode_create_lease_ioctl(struct drm_device *dev,
+ void *data, struct drm_file *file_priv);
+
+int drm_mode_list_lessees_ioctl(struct drm_device *dev,
+ void *data, struct drm_file *file_priv);
+
+int drm_mode_get_lease_ioctl(struct drm_device *dev,
+ void *data, struct drm_file *file_priv);
+
+int drm_mode_revoke_lease_ioctl(struct drm_device *dev,
+ void *data, struct drm_file *file_priv);
+
#endif /* _DRM_LEASE_H_ */
diff --git a/include/drm/drm_mode_object.h b/include/drm/drm_mode_object.h
index c8155cb5a932..7ba3913f30b5 100644
--- a/include/drm/drm_mode_object.h
+++ b/include/drm/drm_mode_object.h
@@ -154,4 +154,6 @@ int drm_object_property_get_value(struct drm_mode_object *obj,
void drm_object_attach_property(struct drm_mode_object *obj,
struct drm_property *property,
uint64_t init_val);
+
+bool drm_mode_object_lease_required(uint32_t type);
#endif
diff --git a/include/uapi/drm/drm.h b/include/uapi/drm/drm.h
index 91d83c1747c0..6fdff5945c8a 100644
--- a/include/uapi/drm/drm.h
+++ b/include/uapi/drm/drm.h
@@ -888,6 +888,11 @@ extern "C" {
#define DRM_IOCTL_SYNCOBJ_RESET DRM_IOWR(0xC4, struct drm_syncobj_array)
#define DRM_IOCTL_SYNCOBJ_SIGNAL DRM_IOWR(0xC5, struct drm_syncobj_array)
+#define DRM_IOCTL_MODE_CREATE_LEASE DRM_IOWR(0xC6, struct drm_mode_create_lease)
+#define DRM_IOCTL_MODE_LIST_LESSEES DRM_IOWR(0xC7, struct drm_mode_list_lessees)
+#define DRM_IOCTL_MODE_GET_LEASE DRM_IOWR(0xC8, struct drm_mode_get_lease)
+#define DRM_IOCTL_MODE_REVOKE_LEASE DRM_IOWR(0xC9, struct drm_mode_revoke_lease)
+
/**
* Device specific ioctls should only be in their respective headers
* The device specific ioctl range is from 0x40 to 0x9f.
diff --git a/include/uapi/drm/drm_mode.h b/include/uapi/drm/drm_mode.h
index 34b6bb34b002..5597a87154e5 100644
--- a/include/uapi/drm/drm_mode.h
+++ b/include/uapi/drm/drm_mode.h
@@ -782,6 +782,72 @@ struct drm_mode_destroy_blob {
__u32 blob_id;
};
+/**
+ * Lease mode resources, creating another drm_master.
+ */
+struct drm_mode_create_lease {
+ /** Pointer to array of object ids (__u32) */
+ __u64 object_ids;
+ /** Number of object ids */
+ __u32 object_count;
+ /** flags for new FD (O_CLOEXEC, etc) */
+ __u32 flags;
+
+ /** Return: unique identifier for lessee. */
+ __u32 lessee_id;
+ /** Return: file descriptor to new drm_master file */
+ __u32 fd;
+};
+
+/**
+ * List lesses from a drm_master
+ */
+struct drm_mode_list_lessees {
+ /** Number of lessees.
+ * On input, provides length of the array.
+ * On output, provides total number. No
+ * more than the input number will be written
+ * back, so two calls can be used to get
+ * the size and then the data.
+ */
+ __u32 count_lessees;
+ __u32 pad;
+
+ /** Pointer to lessees.
+ * pointer to __u64 array of lessee ids
+ */
+ __u64 lessees_ptr;
+};
+
+/**
+ * Get leased objects
+ */
+struct drm_mode_get_lease {
+ /** Number of leased objects.
+ * On input, provides length of the array.
+ * On output, provides total number. No
+ * more than the input number will be written
+ * back, so two calls can be used to get
+ * the size and then the data.
+ */
+ __u32 count_objects;
+ __u32 pad;
+
+ /** Pointer to objects.
+ * pointer to __u32 array of object ids
+ */
+ __u64 objects_ptr;
+};
+
+/**
+ * Revoke lease
+ */
+struct drm_mode_revoke_lease {
+ /** Unique ID of lessee
+ */
+ __u32 lessee_id;
+};
+
#if defined(__cplusplus)
}
#endif
]
|
| 80/2 |
2026/06/15 16:37 |
llm |
fixes-finder |
0m
Model:
Tokens:
input: 18149
output: 55
thoughts: 349
Thoughts: **Analyzing a Potential Kernel Crash**
Okay, so this commit, `62884cd386b8`, added `drm_mode_create_lease_ioctl` and `fill_object_idr`. I see that `fill_object_idr` uses `kcalloc` to allocate memory for `objects`, which seems straightforward enough. But then in `drm_mode_create_lease_ioctl`, there's a `memdup_user` call to allocate `object_ids`. Hmm, the bug report says this is related to an unbounded memory allocation based on a user-controlled value causing a crash, and that sounds like a potential issue here.
Let me think… `memdup_user` is the culprit. And the report says it’s trying to allocate a chunk larger than `KMALLOC_MAX_SIZE`, which triggers a warning from the page allocator, leading to the crash. I know `memdup_user` uses `kmalloc_track_caller`, which by default, doesn't use `__GFP_NOWARN`. So, a failure would be reported. But if it does exceed `KMALLOC_MAX_SIZE`, a warning would be generated, which is exactly what the report says is happening.
The code seems to indicate that the `object_count` comes from user-supplied data, which makes it vulnerable. The use of `memdup_user` with a user-controlled `object_count`... yeah, that's a classic vulnerability pattern. The use of `memdup_array_user` may have been introduced to address this, so I need to check when it was introduced to the `drm_lease.c` file.
|
| 81/2 |
2026/06/15 16:37 |
tool |
git-log |
0m
Args: map[CodeRegexp:memdup_array_user SourcePath:drivers/gpu/drm/drm_lease.c SymbolName:drm_mode_create_lease_ioctl]
Results: map[Output:f37d63e219c3 drm_lease.c: copy user-array safely
7bd224b6625a drm/drm_lease: Remove usage of deprecated DRM_DEBUG_LEASE
4bb2d367a5a2 drm/lease: allow empty leases
56f0729a510f drm: protect drm_master pointers in drm_lease.c
b216a8e7908c drm/lease: fix WARNING in idr_destroy
69ef943dbc14 drm: Use array_size() when creating lease
d7563c55ef9f Merge tag 'drm-misc-next-2018-11-07' of git://anongit.freedesktop.org/drm/drm-misc into drm-next
a0c1af46e9d7 drm/lease: debug output for lease creation
53b3b6bbfde6 Merge tag 'drm-next-2018-10-24' of git://anongit.freedesktop.org/drm/drm
69fdf4206a8b drm: Differentiate the lack of an interface from invalid parameter
]
|
| 82/2 |
2026/06/15 16:38 |
llm |
fixes-finder |
0m
Model:
Tokens:
input: 19208
output: 27
thoughts: 30
Thoughts: Okay, here's my interpretation of those thoughts, tailored for an expert audience, presented in the first person:
**Quick Check: Hash Identifiers**
Right, let's take a quick look at `f37d63e219c3` and `69ef943dbc14`. Given the typical workflow, my immediate assumption is that these are either commit hashes, file hashes (potentially checksums), or identifiers from a system I'm familiar with. I need more context to be certain, but the structure suggests they're likely related to version control or data integrity. My first instinct is to run a quick `git log -p` or a `find /path/to/files -print0 | xargs -0 shasum -a 256` to check the context of each, depending on the environment. I'll need to confirm what the underlying system is to decide the best path to investigate, likely checking the logs to understand what these identifiers relate to. My gut tells me these identifiers are key to understanding the next step. Let's see what they reveal.
|
| 83/2 |
2026/06/15 16:38 |
tool |
git-show |
0m
Args:
Results: map[Output:commit f37d63e219c39199a59b8b8a211412ff27192830
Author: Philipp Stanner <pstanner@redhat.com>
Date: Wed Sep 20 14:36:12 2023 +0200
drm_lease.c: copy user-array safely
Currently, there is no overflow-check with memdup_user().
Use the new function memdup_array_user() instead of memdup_user() for
duplicating the user-space array safely.
Suggested-by: David Airlie <airlied@redhat.com>
Signed-off-by: Philipp Stanner <pstanner@redhat.com>
Reviewed-by: Kees Cook <keescook@chromium.org>
Reviewed-by: Zack Rusin <zackr@vmware.com>
Signed-off-by: Dave Airlie <airlied@redhat.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20230920123612.16914-6-pstanner@redhat.com
diff --git a/drivers/gpu/drm/drm_lease.c b/drivers/gpu/drm/drm_lease.c
index 150fe1555068..94375c6a5425 100644
--- a/drivers/gpu/drm/drm_lease.c
+++ b/drivers/gpu/drm/drm_lease.c
@@ -510,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_user(u64_to_user_ptr(cl->object_ids),
- array_size(object_count, sizeof(__u32)));
+ object_ids = memdup_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);
]
|
| 84/2 |
2026/06/15 16:38 |
llm |
fixes-finder |
0m
Model:
Tokens:
input: 20096
output: 27
thoughts: 214
Thoughts: **Unraveling a Kernel Crash: An Expert's Perspective**
Okay, so I'm looking at this kernel crash report and the first thing that jumps out is that it's due to an unbounded memory allocation. It looks like the code in question is trying to allocate a contiguous chunk of memory that's exceeding the maximum size the slab allocator (`KMALLOC_MAX_SIZE`) can handle, which is, of course, a big no-no. We're getting a warning from the page allocator which is triggering the crash.
The report specifically points the finger at the commit `62884cd386b8`. Ah yes, the one that introduces those new ioctls for managing DRM mode object leases. Let's dig in a bit further to see exactly *where* it's happening. The report mentions `memdup_user` and `kcalloc` which I'll bet are the culprits. That `object_ids = memdup_user` line looks particularly dicey. Taking user input to determine the amount of allocation with no bounds.
I need to confirm that `kzalloc_objs` wasn't added *after* that commit. Gotta make sure we're getting the root cause right and not just a symptom of a later change.
|
| 85/2 |
2026/06/15 16:38 |
tool |
git-show |
0m
Args:
Results: map[Output:
Full output is too long, showing 1000 out of 192786 lines.
[commit 69050f8d6d075dc01af7a5f2f550a8067510366f
Author: Kees Cook <kees@kernel.org>
Date: Fri Feb 20 23:49:23 2026 -0800
treewide: Replace kmalloc with kmalloc_obj for non-scalar types
This is the result of running the Coccinelle script from
scripts/coccinelle/api/kmalloc_objs.cocci. The script is designed to
avoid scalar types (which need careful case-by-case checking), and
instead replace kmalloc-family calls that allocate struct or union
object instances:
Single allocations: kmalloc(sizeof(TYPE), ...)
are replaced with: kmalloc_obj(TYPE, ...)
Array allocations: kmalloc_array(COUNT, sizeof(TYPE), ...)
are replaced with: kmalloc_objs(TYPE, COUNT, ...)
Flex array allocations: kmalloc(struct_size(PTR, FAM, COUNT), ...)
are replaced with: kmalloc_flex(*PTR, FAM, COUNT, ...)
(where TYPE may also be *VAR)
The resulting allocations no longer return "void *", instead returning
"TYPE *".
Signed-off-by: Kees Cook <kees@kernel.org>
diff --git a/arch/alpha/kernel/core_marvel.c b/arch/alpha/kernel/core_marvel.c
index d38f4d6759e4..b5b547732398 100644
--- a/arch/alpha/kernel/core_marvel.c
+++ b/arch/alpha/kernel/core_marvel.c
@@ -861,7 +861,7 @@ marvel_agp_setup(alpha_agp_info *agp)
if (!alpha_agpgart_size)
return -ENOMEM;
- aper = kmalloc(sizeof(*aper), GFP_KERNEL);
+ aper = kmalloc_obj(*aper, GFP_KERNEL);
if (aper == NULL) return -ENOMEM;
aper->arena = agp->hose->sg_pci;
@@ -1059,7 +1059,7 @@ marvel_agp_info(void)
/*
* Allocate the info structure.
*/
- agp = kmalloc(sizeof(*agp), GFP_KERNEL);
+ agp = kmalloc_obj(*agp, GFP_KERNEL);
if (!agp)
return NULL;
diff --git a/arch/alpha/kernel/core_titan.c b/arch/alpha/kernel/core_titan.c
index 77f5d68ed04b..ddaef7b75ba7 100644
--- a/arch/alpha/kernel/core_titan.c
+++ b/arch/alpha/kernel/core_titan.c
@@ -594,7 +594,7 @@ titan_agp_setup(alpha_agp_info *agp)
if (!alpha_agpgart_size)
return -ENOMEM;
- aper = kmalloc(sizeof(struct titan_agp_aperture), GFP_KERNEL);
+ aper = kmalloc_obj(struct titan_agp_aperture, GFP_KERNEL);
if (aper == NULL)
return -ENOMEM;
@@ -760,7 +760,7 @@ titan_agp_info(void)
/*
* Allocate the info structure.
*/
- agp = kmalloc(sizeof(*agp), GFP_KERNEL);
+ agp = kmalloc_obj(*agp, GFP_KERNEL);
if (!agp)
return NULL;
diff --git a/arch/alpha/kernel/module.c b/arch/alpha/kernel/module.c
index cbefa5a77384..6fbc2d179e93 100644
--- a/arch/alpha/kernel/module.c
+++ b/arch/alpha/kernel/module.c
@@ -46,7 +46,7 @@ process_reloc_for_got(Elf64_Rela *rela,
goto found_entry;
}
- g = kmalloc (sizeof (*g), GFP_KERNEL);
+ g = kmalloc_obj(*g, GFP_KERNEL);
g->next = chains[r_sym].next;
g->r_addend = r_addend;
g->got_offset = *poffset;
@@ -93,7 +93,7 @@ module_frob_arch_sections(Elf64_Ehdr *hdr, Elf64_Shdr *sechdrs,
}
nsyms = symtab->sh_size / sizeof(Elf64_Sym);
- chains = kcalloc(nsyms, sizeof(struct got_entry), GFP_KERNEL);
+ chains = kzalloc_objs(struct got_entry, nsyms, GFP_KERNEL);
if (!chains) {
printk(KERN_ERR
"module %s: no memory for symbol chain buffer\n",
diff --git a/arch/alpha/kernel/pci.c b/arch/alpha/kernel/pci.c
index 8e9b4ac86b7e..93eb07018e6b 100644
--- a/arch/alpha/kernel/pci.c
+++ b/arch/alpha/kernel/pci.c
@@ -220,7 +220,7 @@ static void pdev_save_srm_config(struct pci_dev *dev)
printed = 1;
}
- tmp = kmalloc(sizeof(*tmp), GFP_KERNEL);
+ tmp = kmalloc_obj(*tmp, GFP_KERNEL);
if (!tmp) {
printk(KERN_ERR "%s: kmalloc() failed!\n", __func__);
return;
diff --git a/arch/alpha/kernel/setup.c b/arch/alpha/kernel/setup.c
index f0af444a69a4..ea4e7243c0e9 100644
--- a/arch/alpha/kernel/setup.c
+++ b/arch/alpha/kernel/setup.c
@@ -392,7 +392,7 @@ register_cpus(void)
int i;
for_each_possible_cpu(i) {
- struct cpu *p = kzalloc(sizeof(*p), GFP_KERNEL);
+ struct cpu *p = kzalloc_obj(*p, GFP_KERNEL);
if (!p)
return -ENOMEM;
register_cpu(p, i);
diff --git a/arch/arc/kernel/unwind.c b/arch/arc/kernel/unwind.c
index 789cfb9ea14e..dcdc8bd916db 100644
--- a/arch/arc/kernel/unwind.c
+++ b/arch/arc/kernel/unwind.c
@@ -366,7 +366,7 @@ void *unwind_add_table(struct module *module, const void *table_start,
if (table_size <= 0)
return NULL;
- table = kmalloc(sizeof(*table), GFP_KERNEL);
+ table = kmalloc_obj(*table, GFP_KERNEL);
if (!table)
return NULL;
diff --git a/arch/arc/net/bpf_jit_core.c b/arch/arc/net/bpf_jit_core.c
index e3628922c24a..5695da795536 100644
--- a/arch/arc/net/bpf_jit_core.c
+++ b/arch/arc/net/bpf_jit_core.c
@@ -1140,7 +1140,7 @@ static int jit_prepare_final_mem_alloc(struct jit_context *ctx)
}
if (ctx->need_extra_pass) {
- ctx->jit_data = kzalloc(sizeof(*ctx->jit_data), GFP_KERNEL);
+ ctx->jit_data = kzalloc_obj(*ctx->jit_data, GFP_KERNEL);
if (!ctx->jit_data)
return -ENOMEM;
}
diff --git a/arch/arm/common/locomo.c b/arch/arm/common/locomo.c
index cb6ef449b987..4820b1094dfa 100644
--- a/arch/arm/common/locomo.c
+++ b/arch/arm/common/locomo.c
@@ -222,7 +222,7 @@ locomo_init_one_child(struct locomo *lchip, struct locomo_dev_info *info)
struct locomo_dev *dev;
int ret;
- dev = kzalloc(sizeof(struct locomo_dev), GFP_KERNEL);
+ dev = kzalloc_obj(struct locomo_dev, GFP_KERNEL);
if (!dev) {
ret = -ENOMEM;
goto out;
@@ -277,7 +277,7 @@ static int locomo_suspend(struct platform_device *dev, pm_message_t state)
struct locomo_save_data *save;
unsigned long flags;
- save = kmalloc(sizeof(struct locomo_save_data), GFP_KERNEL);
+ save = kmalloc_obj(struct locomo_save_data, GFP_KERNEL);
if (!save)
return -ENOMEM;
@@ -360,7 +360,7 @@ __locomo_probe(struct device *me, struct resource *mem, int irq)
unsigned long r;
int i, ret = -ENODEV;
- lchip = kzalloc(sizeof(struct locomo), GFP_KERNEL);
+ lchip = kzalloc_obj(struct locomo, GFP_KERNEL);
if (!lchip)
return -ENOMEM;
diff --git a/arch/arm/common/sa1111.c b/arch/arm/common/sa1111.c
index 04ff75dcc20e..8bd217789439 100644
--- a/arch/arm/common/sa1111.c
+++ b/arch/arm/common/sa1111.c
@@ -737,7 +737,7 @@ sa1111_init_one_child(struct sa1111 *sachip, struct resource *parent,
unsigned i;
int ret;
- dev = kzalloc(sizeof(struct sa1111_dev), GFP_KERNEL);
+ dev = kzalloc_obj(struct sa1111_dev, GFP_KERNEL);
if (!dev) {
ret = -ENOMEM;
goto err_alloc;
@@ -969,7 +969,7 @@ static int sa1111_suspend_noirq(struct device *dev)
unsigned int val;
void __iomem *base;
- save = kmalloc(sizeof(struct sa1111_save_data), GFP_KERNEL);
+ save = kmalloc_obj(struct sa1111_save_data, GFP_KERNEL);
if (!save)
return -ENOMEM;
sachip->saved_state = save;
diff --git a/arch/arm/common/scoop.c b/arch/arm/common/scoop.c
index dddb73c96826..10e8e9716bd3 100644
--- a/arch/arm/common/scoop.c
+++ b/arch/arm/common/scoop.c
@@ -185,7 +185,7 @@ static int scoop_probe(struct platform_device *pdev)
if (!mem)
return -EINVAL;
- devptr = kzalloc(sizeof(struct scoop_dev), GFP_KERNEL);
+ devptr = kzalloc_obj(struct scoop_dev, GFP_KERNEL);
if (!devptr)
return -ENOMEM;
diff --git a/arch/arm/kernel/atags_proc.c b/arch/arm/kernel/atags_proc.c
index cd09f8ab93e3..6106385d25a0 100644
--- a/arch/arm/kernel/atags_proc.c
+++ b/arch/arm/kernel/atags_proc.c
@@ -54,7 +54,7 @@ static int __init init_atags_procfs(void)
WARN_ON(tag->hdr.tag != ATAG_NONE);
- b = kmalloc(struct_size(b, data, size), GFP_KERNEL);
+ b = kmalloc_flex(*b, data, size, GFP_KERNEL);
if (!b)
goto nomem;
diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c
index 50999886a8b5..504f22b420a8 100644
--- a/arch/arm/kernel/smp.c
+++ b/arch/arm/kernel/smp.c
@@ -108,7 +108,7 @@ static unsigned long get_arch_pgd(pgd_t *pgd)
static int secondary_biglittle_prepare(unsigned int cpu)
{
if (!cpu_vtable[cpu])
- cpu_vtable[cpu] = kzalloc(sizeof(*cpu_vtable[cpu]), GFP_KERNEL);
+ cpu_vtable[cpu] = kzalloc_obj(*cpu_vtable[cpu], GFP_KERNEL);
return cpu_vtable[cpu] ? 0 : -ENOMEM;
}
diff --git a/arch/arm/kernel/sys_oabi-compat.c b/arch/arm/kernel/sys_oabi-compat.c
index 2944721e82a2..fe73d759d078 100644
--- a/arch/arm/kernel/sys_oabi-compat.c
+++ b/arch/arm/kernel/sys_oabi-compat.c
@@ -349,7 +349,7 @@ asmlinkage long sys_oabi_semtimedop(int semid,
return -E2BIG;
if (nsops < 1 || nsops > SEMOPM)
return -EINVAL;
- sops = kvmalloc_array(nsops, sizeof(*sops), GFP_KERNEL);
+ sops = kvmalloc_objs(*sops, nsops, GFP_KERNEL);
if (!sops)
return -ENOMEM;
err = 0;
diff --git a/arch/arm/kernel/unwind.c b/arch/arm/kernel/unwind.c
index f60547dadc93..2b40c22234a9 100644
--- a/arch/arm/kernel/unwind.c
+++ b/arch/arm/kernel/unwind.c
@@ -574,7 +574,7 @@ struct unwind_table *unwind_table_add(unsigned long start, unsigned long size,
unsigned long text_size)
{
unsigned long flags;
- struct unwind_table *tab = kmalloc(sizeof(*tab), GFP_KERNEL);
+ struct unwind_table *tab = kmalloc_obj(*tab, GFP_KERNEL);
pr_debug("%s(%08lx, %08lx, %08lx, %08lx)\n", __func__, start, size,
text_addr, text_size);
diff --git a/arch/arm/kernel/vdso.c b/arch/arm/kernel/vdso.c
index 0108f33d6bed..884f1899dfba 100644
--- a/arch/arm/kernel/vdso.c
+++ b/arch/arm/kernel/vdso.c
@@ -179,8 +179,7 @@ static int __init vdso_init(void)
text_pages = (vdso_end - vdso_start) >> PAGE_SHIFT;
/* Allocate the VDSO text pagelist */
- vdso_text_pagelist = kcalloc(text_pages, sizeof(struct page *),
- GFP_KERNEL);
+ vdso_text_pagelist = kzalloc_objs(struct page *, text_pages, GFP_KERNEL);
if (vdso_text_pagelist == NULL)
return -ENOMEM;
diff --git a/arch/arm/mach-footbridge/dc21285.c b/arch/arm/mach-footbridge/dc21285.c
index 6521ab3d24fa..765a97a30b8a 100644
--- a/arch/arm/mach-footbridge/dc21285.c
+++ b/arch/arm/mach-footbridge/dc21285.c
@@ -262,7 +262,7 @@ int __init dc21285_setup(int nr, struct pci_sys_data *sys)
{
struct resource *res;
- res = kcalloc(2, sizeof(struct resource), GFP_KERNEL);
+ res = kzalloc_objs(struct resource, 2, GFP_KERNEL);
if (!res) {
printk("out of memory for root bus resources");
return 0;
diff --git a/arch/arm/mach-footbridge/ebsa285.c b/arch/arm/mach-footbridge/ebsa285.c
index 21cf9a358b90..d75fc4b541f1 100644
--- a/arch/arm/mach-footbridge/ebsa285.c
+++ b/arch/arm/mach-footbridge/ebsa285.c
@@ -84,7 +84,7 @@ static int __init ebsa285_leds_init(void)
for (i = 0; i < ARRAY_SIZE(ebsa285_leds); i++) {
struct ebsa285_led *led;
- led = kzalloc(sizeof(*led), GFP_KERNEL);
+ led = kzalloc_obj(*led, GFP_KERNEL);
if (!led)
break;
diff --git a/arch/arm/mach-footbridge/netwinder-hw.c b/arch/arm/mach-footbridge/netwinder-hw.c
index 5f7265b1b34c..ae5cf7f1f74a 100644
--- a/arch/arm/mach-footbridge/netwinder-hw.c
+++ b/arch/arm/mach-footbridge/netwinder-hw.c
@@ -727,7 +727,7 @@ static int __init netwinder_leds_init(void)
for (i = 0; i < ARRAY_SIZE(netwinder_leds); i++) {
struct netwinder_led *led;
- led = kzalloc(sizeof(*led), GFP_KERNEL);
+ led = kzalloc_obj(*led, GFP_KERNEL);
if (!led)
break;
diff --git a/arch/arm/mach-imx/mmdc.c b/arch/arm/mach-imx/mmdc.c
index 94e4f4a2f73f..d1d1ef3aa927 100644
--- a/arch/arm/mach-imx/mmdc.c
+++ b/arch/arm/mach-imx/mmdc.c
@@ -477,7 +477,7 @@ static int imx_mmdc_perf_init(struct platform_device *pdev, void __iomem *mmdc_b
char *name;
int ret;
- pmu_mmdc = kzalloc(sizeof(*pmu_mmdc), GFP_KERNEL);
+ pmu_mmdc = kzalloc_obj(*pmu_mmdc, GFP_KERNEL);
if (!pmu_mmdc) {
pr_err("failed to allocate PMU device!\n");
return -ENOMEM;
diff --git a/arch/arm/mach-mvebu/board-v7.c b/arch/arm/mach-mvebu/board-v7.c
index 04ad651d13a0..f7f142d6e49e 100644
--- a/arch/arm/mach-mvebu/board-v7.c
+++ b/arch/arm/mach-mvebu/board-v7.c
@@ -127,7 +127,7 @@ static void __init i2c_quirk(void)
for_each_compatible_node(np, NULL, "marvell,mv78230-i2c") {
struct property *new_compat;
- new_compat = kzalloc(sizeof(*new_compat), GFP_KERNEL);
+ new_compat = kzalloc_obj(*new_compat, GFP_KERNEL);
new_compat->name = kstrdup("compatible", GFP_KERNEL);
new_compat->length = sizeof("marvell,mv78230-a0-i2c");
diff --git a/arch/arm/mach-mvebu/coherency.c b/arch/arm/mach-mvebu/coherency.c
index a6b621ff0b87..4af0df12f654 100644
--- a/arch/arm/mach-mvebu/coherency.c
+++ b/arch/arm/mach-mvebu/coherency.c
@@ -190,7 +190,7 @@ static void __init armada_375_380_coherency_init(struct device_node *np)
for_each_compatible_node(cache_dn, NULL, "arm,pl310-cache") {
struct property *p;
- p = kzalloc(sizeof(*p), GFP_KERNEL);
+ p = kzalloc_obj(*p, GFP_KERNEL);
p->name = kstrdup("arm,io-coherent", GFP_KERNEL);
of_add_property(cache_dn, p);
}
diff --git a/arch/arm/mach-mvebu/mvebu-soc-id.c b/arch/arm/mach-mvebu/mvebu-soc-id.c
index f436c7b8c7ae..ea4159a5b567 100644
--- a/arch/arm/mach-mvebu/mvebu-soc-id.c
+++ b/arch/arm/mach-mvebu/mvebu-soc-id.c
@@ -154,7 +154,7 @@ static int __init mvebu_soc_device(void)
if (!is_id_valid)
return 0;
- soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL);
+ soc_dev_attr = kzalloc_obj(*soc_dev_attr, GFP_KERNEL);
if (!soc_dev_attr)
return -ENOMEM;
diff --git a/arch/arm/mach-mxs/mach-mxs.c b/arch/arm/mach-mxs/mach-mxs.c
index 6e017fa306c8..24dd8a0c6567 100644
--- a/arch/arm/mach-mxs/mach-mxs.c
+++ b/arch/arm/mach-mxs/mach-mxs.c
@@ -387,7 +387,7 @@ static void __init mxs_machine_init(void)
const u32 *ocotp = mxs_get_ocotp();
int ret;
- soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL);
+ soc_dev_attr = kzalloc_obj(*soc_dev_attr, GFP_KERNEL);
if (!soc_dev_attr)
return;
diff --git a/arch/arm/mach-omap1/dma.c b/arch/arm/mach-omap1/dma.c
index 756966cb715f..491254010c0c 100644
--- a/arch/arm/mach-omap1/dma.c
+++ b/arch/arm/mach-omap1/dma.c
@@ -319,7 +319,7 @@ static int __init omap1_system_dma_init(void)
goto exit_iounmap;
}
- d = kzalloc(sizeof(*d), GFP_KERNEL);
+ d = kzalloc_obj(*d, GFP_KERNEL);
if (!d) {
ret = -ENOMEM;
goto exit_iounmap;
diff --git a/arch/arm/mach-omap1/mcbsp.c b/arch/arm/mach-omap1/mcbsp.c
index 37863bdce9ea..a4dae1baae99 100644
--- a/arch/arm/mach-omap1/mcbsp.c
+++ b/arch/arm/mach-omap1/mcbsp.c
@@ -294,8 +294,8 @@ static void omap_mcbsp_register_board_cfg(struct resource *res, int res_count,
{
int i;
- omap_mcbsp_devices = kcalloc(size, sizeof(struct platform_device *),
- GFP_KERNEL);
+ omap_mcbsp_devices = kzalloc_objs(struct platform_device *, size,
+ GFP_KERNEL);
if (!omap_mcbsp_devices) {
printk(KERN_ERR "Could not register McBSP devices\n");
return;
diff --git a/arch/arm/mach-omap1/timer.c b/arch/arm/mach-omap1/timer.c
index 81a912c1145a..09dab51d5728 100644
--- a/arch/arm/mach-omap1/timer.c
+++ b/arch/arm/mach-omap1/timer.c
@@ -125,7 +125,7 @@ static int __init omap1_dm_timer_init(void)
goto err_free_pdev;
}
- pdata = kzalloc(sizeof(*pdata), GFP_KERNEL);
+ pdata = kzalloc_obj(*pdata, GFP_KERNEL);
if (!pdata) {
ret = -ENOMEM;
goto err_free_pdata;
diff --git a/arch/arm/mach-omap2/clkt2xxx_virt_prcm_set.c b/arch/arm/mach-omap2/clkt2xxx_virt_prcm_set.c
index 96c5cdc718c8..0b9d4c7b6711 100644
--- a/arch/arm/mach-omap2/clkt2xxx_virt_prcm_set.c
+++ b/arch/arm/mach-omap2/clkt2xxx_virt_prcm_set.c
@@ -237,7 +237,7 @@ void omap2xxx_clkt_vps_init(void)
omap2xxx_clkt_vps_late_init();
omap2xxx_clkt_vps_check_bootloader_rates();
- hw = kzalloc(sizeof(*hw), GFP_KERNEL);
+ hw = kzalloc_obj(*hw, GFP_KERNEL);
if (!hw)
return;
init.name = "virt_prcm_set";
diff --git a/arch/arm/mach-omap2/id.c b/arch/arm/mach-omap2/id.c
index 7f387706368a..fd9e4146db35 100644
--- a/arch/arm/mach-omap2/id.c
+++ b/arch/arm/mach-omap2/id.c
@@ -787,7 +787,7 @@ void __init omap_soc_device_init(void)
struct soc_device *soc_dev;
struct soc_device_attribute *soc_dev_attr;
- soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL);
+ soc_dev_attr = kzalloc_obj(*soc_dev_attr, GFP_KERNEL);
if (!soc_dev_attr)
return;
diff --git a/arch/arm/mach-omap2/omap-iommu.c b/arch/arm/mach-omap2/omap-iommu.c
index 9c8a85198e16..debc3f0d0184 100644
--- a/arch/arm/mach-omap2/omap-iommu.c
+++ b/arch/arm/mach-omap2/omap-iommu.c
@@ -99,7 +99,7 @@ static struct powerdomain *_get_pwrdm(struct device *dev)
return NULL;
}
- entry = kmalloc(sizeof(*entry), GFP_KERNEL);
+ entry = kmalloc_obj(*entry, GFP_KERNEL);
if (entry) {
entry->dev = dev;
entry->pwrdm = pwrdm;
diff --git a/arch/arm/mach-omap2/omap_device.c b/arch/arm/mach-omap2/omap_device.c
index 800980057373..ab8adccbd7dd 100644
--- a/arch/arm/mach-omap2/omap_device.c
+++ b/arch/arm/mach-omap2/omap_device.c
@@ -156,7 +156,7 @@ static int omap_device_build_from_dt(struct platform_device *pdev)
!omap_hwmod_parse_module_range(NULL, node, &res))
return -ENODEV;
- hwmods = kcalloc(oh_cnt, sizeof(struct omap_hwmod *), GFP_KERNEL);
+ hwmods = kzalloc_objs(struct omap_hwmod *, oh_cnt, GFP_KERNEL);
if (!hwmods) {
ret = -ENOMEM;
goto odbfd_exit;
@@ -309,7 +309,7 @@ static struct omap_device *omap_device_alloc(struct platform_device *pdev,
int i;
struct omap_hwmod **hwmods;
- od = kzalloc(sizeof(struct omap_device), GFP_KERNEL);
+ od = kzalloc_obj(struct omap_device, GFP_KERNEL);
if (!od)
goto oda_exit1;
diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c
index 111677878d9c..3591ca1f59c6 100644
--- a/arch/arm/mach-omap2/omap_hwmod.c
+++ b/arch/arm/mach-omap2/omap_hwmod.c
@@ -3392,7 +3392,7 @@ static int omap_hwmod_allocate_module(struct device *dev, struct omap_hwmod *oh,
void __iomem *regs = NULL;
unsigned long flags;
- sysc = kzalloc(sizeof(*sysc), GFP_KERNEL);
+ sysc = kzalloc_obj(*sysc, GFP_KERNEL);
if (!sysc)
return -ENOMEM;
@@ -3422,7 +3422,7 @@ static int omap_hwmod_allocate_module(struct device *dev, struct omap_hwmod *oh,
}
if (list_empty(&oh->slave_ports)) {
- oi = kzalloc(sizeof(*oi), GFP_KERNEL);
+ oi = kzalloc_obj(*oi, GFP_KERNEL);
if (!oi)
goto out_free_class;
@@ -3525,7 +3525,7 @@ int omap_hwmod_init_module(struct device *dev,
oh = _lookup(data->name);
if (!oh) {
- oh = kzalloc(sizeof(*oh), GFP_KERNEL);
+ oh = kzalloc_obj(*oh, GFP_KERNEL);
if (!oh)
return -ENOMEM;
@@ -3536,7 +3536,7 @@ int omap_hwmod_init_module(struct device *dev,
/* Unused, can be handled by PRM driver handling resets */
oh->prcm.omap4.flags = HWMOD_OMAP4_NO_CONTEXT_LOSS_BIT;
- oh->class = kzalloc(sizeof(*oh->class), GFP_KERNEL);
+ oh->class = kzalloc_obj(*oh->class, GFP_KERNEL);
if (!oh->class) {
kfree(oh);
return -ENOMEM;
diff --git a/arch/arm/mach-omap2/pm33xx-core.c b/arch/arm/mach-omap2/pm33xx-core.c
index 4abb86dc98fd..e3f47fb2d4ef 100644
--- a/arch/arm/mach-omap2/pm33xx-core.c
+++ b/arch/arm/mach-omap2/pm33xx-core.c
@@ -410,7 +410,7 @@ static int __init amx3_idle_init(struct device_node *cpu_node, int cpu)
state_count++;
}
- idle_states = kcalloc(state_count, sizeof(*idle_states), GFP_KERNEL);
+ idle_states = kzalloc_objs(*idle_states, state_count, GFP_KERNEL);
if (!idle_states)
return -ENOMEM;
diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c
index 68975771e633..9992549c7336 100644
--- a/arch/arm/mach-omap2/pm34xx.c
+++ b/arch/arm/mach-omap2/pm34xx.c
@@ -410,7 +410,7 @@ static int __init pwrdms_setup(struct powerdomain *pwrdm, void *unused)
if (!pwrdm->pwrsts)
return 0;
- pwrst = kmalloc(sizeof(struct power_state), GFP_ATOMIC);
+ pwrst = kmalloc_obj(struct power_state, GFP_ATOMIC);
if (!pwrst)
return -ENOMEM;
pwrst->pwrdm = pwrdm;
diff --git a/arch/arm/mach-omap2/pm44xx.c b/arch/arm/mach-omap2/pm44xx.c
index 37b168119fe4..554352e9e1c6 100644
--- a/arch/arm/mach-omap2/pm44xx.c
+++ b/arch/arm/mach-omap2/pm44xx.c
@@ -132,7 +132,7 @@ static int __init pwrdms_setup(struct powerdomain *pwrdm, void *unused)
!strncmp(pwrdm->name, "l4per", 5))
pwrdm_set_logic_retst(pwrdm, PWRDM_POWER_OFF);
- pwrst = kmalloc(sizeof(struct power_state), GFP_ATOMIC);
+ pwrst = kmalloc_obj(struct power_state, GFP_ATOMIC);
if (!pwrst)
return -ENOMEM;
diff --git a/arch/arm/mach-omap2/sr_device.c b/arch/arm/mach-omap2/sr_device.c
index d2133423b0c9..9d1a14771590 100644
--- a/arch/arm/mach-omap2/sr_device.c
+++ b/arch/arm/mach-omap2/sr_device.c
@@ -39,7 +39,7 @@ static void __init sr_set_nvalues(struct omap_volt_data *volt_data,
while (volt_data[count].volt_nominal)
count++;
- nvalue_table = kcalloc(count, sizeof(*nvalue_table), GFP_KERNEL);
+ nvalue_table = kzalloc_objs(*nvalue_table, count, GFP_KERNEL);
if (!nvalue_table)
return;
diff --git a/arch/arm/mach-orion5x/pci.c b/arch/arm/mach-orion5x/pci.c
index 3313bc5a63ea..2ee1ff7335db 100644
--- a/arch/arm/mach-orion5x/pci.c
+++ b/arch/arm/mach-orion5x/pci.c
@@ -169,7 +169,7 @@ static int __init pcie_setup(struct pci_sys_data *sys)
/*
* Request resources.
*/
- res = kzalloc(sizeof(struct resource), GFP_KERNEL);
+ res = kzalloc_obj(struct resource, GFP_KERNEL);
if (!res)
panic("pcie_setup unable to alloc resources");
@@ -490,7 +490,7 @@ static int __init pci_setup(struct pci_sys_data *sys)
/*
* Request resources
*/
- res = kzalloc(sizeof(struct resource), GFP_KERNEL);
+ res = kzalloc_obj(struct resource, GFP_KERNEL);
if (!res)
panic("pci_setup unable to alloc resources");
diff --git a/arch/arm/mach-rpc/ecard.c b/arch/arm/mach-rpc/ecard.c
index 2cde4c83b7f9..9f0edac1697c 100644
--- a/arch/arm/mach-rpc/ecard.c
+++ b/arch/arm/mach-rpc/ecard.c
@@ -692,7 +692,7 @@ static struct expansion_card *__init ecard_alloc_card(int type, int slot)
unsigned long base;
int i;
- ec = kzalloc(sizeof(ecard_t), GFP_KERNEL);
+ ec = kzalloc_obj(ecard_t, GFP_KERNEL);
if (!ec) {
ec = ERR_PTR(-ENOMEM);
goto nomem;
diff --git a/arch/arm/mach-sa1100/clock.c b/arch/arm/mach-sa1100/clock.c
index e8691921c69a..e4c7a0b78783 100644
--- a/arch/arm/mach-sa1100/clock.c
+++ b/arch/arm/mach-sa1100/clock.c
@@ -107,7 +107,7 @@ int __init sa11xx_clk_init(void)
clk_hw_register_clkdev(hw, "OSTIMER0", NULL);
- hw = kzalloc(sizeof(*hw), GFP_KERNEL);
+ hw = kzalloc_obj(*hw, GFP_KERNEL);
if (!hw)
return -ENOMEM;
hw->init = &clk_mpll_init_data;
@@ -129,7 +129,7 @@ int __init sa11xx_clk_init(void)
FAlnMsk(TUCR_TSEL), 0, &tucr_lock);
clk_set_rate(hw->clk, 3686400);
- hw = kzalloc(sizeof(*hw), GFP_KERNEL);
+ hw = kzalloc_obj(*hw, GFP_KERNEL);
if (!hw)
return -ENOMEM;
hw->init = &clk_gpio27_init_data;
diff --git a/arch/arm/mach-sa1100/generic.c b/arch/arm/mach-sa1100/generic.c
index 5383a26f5116..078667b52b8a 100644
--- a/arch/arm/mach-sa1100/generic.c
+++ b/arch/arm/mach-sa1100/generic.c
@@ -321,7 +321,7 @@ int __init sa11x0_register_fixed_regulator(int n,
{
struct regulator_init_data *id;
- cfg->init_data = id = kzalloc(sizeof(*cfg->init_data), GFP_KERNEL);
+ cfg->init_data = id = kzalloc_obj(*cfg->init_data, GFP_KERNEL);
if (!cfg->init_data)
return -ENOMEM;
diff --git a/arch/arm/mach-sa1100/neponset.c b/arch/arm/mach-sa1100/neponset.c
index 88fe79f0a4ed..f8960373fa06 100644
--- a/arch/arm/mach-sa1100/neponset.c
+++ b/arch/arm/mach-sa1100/neponset.c
@@ -276,7 +276,7 @@ static int neponset_probe(struct platform_device *dev)
goto err_alloc;
}
- d = kzalloc(sizeof(*d), GFP_KERNEL);
+ d = kzalloc_obj(*d, GFP_KERNEL);
if (!d) {
ret = -ENOMEM;
goto err_alloc;
diff --git a/arch/arm/mach-shmobile/regulator-quirk-rcar-gen2.c b/arch/arm/mach-shmobile/regulator-quirk-rcar-gen2.c
index 117e7b07995b..c6659131f21b 100644
--- a/arch/arm/mach-shmobile/regulator-quirk-rcar-gen2.c
+++ b/arch/arm/mach-shmobile/regulator-quirk-rcar-gen2.c
@@ -164,7 +164,7 @@ static int __init rcar_gen2_regulator_quirk(void)
if (ret) /* Skip invalid entry and continue */
continue;
- quirk = kzalloc(sizeof(*quirk), GFP_KERNEL);
+ quirk = kzalloc_obj(*quirk, GFP_KERNEL);
if (!quirk) {
ret = -ENOMEM;
of_node_put(np);
diff --git a/arch/arm/mach-versatile/spc.c b/arch/arm/mach-versatile/spc.c
index 2d27777a00d3..d77ed8ce5f32 100644
--- a/arch/arm/mach-versatile/spc.c
+++ b/arch/arm/mach-versatile/spc.c
@@ -395,7 +395,7 @@ static int ve_spc_populate_opps(uint32_t cluster)
uint32_t data = 0, off, ret, idx;
struct ve_spc_opp *opps;
- opps = kcalloc(MAX_OPPS, sizeof(*opps), GFP_KERNEL);
+ opps = kzalloc_objs(*opps, MAX_OPPS, GFP_KERNEL);
if (!opps)
return -ENOMEM;
@@ -442,7 +442,7 @@ static int ve_init_opp_table(struct device *cpu_dev)
int __init ve_spc_init(void __iomem *baseaddr, u32 a15_clusid, int irq)
{
int ret;
- info = kzalloc(sizeof(*info), GFP_KERNEL);
+ info = kzalloc_obj(*info, GFP_KERNEL);
if (!info)
return -ENOMEM;
@@ -525,7 +525,7 @@ static struct clk *ve_spc_clk_register(struct device *cpu_dev)
struct clk_init_data init;
struct clk_spc *spc;
- spc = kzalloc(sizeof(*spc), GFP_KERNEL);
+ spc = kzalloc_obj(*spc, GFP_KERNEL);
if (!spc)
return ERR_PTR(-ENOMEM);
diff --git a/arch/arm/mach-versatile/versatile.c b/arch/arm/mach-versatile/versatile.c
index f0c80d4663ca..53d02ce2ad43 100644
--- a/arch/arm/mach-versatile/versatile.c
+++ b/arch/arm/mach-versatile/versatile.c
@@ -142,7 +142,7 @@ static void __init versatile_dt_pci_init(void)
goto out_put_node;
}
- newprop = kzalloc(sizeof(*newprop), GFP_KERNEL);
+ newprop = kzalloc_obj(*newprop, GFP_KERNEL);
if (!newprop)
goto out_put_node;
diff --git a/arch/arm/mach-zynq/common.c b/arch/arm/mach-zynq/common.c
index 15e8a321a713..ddb06d5ca55d 100644
--- a/arch/arm/mach-zynq/common.c
+++ b/arch/arm/mach-zynq/common.c
@@ -108,7 +108,7 @@ static void __init zynq_init_machine(void)
struct soc_device *soc_dev;
struct device *parent = NULL;
- soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL);
+ soc_dev_attr = kzalloc_obj(*soc_dev_attr, GFP_KERNEL);
if (!soc_dev_attr)
goto out;
diff --git a/arch/arm/mm/cache-l2x0-pmu.c b/arch/arm/mm/cache-l2x0-pmu.c
index 93ef0502b7ff..3d62bd48086b 100644
--- a/arch/arm/mm/cache-l2x0-pmu.c
+++ b/arch/arm/mm/cache-l2x0-pmu.c
@@ -507,7 +507,7 @@ static __init int l2x0_pmu_init(void)
if (!l2x0_base)
return 0;
- l2x0_pmu = kzalloc(sizeof(*l2x0_pmu), GFP_KERNEL);
+ l2x0_pmu = kzalloc_obj(*l2x0_pmu, GFP_KERNEL);
if (!l2x0_pmu) {
pr_warn("Unable to allocate L2x0 PMU\n");
return -ENOMEM;
diff --git a/arch/arm/mm/cache-uniphier.c b/arch/arm/mm/cache-uniphier.c
index 84a2f17ff32d..c601532f7a77 100644
--- a/arch/arm/mm/cache-uniphier.c
+++ b/arch/arm/mm/cache-uniphier.c
@@ -342,7 +342,7 @@ static int __init __uniphier_cache_init(struct device_node *np,
return -EINVAL;
}
- data = kzalloc(sizeof(*data), GFP_KERNEL);
+ data = kzalloc_obj(*data, GFP_KERNEL);
if (!data)
return -ENOMEM;
diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c
index a4c765d24692..7aca3e747ad5 100644
--- a/arch/arm/mm/dma-mapping.c
+++ b/arch/arm/mm/dma-mapping.c
@@ -558,8 +558,8 @@ static void *__dma_alloc(struct device *dev, size_t size, dma_addr_t *handle,
}
#endif
- buf = kzalloc(sizeof(*buf),
- gfp & ~(__GFP_DMA | __GFP_DMA32 | __GFP_HIGHMEM));
+ buf = kzalloc_obj(*buf,
+ gfp & ~(__GFP_DMA | __GFP_DMA32 | __GFP_HIGHMEM));
if (!buf)
return NULL;
@@ -1504,7 +1504,7 @@ arm_iommu_create_mapping(struct device *dev, dma_addr_t base, u64 size)
bitmap_size = PAGE_SIZE;
}
- mapping = kzalloc(sizeof(struct dma_iommu_mapping), GFP_KERNEL);
+ mapping = kzalloc_obj(struct dma_iommu_mapping, GFP_KERNEL);
if (!mapping)
goto err;
diff --git a/arch/arm/mm/pgd.c b/arch/arm/mm/pgd.c
index 4eb81b7ed03a..447945836c3f 100644
--- a/arch/arm/mm/pgd.c
+++ b/arch/arm/mm/pgd.c
@@ -17,7 +17,7 @@
#include "mm.h"
#ifdef CONFIG_ARM_LPAE
-#define _pgd_alloc(mm) kmalloc_array(PTRS_PER_PGD, sizeof(pgd_t), GFP_KERNEL | __GFP_ZERO)
+#define _pgd_alloc(mm) kmalloc_objs(pgd_t, PTRS_PER_PGD, GFP_KERNEL | __GFP_ZERO)
#define _pgd_free(mm, pgd) kfree(pgd)
#else
#define _pgd_alloc(mm) __pgd_alloc(mm, 2)
diff --git a/arch/arm/probes/kprobes/test-core.c b/arch/arm/probes/kprobes/test-core.c
index 171c7076b89f..ef93f2f1db62 100644
--- a/arch/arm/probes/kprobes/test-core.c
+++ b/arch/arm/probes/kprobes/test-core.c
@@ -763,9 +763,8 @@ static int coverage_start_fn(const struct decode_header *h, void *args)
static int coverage_start(const union decode_item *table)
{
- coverage.base = kmalloc_array(MAX_COVERAGE_ENTRIES,
- sizeof(struct coverage_entry),
- GFP_KERNEL);
+ coverage.base = kmalloc_objs(struct coverage_entry,
+ MAX_COVERAGE_ENTRIES, GFP_KERNEL);
coverage.num_entries = 0;
coverage.nesting = 0;
return table_iter(table, coverage_start_fn, &coverage);
diff --git a/arch/arm/xen/enlighten.c b/arch/arm/xen/enlighten.c
index 8655bc3d3634..9c3e6145b810 100644
--- a/arch/arm/xen/enlighten.c
+++ b/arch/arm/xen/enlighten.c
@@ -339,7 +339,7 @@ int __init arch_xen_unpopulated_init(struct resource **res)
return -EINVAL;
}
- regs = kcalloc(nr_reg, sizeof(*regs), GFP_KERNEL);
+ regs = kzalloc_objs(*regs, nr_reg, GFP_KERNEL);
if (!regs) {
of_node_put(np);
return -ENOMEM;
@@ -383,7 +383,7 @@ int __init arch_xen_unpopulated_init(struct resource **res)
start = regs[i - 1].end + 1;
end = regs[i].start - 1;
- tmp_res = kzalloc(sizeof(*tmp_res), GFP_KERNEL);
+ tmp_res = kzalloc_obj(*tmp_res, GFP_KERNEL);
if (!tmp_res) {
rc = -ENOMEM;
goto err;
diff --git a/arch/arm/xen/p2m.c b/arch/arm/xen/p2m.c
index 9da57a5b81c7..d911d91d5832 100644
--- a/arch/arm/xen/p2m.c
+++ b/arch/arm/xen/p2m.c
@@ -176,7 +176,7 @@ bool __set_phys_to_machine_multi(unsigned long pfn,
return true;
}
- p2m_entry = kzalloc(sizeof(*p2m_entry), GFP_NOWAIT);
+ p2m_entry = kzalloc_obj(*p2m_entry, GFP_NOWAIT);
if (!p2m_entry)
return false;
diff --git a/arch/arm64/kernel/machine_kexec_file.c b/arch/arm64/kernel/machine_kexec_file.c
index 410060ebd86d..9038d46dacf5 100644
--- a/arch/arm64/kernel/machine_kexec_file.c
+++ b/arch/arm64/kernel/machine_kexec_file.c
@@ -52,7 +52,7 @@ static int prepare_elf_headers(void **addr, unsigned long *sz)
for_each_mem_range(i, &start, &end)
nr_ranges++;
- cmem = kmalloc(struct_size(cmem, ranges, nr_ranges), GFP_KERNEL);
+ cmem = kmalloc_flex(*cmem, ranges, nr_ranges, GFP_KERNEL);
if (!cmem)
return -ENOMEM;
diff --git a/arch/arm64/kernel/vdso.c b/arch/arm64/kernel/vdso.c
index 78ddf6bdecad..34d761ef08b0 100644
--- a/arch/arm64/kernel/vdso.c
+++ b/arch/arm64/kernel/vdso.c
@@ -81,9 +81,8 @@ static int __init __vdso_init(enum vdso_abi abi)
vdso_info[abi].vdso_code_start) >>
PAGE_SHIFT;
- vdso_pagelist = kcalloc(vdso_info[abi].vdso_pages,
- sizeof(struct page *),
- GFP_KERNEL);
+ vdso_pagelist = kzalloc_objs(struct page *, vdso_info[abi].vdso_pages,
+ GFP_KERNEL);
if (vdso_pagelist == NULL)
return -ENOMEM;
diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c
index 94d5b0b99fd1..29f0326f7e00 100644
--- a/arch/arm64/kvm/arm.c
+++ b/arch/arm64/kvm/arm.c
@@ -854,8 +854,8 @@ static void kvm_init_mpidr_data(struct kvm *kvm)
* iterative method. Single vcpu VMs do not need this either.
*/
if (struct_size(data, cmpidr_to_idx, nr_entries) <= PAGE_SIZE)
- data = kzalloc(struct_size(data, cmpidr_to_idx, nr_entries),
- GFP_KERNEL_ACCOUNT);
+ data = kzalloc_flex(*data, cmpidr_to_idx, nr_entries,
+ GFP_KERNEL_ACCOUNT);
if (!data)
goto out;
diff --git a/arch/arm64/kvm/mmu.c b/arch/arm64/kvm/mmu.c
index 8c5d259810b2..f6d8b294525d 100644
--- a/arch/arm64/kvm/mmu.c
+++ b/arch/arm64/kvm/mmu.c
@@ -487,7 +487,7 @@ static int share_pfn_hyp(u64 pfn)
goto unlock;
}
- this = kzalloc(sizeof(*this), GFP_KERNEL);
+ this = kzalloc_obj(*this, GFP_KERNEL);
if (!this) {
ret = -ENOMEM;
goto unlock;
@@ -978,7 +978,7 @@ int kvm_init_stage2_mmu(struct kvm *kvm, struct kvm_s2_mmu *mmu, unsigned long t
if (err)
return err;
- pgt = kzalloc(sizeof(*pgt), GFP_KERNEL_ACCOUNT);
+ pgt = kzalloc_obj(*pgt, GFP_KERNEL_ACCOUNT);
if (!pgt)
return -ENOMEM;
@@ -1155,7 +1155,8 @@ int topup_hyp_memcache(struct kvm_hyp_memcache *mc, unsigned long min_pages)
return 0;
if (!mc->mapping) {
- mc->mapping = kzalloc(sizeof(struct pkvm_mapping), GFP_KERNEL_ACCOUNT);
+ mc->mapping = kzalloc_obj(struct pkvm_mapping,
+ GFP_KERNEL_ACCOUNT);
if (!mc->mapping)
return -ENOMEM;
}
@@ -2328,7 +2329,7 @@ int __init kvm_mmu_init(u32 hyp_va_bits)
goto out;
}
- hyp_pgtable = kzalloc(sizeof(*hyp_pgtable), GFP_KERNEL);
+ hyp_pgtable = kzalloc_obj(*hyp_pgtable, GFP_KERNEL);
if (!hyp_pgtable) {
kvm_err("Hyp mode page-table not allocated\n");
err = -ENOMEM;
diff --git a/arch/arm64/kvm/nested.c b/arch/arm64/kvm/nested.c
index eeea5e692370..620126d1f0dc 100644
--- a/arch/arm64/kvm/nested.c
+++ b/arch/arm64/kvm/nested.c
@@ -1215,8 +1215,8 @@ int kvm_vcpu_allocate_vncr_tlb(struct kvm_vcpu *vcpu)
if (!kvm_has_feat(vcpu->kvm, ID_AA64MMFR4_EL1, NV_frac, NV2_ONLY))
return 0;
- vcpu->arch.vncr_tlb = kzalloc(sizeof(*vcpu->arch.vncr_tlb),
- GFP_KERNEL_ACCOUNT);
+ vcpu->arch.vncr_tlb = kzalloc_obj(*vcpu->arch.vncr_tlb,
+ GFP_KERNEL_ACCOUNT);
if (!vcpu->arch.vncr_tlb)
return -ENOMEM;
@@ -1704,8 +1704,8 @@ int kvm_init_nv_sysregs(struct kvm_vcpu *vcpu)
if (kvm->arch.sysreg_masks)
goto out;
- kvm->arch.sysreg_masks = kzalloc(sizeof(*(kvm->arch.sysreg_masks)),
- GFP_KERNEL_ACCOUNT);
+ kvm->arch.sysreg_masks = kzalloc_obj(*(kvm->arch.sysreg_masks),
+ GFP_KERNEL_ACCOUNT);
if (!kvm->arch.sysreg_masks)
return -ENOMEM;
diff --git a/arch/arm64/kvm/pmu-emul.c b/arch/arm64/kvm/pmu-emul.c
index b03dbda7f1ab..3a7b6e78a949 100644
--- a/arch/arm64/kvm/pmu-emul.c
+++ b/arch/arm64/kvm/pmu-emul.c
@@ -797,7 +797,7 @@ void kvm_host_pmu_init(struct arm_pmu *pmu)
guard(mutex)(&arm_pmus_lock);
- entry = kmalloc(sizeof(*entry), GFP_KERNEL);
+ entry = kmalloc_obj(*entry, GFP_KERNEL);
if (!entry)
return;
diff --git a/arch/arm64/kvm/ptdump.c b/arch/arm64/kvm/ptdump.c
index 6cbe018fd6fd..6a8836207a79 100644
--- a/arch/arm64/kvm/ptdump.c
+++ b/arch/arm64/kvm/ptdump.c
@@ -119,7 +119,7 @@ static struct kvm_ptdump_guest_state *kvm_ptdump_parser_create(struct kvm *kvm)
struct kvm_pgtable *pgtable = mmu->pgt;
int ret;
- st = kzalloc(sizeof(struct kvm_ptdump_guest_state), GFP_KERNEL_ACCOUNT);
+ st = kzalloc_obj(struct kvm_ptdump_guest_state, GFP_KERNEL_ACCOUNT);
if (!st)
return ERR_PTR(-ENOMEM);
diff --git a/arch/arm64/kvm/vgic/vgic-debug.c b/arch/arm64/kvm/vgic/vgic-debug.c
index 2c6776a1779b..fa1de8784617 100644
--- a/arch/arm64/kvm/vgic/vgic-debug.c
+++ b/arch/arm64/kvm/vgic/vgic-debug.c
@@ -104,7 +104,7 @@ static void *vgic_debug_start(struct seq_file *s, loff_t *pos)
struct kvm *kvm = s->private;
struct vgic_state_iter *iter;
- iter = kmalloc(sizeof(*iter), GFP_KERNEL);
+ iter = kmalloc_obj(*iter, GFP_KERNEL);
if (!iter)
return ERR_PTR(-ENOMEM);
@@ -375,7 +375,7 @@ static void *vgic_its_debug_start(struct seq_file *s, loff_t *pos)
if (!dev)
return NULL;
- iter = kmalloc(sizeof(*iter), GFP_KERNEL);
+ iter = kmalloc_obj(*iter, GFP_KERNEL);
if (!iter)
]
]
|
| 86/2 |
2026/06/15 16:38 |
llm |
fixes-finder |
0m
Model:
Tokens:
input: 37361
output: 53
thoughts: 2145
Thoughts: **Analysis of the Kernel Memory Allocation Bug**
Okay, let's break this down. My initial thought was that the change from `kcalloc` to `kzalloc_objs` in commit `69050f8d6d07` was the source of the problem. However, the use of `kcalloc` itself in the `fill_object_idr` function, introduced in commit `62884cd386b8`, immediately flags this as the likely culprit. The unbounded nature of `kcalloc`, coupled with a user-controlled value for the object count, is a classic recipe for trouble.
The description of the crash pinpoints the unbounded allocation. We're looking at a scenario where a large contiguous memory chunk is requested, exceeding `KMALLOC_MAX_SIZE`. The switch to `kzalloc_objs` doesn't inherently worsen the situation; the core issue is the allocation itself. The key is that `kzalloc_objs` expands to `kzalloc` with `GFP_KERNEL` without the safety net of `__GFP_NOWARN`. This is what triggers the warning.
I had to backtrack to the introduction of `fill_object_idr` and its associated `drm_mode_create_lease_ioctl`, which is where the user-supplied `object_count` comes into play. Upon verifying commit `62884cd386b8` I confirmed this introduced both, and included the problematic `kcalloc` call. This is where the vulnerability was introduced.
The integer overflow fix, implemented in `f37d63e219c3`, changed `memdup_user` to `memdup_array_user` but did not address the fundamental issue of the unbounded memory allocation, it only helped a little by dealing with integer overflow. The root cause of the warning, the large allocation, remained unaddressed.
I confirmed that `62884cd386b876638720ef88374b31a84ca7ee5f` is the correct hash for that commit.
Therefore, the original commit `62884cd386b8` which introduced both `fill_object_idr` and `drm_mode_create_lease_ioctl` and subsequently the `kcalloc`, is the commit that introduced the bug. The introduction of this ioctl allowed an unbounded `object_count` to be passed into both the `kcalloc` and `memdup_user` calls. The fix, which replaced both `kzalloc_objs` with `kvcalloc` and `memdup_array_user` to `vmemdup_array_user` finally addressed the problem, ensuring that the allocation size is bounded, and that the buffer copy is safer and will properly catch overflows.
|
| 87/2 |
2026/06/15 16:38 |
tool |
set-results |
0m
Args: map[FixesHash:62884cd386b876638720ef88374b31a84ca7ee5f]
Results: map[FixesHash:62884cd386b876638720ef88374b31a84ca7ee5f]
|
| 88/1 |
2026/06/15 16:38 |
action |
format-fixes |
0m
Results: map[Fixes:map[Hash:62884cd386b876638720ef88374b31a84ca7ee5f Title:drm: Add four ioctls for managing drm mode object leases [v7]]]
|
| 89/1 |
2026/06/15 16:38 |
action |
get-maintainers |
0m
Results: map[Recipients:[map[Email:airlied@gmail.com Name:David Airlie To:true] map[Email:dri-devel@lists.freedesktop.org Name: To:true] map[Email:linux-kernel@vger.kernel.org Name: To:false] map[Email:maarten.lankhorst@linux.intel.com Name:Maarten Lankhorst To:true] map[Email:mripard@kernel.org Name:Maxime Ripard To:true] map[Email:simona@ffwll.ch Name:Simona Vetter To:true] map[Email:tzimmermann@suse.de Name:Thomas Zimmermann To:true]]]
|
| 90/1 |
2026/06/15 16:38 |
action |
get-recent-commits |
0m
Results: map[RecentCommits:Convert more 'alloc_obj' cases to default GFP_KERNEL arguments
treewide: Replace kmalloc with kmalloc_obj for non-scalar types
drm_lease.c: copy user-array safely
drm: Remove unnecessary include statements for drm_crtc_helper.h
drm/drm_lease: Remove usage of deprecated DRM_DEBUG_LEASE
drm/lease: allow empty leases
drm: clean up unused kerneldoc in drm_lease.c
drm: clarify usage of drm leases
drm: protect drm_master pointers in drm_lease.c
drm: Don't include drm_legacy.h in drm_lease.c
drm : Insert blank lines after declarations.
drm/lease: fix WARNING in idr_destroy
treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 157
drm: drop use of drmP.h in drm/*
drm/lease: Check for lessor outside of locks
drm/lease: Drop recursive leads checks
drm/leases: Drop object_id validation for negative ids
drm: Use array_size() when creating lease
drm: Rename crtc_idr as object_idr to KMS cleanups
drm/lease: Send a distinct uevent
]
|
| 91/1 |
2026/06/15 16:38 |
agent |
description-generator |
0m
Model:
Instruction:
You are an experienced Linux kernel developer tasked with writing a commit description for
a kernel bug fixing commit. The description should start with a one-line summary,
and then include description of the bug being fixed, and how it's fixed by the provided patch.
The one-line summary should describe the change being made, rather than mention the tool that
detected the bug.
The description must not contain lines starting with '#' because they will dropped by git as comments.
The description must not contain lines starting with '--' or '---' (including inline code diffs)
because they may confuse git/patch utilities.
Your final reply should contain only the text of the commit description.
The one-line summary must be not longer than 72 characters.
IMPORTANT: Do not wrap lines manually (e.g., at 80 characters); we will reformat the text
automatically, so keep paragraphs as single lines without newlines.
Generally try to phrase the description without mentioning syzkaller
(avoid phrases like "the bug was triggered by syzkaller" or "the bug was triggered by fuzzer", etc).
How the bug was triggered is generally an irrelevant detail.
Any bug triggered by a fuzzer can also be triggered by a malicious user, or a buggy program.
If the crash is reported by a sanitizer (e.g., KASAN, KMSAN, lockdep), include the relevant
parts of the sanitizer output to illustrate the problem. Exclude less relevant sections,
as the stack trace can be very long. Describe the execution path that leads to the manifestation
of the kernel bug.
If the patch removes the WARN_ON macro, refer to the fact that WARN_ON
must not be used for conditions that can legitimately happen, and that pr_err
should be used instead if necessary.
Don't assume that panic_on_warn is set, and that WARNINGs are fatal.
While panic_on_warn may be set when the bug was reproduced, it's generally not set on production systems.
Prefer calling several tools at the same time to save round-trips.
Prompt:
The crash that corresponds to the bug is:
------------[ cut here ]------------
WARNING: mm/page_alloc.c:5197 at __alloc_frozen_pages_noprof+0x2ce/0x380 mm/page_alloc.c:5197, CPU#0: syz.0.17/6137
Modules linked in:
CPU: 0 UID: 0 PID: 6137 Comm: syz.0.17 Not tainted syzkaller #1 PREEMPT(full)
Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.16.3-debian-1.16.3-2 04/01/2014
RIP: 0010:__alloc_frozen_pages_noprof+0x2ce/0x380 mm/page_alloc.c:5197
Code: 74 10 4c 89 e7 89 54 24 0c e8 6e a2 0d 00 8b 54 24 0c 49 83 3c 24 00 0f 85 ab fe ff ff e9 ac fe ff ff c6 05 92 0e b2 0d 01 90 <0f> 0b 90 e9 17 ff ff ff a9 00 00 08 00 48 8b 4c 24 10 4c 8d 44 24
RSP: 0018:ffffc90003aa7800 EFLAGS: 00010246
RAX: ffffc90003aa7800 RBX: 000000000000000b RCX: 0000000000000000
RDX: 0000000000000000 RSI: 0000000000000000 RDI: ffffc90003aa7868
RBP: ffffc90003aa78e8 R08: ffffc90003aa7867 R09: 0000000000000000
R10: ffffc90003aa7840 R11: fffff52000754f0d R12: 0000000000000000
R13: 1ffff92000754f04 R14: 0000000000040dc0 R15: dffffc0000000000
FS: 00007fe037ac16c0(0000) GS:ffff8881a59ad000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 00002000003d0000 CR3: 0000000104ab0000 CR4: 00000000000006f0
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
drm_ioctl_kernel+0x2df/0x3b0 drivers/gpu/drm/drm_ioctl.c:805
drm_ioctl+0x6fa/0xbc0 drivers/gpu/drm/drm_ioctl.c:902
vfs_ioctl fs/ioctl.c:51 [inline]
__do_sys_ioctl fs/ioctl.c:597 [inline]
__se_sys_ioctl+0xfc/0x170 fs/ioctl.c:583
do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
do_syscall_64+0x15f/0x560 arch/x86/entry/syscall_64.c:94
entry_SYSCALL_64_after_hwframe+0x77/0x7f
RIP: 0033:0x7fe036b9ce59
Code: ff c3 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 44 00 00 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 c7 c1 e8 ff ff ff f7 d8 64 89 01 48
RSP: 002b:00007fe037ac1028 EFLAGS: 00000246 ORIG_RAX: 0000000000000010
RAX: ffffffffffffffda RBX: 00007fe036e15fa0 RCX: 00007fe036b9ce59
RDX: 00002000000003c0 RSI: 00000000c01864c6 RDI: 0000000000000003
RBP: 00007fe036c32d6f R08: 0000000000000000 R09: 0000000000000000
R10: 0000000000000000 R11: 0000000000000246 R12: 0000000000000000
R13: 00007fe036e16038 R14: 00007fe036e15fa0 R15: 00007fffcab0e958
</TASK>
The explanation of the root cause of the bug is:
The root cause of this kernel crash is an unbounded memory allocation based on a user-controlled value, which attempts to allocate a contiguous memory chunk larger than the maximum allowed by the slab allocator (`KMALLOC_MAX_SIZE`), triggering a warning in the page allocator.
### Detailed Root Cause Analysis
1. **User-controlled `object_count`**:
In `drivers/gpu/drm/drm_lease.c`, the `drm_mode_create_lease_ioctl()` function retrieves `object_count` directly from the user-provided `struct drm_mode_create_lease` argument:
```c
object_count = cl->object_count;
```
The syzkaller reproducer sets this value to `0xf4240` (1,000,000).
2. **First Allocation (`memdup_array_user`)**:
The ioctl first allocates an array to hold the object IDs:
```c
object_ids = memdup_array_user(u64_to_user_ptr(cl->object_ids),
object_count, sizeof(__u32));
```
For `1,000,000` objects, this requires `4,000,000` bytes (~3.8 MB). This size is typically just under the `KMALLOC_MAX_SIZE` limit (usually 4 MB on many architectures). Furthermore, `memdup_array_user()` internally uses `memdup_user()`, which allocates memory with the `__GFP_NOWARN` flag. Thus, even if it were to fail, it would gracefully return `-ENOMEM` without triggering a kernel warning.
3. **Second Allocation (`kzalloc_objs`)**:
After successfully allocating `object_ids`, the ioctl calls `fill_object_idr()`:
```c
ret = fill_object_idr(dev, lessor_priv, &leases, object_count, object_ids);
```
Inside `fill_object_idr()`, the kernel attempts to allocate an array of pointers for the objects:
```c
objects = kzalloc_objs(struct drm_mode_object *, object_count);
```
The size of `struct drm_mode_object *` is 8 bytes (on 64-bit systems). For `1,000,000` objects, this requires `8,000,000` bytes (~7.6 MB). This size strictly exceeds the `KMALLOC_MAX_SIZE` limit.
Unlike `memdup_user()`, the `kzalloc_objs()` macro expands to a standard `kzalloc()` call using `GFP_KERNEL | __GFP_ZERO` **without** the `__GFP_NOWARN` flag.
4. **The Crash (Warning)**:
Because the requested size is larger than `KMALLOC_MAX_SIZE`, the SLUB allocator passes the request directly to the page allocator (`___kmalloc_large_node`). The page allocator calculates the required page order (order 11 for 8 MB). Since order 11 is strictly greater than `MAX_PAGE_ORDER` (typically 10), the page allocator hits the following safety check in `__alloc_frozen_pages_noprof()`:
```c
if (WARN_ON_ONCE_GFP(order > MAX_PAGE_ORDER, gfp))
return NULL;
```
Because `__GFP_NOWARN` was not provided, this triggers the `WARN_ON_ONCE_GFP` warning, which syzkaller correctly identifies as a crash.
### Proposed Fix
To fix this issue, both allocations should be updated to use the `kvmalloc` family of functions. These functions automatically fall back to `vmalloc()` for large allocations (avoiding memory fragmentation issues) and internally apply `__GFP_NOWARN` when attempting the initial `kmalloc()`, preventing the page allocator warning.
1. In `drm_mode_create_lease_ioctl()`, replace `memdup_array_user()` with `vmemdup_array_user()`, and change the corresponding `kfree()` to `kvfree()`:
```c
// drivers/gpu/drm/drm_lease.c : ~512
- 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));
// drivers/gpu/drm/drm_lease.c : ~523
- kfree(object_ids);
+ kvfree(object_ids);
```
2. In `fill_object_idr()`, replace `kzalloc_objs()` with `kvcalloc()`, and change the corresponding `kfree()` to `kvfree()`:
```c
// drivers/gpu/drm/drm_lease.c : ~389
- objects = kzalloc_objs(struct drm_mode_object *, object_count);
+ objects = kvcalloc(object_count, sizeof(struct drm_mode_object *), GFP_KERNEL);
// drivers/gpu/drm/drm_lease.c : ~465
- kfree(objects);
+ kvfree(objects);
```
This ensures that userspace cannot trigger a kernel warning by passing an arbitrarily large `object_count`, and the kernel will gracefully return `-ENOMEM` if the system truly cannot satisfy the `vmalloc` request.
The diff of the bug fix is:
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);
Additional description of the patch:
I have implemented the proposed fix.
### Explanation of the Fix
The crash is caused by an unbounded memory allocation in `drm_mode_create_lease_ioctl()` where the `object_count` is directly controlled by the user. A malicious or buggy userspace program can pass a very large `object_count` (e.g., 1,000,000), causing the kernel to attempt allocating a contiguous memory chunk that exceeds the maximum allowed size by the slab allocator (`KMALLOC_MAX_SIZE`).
There are two allocations involved:
1. **`object_ids` array**: Allocated using `memdup_array_user()`. While this doesn't trigger a warning because `memdup_user()` internally uses `__GFP_NOWARN`, it still attempts a large contiguous allocation (up to ~4MB) which can fail due to memory fragmentation.
2. **`objects` array**: Allocated using `kzalloc_objs()` in `fill_object_idr()`. This macro expands to a standard `kzalloc()` call without the `__GFP_NOWARN` flag. For 1,000,000 objects, this requires ~8MB of memory. Since this 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`.
To fix this, I replaced both allocations with their `kvmalloc` family equivalents:
- In `drm_mode_create_lease_ioctl()`, `memdup_array_user()` was replaced with `vmemdup_array_user()`, and the corresponding `kfree()` was changed to `kvfree()`.
- In `fill_object_idr()`, `kzalloc_objs()` was replaced with `kvcalloc()`, and the corresponding `kfree()` was changed to `kvfree()`.
The `kvmalloc` family of functions attempts a `kmalloc()` first (with `__GFP_NOWARN` applied internally to prevent warnings if it fails), and gracefully falls back to `vmalloc()` for large allocations. This not only prevents the kernel warning but also makes the allocations more robust against memory fragmentation, as `vmalloc()` can satisfy large requests using non-contiguous physical pages. If the system truly cannot satisfy the request, it will gracefully return `-ENOMEM` to userspace.
Here are summaries of recent commits that touched the same files.
Format the summary line consistently with these, look how prefixes
are specified, letter capitalization, style, etc.
Convert more 'alloc_obj' cases to default GFP_KERNEL arguments
treewide: Replace kmalloc with kmalloc_obj for non-scalar types
drm_lease.c: copy user-array safely
drm: Remove unnecessary include statements for drm_crtc_helper.h
drm/drm_lease: Remove usage of deprecated DRM_DEBUG_LEASE
drm/lease: allow empty leases
drm: clean up unused kerneldoc in drm_lease.c
drm: clarify usage of drm leases
drm: protect drm_master pointers in drm_lease.c
drm: Don't include drm_legacy.h in drm_lease.c
drm : Insert blank lines after declarations.
drm/lease: fix WARNING in idr_destroy
treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 157
drm: drop use of drmP.h in drm/*
drm/lease: Check for lessor outside of locks
drm/lease: Drop recursive leads checks
drm/leases: Drop object_id validation for negative ids
drm: Use array_size() when creating lease
drm: Rename crtc_idr as object_idr to KMS cleanups
drm/lease: Send a distinct uevent
Reply: drm/lease: use kvmalloc for user-controlled allocations
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.
|
| 92/2 |
2026/06/15 16:38 |
llm |
description-generator |
0m
Model:
Tokens:
input: 8492
output: 594
thoughts: 2730
Thoughts: **My Thoughts on the Fix**
Okay, so I've been looking at this `drm_lease.c` code, and I see a potential issue in how it handles memory allocation. Specifically, in `drm_mode_create_lease_ioctl()`, the `object_count` comes from user space, and it's used to determine the size of the memory allocation for `object_ids` and `objects`. A user could provide a large `object_count`, and that could cause some problems. If the requested allocation is too big, it exceeds `KMALLOC_MAX_SIZE`. The code uses `kzalloc_objs()`, which eventually calls `kzalloc()` without the `__GFP_NOWARN` flag. This then goes to the page allocator when it's too big, triggering a `WARN_ON_ONCE_GFP` because it's trying to allocate a page order greater than `MAX_PAGE_ORDER`. I see the call trace:
`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 address this, I'm thinking we should change how the allocation is done. Instead of `memdup_array_user()` and `kzalloc_objs()`, I'll use `vmemdup_array_user()` and `kvcalloc()` and replace the associated `kfree` calls with `kvfree()`. The `kvmalloc` family of functions is the right choice here. It tries a `kmalloc()` first with `__GFP_NOWARN`, and if that fails, it falls back to `vmalloc()`. This should prevent the warning. Also, it's more robust, because it can handle fragmentation and will return `-ENOMEM` gracefully if it can't fulfill the request. That seems like a much better approach. So the one-line summary should be: `drm/lease: use kvmalloc for user-controlled allocations`.
|