| 0/0 |
2026/05/20 06:07 |
flow |
assessment-security |
1h04m
Results: map[DenialOfService:true Explanation:The bug report indicates a lockdep warning about a possible circular locking
dependency (deadlock) involving `slab_mutex`, `fs_reclaim`, `cpu_hotplug_lock`,
and several locks related to the Network Block Device (NBD) and network sockets.
### Analysis of the Dependency Chain
The lockdep report shows the following existing dependency chain:
1. `fs_reclaim` -> `q_usage_counter` (established during `blk_alloc_queue`)
2. `q_usage_counter` -> `elevator_lock` (from `elevator_change` calling
`blk_mq_freeze_queue`)
3. `elevator_lock` -> `srcu` (from `elevator_change` calling
`blk_mq_quiesce_queue`)
4. `srcu` -> `cmd->lock` (from `blk_mq_run_hw_queue` dispatching requests to
NBD)
5. `cmd->lock` -> `tx_lock` (from `nbd_queue_rq` calling `nbd_handle_cmd`)
6. `tx_lock` -> `sk_lock` (from `send_disconnects` calling `sock_xmit`)
7. `sk_lock` -> `cpu_hotplug_lock` (from `inet_stream_connect` calling
`cpus_read_lock`)
8. `cpu_hotplug_lock` -> `slab_mutex` (from `kmem_cache_destroy` acquiring both)
The new dependency that triggers the warning is:
`slab_mutex` -> `fs_reclaim`
This new dependency is established because `__kmem_cache_create_args` holds
`slab_mutex` and then performs memory allocations with `GFP_KERNEL` (which can
enter direct memory reclaim and acquire `fs_reclaim`). In the syzbot report,
this happens during `ubi_attach_mtd_dev` which dynamically creates a kmem cache
for the attached device.
### Security Impact
* **Exploitable**: No. This is a locking issue (deadlock) and does not result in
memory corruption, out-of-bounds access, or use-after-free. It cannot be
exploited for privilege escalation.
* **Denial of Service**: Yes. If the exact timing conditions are met, the
circular dependency can lead to a system deadlock (hang), resulting in a Denial
of Service.
* **Accessible From Unprivileged Processes / User Namespaces**: No. Triggering
this deadlock requires setting up the entire dependency chain. The chain heavily
relies on the Network Block Device (NBD) subsystem (`cmd->lock`, `tx_lock`).
Configuring NBD devices and sending netlink commands to them requires global
`CAP_SYS_ADMIN` (checked via `netlink_capable(skb, CAP_SYS_ADMIN)` which
verifies capabilities in the `init_user_ns`). Additionally, dynamically creating
kmem caches (which triggers the `slab_mutex` -> `fs_reclaim` link) is typically
restricted to module initialization or privileged operations like `ubi_attach`
(which requires global `CAP_SYS_RESOURCE`). Thus, unprivileged users (even
within user namespaces) cannot set up the required environment or trigger the
deadlock.
### Conclusion
This is a complex lockdep warning involving NBD, networking, and slab cache
creation. It represents a theoretical deadlock that could cause a Denial of
Service, but it is strictly limited to highly privileged users
(root/CAP_SYS_ADMIN) who can configure NBD devices and attach UBI devices. It
poses no security risk to unprivileged users. Exploitable:false FilesystemTrigger:false NetworkTrigger:false PeripheralTrigger:false RemoteTrigger:false Unprivileged:false UserNamespace:false VMGuestTrigger:false VMHostTrigger:false]
|
| 1/1 |
2026/05/20 06:07 |
action |
syz-repro-to-c-repro |
0m
Results:
|
| 2/1 |
2026/05/20 06:07 |
action |
kernel-checkouter |
1m
Results: map[KernelSrc:/app/workdir/cache/src/8912ecf9ca00a9ea88c66924b7c9f926dcb5d760]
|
| 3/1 |
2026/05/20 06:08 |
action |
kernel-builder |
32m
Results: map[KernelObj:/app/workdir/cache/build/9be3cd2d1cd0a56892c3b7444156cbf619900d2f]
|
| 4/1 |
2026/05/20 06:41 |
action |
codesearch-prepare |
25m
Results: map[Index:codesearch-index]
|
| 5/1 |
2026/05/20 07:06 |
agent |
expert |
6m
Model:
Results: map[DenialOfService:true Exploitable:false FilesystemTrigger:false NetworkTrigger:false PeripheralTrigger:false RemoteTrigger:false Unprivileged:false UserNamespace:false VMGuestTrigger:false VMHostTrigger:false]
Instruction:
You are an experienced Linux kernel security engineer. Your task is to analyze given kernel bug report
and determine its security impact based on the following dimensions.
Use the provided tools to examine the source code, check for capability checks (e.g., capable(), ns_capable()),
and understand the nature of the bug. Analyze the given kernel build and configuration.
You can check the kernel config by grepping ".config" file; you can check kernel cmdline by greeping
".config" file for "CONFIG_CMDLINE=". Assume sysctl parameters have default values.
But analyze for the corresponding production build w/o debugging tools enabled (like KASAN, KMSAN, UBSAN).
Don't make assumptions; verify them with source code access. Try different strategies when analyzing the bug:
- think of ways in which the vulnerable code is unreachable
- or the other way around: try to come up with different ideas of how an unprivileged user can reach the bug
If still unsure err on the side of the bug being non-exploitable/not-accessible.
In the final reply, provide a reasoning for your assessment.
Analysis dimensions:
* Exploitable:
Determine if the bug can result in memory corruption or elevated privileges.
Memory safety issues are almost always exploitable (KASAN or UBSAN reports for use-after-free, out-of-bounds;
refcounting issues, corrupted lists, etc). When kernel is crashing on a completly wild pointer access
(e.g. user-space address, or non-canonical address, but not on NULL or address corresponding to KASAN shadow
for NULL address), including both data accesses and control tranfers, that's also usually implies possibility
of exploitation. Such reports usually say "unable to handle kernel paging request".
Uses of uninitialized values detected by KMSAN may be exploitable b/c attacker frequently can affect uninit
values with spraying techniques. However, for these exploitabability depends on how exactly the uninit value
is used in the code, and what it affects.
Think of what happens after the bug is triggered. Some bugs cause kernel panic and halt execution,
they are harder to exploit. For example, BUG reports halts the kernel. However, WARNING reports don't halt
execution in production builds. Debug bug detection tools (like KASAN, KMSAN, KCSAN, UBSAN) are also not enabled
in production builds, so attacker can freely exploit these bugs w/o being detected by these tools.
If you see an integer overflow, think how the overflowed value used later (if it's used as allocation size,
or an array index). If you see an out-of-bounds read, think if it's followed by an out-of-bounds write as well.
Some KCSAN data-races may be exploitable by skilled attackers as well. Think what data structures got corrupted
as the result of data races and how. However, note that kernel has lots of "benign" data races that don't lead
to any runtime misbehavior at all.
* Denial Of Service:
Determine if the bug can result in denial-of-service. Most bugs can, since they cause system crash,
hangs, deadlocks, or resource leaks. This is mostly applicable to WARNING bugs that won't cause system crash
in production. For these think what will be consequences of the violation of the kernel assumptions flagged
by the WARNING. In some cases the unexpected condition is also properly handled by the normal control flow
(e.g. with "if (WARN_ON(...))"), these won't cause denial-of-service. If the condition is not handled,
then it may or may not cause denial-of-service.
* Accessible From Unprivileged Processes:
Determine if the bug can be reached from a typical (non-root) user process that does NOT have any special capabilities
(like CAP_SYS_ADMIN, CAP_NET_ADMIN, CAP_NET_RAW, CAP_PERFMON) or access to device nodes restricted to root.
Assume that unprivileged_bpf_disabled=1, that is eBPF loading is not accessible. However, cBPF (classical BPF)
is still accessible to non-root processes.
Assume that user namespaces are not accessible, that is, the process cannot get the mentioned capabilities even
within a new user namespace (checked by ns_capable() function in the kernel sources).
* Accessible From User Namespaces:
Determine if the bug can be reached within a user-namespace where the process has all capabilities
(including CAP_SYS_ADMIN, CAP_NET_ADMIN, CAP_NET_RAW, CAP_PERFMON). Such capabilities are checked with ns_capable()
function in the kernel sources.
* VM Guest Trigger:
Determine if the bug can be triggered from the context of a typical KVM guest (e.g., set up by a QEMU VMM).
Consider accesses to standard Linux host paravirtualized features (virtio-blk, virtio-net, etc.),
and handling of VM exits in the KVM code.
* VM Host Trigger in The Confidetial Computing Context:
Determine if the bug can be triggered in a confidential computing guest kernel from the context of a KVM host.
Consider access to standard Linux guest paravirtualized features (virtio-blk, virtio-net, etc.).
* Ethernet Network Trigger:
Determine if the bug can be triggered by processing ingress network Ethernet traffic, either directly (network stack)
or via drivers exposed to network data.
* Other Remote Trigger:
Determine if the bug can be triggered by processing remote traffic other than Ethernet (Wifi, Bluetooth, NFC, etc).
* Peripheral Trigger:
Determine if the bug can be triggered via an untrusted peripheral device that can be physically plugged
into a system, such as a USB device or a niche hardware driver handling external hardware inputs.
This is particularly important for mobile and desktop environments where users can plug in unknown devices.
* Malicious Filesystem Trigger:
Determine if the bug can be triggered by the kernel mounting and parsing a malicious filesystem image.
This is highly critical for Desktop and Mobile environments where external media or downloaded images
might be auto-mounted.
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 kernel bug report is:
ubi16: attaching mtd0
======================================================
WARNING: possible circular locking dependency detected
syzkaller #0 Tainted: G L
------------------------------------------------------
syz.0.3086/17300 is trying to acquire lock:
ffffffff8e9b1800 (fs_reclaim){+.+.}-{0:0}, at: might_alloc include/linux/sched/mm.h:317 [inline]
ffffffff8e9b1800 (fs_reclaim){+.+.}-{0:0}, at: slab_pre_alloc_hook mm/slub.c:4520 [inline]
ffffffff8e9b1800 (fs_reclaim){+.+.}-{0:0}, at: slab_alloc_node mm/slub.c:4875 [inline]
ffffffff8e9b1800 (fs_reclaim){+.+.}-{0:0}, at: kmem_cache_alloc_noprof+0x4c/0x6e0 mm/slub.c:4905
but task is already holding lock:
ffffffff8e97f180 (slab_mutex){+.+.}-{4:4}, at: __kmem_cache_create_args+0x44/0x420 mm/slab_common.c:350
which lock already depends on the new lock.
the existing dependency chain (in reverse order) is:
-> #8 (slab_mutex){+.+.}-{4:4}:
__mutex_lock_common kernel/locking/mutex.c:646 [inline]
__mutex_lock+0x1a4/0x1b10 kernel/locking/mutex.c:820
kmem_cache_destroy mm/slab_common.c:557 [inline]
kmem_cache_destroy+0x59/0x180 mm/slab_common.c:527
p9_client_destroy+0x20c/0x3a0 net/9p/client.c:965
v9fs_session_close+0x49/0x2d0 fs/9p/v9fs.c:543
v9fs_kill_super+0x4d/0xa0 fs/9p/vfs_super.c:175
deactivate_locked_super+0xc1/0x1b0 fs/super.c:476
v9fs_get_tree+0x68c/0xb50 fs/9p/vfs_super.c:156
vfs_get_tree+0x92/0x320 fs/super.c:1754
fc_mount fs/namespace.c:1193 [inline]
do_new_mount_fc fs/namespace.c:3758 [inline]
do_new_mount fs/namespace.c:3834 [inline]
path_mount+0x7d0/0x23d0 fs/namespace.c:4154
do_mount fs/namespace.c:4167 [inline]
__do_sys_mount fs/namespace.c:4383 [inline]
__se_sys_mount fs/namespace.c:4360 [inline]
__x64_sys_mount+0x293/0x310 fs/namespace.c:4360
do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
do_syscall_64+0x10b/0xf80 arch/x86/entry/syscall_64.c:94
entry_SYSCALL_64_after_hwframe+0x77/0x7f
-> #7 (cpu_hotplug_lock){++++}-{0:0}:
percpu_down_read_internal include/linux/percpu-rwsem.h:53 [inline]
percpu_down_read include/linux/percpu-rwsem.h:77 [inline]
cpus_read_lock+0x42/0x170 kernel/cpu.c:490
static_key_disable+0x12/0x20 kernel/jump_label.c:247
__inet_hash_connect+0x143e/0x2000 net/ipv4/inet_hashtables.c:1083
tcp_v4_connect+0xeb3/0x1b40 net/ipv4/tcp_ipv4.c:306
__inet_stream_connect+0x208/0xfa0 net/ipv4/af_inet.c:684
inet_stream_connect+0x57/0xa0 net/ipv4/af_inet.c:755
__sys_connect_file+0x141/0x1a0 net/socket.c:2148
__sys_connect+0x141/0x170 net/socket.c:2167
__do_sys_connect net/socket.c:2173 [inline]
__se_sys_connect net/socket.c:2170 [inline]
__x64_sys_connect+0x72/0xb0 net/socket.c:2170
do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
do_syscall_64+0x10b/0xf80 arch/x86/entry/syscall_64.c:94
entry_SYSCALL_64_after_hwframe+0x77/0x7f
-> #6 (sk_lock-AF_INET){+.+.}-{0:0}:
lock_sock_nested+0x41/0xf0 net/core/sock.c:3783
lock_sock include/net/sock.h:1713 [inline]
tcp_sendmsg+0x20/0x50 net/ipv4/tcp.c:1454
inet_sendmsg+0xb9/0x140 net/ipv4/af_inet.c:866
sock_sendmsg_nosec net/socket.c:787 [inline]
__sock_sendmsg net/socket.c:802 [inline]
sock_sendmsg+0x337/0x3d0 net/socket.c:825
__sock_xmit+0x26e/0x540 drivers/block/nbd.c:576
sock_xmit drivers/block/nbd.c:605 [inline]
send_disconnects drivers/block/nbd.c:1406 [inline]
nbd_disconnect.isra.0+0x329/0x401 drivers/block/nbd.c:1421
__nbd_ioctl drivers/block/nbd.c:1601 [inline]
nbd_ioctl.cold+0xd/0xbf drivers/block/nbd.c:1663
blkdev_ioctl+0x5ad/0x6f0 block/ioctl.c:797
vfs_ioctl fs/ioctl.c:51 [inline]
__do_sys_ioctl fs/ioctl.c:597 [inline]
__se_sys_ioctl fs/ioctl.c:583 [inline]
__x64_sys_ioctl+0x18e/0x210 fs/ioctl.c:583
do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
do_syscall_64+0x10b/0xf80 arch/x86/entry/syscall_64.c:94
entry_SYSCALL_64_after_hwframe+0x77/0x7f
-> #5 (&nsock->tx_lock){+.+.}-{4:4}:
__mutex_lock_common kernel/locking/mutex.c:646 [inline]
__mutex_lock+0x1a4/0x1b10 kernel/locking/mutex.c:820
nbd_handle_cmd drivers/block/nbd.c:1143 [inline]
nbd_queue_rq+0x428/0x1080 drivers/block/nbd.c:1207
blk_mq_dispatch_rq_list+0x422/0x1e70 block/blk-mq.c:2148
__blk_mq_do_dispatch_sched block/blk-mq-sched.c:168 [inline]
blk_mq_do_dispatch_sched block/blk-mq-sched.c:182 [inline]
__blk_mq_sched_dispatch_requests+0xcea/0x1620 block/blk-mq-sched.c:307
blk_mq_sched_dispatch_requests+0xd7/0x1c0 block/blk-mq-sched.c:329
blk_mq_run_hw_queue+0x23c/0x670 block/blk-mq.c:2386
blk_mq_dispatch_list+0x51d/0x1360 block/blk-mq.c:2949
blk_mq_flush_plug_list block/blk-mq.c:2997 [inline]
blk_mq_flush_plug_list+0x130/0x600 block/blk-mq.c:2969
__blk_flush_plug+0x2c4/0x4b0 block/blk-core.c:1230
blk_finish_plug block/blk-core.c:1257 [inline]
__submit_bio+0x584/0x6c0 block/blk-core.c:649
__submit_bio_noacct_mq block/blk-core.c:722 [inline]
submit_bio_noacct_nocheck+0x543/0xbf0 block/blk-core.c:753
submit_bio_noacct+0xd18/0x2000 block/blk-core.c:884
blk_crypto_submit_bio include/linux/blk-crypto.h:203 [inline]
submit_bh_wbc+0x681/0x890 fs/buffer.c:2737
submit_bh fs/buffer.c:2742 [inline]
block_read_full_folio+0x264/0x8e0 fs/buffer.c:2344
filemap_read_folio+0xfc/0x3b0 mm/filemap.c:2502
do_read_cache_folio+0x2d7/0x6b0 mm/filemap.c:4107
read_mapping_folio include/linux/pagemap.h:1017 [inline]
read_part_sector+0xd1/0x370 block/partitions/core.c:724
adfspart_check_ICS+0x91/0x7d0 block/partitions/acorn.c:356
check_partition block/partitions/core.c:143 [inline]
blk_add_partitions block/partitions/core.c:591 [inline]
bdev_disk_changed+0x7a3/0x1250 block/partitions/core.c:695
blkdev_get_whole+0x187/0x290 block/bdev.c:756
bdev_open+0x2c7/0xe40 block/bdev.c:965
blkdev_open+0x34e/0x4f0 block/fops.c:697
do_dentry_open+0x6d8/0x1660 fs/open.c:947
vfs_open+0x82/0x3f0 fs/open.c:1079
do_open fs/namei.c:4699 [inline]
path_openat+0x208c/0x31a0 fs/namei.c:4858
do_file_open+0x20e/0x430 fs/namei.c:4887
do_sys_openat2+0x10d/0x1e0 fs/open.c:1364
do_sys_open fs/open.c:1370 [inline]
__do_sys_openat fs/open.c:1386 [inline]
__se_sys_openat fs/open.c:1381 [inline]
__x64_sys_openat+0x12d/0x210 fs/open.c:1381
do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
do_syscall_64+0x10b/0xf80 arch/x86/entry/syscall_64.c:94
entry_SYSCALL_64_after_hwframe+0x77/0x7f
-> #4 (&cmd->lock){+.+.}-{4:4}:
__mutex_lock_common kernel/locking/mutex.c:646 [inline]
__mutex_lock+0x1a4/0x1b10 kernel/locking/mutex.c:820
nbd_queue_rq+0xba/0x1080 drivers/block/nbd.c:1199
blk_mq_dispatch_rq_list+0x422/0x1e70 block/blk-mq.c:2148
__blk_mq_do_dispatch_sched block/blk-mq-sched.c:168 [inline]
blk_mq_do_dispatch_sched block/blk-mq-sched.c:182 [inline]
__blk_mq_sched_dispatch_requests+0xcea/0x1620 block/blk-mq-sched.c:307
blk_mq_sched_dispatch_requests+0xd7/0x1c0 block/blk-mq-sched.c:329
blk_mq_run_hw_queue+0x23c/0x670 block/blk-mq.c:2386
blk_mq_dispatch_list+0x51d/0x1360 block/blk-mq.c:2949
blk_mq_flush_plug_list block/blk-mq.c:2997 [inline]
blk_mq_flush_plug_list+0x130/0x600 block/blk-mq.c:2969
__blk_flush_plug+0x2c4/0x4b0 block/blk-core.c:1230
blk_finish_plug block/blk-core.c:1257 [inline]
__submit_bio+0x584/0x6c0 block/blk-core.c:649
__submit_bio_noacct_mq block/blk-core.c:722 [inline]
submit_bio_noacct_nocheck+0x543/0xbf0 block/blk-core.c:753
submit_bio_noacct+0xd18/0x2000 block/blk-core.c:884
blk_crypto_submit_bio include/linux/blk-crypto.h:203 [inline]
submit_bh_wbc+0x681/0x890 fs/buffer.c:2737
submit_bh fs/buffer.c:2742 [inline]
block_read_full_folio+0x264/0x8e0 fs/buffer.c:2344
filemap_read_folio+0xfc/0x3b0 mm/filemap.c:2502
do_read_cache_folio+0x2d7/0x6b0 mm/filemap.c:4107
read_mapping_folio include/linux/pagemap.h:1017 [inline]
read_part_sector+0xd1/0x370 block/partitions/core.c:724
adfspart_check_ICS+0x91/0x7d0 block/partitions/acorn.c:356
check_partition block/partitions/core.c:143 [inline]
blk_add_partitions block/partitions/core.c:591 [inline]
bdev_disk_changed+0x7a3/0x1250 block/partitions/core.c:695
blkdev_get_whole+0x187/0x290 block/bdev.c:756
bdev_open+0x2c7/0xe40 block/bdev.c:965
blkdev_open+0x34e/0x4f0 block/fops.c:697
do_dentry_open+0x6d8/0x1660 fs/open.c:947
vfs_open+0x82/0x3f0 fs/open.c:1079
do_open fs/namei.c:4699 [inline]
path_openat+0x208c/0x31a0 fs/namei.c:4858
do_file_open+0x20e/0x430 fs/namei.c:4887
do_sys_openat2+0x10d/0x1e0 fs/open.c:1364
do_sys_open fs/open.c:1370 [inline]
__do_sys_openat fs/open.c:1386 [inline]
__se_sys_openat fs/open.c:1381 [inline]
__x64_sys_openat+0x12d/0x210 fs/open.c:1381
do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
do_syscall_64+0x10b/0xf80 arch/x86/entry/syscall_64.c:94
entry_SYSCALL_64_after_hwframe+0x77/0x7f
-> #3 (set->srcu){.+.+}-{0:0}:
srcu_lock_sync include/linux/srcu.h:199 [inline]
__synchronize_srcu+0xa2/0x300 kernel/rcu/srcutree.c:1481
blk_mq_wait_quiesce_done block/blk-mq.c:284 [inline]
blk_mq_wait_quiesce_done block/blk-mq.c:281 [inline]
blk_mq_quiesce_queue block/blk-mq.c:304 [inline]
blk_mq_quiesce_queue+0x149/0x1c0 block/blk-mq.c:299
elevator_switch+0x17b/0x7e0 block/elevator.c:576
elevator_change+0x352/0x530 block/elevator.c:681
elevator_set_default+0x29e/0x360 block/elevator.c:754
blk_register_queue+0x48e/0x630 block/blk-sysfs.c:987
__add_disk+0x73f/0xe40 block/genhd.c:528
add_disk_fwnode+0x118/0x5c0 block/genhd.c:597
add_disk include/linux/blkdev.h:794 [inline]
nbd_dev_add+0x77a/0xb10 drivers/block/nbd.c:1984
nbd_init+0x291/0x2b0 drivers/block/nbd.c:2692
do_one_initcall+0x121/0x750 init/main.c:1392
do_initcall_level init/main.c:1454 [inline]
do_initcalls init/main.c:1470 [inline]
do_basic_setup init/main.c:1490 [inline]
kernel_init_freeable+0x6ea/0x7b0 init/main.c:1703
kernel_init+0x1f/0x1e0 init/main.c:1593
ret_from_fork+0x72b/0xd50 arch/x86/kernel/process.c:158
ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:245
-> #2 (&q->elevator_lock){+.+.}-{4:4}:
__mutex_lock_common kernel/locking/mutex.c:646 [inline]
__mutex_lock+0x1a4/0x1b10 kernel/locking/mutex.c:820
elevator_change+0x1bc/0x530 block/elevator.c:679
elevator_set_none+0x92/0xf0 block/elevator.c:769
blk_mq_elv_switch_none block/blk-mq.c:5131 [inline]
__blk_mq_update_nr_hw_queues block/blk-mq.c:5176 [inline]
blk_mq_update_nr_hw_queues+0x4c1/0x15f0 block/blk-mq.c:5241
nbd_start_device+0x1a6/0xbd0 drivers/block/nbd.c:1489
nbd_genl_connect+0xff2/0x1a40 drivers/block/nbd.c:2239
genl_family_rcv_msg_doit+0x214/0x300 net/netlink/genetlink.c:1114
genl_family_rcv_msg net/netlink/genetlink.c:1194 [inline]
genl_rcv_msg+0x560/0x800 net/netlink/genetlink.c:1209
netlink_rcv_skb+0x159/0x420 net/netlink/af_netlink.c:2550
genl_rcv+0x28/0x40 net/netlink/genetlink.c:1218
netlink_unicast_kernel net/netlink/af_netlink.c:1318 [inline]
netlink_unicast+0x585/0x850 net/netlink/af_netlink.c:1344
netlink_sendmsg+0x8b0/0xda0 net/netlink/af_netlink.c:1894
sock_sendmsg_nosec net/socket.c:787 [inline]
__sock_sendmsg net/socket.c:802 [inline]
____sys_sendmsg+0x9e1/0xb70 net/socket.c:2698
___sys_sendmsg+0x190/0x1e0 net/socket.c:2752
__sys_sendmsg+0x170/0x220 net/socket.c:2784
do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
do_syscall_64+0x10b/0xf80 arch/x86/entry/syscall_64.c:94
entry_SYSCALL_64_after_hwframe+0x77/0x7f
-> #1 (&q->q_usage_counter(io)#50){++++}-{0:0}:
blk_alloc_queue+0x610/0x790 block/blk-core.c:461
blk_mq_alloc_queue+0x174/0x290 block/blk-mq.c:4450
__blk_mq_alloc_disk+0x29/0x120 block/blk-mq.c:4497
nbd_dev_add+0x492/0xb10 drivers/block/nbd.c:1954
nbd_init+0x291/0x2b0 drivers/block/nbd.c:2692
do_one_initcall+0x121/0x750 init/main.c:1392
do_initcall_level init/main.c:1454 [inline]
do_initcalls init/main.c:1470 [inline]
do_basic_setup init/main.c:1490 [inline]
kernel_init_freeable+0x6ea/0x7b0 init/main.c:1703
kernel_init+0x1f/0x1e0 init/main.c:1593
ret_from_fork+0x72b/0xd50 arch/x86/kernel/process.c:158
ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:245
-> #0 (fs_reclaim){+.+.}-{0:0}:
check_prev_add kernel/locking/lockdep.c:3165 [inline]
check_prevs_add kernel/locking/lockdep.c:3284 [inline]
validate_chain kernel/locking/lockdep.c:3908 [inline]
__lock_acquire+0x14b8/0x2630 kernel/locking/lockdep.c:5237
lock_acquire kernel/locking/lockdep.c:5868 [inline]
lock_acquire+0x1b1/0x370 kernel/locking/lockdep.c:5825
__fs_reclaim_acquire mm/page_alloc.c:4325 [inline]
fs_reclaim_acquire+0xc4/0x100 mm/page_alloc.c:4339
might_alloc include/linux/sched/mm.h:317 [inline]
slab_pre_alloc_hook mm/slub.c:4520 [inline]
slab_alloc_node mm/slub.c:4875 [inline]
kmem_cache_alloc_noprof+0x4c/0x6e0 mm/slub.c:4905
create_cache mm/slab_common.c:249 [inline]
__kmem_cache_create_args+0x366/0x420 mm/slab_common.c:380
__kmem_cache_create include/linux/slab.h:390 [inline]
alloc_ai drivers/mtd/ubi/attach.c:1464 [inline]
ubi_attach+0x32a/0x4d30 drivers/mtd/ubi/attach.c:1560
ubi_attach_mtd_dev+0x139f/0x32a0 drivers/mtd/ubi/build.c:1004
ctrl_cdev_ioctl+0x36a/0x400 drivers/mtd/ubi/cdev.c:1113
vfs_ioctl fs/ioctl.c:51 [inline]
__do_sys_ioctl fs/ioctl.c:597 [inline]
__se_sys_ioctl fs/ioctl.c:583 [inline]
__x64_sys_ioctl+0x18e/0x210 fs/ioctl.c:583
do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
do_syscall_64+0x10b/0xf80 arch/x86/entry/syscall_64.c:94
entry_SYSCALL_64_after_hwframe+0x77/0x7f
other info that might help us debug this:
Chain exists of:
fs_reclaim --> cpu_hotplug_lock --> slab_mutex
Possible unsafe locking scenario:
CPU0 CPU1
---- ----
lock(slab_mutex);
lock(cpu_hotplug_lock);
lock(slab_mutex);
lock(fs_reclaim);
*** DEADLOCK ***
2 locks held by syz.0.3086/17300:
#0: ffffffff8f931ca0 (ubi_devices_mutex){+.+.}-{4:4}, at: ctrl_cdev_ioctl+0x323/0x400 drivers/mtd/ubi/cdev.c:1112
#1: ffffffff8e97f180 (slab_mutex){+.+.}-{4:4}, at: __kmem_cache_create_args+0x44/0x420 mm/slab_common.c:350
stack backtrace:
CPU: 0 UID: 0 PID: 17300 Comm: syz.0.3086 Tainted: G L syzkaller #0 PREEMPT(full)
Tainted: [L]=SOFTLOCKUP
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 04/18/2026
Call Trace:
<TASK>
__dump_stack lib/dump_stack.c:94 [inline]
dump_stack_lvl+0x100/0x190 lib/dump_stack.c:120
print_circular_bug.cold+0x178/0x1c7 kernel/locking/lockdep.c:2043
check_noncircular+0x146/0x160 kernel/locking/lockdep.c:2175
check_prev_add kernel/locking/lockdep.c:3165 [inline]
check_prevs_add kernel/locking/lockdep.c:3284 [inline]
validate_chain kernel/locking/lockdep.c:3908 [inline]
__lock_acquire+0x14b8/0x2630 kernel/locking/lockdep.c:5237
lock_acquire kernel/locking/lockdep.c:5868 [inline]
lock_acquire+0x1b1/0x370 kernel/locking/lockdep.c:5825
__fs_reclaim_acquire mm/page_alloc.c:4325 [inline]
fs_reclaim_acquire+0xc4/0x100 mm/page_alloc.c:4339
might_alloc include/linux/sched/mm.h:317 [inline]
slab_pre_alloc_hook mm/slub.c:4520 [inline]
slab_alloc_node mm/slub.c:4875 [inline]
kmem_cache_alloc_noprof+0x4c/0x6e0 mm/slub.c:4905
create_cache mm/slab_common.c:249 [inline]
__kmem_cache_create_args+0x366/0x420 mm/slab_common.c:380
__kmem_cache_create include/linux/slab.h:390 [inline]
alloc_ai drivers/mtd/ubi/attach.c:1464 [inline]
ubi_attach+0x32a/0x4d30 drivers/mtd/ubi/attach.c:1560
ubi_attach_mtd_dev+0x139f/0x32a0 drivers/mtd/ubi/build.c:1004
ctrl_cdev_ioctl+0x36a/0x400 drivers/mtd/ubi/cdev.c:1113
vfs_ioctl fs/ioctl.c:51 [inline]
__do_sys_ioctl fs/ioctl.c:597 [inline]
__se_sys_ioctl fs/ioctl.c:583 [inline]
__x64_sys_ioctl+0x18e/0x210 fs/ioctl.c:583
do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
do_syscall_64+0x10b/0xf80 arch/x86/entry/syscall_64.c:94
entry_SYSCALL_64_after_hwframe+0x77/0x7f
RIP: 0033:0x7f0959f9cdd9
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:00007f095ae60028 EFLAGS: 00000246 ORIG_RAX: 0000000000000010
RAX: ffffffffffffffda RBX: 00007f095a216090 RCX: 00007f0959f9cdd9
RDX: 0000200000000440 RSI: 0000000040186f40 RDI: 0000000000000009
RBP: 00007f095a032d69 R08: 0000000000000000 R09: 0000000000000000
R10: 0000000000000000 R11: 0000000000000246 R12: 0000000000000000
R13: 00007f095a216128 R14: 00007f095a216090 R15: 00007ffd41037cc8
</TASK>
ubi16: scanning is finished
ubi16 error: ubi_read_volume_table: the layout volume was not found
ubi16 error: ubi_attach_mtd_dev: failed to attach mtd0, error -22
Reply: The bug report indicates a lockdep warning about a possible circular locking dependency (deadlock) involving `slab_mutex`, `fs_reclaim`, `cpu_hotplug_lock`, and several locks related to the Network Block Device (NBD) and network sockets.
### Analysis of the Dependency Chain
The lockdep report shows the following existing dependency chain:
1. `fs_reclaim` -> `q_usage_counter` (established during `blk_alloc_queue`)
2. `q_usage_counter` -> `elevator_lock` (from `elevator_change` calling `blk_mq_freeze_queue`)
3. `elevator_lock` -> `srcu` (from `elevator_change` calling `blk_mq_quiesce_queue`)
4. `srcu` -> `cmd->lock` (from `blk_mq_run_hw_queue` dispatching requests to NBD)
5. `cmd->lock` -> `tx_lock` (from `nbd_queue_rq` calling `nbd_handle_cmd`)
6. `tx_lock` -> `sk_lock` (from `send_disconnects` calling `sock_xmit`)
7. `sk_lock` -> `cpu_hotplug_lock` (from `inet_stream_connect` calling `cpus_read_lock`)
8. `cpu_hotplug_lock` -> `slab_mutex` (from `kmem_cache_destroy` acquiring both)
The new dependency that triggers the warning is:
`slab_mutex` -> `fs_reclaim`
This new dependency is established because `__kmem_cache_create_args` holds `slab_mutex` and then performs memory allocations with `GFP_KERNEL` (which can enter direct memory reclaim and acquire `fs_reclaim`). In the syzbot report, this happens during `ubi_attach_mtd_dev` which dynamically creates a kmem cache for the attached device.
### Security Impact
* **Exploitable**: No. This is a locking issue (deadlock) and does not result in memory corruption, out-of-bounds access, or use-after-free. It cannot be exploited for privilege escalation.
* **Denial of Service**: Yes. If the exact timing conditions are met, the circular dependency can lead to a system deadlock (hang), resulting in a Denial of Service.
* **Accessible From Unprivileged Processes / User Namespaces**: No. Triggering this deadlock requires setting up the entire dependency chain. The chain heavily relies on the Network Block Device (NBD) subsystem (`cmd->lock`, `tx_lock`). Configuring NBD devices and sending netlink commands to them requires global `CAP_SYS_ADMIN` (checked via `netlink_capable(skb, CAP_SYS_ADMIN)` which verifies capabilities in the `init_user_ns`). Additionally, dynamically creating kmem caches (which triggers the `slab_mutex` -> `fs_reclaim` link) is typically restricted to module initialization or privileged operations like `ubi_attach` (which requires global `CAP_SYS_RESOURCE`). Thus, unprivileged users (even within user namespaces) cannot set up the required environment or trigger the deadlock.
### Conclusion
This is a complex lockdep warning involving NBD, networking, and slab cache creation. It represents a theoretical deadlock that could cause a Denial of Service, but it is strictly limited to highly privileged users (root/CAP_SYS_ADMIN) who can configure NBD devices and attach UBI devices. It poses no security risk to unprivileged users.
|
| 6/2 |
2026/05/20 07:06 |
llm |
expert |
0m
Model:
Tokens:
input: 13257
output: 23
thoughts: 1275
Thoughts: **Analyzing a Circular Locking Dependency in the Kernel**
Okay, so I'm looking at this lockdep warning, and it's highlighting a potential circular dependency. Specifically, I see that the `syzkaller` process is trying to acquire `fs_reclaim`, but it's already holding `slab_mutex`. This is immediately concerning, as it suggests a classic deadlock scenario, where two or more threads are waiting for each other to release a resource.
The warning presents the dependency chain, and I need to parse this carefully:
It looks like the chain is:
1. `slab_mutex` ->
2. `cpu_hotplug_lock` ->
3. `sk_lock-AF_INET` ->
4. `&nsock->tx_lock` ->
5. `&cmd->lock` ->
6. `set->srcu` ->
7. `&q->elevator_lock` ->
8. `&q->q_usage_counter(io)#50` ->
9. `fs_reclaim`
Now, let's zoom in on the critical point. The report indicates that `__kmem_cache_create_args` is the function of interest. Specifically, I'm concerned that `__kmem_cache_create_args` holds `slab_mutex`... then proceeds to allocate with `GFP_KERNEL`. This is a smell. Allocations with `GFP_KERNEL` can trigger reclaim and that, by implication, means we are trying to acquire `fs_reclaim`. This could certainly create a circular dependency.
Let's quickly check the implementation of `__kmem_cache_create_args` in `mm/slab_common.c` to confirm this.
|
| 7/2 |
2026/05/20 07:06 |
tool |
grepper |
0m
Args: map[Expression:__kmem_cache_create_args]
Results: map[Output:include/linux/slab.h=285=struct kmem_cache_args {
--
include/linux/slab.h-376-
include/linux/slab.h:377:struct kmem_cache *__kmem_cache_create_args(const char *name,
include/linux/slab.h-378- unsigned int object_size,
--
include/linux/slab.h=382=__kmem_cache_create(const char *name, unsigned int size, unsigned int align,
--
include/linux/slab.h-389-
include/linux/slab.h:390: return __kmem_cache_create_args(name, size, &kmem_args, flags);
include/linux/slab.h-391-}
--
include/linux/slab.h=412=kmem_cache_create_usercopy(const char *name, unsigned int size,
--
include/linux/slab.h-423-
include/linux/slab.h:424: return __kmem_cache_create_args(name, size, &kmem_args, flags);
include/linux/slab.h-425-}
--
include/linux/slab.h=429=__kmem_cache_default_args(const char *name, unsigned int size,
--
include/linux/slab.h-438-
include/linux/slab.h:439: return __kmem_cache_create_args(name, size, &kmem_default_args, flags);
include/linux/slab.h-440-}
--
include/linux/slab.h-454- *
include/linux/slab.h:455: * See __kmem_cache_create_args() which implements this.
include/linux/slab.h-456- *
--
include/linux/slab.h-468- _Generic((__args), \
include/linux/slab.h:469: struct kmem_cache_args *: __kmem_cache_create_args, \
include/linux/slab.h-470- void *: __kmem_cache_default_args, \
--
include/linux/slab.h=474=int kmem_cache_shrink(struct kmem_cache *s);
--
include/linux/slab.h-484-#define KMEM_CACHE(__struct, __flags) \
include/linux/slab.h:485: __kmem_cache_create_args(#__struct, sizeof(struct __struct), \
include/linux/slab.h-486- &(struct kmem_cache_args) { \
--
include/linux/slab.h-494-#define KMEM_CACHE_USERCOPY(__struct, __flags, __field) \
include/linux/slab.h:495: __kmem_cache_create_args(#__struct, sizeof(struct __struct), \
include/linux/slab.h-496- &(struct kmem_cache_args) { \
--
mm/slab_common.c=267=__kmem_cache_alias(const char *name, unsigned int size, slab_flags_t flags,
--
mm/slab_common.c-291-/**
mm/slab_common.c:292: * __kmem_cache_create_args - Create a kmem cache.
mm/slab_common.c-293- * @name: A string which is used in /proc/slabinfo to identify this cache.
--
mm/slab_common.c-317- */
mm/slab_common.c:318:struct kmem_cache *__kmem_cache_create_args(const char *name,
mm/slab_common.c-319- unsigned int object_size,
--
mm/slab_common.c-401-}
mm/slab_common.c:402:EXPORT_SYMBOL(__kmem_cache_create_args);
mm/slab_common.c-403-
--
tools/include/linux/slab.h=153=struct kmem_cache *
tools/include/linux/slab.h:154:__kmem_cache_create_args(const char *name, unsigned int size,
tools/include/linux/slab.h-155- struct kmem_cache_args *args, unsigned int flags);
--
tools/include/linux/slab.h=159=__kmem_cache_default_args(const char *name, unsigned int size,
--
tools/include/linux/slab.h-163-
tools/include/linux/slab.h:164: return __kmem_cache_create_args(name, size, &kmem_default_args, flags);
tools/include/linux/slab.h-165-}
--
tools/include/linux/slab.h=168=__kmem_cache_create(const char *name, unsigned int size, unsigned int align,
--
tools/include/linux/slab.h-175-
tools/include/linux/slab.h:176: return __kmem_cache_create_args(name, size, &kmem_args, flags);
tools/include/linux/slab.h-177-}
--
tools/include/linux/slab.h-180- _Generic((__args), \
tools/include/linux/slab.h:181: struct kmem_cache_args *: __kmem_cache_create_args, \
tools/include/linux/slab.h-182- void *: __kmem_cache_default_args, \
--
tools/testing/shared/linux.c=230=struct kmem_cache *
tools/testing/shared/linux.c:231:__kmem_cache_create_args(const char *name, unsigned int size,
tools/testing/shared/linux.c-232- struct kmem_cache_args *args,
]
|
| 8/2 |
2026/05/20 07:06 |
llm |
expert |
0m
Model:
Tokens:
input: 16427
output: 45
thoughts: 26
Thoughts: Here's my take on the thought process, summarized as you requested:
**Diving into Slab Allocation**
Okay, time to dig into the guts of the kernel's slab allocator again. I'm going to focus on `__kmem_cache_create_args` specifically. I know this function is the core of how new slab caches are brought into existence. Looking at it in `mm/slab_common.c` is the logical place to start – that's where the fundamental cache management logic resides. I want to refresh my memory on the argument handling in this core function. My interest lies in understanding the finer points of how memory is carved up and managed at the slab level. I anticipate a deeper look at its implementation will provide further insights on efficient memory utilization for the kernel.
|
| 9/2 |
2026/05/20 07:06 |
tool |
codesearch-definition-source |
0m
Args: map[ContextFile:mm/slab_common.c IncludeLines:true Name:__kmem_cache_create_args]
Results: map[SourceCode: 291: /**
292: * __kmem_cache_create_args - Create a kmem cache.
293: * @name: A string which is used in /proc/slabinfo to identify this cache.
294: * @object_size: The size of objects to be created in this cache.
295: * @args: Additional arguments for the cache creation (see
296: * &struct kmem_cache_args).
297: * @flags: See the descriptions of individual flags. The common ones are listed
298: * in the description below.
299: *
300: * Not to be called directly, use the kmem_cache_create() wrapper with the same
301: * parameters.
302: *
303: * Commonly used @flags:
304: *
305: * &SLAB_ACCOUNT - Account allocations to memcg.
306: *
307: * &SLAB_HWCACHE_ALIGN - Align objects on cache line boundaries.
308: *
309: * &SLAB_RECLAIM_ACCOUNT - Objects are reclaimable.
310: *
311: * &SLAB_TYPESAFE_BY_RCU - Slab page (not individual objects) freeing delayed
312: * by a grace period - see the full description before using.
313: *
314: * Context: Cannot be called within a interrupt, but can be interrupted.
315: *
316: * Return: a pointer to the cache on success, NULL on failure.
317: */
318: struct kmem_cache *__kmem_cache_create_args(const char *name,
319: unsigned int object_size,
320: struct kmem_cache_args *args,
321: slab_flags_t flags)
322: {
323: struct kmem_cache *s = NULL;
324: const char *cache_name;
325: int err;
326:
327: #ifdef CONFIG_SLUB_DEBUG
328: /*
329: * If no slab_debug was enabled globally, the static key is not yet
330: * enabled by setup_slub_debug(). Enable it if the cache is being
331: * created with any of the debugging flags passed explicitly.
332: * It's also possible that this is the first cache created with
333: * SLAB_STORE_USER and we should init stack_depot for it.
334: */
335: if (flags & SLAB_DEBUG_FLAGS)
336: static_branch_enable(&slub_debug_enabled);
337: if (flags & SLAB_STORE_USER)
338: stack_depot_init();
339: #else
340: flags &= ~SLAB_DEBUG_FLAGS;
341: #endif
342:
343: /*
344: * Caches with specific capacity are special enough. It's simpler to
345: * make them unmergeable.
346: */
347: if (args->sheaf_capacity)
348: flags |= SLAB_NO_MERGE;
349:
350: mutex_lock(&slab_mutex);
351:
352: err = kmem_cache_sanity_check(name, object_size);
353: if (err) {
354: goto out_unlock;
355: }
356:
357: if (flags & ~SLAB_FLAGS_PERMITTED) {
358: err = -EINVAL;
359: goto out_unlock;
360: }
361:
362: /* Fail closed on bad usersize of useroffset values. */
363: if (!IS_ENABLED(CONFIG_HARDENED_USERCOPY) ||
364: WARN_ON(!args->usersize && args->useroffset) ||
365: WARN_ON(object_size < args->usersize ||
366: object_size - args->usersize < args->useroffset))
367: args->usersize = args->useroffset = 0;
368:
369: s = __kmem_cache_alias(name, object_size, flags, args);
370: if (s)
371: goto out_unlock;
372:
373: cache_name = kstrdup_const(name, GFP_KERNEL);
374: if (!cache_name) {
375: err = -ENOMEM;
376: goto out_unlock;
377: }
378:
379: args->align = calculate_alignment(flags, args->align, object_size);
380: s = create_cache(cache_name, object_size, args, flags);
381: if (IS_ERR(s)) {
382: err = PTR_ERR(s);
383: kfree_const(cache_name);
384: }
385:
386: out_unlock:
387: mutex_unlock(&slab_mutex);
388:
389: if (err) {
390: if (flags & SLAB_PANIC)
391: panic("%s: Failed to create slab '%s'. Error %d\n",
392: __func__, name, err);
393: else {
394: pr_warn("%s(%s) failed with error %d\n",
395: __func__, name, err);
396: dump_stack();
397: }
398: return NULL;
399: }
400: return s;
401: }
SourceFile:mm/slab_common.c]
|
| 10/2 |
2026/05/20 07:06 |
llm |
expert |
0m
Model:
Tokens:
input: 18348
output: 39
thoughts: 77
Thoughts: Okay, let's break this down.
**Memory Allocation Deep Dive**
Alright, line 373, here we are, creating the cache name with `cache_name = kstrdup_const(name, GFP_KERNEL);`. Simple string duplication, allocating kernel memory with `kstrdup_const`. Nothing too complex there. Now, the real question is what happens with that cache name.
Then, line 380: `s = create_cache(cache_name, object_size, args, flags);`. We call `create_cache`... and there it is. **`create_cache` itself also allocates memory**. This is the key point. We're double-dipping, potentially. We have an allocation for the `cache_name` and *another* allocation within `create_cache`. Let's step into `create_cache`. We need to see exactly what kind of memory management is happening in there. Is it just internal metadata for the cache, or is it allocating buffers for objects? We need to verify the allocation patterns to ensure we're efficient and avoid memory fragmentation, or even leaks. I should review `create_cache` to figure out what's really happening.
|
| 11/2 |
2026/05/20 07:06 |
tool |
codesearch-definition-source |
0m
Args: map[ContextFile:mm/slab_common.c IncludeLines:true Name:create_cache]
Results: map[SourceCode: 232: static struct kmem_cache *create_cache(const char *name,
233: unsigned int object_size,
234: struct kmem_cache_args *args,
235: slab_flags_t flags)
236: {
237: struct kmem_cache *s;
238: int err;
239:
240: /* If a custom freelist pointer is requested make sure it's sane. */
241: err = -EINVAL;
242: if (args->use_freeptr_offset &&
243: (args->freeptr_offset >= object_size ||
244: (!(flags & SLAB_TYPESAFE_BY_RCU) && !args->ctor) ||
245: !IS_ALIGNED(args->freeptr_offset, __alignof__(freeptr_t))))
246: goto out;
247:
248: err = -ENOMEM;
249: s = kmem_cache_zalloc(kmem_cache, GFP_KERNEL);
250: if (!s)
251: goto out;
252: err = do_kmem_cache_create(s, name, object_size, args, flags);
253: if (err)
254: goto out_free_cache;
255:
256: s->refcount = 1;
257: list_add(&s->list, &slab_caches);
258: return s;
259:
260: out_free_cache:
261: kmem_cache_free(kmem_cache, s);
262: out:
263: return ERR_PTR(err);
264: }
SourceFile:mm/slab_common.c]
|
| 12/2 |
2026/05/20 07:06 |
llm |
expert |
0m
Model:
Tokens:
input: 19252
output: 41
thoughts: 1264
Thoughts: **Analyzing a Kernel Lock Dependency Issue**
Okay, so I'm looking at this syzbot report, and it appears we have a lock dependency issue, specifically related to `slab_mutex` and `fs_reclaim`. Line 249 of `create_cache` uses `kmem_cache_zalloc`, and `kstrdup_const` uses `kstrdup`, both which call for `GFP_KERNEL` allocation. This means that `__kmem_cache_create_args` holds `slab_mutex` during a `GFP_KERNEL` allocation. This is a potential problem because, as we know, `slab_mutex` can be involved in a dependency chain with `fs_reclaim`.
The syzbot report is highlighting the following: a process is trying to acquire `fs_reclaim`, but it's already holding `slab_mutex`. This is the deadlock. The report shows the call chain starting at `kmem_cache_destroy`, going through `p9_client_destroy`, `v9fs_session_close`, `v9fs_kill_super`, `deactivate_locked_super`, `v9fs_get_tree`, `vfs_get_tree`, `fc_mount`, `do_new_mount_fc`, `do_new_mount`, `path_mount`, `do_mount` to `__do_sys_mount`. `kmem_cache_destroy` acquires `slab_mutex`.
Now, the classic dependency chain is: `fs_reclaim` -> `cpu_hotplug_lock` -> `slab_mutex`. The syzbot report shows that the task is trying to acquire `fs_reclaim` while holding `slab_mutex`, and this chain is much deeper.
Digging further, I see that the full dependency chain is: `fs_reclaim` -> `q_usage_counter` -> `elevator_lock` -> `srcu` -> `cmd->lock` -> `tx_lock` -> `sk_lock` -> `cpu_hotplug_lock` -> `slab_mutex`. So it looks like `slab_mutex` is dependent on `fs_reclaim`.
So the actual lock ordering issue is: The syzbot report clearly states the task is holding `slab_mutex` and trying to acquire `fs_reclaim`. Because `__kmem_cache_create_args` is doing `GFP_KERNEL` allocation *under* `slab_mutex`, this means the task has `slab_mutex` and tries to acquire `fs_reclaim`. This breaks the existing chain.
The interesting part is that `fs_reclaim` to `q_usage_counter` occurs within `blk_alloc_queue`, which is the entry point for `nbd_dev_add`. We need to verify that `blk_alloc_queue` does indeed acquire `q_usage_counter`.
|
| 13/2 |
2026/05/20 07:06 |
tool |
codesearch-definition-source |
0m
Args: map[ContextFile:block/blk-core.c IncludeLines:true Name:blk_alloc_queue]
Results: map[SourceCode: 393: struct request_queue *blk_alloc_queue(struct queue_limits *lim, int node_id)
394: {
395: struct request_queue *q;
396: int error;
397:
398: q = kmem_cache_alloc_node(blk_requestq_cachep, GFP_KERNEL | __GFP_ZERO,
399: node_id);
400: if (!q)
401: return ERR_PTR(-ENOMEM);
402:
403: q->last_merge = NULL;
404:
405: q->id = ida_alloc(&blk_queue_ida, GFP_KERNEL);
406: if (q->id < 0) {
407: error = q->id;
408: goto fail_q;
409: }
410:
411: q->stats = blk_alloc_queue_stats();
412: if (!q->stats) {
413: error = -ENOMEM;
414: goto fail_id;
415: }
416:
417: error = blk_set_default_limits(lim);
418: if (error)
419: goto fail_stats;
420: q->limits = *lim;
421:
422: q->node = node_id;
423:
424: atomic_set(&q->nr_active_requests_shared_tags, 0);
425:
426: timer_setup(&q->timeout, blk_rq_timed_out_timer, 0);
427: INIT_WORK(&q->timeout_work, blk_timeout_work);
428: INIT_LIST_HEAD(&q->icq_list);
429:
430: refcount_set(&q->refs, 1);
431: mutex_init(&q->debugfs_mutex);
432: mutex_init(&q->elevator_lock);
433: mutex_init(&q->sysfs_lock);
434: mutex_init(&q->limits_lock);
435: mutex_init(&q->rq_qos_mutex);
436: spin_lock_init(&q->queue_lock);
437:
438: init_waitqueue_head(&q->mq_freeze_wq);
439: mutex_init(&q->mq_freeze_lock);
440:
441: blkg_init_queue(q);
442:
443: /*
444: * Init percpu_ref in atomic mode so that it's faster to shutdown.
445: * See blk_register_queue() for details.
446: */
447: error = percpu_ref_init(&q->q_usage_counter,
448: blk_queue_usage_counter_release,
449: PERCPU_REF_INIT_ATOMIC, GFP_KERNEL);
450: if (error)
451: goto fail_stats;
452: lockdep_register_key(&q->io_lock_cls_key);
453: lockdep_register_key(&q->q_lock_cls_key);
454: lockdep_init_map(&q->io_lockdep_map, "&q->q_usage_counter(io)",
455: &q->io_lock_cls_key, 0);
456: lockdep_init_map(&q->q_lockdep_map, "&q->q_usage_counter(queue)",
457: &q->q_lock_cls_key, 0);
458:
459: /* Teach lockdep about lock ordering (reclaim WRT queue freeze lock). */
460: fs_reclaim_acquire(GFP_KERNEL);
461: rwsem_acquire_read(&q->io_lockdep_map, 0, 0, _RET_IP_);
462: rwsem_release(&q->io_lockdep_map, _RET_IP_);
463: fs_reclaim_release(GFP_KERNEL);
464:
465: q->nr_requests = BLKDEV_DEFAULT_RQ;
466: q->async_depth = BLKDEV_DEFAULT_RQ;
467:
468: return q;
469:
470: fail_stats:
471: blk_free_queue_stats(q->stats);
472: fail_id:
473: ida_free(&blk_queue_ida, q->id);
474: fail_q:
475: kmem_cache_free(blk_requestq_cachep, q);
476: return ERR_PTR(error);
477: }
SourceFile:block/blk-core.c]
|
| 14/2 |
2026/05/20 07:06 |
llm |
expert |
0m
Model:
Tokens:
input: 22569
output: 43
thoughts: 492
Thoughts: **Lock Ordering Conundrum in Block Layer Initialization**
Okay, so `blk_alloc_queue` is explicitly setting up a lock ordering that's crucial for understanding the dependencies. It's using `fs_reclaim_acquire` and `rwsem_acquire_read` to teach lockdep that `fs_reclaim` happens before `q_usage_counter`. Specifically, this looks like: `fs_reclaim` -> `q_usage_counter`. That's straightforward enough.
Then, the trace shows that `q_usage_counter` goes before `elevator_lock`, which is expected. I have seen this before: `q_usage_counter` -> `elevator_lock` is from the call stack: `nbd_start_device` -> `blk_mq_update_nr_hw_queues` -> `elevator_change` and the like. This makes sense in the overall architecture.
But, hang on a second... `nbd_start_device` is calling `blk_mq_update_nr_hw_queues`, and that's *acquiring* `elevator_lock`. However, I can't immediately see where it might be acquiring `q_usage_counter`. This is where it gets interesting and I need to investigate further. It's time to dig into the `nbd_start_device` function itself to figure out the missing piece.
|
| 15/2 |
2026/05/20 07:07 |
tool |
codesearch-definition-source |
0m
Args: map[ContextFile:drivers/block/nbd.c IncludeLines:true Name:nbd_start_device]
Results: map[SourceCode:1471: static int nbd_start_device(struct nbd_device *nbd)
1472: {
1473: struct nbd_config *config = nbd->config;
1474: int num_connections = config->num_connections;
1475: int error = 0, i;
1476:
1477: if (nbd->pid)
1478: return -EBUSY;
1479: if (!config->socks)
1480: return -EINVAL;
1481: if (num_connections > 1 &&
1482: !(config->flags & NBD_FLAG_CAN_MULTI_CONN)) {
1483: dev_err(disk_to_dev(nbd->disk), "server does not support multiple connections per device.\n");
1484: return -EINVAL;
1485: }
1486:
1487: retry:
1488: mutex_unlock(&nbd->config_lock);
1489: blk_mq_update_nr_hw_queues(&nbd->tag_set, num_connections);
1490: mutex_lock(&nbd->config_lock);
1491:
1492: /* if another code path updated nr_hw_queues, retry until succeed */
1493: if (num_connections != config->num_connections) {
1494: num_connections = config->num_connections;
1495: goto retry;
1496: }
1497:
1498: nbd->pid = task_pid_nr(current);
1499:
1500: nbd_parse_flags(nbd);
1501:
1502: error = device_create_file(disk_to_dev(nbd->disk), &pid_attr);
1503: if (error) {
1504: dev_err(disk_to_dev(nbd->disk), "device_create_file failed for pid!\n");
1505: return error;
1506: }
1507: set_bit(NBD_RT_HAS_PID_FILE, &config->runtime_flags);
1508:
1509: nbd_dev_dbg_init(nbd);
1510: for (i = 0; i < num_connections; i++) {
1511: struct recv_thread_args *args;
1512:
1513: args = kzalloc_obj(*args);
1514: if (!args) {
1515: sock_shutdown(nbd);
1516: /*
1517: * If num_connections is m (2 < m),
1518: * and NO.1 ~ NO.n(1 < n < m) kzallocs are successful.
1519: * But NO.(n + 1) failed. We still have n recv threads.
1520: * So, add flush_workqueue here to prevent recv threads
1521: * dropping the last config_refs and trying to destroy
1522: * the workqueue from inside the workqueue.
1523: */
1524: if (i)
1525: flush_workqueue(nbd->recv_workq);
1526: return -ENOMEM;
1527: }
1528: sk_set_memalloc(config->socks[i]->sock->sk);
1529: if (nbd->tag_set.timeout)
1530: config->socks[i]->sock->sk->sk_sndtimeo =
1531: nbd->tag_set.timeout;
1532: atomic_inc(&config->recv_threads);
1533: refcount_inc(&nbd->config_refs);
1534: INIT_WORK(&args->work, recv_work);
1535: args->nbd = nbd;
1536: args->nsock = config->socks[i];
1537: args->index = i;
1538: queue_work(nbd->recv_workq, &args->work);
1539: }
1540: return nbd_set_size(nbd, config->bytesize, nbd_blksize(config));
1541: }
SourceFile:drivers/block/nbd.c]
|
| 16/2 |
2026/05/20 07:07 |
llm |
expert |
0m
Model:
Tokens:
input: 24589
output: 48
thoughts: 44
Thoughts: Okay, here's my take on those thoughts, framed as an expert's internal monologue:
**Investigating `blk_mq_update_nr_hw_queues`**
Right, so `blk_mq_update_nr_hw_queues`. I see that the code is dealing with updating the number of hardware queues, which is core to block I/O performance. My immediate concern, as always when dealing with concurrent data structures, is synchronization. The question that pops up in my mind is, "Does this function properly handle the concurrency?" specifically, I wonder if it uses appropriate locking or atomic operations. It looks like it's acquiring `q_usage_counter`. Good, that means it is using a lock to protect the shared data. Let me go check `blk_mq_update_nr_hw_queues` to confirm. I want to see precisely how and when that counter is being managed. That will be the key to understanding its correctness. I'll need to dig into the details to assess its impact on the system.
|
| 17/2 |
2026/05/20 07:07 |
tool |
codesearch-definition-source |
0m
Args: map[ContextFile:block/blk-mq.c IncludeLines:true Name:blk_mq_update_nr_hw_queues]
Results: map[SourceCode:5237: void blk_mq_update_nr_hw_queues(struct blk_mq_tag_set *set, int nr_hw_queues)
5238: {
5239: down_write(&set->update_nr_hwq_lock);
5240: mutex_lock(&set->tag_list_lock);
5241: __blk_mq_update_nr_hw_queues(set, nr_hw_queues);
5242: mutex_unlock(&set->tag_list_lock);
5243: up_write(&set->update_nr_hwq_lock);
5244: }
SourceFile:block/blk-mq.c]
|
| 18/2 |
2026/05/20 07:07 |
llm |
expert |
0m
Model:
Tokens:
input: 25103
output: 45
thoughts: 1400
Thoughts: **Lock Dependency Analysis in Block Layer**
Okay, let's break this down. My initial thought was, "Hey, `__blk_mq_update_nr_hw_queues` is calling `blk_mq_elv_switch_none`, which in turn calls `elevator_change`. That's interesting, but where is `q_usage_counter` being acquired in relation to the `elevator_lock`?"
The lockdep trace provides some clues. It shows that `elevator_lock` is acquired within `elevator_change`, and the call chain is clearly laid out, starting with `__blk_mq_update_nr_hw_queues` and ultimately tracing back to a `genl_family_rcv_msg_doit` call. The important part is how `elevator_lock` is acquired: through `elevator_change` called by `blk_mq_elv_switch_none`.
Now, I needed to understand where `q_usage_counter` comes into play. The trace then showed a completely separate path, starting with `blk_alloc_queue`, where `q_usage_counter` is acquired and released. The key is that the trace clearly shows that `blk_alloc_queue` takes `q_usage_counter`. This is interesting, but I don't see the dependency between `elevator_lock` and `q_usage_counter` directly from this second trace.
I was getting nowhere, but then I remember `blk_mq_elv_switch_none` may freeze the queue. Let's check the code for `blk_mq_elv_switch_none` - and bingo, here is the answer. It calls `blk_mq_freeze_queue`, which acquires `q_usage_counter`!
|
| 19/2 |
2026/05/20 07:07 |
tool |
codesearch-definition-source |
0m
Args: map[ContextFile:block/blk-mq.c IncludeLines:true Name:blk_mq_elv_switch_none]
Results: map[SourceCode:5093: /*
5094: * Stores elevator name and type in ctx and set current elevator to none.
5095: */
5096: static int blk_mq_elv_switch_none(struct request_queue *q,
5097: struct xarray *elv_tbl)
5098: {
5099: struct elv_change_ctx *ctx;
5100:
5101: lockdep_assert_held_write(&q->tag_set->update_nr_hwq_lock);
5102:
5103: /*
5104: * Accessing q->elevator without holding q->elevator_lock is safe here
5105: * because we're called from nr_hw_queue update which is protected by
5106: * set->update_nr_hwq_lock in the writer context. So, scheduler update/
5107: * switch code (which acquires the same lock in the reader context)
5108: * can't run concurrently.
5109: */
5110: if (q->elevator) {
5111: ctx = xa_load(elv_tbl, q->id);
5112: if (WARN_ON_ONCE(!ctx))
5113: return -ENOENT;
5114:
5115: ctx->name = q->elevator->type->elevator_name;
5116:
5117: /*
5118: * Before we switch elevator to 'none', take a reference to
5119: * the elevator module so that while nr_hw_queue update is
5120: * running, no one can remove elevator module. We'd put the
5121: * reference to elevator module later when we switch back
5122: * elevator.
5123: */
5124: __elevator_get(q->elevator->type);
5125:
5126: /*
5127: * Store elevator type so that we can release the reference
5128: * taken above later.
5129: */
5130: ctx->type = q->elevator->type;
5131: elevator_set_none(q);
5132: }
5133: return 0;
5134: }
SourceFile:block/blk-mq.c]
|
| 20/2 |
2026/05/20 07:07 |
llm |
expert |
0m
Model:
Tokens:
input: 27568
output: 39
thoughts: 28
Thoughts: Here's my thought process, summarized as requested:
**Digging into `elevator_set_none`**
Okay, hold on a second. I'm seeing `elevator_set_none` called, and I'm pretty sure that calls `elevator_change` directly, right? I need to verify that. My intuition is telling me that there's a specific function call that I need to confirm; it’s a standard convention but I have to be certain. Let me go double check the implementation of `elevator_set_none` to make absolutely sure. I need to understand the control flow here perfectly.
|
| 21/2 |
2026/05/20 07:07 |
tool |
codesearch-definition-source |
0m
Args: map[ContextFile:block/elevator.c IncludeLines:true Name:elevator_set_none]
Results: map[SourceCode: 762: void elevator_set_none(struct request_queue *q)
763: {
764: struct elv_change_ctx ctx = {
765: .name = "none",
766: };
767: int err;
768:
769: err = elevator_change(q, &ctx);
770: if (err < 0)
771: pr_warn("%s: set none elevator failed %d\n", __func__, err);
772: }
SourceFile:block/elevator.c]
|
| 22/2 |
2026/05/20 07:07 |
llm |
expert |
0m
Model:
Tokens:
input: 27946
output: 37
thoughts: 7
Thoughts: Okay, here's my attempt at summarizing the thought process, tailored for an expert audience, and written in the first person:
**Elevator Change Inquiry**
So, I'm thinking about the current state of things, and I'm encountering a bit of a mental blip here... specifically, I'm finding myself wondering about the implications of a hypothetical operation, what I'm calling `elevator_change`. Is this even a valid query, a worthwhile operation to consider, given the context? What are the likely edge cases or constraints to watch out for? Should I be considering the performance implications of this hypothetical process? Is this specific term even being utilized in a relevant way? It's the nuance of this `elevator_change` that I'm trying to wrap my head around. I'm probably going to need to dig deeper into the system's current state and explore the potential impact of an action such as `elevator_change`. I'm going to need to consider all the pieces involved and ensure this process is well-formed.
|
| 23/2 |
2026/05/20 07:07 |
tool |
codesearch-definition-source |
0m
Args: map[ContextFile:block/elevator.c IncludeLines:true Name:elevator_change]
Results: map[SourceCode: 650: /*
651: * Switch this queue to the given IO scheduler.
652: */
653: static int elevator_change(struct request_queue *q, struct elv_change_ctx *ctx)
654: {
655: unsigned int memflags;
656: struct blk_mq_tag_set *set = q->tag_set;
657: int ret = 0;
658:
659: lockdep_assert_held(&set->update_nr_hwq_lock);
660:
661: if (strncmp(ctx->name, "none", 4)) {
662: ret = blk_mq_alloc_sched_res(q, ctx->type, &ctx->res,
663: set->nr_hw_queues);
664: if (ret)
665: return ret;
666: }
667:
668: memflags = blk_mq_freeze_queue(q);
669: /*
670: * May be called before adding disk, when there isn't any FS I/O,
671: * so freezing queue plus canceling dispatch work is enough to
672: * drain any dispatch activities originated from passthrough
673: * requests, then no need to quiesce queue which may add long boot
674: * latency, especially when lots of disks are involved.
675: *
676: * Disk isn't added yet, so verifying queue lock only manually.
677: */
678: blk_mq_cancel_work_sync(q);
679: mutex_lock(&q->elevator_lock);
680: if (!(q->elevator && elevator_match(q->elevator->type, ctx->name)))
681: ret = elevator_switch(q, ctx);
682: mutex_unlock(&q->elevator_lock);
683: blk_mq_unfreeze_queue(q, memflags);
684: if (!ret)
685: ret = elevator_change_done(q, ctx);
686:
687: /*
688: * Free sched resource if it's allocated but we couldn't switch elevator.
689: */
690: if (!ctx->new)
691: blk_mq_free_sched_res(&ctx->res, ctx->type, set);
692:
693: return ret;
694: }
SourceFile:block/elevator.c]
|
| 24/2 |
2026/05/20 07:07 |
llm |
expert |
0m
Model:
Tokens:
input: 28929
output: 43
thoughts: 155
Thoughts: **Analyzing the Lock Ordering in the Block Layer**
Okay, so I'm tracing this `elevator_change` function and it looks like it calls `blk_mq_freeze_queue` on a given queue, `q`. Right off the bat, `blk_mq_freeze_queue` grabs `q_usage_counter`. Interesting. Then, *after* that, within the same function `elevator_change` we have `q->elevator_lock` being acquired. So, to be clear, the order of lock acquisition is `q_usage_counter` -> `elevator_lock`. This is important, I need to keep this straight.
Hmm, but what is `blk_mq_freeze_queue` actually doing under the hood? It waits for `q_usage_counter` to hit zero. This makes me wonder: does the function actually hold the lockdep map of `q_usage_counter` while it's waiting? I need to verify how `blk_mq_freeze_queue` is implemented. I should probably dive into the code for it right now. I need to make sure this lock ordering is correct and isn't introducing a potential deadlock scenario.
|
| 25/2 |
2026/05/20 07:07 |
tool |
codesearch-definition-source |
0m
Args: map[ContextFile:block/blk-mq.c IncludeLines:true Name:blk_mq_freeze_queue]
Results: map[SourceCode: 951: static inline unsigned int __must_check
952: blk_mq_freeze_queue(struct request_queue *q)
953: {
954: unsigned int memflags = memalloc_noio_save();
955:
956: blk_mq_freeze_queue_nomemsave(q);
957: return memflags;
958: }
SourceFile:include/linux/blk-mq.h]
|
| 26/2 |
2026/05/20 07:07 |
llm |
expert |
0m
Model:
Tokens:
input: 29520
output: 47
thoughts: 17
Thoughts: Okay, here's my interpretation of that thought process, assuming I'm an expert in this field, rendered in the first person:
**Diving into `blk_mq_freeze_queue_nomemsave`**
Alright, time to dive into `blk_mq_freeze_queue_nomemsave`. It's crucial, obviously, because freezing a queue without saving memory implications is a significant operation in our block layer. I need to understand its exact purpose and how it fits into the broader picture of block device management, especially around situations that are memory constrained. Let's see... what exactly are the potential failure modes? Are we talking about race conditions? Deadlocks? Resource exhaustion? I'll probably need to consider the surrounding context to truly grasp its nuances, and how its integration with other parts of the scheduler works, and whether a related, or contrasting, function is used for memory-saving contexts. The `nomemsave` suffix is important, that always needs consideration. Right, let's get into the code and see what we're really dealing with.
|
| 27/2 |
2026/05/20 07:07 |
tool |
codesearch-definition-source |
0m
Args: map[ContextFile:block/blk-mq.c IncludeLines:true Name:blk_mq_freeze_queue_nomemsave]
Results: map[SourceCode: 204: void blk_mq_freeze_queue_nomemsave(struct request_queue *q)
205: {
206: blk_freeze_queue_start(q);
207: blk_mq_freeze_queue_wait(q);
208: }
SourceFile:block/blk-mq.c]
|
| 28/2 |
2026/05/20 07:07 |
llm |
expert |
0m
Model:
Tokens:
input: 29919
output: 43
thoughts: 10
Thoughts: Okay, here's my attempt at summarizing the thought process, tailored for an expert audience, and written in the first person:
**Diving into Block Device Freezing**
Right, let's see... `blk_freeze_queue_start`. That's the entry point. I'm immediately thinking about the implications. We're about to initiate a freeze of a block device queue. This means we're going to put a pause on I/O operations. The key considerations here are atomicity and consistency. I need to think through the possible race conditions that might exist. What happens if a request is in flight? Does the call block until those inflight requests are complete, or is some other mechanism being used to gracefully quiesce the queue? I should check the queue depth to see if all requests have returned. We need to look at how we're signaling the freeze. Is it via a flag, a lock, or something more complex? The goal, of course, is to ensure that the filesystem, or any higher-level layer using the device, can reach a consistent state, something that can be restored. I must bear in mind all the potential issues that could arise from this operation, from potential deadlocks to device timeouts. This needs to be carefully implemented and well tested. We are looking at taking the system to a consistent state from the block level, so this operation is very low-level. I am also thinking about what exactly the freeze entails in terms of locks and resource handling.
|
| 29/2 |
2026/05/20 07:07 |
tool |
codesearch-definition-source |
0m
Args: map[ContextFile:block/blk-mq.c IncludeLines:true Name:blk_freeze_queue_start]
Results: map[SourceCode: 182: void blk_freeze_queue_start(struct request_queue *q)
183: {
184: if (__blk_freeze_queue_start(q, current))
185: blk_freeze_acquire_lock(q);
186: }
SourceFile:block/blk-mq.c]
|
| 30/2 |
2026/05/20 07:07 |
llm |
expert |
0m
Model:
Tokens:
input: 30391
output: 43
thoughts: 10
Thoughts: Okay, here's my interpretation of that thought process, tailored for an expert audience, and written in the first person:
**Acquiring the Block Layer Freeze Lock**
Right, let's break this down. The mention of `blk_freeze_acquire_lock` immediately flags a critical operation within the block layer. My mental gears are already turning, considering the implications of freezing. This isn't just a casual access; it signifies the start of a coordinated effort to pause I/O operations, likely for a consistent snapshot, a filesystem operation, or perhaps even a full system freeze during a power-off sequence.
I'm thinking about the potential contention points. What's the lock implementation? Is it a spinlock, mutex, or something more sophisticated? What are the implications if it's held for an extended duration? I need to consider the impact on any other operations that might also need that lock. Is there a priority inversion scenario I should keep in mind?
More importantly, *why* are we acquiring this lock *now*? Is this happening in response to a specific request, or is it part of some scheduled maintenance? Knowing the context is crucial to evaluating the potential impact of this lock acquisition. I'm wondering if this is a critical section and what operations are dependent on this lock being held.
I'm wondering if it could be a nested lock situation, and the potential for deadlock. And what about the implications for error handling if the lock acquisition fails? Are there retry mechanisms? What's the fall-back strategy?
|
| 31/2 |
2026/05/20 07:07 |
tool |
codesearch-definition-source |
0m
Args: map[ContextFile:block/blk-mq.c IncludeLines:true Name:blk_freeze_acquire_lock]
Results: map[SourceCode: 726: static inline void blk_freeze_acquire_lock(struct request_queue *q)
727: {
728: if (!q->mq_freeze_disk_dead)
729: rwsem_acquire(&q->io_lockdep_map, 0, 1, _RET_IP_);
730: if (!q->mq_freeze_queue_dying)
731: rwsem_acquire(&q->q_lockdep_map, 0, 1, _RET_IP_);
732: }
SourceFile:block/blk.h]
|
| 32/2 |
2026/05/20 07:07 |
llm |
expert |
0m
Model:
Tokens:
input: 30940
output: 45
thoughts: 823
Thoughts: **Analyzing the Lock Ordering in blk-mq**
Okay, so I'm looking at this lock dependency chain, trying to piece together the ordering within `blk-mq`. First, I see `rwsem_acquire(&q->io_lockdep_map, 0, 1, _RET_IP_);` which points to `q_usage_counter(io)`. Right, `blk_mq_freeze_queue` is acquiring that. Then we've got `elevator_change` acquiring `elevator_lock`. So, we've established the dependency: `q_usage_counter(io)` -> `elevator_lock`. No surprises there.
Now, the interesting part. It looks like `elevator_lock` has a dependency on `srcu`. Let me trace that. Ah, here it is: `elevator_change` -> `elevator_switch` -> `blk_mq_quiesce_queue` -> `synchronize_srcu(&set->srcu)`. Wait, `synchronize_srcu` is *acquiring* the SRCU lock, `set->srcu`! That makes sense from the lockdep perspective. And right, `elevator_change` does hold `elevator_lock` when it calls `elevator_switch` because `mutex_lock(&q->elevator_lock);` then `elevator_switch(q, ctx);`. So, that confirms the dependency: `elevator_lock` -> `set->srcu`.
Okay, next link in the chain. We've got `set->srcu` dependent on `cmd->lock`. This comes from: `nbd_queue_rq` which calls `blk_mq_dispatch_rq_list`. Hmmm, where is `set->srcu` acquired relative to `nbd_queue_rq`? I see that `blk_mq_dispatch_rq_list` is called under `rcu_read_lock` or `srcu_read_lock`. Let me double-check how that works. I'll need to look at `blk_mq_run_hw_queue`.
|
| 33/2 |
2026/05/20 07:08 |
tool |
codesearch-definition-source |
0m
Args: map[ContextFile:block/blk-mq.c IncludeLines:true Name:blk_mq_run_hw_queue]
Results: map[SourceCode:2343: /**
2344: * blk_mq_run_hw_queue - Start to run a hardware queue.
2345: * @hctx: Pointer to the hardware queue to run.
2346: * @async: If we want to run the queue asynchronously.
2347: *
2348: * Check if the request queue is not in a quiesced state and if there are
2349: * pending requests to be sent. If this is true, run the queue to send requests
2350: * to hardware.
2351: */
2352: void blk_mq_run_hw_queue(struct blk_mq_hw_ctx *hctx, bool async)
2353: {
2354: bool need_run;
2355:
2356: /*
2357: * We can't run the queue inline with interrupts disabled.
2358: */
2359: WARN_ON_ONCE(!async && in_interrupt());
2360:
2361: might_sleep_if(!async && hctx->flags & BLK_MQ_F_BLOCKING);
2362:
2363: need_run = blk_mq_hw_queue_need_run(hctx);
2364: if (!need_run) {
2365: unsigned long flags;
2366:
2367: /*
2368: * Synchronize with blk_mq_unquiesce_queue(), because we check
2369: * if hw queue is quiesced locklessly above, we need the use
2370: * ->queue_lock to make sure we see the up-to-date status to
2371: * not miss rerunning the hw queue.
2372: */
2373: spin_lock_irqsave(&hctx->queue->queue_lock, flags);
2374: need_run = blk_mq_hw_queue_need_run(hctx);
2375: spin_unlock_irqrestore(&hctx->queue->queue_lock, flags);
2376:
2377: if (!need_run)
2378: return;
2379: }
2380:
2381: if (async || !cpumask_test_cpu(raw_smp_processor_id(), hctx->cpumask)) {
2382: blk_mq_delay_run_hw_queue(hctx, 0);
2383: return;
2384: }
2385:
2386: blk_mq_run_dispatch_ops(hctx->queue,
2387: blk_mq_sched_dispatch_requests(hctx));
2388: }
SourceFile:block/blk-mq.c]
|
| 34/2 |
2026/05/20 07:08 |
llm |
expert |
0m
Model:
Tokens:
input: 33021
output: 45
thoughts: 12
Thoughts: Okay, here's my attempt at summarizing the thought process, as requested, aimed at an expert audience and in the first person:
**Navigating the `blk_mq_run_dispatch_ops` Landscape**
Right, let's dive into this `blk_mq_run_dispatch_ops` function. Immediately, my mind jumps to its core purpose: orchestrating the dispatch operations within the blk-mq framework. I see it as the central nervous system, coordinating the flow of I/O requests to the hardware.
Thinking through the implications, I need to consider all possible scenarios, as it's the heart of the block layer I/O process. The critical part is understanding how this function interacts with the request queues, how it deals with pending requests, and how it translates the logical request structure into a hardware-level command. Where it fits into the I/O path. I'm visualizing the data structures involved: the `blk_mq_queue_data`, the request structs themselves, and how they relate to the underlying hardware queues.
I'm starting to think about concurrency. I'm sure this function has to be careful about managing locks, dealing with interrupts, and handling potential races, especially when multiple requests are arriving concurrently. And the efficiency of this function will clearly have an impact on overall system performance. I need to be aware of any potential bottlenecks within `blk_mq_run_dispatch_ops`.
I also start to think about the different dispatching strategies implemented within the framework. Is this a simple FIFO queue, or are there sophisticated scheduling algorithms at play? Are there different dispatch functions for different types of requests? This will be critical for understanding how the system prioritizes I/O.
Now, I'm thinking about error handling. What happens if a dispatch operation fails? How does the function report errors back to the upper layers of the block stack? Does it implement any retry mechanisms, or does it simply return an error code? This part is crucial for system stability.
And finally, I'm wondering about performance monitoring and tuning. Are there any performance counters or tracepoints that I can use to monitor the behavior of `blk_mq_run_dispatch_ops`? Identifying and mitigating the source of any bottleneck here could be essential for getting the most out of the storage subsystem. Overall, this is an area that warrants deep study.
|
| 35/2 |
2026/05/20 07:08 |
tool |
codesearch-definition-source |
0m
Error: requested entity does not exist
Args: map[ContextFile:block/blk-mq.c IncludeLines:true Name:blk_mq_run_dispatch_ops]
Results: map[SourceCode: SourceFile:]
|
| 36/2 |
2026/05/20 07:08 |
llm |
expert |
0m
Model:
Tokens:
input: 33592
output: 23
thoughts: 16
Thoughts: Okay, here's my attempt at summarizing that thought process, tailored for an expert audience:
**Analyzing the `blk_mq_run_dispatch_ops` Landscape**
Alright, my brain is immediately zeroing in on `blk_mq_run_dispatch_ops`. That's a key function in the block layer, central to the multi-queue block layer's operation, so it warrants a deep dive. I'm thinking, "Let's use `grep` to quickly get an overview of its usage and context." I want to see where this function is called, what data structures it interacts with, and how it fits into the broader I/O flow. This will give me a solid starting point for understanding its role and potential performance implications. Specifically, I'm hoping to determine which code paths rely on it to dispatch I/O requests. Knowing that, I can quickly hone in on the important areas for further investigation, especially if I'm looking for a specific optimization target or trying to debug a performance bottleneck. I also want to see if any obvious patterns emerge in the surrounding code that could indicate opportunities for improvement, or perhaps potential areas of concern, like lock contention or synchronization issues.
|
| 37/2 |
2026/05/20 07:08 |
tool |
grepper |
0m
Args: map[Expression:blk_mq_run_dispatch_ops]
Results: map[Output:block/blk-mq.c=2325=static inline bool blk_mq_hw_queue_need_run(struct blk_mq_hw_ctx *hctx)
--
block/blk-mq.c-2336- */
block/blk-mq.c:2337: __blk_mq_run_dispatch_ops(hctx->queue, false,
block/blk-mq.c-2338- need_run = !blk_queue_quiesced(hctx->queue) &&
--
block/blk-mq.c=2352=void blk_mq_run_hw_queue(struct blk_mq_hw_ctx *hctx, bool async)
--
block/blk-mq.c-2385-
block/blk-mq.c:2386: blk_mq_run_dispatch_ops(hctx->queue,
block/blk-mq.c-2387- blk_mq_sched_dispatch_requests(hctx));
--
block/blk-mq.c=2557=static void blk_mq_run_work_fn(struct work_struct *work)
--
block/blk-mq.c-2561-
block/blk-mq.c:2562: blk_mq_run_dispatch_ops(hctx->queue,
block/blk-mq.c-2563- blk_mq_sched_dispatch_requests(hctx));
--
block/blk-mq.c=2586=static void blk_mq_insert_requests(struct blk_mq_hw_ctx *hctx,
--
block/blk-mq.c-2597- if (!hctx->dispatch_busy && !run_queue_async) {
block/blk-mq.c:2598: blk_mq_run_dispatch_ops(hctx->queue,
block/blk-mq.c-2599- blk_mq_try_issue_list_directly(hctx, list));
--
block/blk-mq.c=2890=static void blk_mq_dispatch_queue_requests(struct rq_list *rqs, unsigned depth)
--
block/blk-mq.c-2902- if (q->mq_ops->queue_rqs) {
block/blk-mq.c:2903: blk_mq_run_dispatch_ops(q, __blk_mq_flush_list(q, rqs));
block/blk-mq.c-2904- if (rq_list_empty(rqs))
--
block/blk-mq.c-2907-
block/blk-mq.c:2908: blk_mq_run_dispatch_ops(q, blk_mq_issue_direct(rqs));
block/blk-mq.c-2909-}
--
block/blk-mq.c=3141=void blk_mq_submit_bio(struct bio *bio)
--
block/blk-mq.c-3254- } else {
block/blk-mq.c:3255: blk_mq_run_dispatch_ops(q, blk_mq_try_issue_directly(hctx, rq));
block/blk-mq.c-3256- }
--
block/blk-mq.c=3273=blk_status_t blk_insert_cloned_request(struct request *rq)
--
block/blk-mq.c-3323- */
block/blk-mq.c:3324: blk_mq_run_dispatch_ops(q,
block/blk-mq.c-3325- ret = blk_mq_request_issue_directly(rq, true));
--
block/blk-mq.h=403=static inline bool hctx_may_queue(struct blk_mq_hw_ctx *hctx,
--
block/blk-mq.h-438-/* run the code block in @dispatch_ops with rcu/srcu read lock held */
block/blk-mq.h:439:#define __blk_mq_run_dispatch_ops(q, check_sleep, dispatch_ops) \
block/blk-mq.h-440-do { \
--
block/blk-mq.h-455-
block/blk-mq.h:456:#define blk_mq_run_dispatch_ops(q, dispatch_ops) \
block/blk-mq.h:457: __blk_mq_run_dispatch_ops(q, true, dispatch_ops) \
block/blk-mq.h-458-
]
|
| 38/2 |
2026/05/20 07:08 |
llm |
expert |
0m
Model:
Tokens:
input: 35038
output: 46
thoughts: 36
Thoughts: Okay, here's my interpretation of that thought process, assuming I'm already deep in kernel internals:
**Diving into Block Layer Dispatch**
Right, `__blk_mq_run_dispatch_ops`. I know that name. It's a macro; I'm pretty sure it's part of the blk-mq framework, involved in dispatching operations. And, aha, it's immediately apparent: it's protecting against concurrent access using either `rcu_read_lock` or `srcu_read_lock`. So, the lock choice hinges on specific configurations or scenarios... it is looking like RCU is used if it can be, and SRCU otherwise. That's good, that's what I expected to see. It's a key part of how the block layer handles its internal data structures safely. Now, I have to figure out *why* RCU or SRCU is the right choice here, and where this is used.
|
| 39/2 |
2026/05/20 07:08 |
tool |
codesearch-definition-source |
0m
Error: requested entity does not exist
Args: map[ContextFile:block/blk-mq.h IncludeLines:true Name:__blk_mq_run_dispatch_ops]
Results: map[SourceCode: SourceFile:]
|
| 40/2 |
2026/05/20 07:08 |
llm |
expert |
0m
Model:
Tokens:
input: 35347
output: 24
thoughts: 20
Thoughts: Here's a first-person summary, tailored for an expert audience, based on the provided instruction:
**Diving into block/blk-mq.h for a Deeper Look**
Okay, let's pull up `block/blk-mq.h` and focus specifically around line 439. I'm expecting to find some crucial definitions or structures there related to the block multi-queue implementation, given the file's purpose. It's likely we'll see something related to how requests are enqueued or dequeued, perhaps some queue head structures, or maybe the definition of data structures specific to the blk-mq framework itself. I'm particularly interested in seeing how they're handling completions or potentially interrupt contexts. Time to dig in and see if this hunch holds up.
|
| 41/2 |
2026/05/20 07:08 |
tool |
grepper |
0m
Args: map[Expression:__blk_mq_run_dispatch_ops]
Results: map[Output:block/blk-mq.c=2325=static inline bool blk_mq_hw_queue_need_run(struct blk_mq_hw_ctx *hctx)
--
block/blk-mq.c-2336- */
block/blk-mq.c:2337: __blk_mq_run_dispatch_ops(hctx->queue, false,
block/blk-mq.c-2338- need_run = !blk_queue_quiesced(hctx->queue) &&
--
block/blk-mq.h=403=static inline bool hctx_may_queue(struct blk_mq_hw_ctx *hctx,
--
block/blk-mq.h-438-/* run the code block in @dispatch_ops with rcu/srcu read lock held */
block/blk-mq.h:439:#define __blk_mq_run_dispatch_ops(q, check_sleep, dispatch_ops) \
block/blk-mq.h-440-do { \
--
block/blk-mq.h-456-#define blk_mq_run_dispatch_ops(q, dispatch_ops) \
block/blk-mq.h:457: __blk_mq_run_dispatch_ops(q, true, dispatch_ops) \
block/blk-mq.h-458-
]
|
| 42/2 |
2026/05/20 07:08 |
llm |
expert |
0m
Model:
Tokens:
input: 35909
output: 26
thoughts: 20
Thoughts: Here's a first-person summary, tailored for an expert audience, based on the provided instruction:
**Diving into block/blk-mq.h for a Deeper Look**
Okay, let's pull up `block/blk-mq.h` and focus specifically around line 439. I'm expecting to find some crucial definitions or structures there related to the block multi-queue implementation, given the file's purpose. It's likely we'll see something related to how requests are enqueued or dequeued, perhaps some queue head structures, or maybe the definition of data structures specific to the blk-mq framework itself. I'm particularly interested in seeing how they're handling completions or potentially interrupt contexts. Time to dig in and see if this hunch holds up.
|
| 43/2 |
2026/05/20 07:08 |
tool |
grepper |
0m
Args: map[Expression:#define __blk_mq_run_dispatch_ops]
Results: map[Output:block/blk-mq.h=403=static inline bool hctx_may_queue(struct blk_mq_hw_ctx *hctx,
--
block/blk-mq.h-438-/* run the code block in @dispatch_ops with rcu/srcu read lock held */
block/blk-mq.h:439:#define __blk_mq_run_dispatch_ops(q, check_sleep, dispatch_ops) \
block/blk-mq.h-440-do { \
]
|
| 44/2 |
2026/05/20 07:08 |
llm |
expert |
0m
Model:
Tokens:
input: 36260
output: 22
thoughts: 17
Thoughts: Here's a first-person summary, tailored for an expert audience, of the thought process described:
**Diving into blk-mq.h**
Okay, let's cut to the chase and crack open `block/blk-mq.h` directly. No need for any preliminary explanations or context; I'm familiar enough with block layer concepts and the general architecture. I want to get straight into the definitions and data structures that drive the modern multi-queue block layer. I'm looking for the core elements that define the queuing disciplines, command submission paths, and completion handling within blk-mq. I'll be focused on how the interfaces are structured and what implications this has for scalability and concurrency. I'm expecting to immediately grok the basic building blocks and how they relate to the underlying hardware queues and I/O scheduler interaction.
|
| 45/2 |
2026/05/20 07:08 |
tool |
read-file |
0m
Args:
Results: map[Contents:/* SPDX-License-Identifier: GPL-2.0 */
#ifndef INT_BLK_MQ_H
#define INT_BLK_MQ_H
#include <linux/blk-mq.h>
#include "blk-stat.h"
struct blk_mq_tag_set;
struct elevator_tags;
struct blk_mq_ctxs {
struct kobject kobj;
struct blk_mq_ctx __percpu *queue_ctx;
};
/**
* struct blk_mq_ctx - State for a software queue facing the submitting CPUs
*/
struct blk_mq_ctx {
struct {
spinlock_t lock;
struct list_head rq_lists[HCTX_MAX_TYPES];
} ____cacheline_aligned_in_smp;
unsigned int cpu;
unsigned short index_hw[HCTX_MAX_TYPES];
struct blk_mq_hw_ctx *hctxs[HCTX_MAX_TYPES];
struct request_queue *queue;
struct blk_mq_ctxs *ctxs;
struct kobject kobj;
} ____cacheline_aligned_in_smp;
enum {
BLK_MQ_NO_TAG = -1U,
BLK_MQ_TAG_MIN = 1,
BLK_MQ_TAG_MAX = BLK_MQ_NO_TAG - 1,
};
#define BLK_MQ_CPU_WORK_BATCH (8)
typedef unsigned int __bitwise blk_insert_t;
#define BLK_MQ_INSERT_AT_HEAD ((__force blk_insert_t)0x01)
void blk_mq_submit_bio(struct bio *bio);
int blk_mq_poll(struct request_queue *q, blk_qc_t cookie, struct io_comp_batch *iob,
unsigned int flags);
void blk_mq_exit_queue(struct request_queue *q);
struct elevator_tags *blk_mq_update_nr_requests(struct request_queue *q,
struct elevator_tags *tags,
unsigned int nr);
void blk_mq_wake_waiters(struct request_queue *q);
bool blk_mq_dispatch_rq_list(struct blk_mq_hw_ctx *hctx, struct list_head *,
bool);
void blk_mq_flush_busy_ctxs(struct blk_mq_hw_ctx *hctx, struct list_head *list);
struct request *blk_mq_dequeue_from_ctx(struct blk_mq_hw_ctx *hctx,
struct blk_mq_ctx *start);
void blk_mq_put_rq_ref(struct request *rq);
/*
* Internal helpers for allocating/freeing the request map
*/
void blk_mq_free_rqs(struct blk_mq_tag_set *set, struct blk_mq_tags *tags,
unsigned int hctx_idx);
void blk_mq_free_rq_map(struct blk_mq_tag_set *set, struct blk_mq_tags *tags);
struct blk_mq_tags *blk_mq_alloc_map_and_rqs(struct blk_mq_tag_set *set,
unsigned int hctx_idx, unsigned int depth);
void blk_mq_free_map_and_rqs(struct blk_mq_tag_set *set,
struct blk_mq_tags *tags,
unsigned int hctx_idx);
/*
* CPU -> queue mappings
*/
extern int blk_mq_hw_queue_to_node(struct blk_mq_queue_map *qmap, unsigned int);
/*
* blk_mq_map_queue_type() - map (hctx_type,cpu) to hardware queue
* @q: request queue
* @type: the hctx type index
* @cpu: CPU
*/
static inline struct blk_mq_hw_ctx *blk_mq_map_queue_type(struct request_queue *q,
enum hctx_type type,
unsigned int cpu)
{
return queue_hctx((q), (q->tag_set->map[type].mq_map[cpu]));
}
static inline enum hctx_type blk_mq_get_hctx_type(blk_opf_t opf)
{
enum hctx_type type = HCTX_TYPE_DEFAULT;
/*
* The caller ensure that if REQ_POLLED, poll must be enabled.
*/
if (opf & REQ_POLLED)
type = HCTX_TYPE_POLL;
else if ((opf & REQ_OP_MASK) == REQ_OP_READ)
type = HCTX_TYPE_READ;
return type;
}
/*
* blk_mq_map_queue() - map (cmd_flags,type) to hardware queue
* @opf: operation type (REQ_OP_*) and flags (e.g. REQ_POLLED).
* @ctx: software queue cpu ctx
*/
static inline struct blk_mq_hw_ctx *blk_mq_map_queue(blk_opf_t opf,
struct blk_mq_ctx *ctx)
{
return ctx->hctxs[blk_mq_get_hctx_type(opf)];
}
/*
* Default to double of smaller one between hw queue_depth and
* 128, since we don't split into sync/async like the old code
* did. Additionally, this is a per-hw queue depth.
*/
static inline unsigned int blk_mq_default_nr_requests(
struct blk_mq_tag_set *set)
{
return 2 * min_t(unsigned int, set->queue_depth, BLKDEV_DEFAULT_RQ);
}
/*
* sysfs helpers
*/
extern void blk_mq_sysfs_init(struct request_queue *q);
extern void blk_mq_sysfs_deinit(struct request_queue *q);
int blk_mq_sysfs_register(struct gendisk *disk);
void blk_mq_sysfs_unregister(struct gendisk *disk);
int blk_mq_sysfs_register_hctxs(struct request_queue *q);
void blk_mq_sysfs_unregister_hctxs(struct request_queue *q);
extern void blk_mq_hctx_kobj_init(struct blk_mq_hw_ctx *hctx);
void blk_mq_free_plug_rqs(struct blk_plug *plug);
void blk_mq_flush_plug_list(struct blk_plug *plug, bool from_schedule);
void blk_mq_cancel_work_sync(struct request_queue *q);
void blk_mq_release(struct request_queue *q);
static inline struct blk_mq_ctx *__blk_mq_get_ctx(struct request_queue *q,
unsigned int cpu)
{
return per_cpu_ptr(q->queue_ctx, cpu);
}
/*
* This assumes per-cpu software queueing queues. They could be per-node
* as well, for instance. For now this is hardcoded as-is. Note that we don't
* care about preemption, since we know the ctx's are persistent. This does
* mean that we can't rely on ctx always matching the currently running CPU.
*/
static inline struct blk_mq_ctx *blk_mq_get_ctx(struct request_queue *q)
{
return __blk_mq_get_ctx(q, raw_smp_processor_id());
}
struct blk_mq_alloc_data {
/* input parameter */
struct request_queue *q;
blk_mq_req_flags_t flags;
unsigned int shallow_depth;
blk_opf_t cmd_flags;
req_flags_t rq_flags;
/* allocate multiple requests/tags in one go */
unsigned int nr_tags;
struct rq_list *cached_rqs;
/* input & output parameter */
struct blk_mq_ctx *ctx;
struct blk_mq_hw_ctx *hctx;
};
struct blk_mq_tags *blk_mq_init_tags(unsigned int nr_tags,
unsigned int reserved_tags, unsigned int flags, int node);
void blk_mq_free_tags(struct blk_mq_tag_set *set, struct blk_mq_tags *tags);
unsigned int blk_mq_get_tag(struct blk_mq_alloc_data *data);
unsigned long blk_mq_get_tags(struct blk_mq_alloc_data *data, int nr_tags,
unsigned int *offset);
void blk_mq_put_tag(struct blk_mq_tags *tags, struct blk_mq_ctx *ctx,
unsigned int tag);
void blk_mq_put_tags(struct blk_mq_tags *tags, int *tag_array, int nr_tags);
void blk_mq_tag_resize_shared_tags(struct blk_mq_tag_set *set,
unsigned int size);
void blk_mq_tag_update_sched_shared_tags(struct request_queue *q,
unsigned int nr);
void blk_mq_tag_wakeup_all(struct blk_mq_tags *tags, bool);
void blk_mq_queue_tag_busy_iter(struct request_queue *q, busy_tag_iter_fn *fn,
void *priv);
void blk_mq_all_tag_iter(struct blk_mq_tags *tags, busy_tag_iter_fn *fn,
void *priv);
static inline struct sbq_wait_state *bt_wait_ptr(struct sbitmap_queue *bt,
struct blk_mq_hw_ctx *hctx)
{
if (!hctx)
return &bt->ws[0];
return sbq_wait_ptr(bt, &hctx->wait_index);
}
void __blk_mq_tag_busy(struct blk_mq_hw_ctx *);
void __blk_mq_tag_idle(struct blk_mq_hw_ctx *);
static inline void blk_mq_tag_busy(struct blk_mq_hw_ctx *hctx)
{
if (hctx->flags & BLK_MQ_F_TAG_QUEUE_SHARED)
__blk_mq_tag_busy(hctx);
}
static inline void blk_mq_tag_idle(struct blk_mq_hw_ctx *hctx)
{
if (hctx->flags & BLK_MQ_F_TAG_QUEUE_SHARED)
__blk_mq_tag_idle(hctx);
}
static inline bool blk_mq_tag_is_reserved(struct blk_mq_tags *tags,
unsigned int tag)
{
return tag < tags->nr_reserved_tags;
}
static inline bool blk_mq_is_shared_tags(unsigned int flags)
{
return flags & BLK_MQ_F_TAG_HCTX_SHARED;
}
static inline struct blk_mq_tags *blk_mq_tags_from_data(struct blk_mq_alloc_data *data)
{
if (data->rq_flags & RQF_SCHED_TAGS)
return data->hctx->sched_tags;
return data->hctx->tags;
}
static inline bool blk_mq_hctx_stopped(struct blk_mq_hw_ctx *hctx)
{
/* Fast path: hardware queue is not stopped most of the time. */
if (likely(!test_bit(BLK_MQ_S_STOPPED, &hctx->state)))
return false;
/*
* This barrier is used to order adding of dispatch list before and
* the test of BLK_MQ_S_STOPPED below. Pairs with the memory barrier
* in blk_mq_start_stopped_hw_queue() so that dispatch code could
* either see BLK_MQ_S_STOPPED is cleared or dispatch list is not
* empty to avoid missing dispatching requests.
*/
smp_mb();
return test_bit(BLK_MQ_S_STOPPED, &hctx->state);
}
static inline bool blk_mq_hw_queue_mapped(struct blk_mq_hw_ctx *hctx)
{
return hctx->nr_ctx && hctx->tags;
}
void blk_mq_in_driver_rw(struct block_device *part, unsigned int inflight[2]);
static inline void blk_mq_put_dispatch_budget(struct request_queue *q,
int budget_token)
{
if (q->mq_ops->put_budget)
q->mq_ops->put_budget(q, budget_token);
}
static inline int blk_mq_get_dispatch_budget(struct request_queue *q)
{
if (q->mq_ops->get_budget)
return q->mq_ops->get_budget(q);
return 0;
}
static inline void blk_mq_set_rq_budget_token(struct request *rq, int token)
{
if (token < 0)
return;
if (rq->q->mq_ops->set_rq_budget_token)
rq->q->mq_ops->set_rq_budget_token(rq, token);
}
static inline int blk_mq_get_rq_budget_token(struct request *rq)
{
if (rq->q->mq_ops->get_rq_budget_token)
return rq->q->mq_ops->get_rq_budget_token(rq);
return -1;
}
static inline void __blk_mq_add_active_requests(struct blk_mq_hw_ctx *hctx,
int val)
{
if (blk_mq_is_shared_tags(hctx->flags))
atomic_add(val, &hctx->queue->nr_active_requests_shared_tags);
else
atomic_add(val, &hctx->nr_active);
}
static inline void __blk_mq_inc_active_requests(struct blk_mq_hw_ctx *hctx)
{
__blk_mq_add_active_requests(hctx, 1);
}
static inline void __blk_mq_sub_active_requests(struct blk_mq_hw_ctx *hctx,
int val)
{
if (blk_mq_is_shared_tags(hctx->flags))
atomic_sub(val, &hctx->queue->nr_active_requests_shared_tags);
else
atomic_sub(val, &hctx->nr_active);
}
static inline void __blk_mq_dec_active_requests(struct blk_mq_hw_ctx *hctx)
{
__blk_mq_sub_active_requests(hctx, 1);
}
static inline void blk_mq_add_active_requests(struct blk_mq_hw_ctx *hctx,
int val)
{
if (hctx->flags & BLK_MQ_F_TAG_QUEUE_SHARED)
__blk_mq_add_active_requests(hctx, val);
}
static inline void blk_mq_inc_active_requests(struct blk_mq_hw_ctx *hctx)
{
if (hctx->flags & BLK_MQ_F_TAG_QUEUE_SHARED)
__blk_mq_inc_active_requests(hctx);
}
static inline void blk_mq_sub_active_requests(struct blk_mq_hw_ctx *hctx,
int val)
{
if (hctx->flags & BLK_MQ_F_TAG_QUEUE_SHARED)
__blk_mq_sub_active_requests(hctx, val);
}
static inline void blk_mq_dec_active_requests(struct blk_mq_hw_ctx *hctx)
{
if (hctx->flags & BLK_MQ_F_TAG_QUEUE_SHARED)
__blk_mq_dec_active_requests(hctx);
}
static inline int __blk_mq_active_requests(struct blk_mq_hw_ctx *hctx)
{
if (blk_mq_is_shared_tags(hctx->flags))
return atomic_read(&hctx->queue->nr_active_requests_shared_tags);
return atomic_read(&hctx->nr_active);
}
static inline void __blk_mq_put_driver_tag(struct blk_mq_hw_ctx *hctx,
struct request *rq)
{
blk_mq_dec_active_requests(hctx);
blk_mq_put_tag(hctx->tags, rq->mq_ctx, rq->tag);
rq->tag = BLK_MQ_NO_TAG;
}
static inline void blk_mq_put_driver_tag(struct request *rq)
{
if (rq->tag == BLK_MQ_NO_TAG || rq->internal_tag == BLK_MQ_NO_TAG)
return;
__blk_mq_put_driver_tag(rq->mq_hctx, rq);
}
bool __blk_mq_alloc_driver_tag(struct request *rq);
static inline bool blk_mq_get_driver_tag(struct request *rq)
{
if (rq->tag == BLK_MQ_NO_TAG && !__blk_mq_alloc_driver_tag(rq))
return false;
return true;
}
static inline void blk_mq_clear_mq_map(struct blk_mq_queue_map *qmap)
{
int cpu;
for_each_possible_cpu(cpu)
qmap->mq_map[cpu] = 0;
}
/* Free all requests on the list */
static inline void blk_mq_free_requests(struct list_head *list)
{
while (!list_empty(list)) {
struct request *rq = list_entry_rq(list->next);
list_del_init(&rq->queuelist);
blk_mq_free_request(rq);
}
}
/*
* For shared tag users, we track the number of currently active users
* and attempt to provide a fair share of the tag depth for each of them.
*/
static inline bool hctx_may_queue(struct blk_mq_hw_ctx *hctx,
struct sbitmap_queue *bt)
{
unsigned int depth, users;
if (!hctx || !(hctx->flags & BLK_MQ_F_TAG_QUEUE_SHARED))
return true;
/*
* Don't try dividing an ant
*/
if (bt->sb.depth == 1)
return true;
if (blk_mq_is_shared_tags(hctx->flags)) {
struct request_queue *q = hctx->queue;
if (!test_bit(QUEUE_FLAG_HCTX_ACTIVE, &q->queue_flags))
return true;
} else {
if (!test_bit(BLK_MQ_S_TAG_ACTIVE, &hctx->state))
return true;
}
users = READ_ONCE(hctx->tags->active_queues);
if (!users)
return true;
/*
* Allow at least some tags
*/
depth = max((bt->sb.depth + users - 1) / users, 4U);
return __blk_mq_active_requests(hctx) < depth;
}
/* run the code block in @dispatch_ops with rcu/srcu read lock held */
#define __blk_mq_run_dispatch_ops(q, check_sleep, dispatch_ops) \
do { \
if ((q)->tag_set->flags & BLK_MQ_F_BLOCKING) { \
struct blk_mq_tag_set *__tag_set = (q)->tag_set; \
int srcu_idx; \
\
might_sleep_if(check_sleep); \
srcu_idx = srcu_read_lock(__tag_set->srcu); \
(dispatch_ops); \
srcu_read_unlock(__tag_set->srcu, srcu_idx); \
} else { \
rcu_read_lock(); \
(dispatch_ops); \
rcu_read_unlock(); \
} \
} while (0)
#define blk_mq_run_dispatch_ops(q, dispatch_ops) \
__blk_mq_run_dispatch_ops(q, true, dispatch_ops) \
static inline bool blk_mq_can_poll(struct request_queue *q)
{
return (q->limits.features & BLK_FEAT_POLL) &&
q->tag_set->map[HCTX_TYPE_POLL].nr_queues;
}
#endif
]
|
| 46/2 |
2026/05/20 07:08 |
llm |
expert |
0m
Model:
Tokens:
input: 41594
output: 43
thoughts: 344
Thoughts: **Analyzing the Lock Acquisition in the Block Layer**
Okay, so I'm tracing this `__blk_mq_run_dispatch_ops` function and how it interfaces with the NBD driver. First, I see this conditional block: if the tag set has the `BLK_MQ_F_BLOCKING` flag, we enter a critical section managed with SRCU. The crucial bit here is `(dispatch_ops)`, which is expanded to `blk_mq_sched_dispatch_requests(hctx)`.
Digging deeper into `blk_mq_sched_dispatch_requests`, it calls `blk_mq_do_dispatch_sched`, which then leads us to `blk_mq_dispatch_rq_list` and eventually to `nbd_queue_rq`. *This* is where it gets interesting because `nbd_queue_rq` acquires `cmd->lock`. This is the first significant lock acquisition I'm spotting.
Now, the connection I need to trace is between `set->srcu` and `cmd->lock`… because of the SRCU read lock and then the `cmd->lock` that is taken.
The next step is to understand the relationship between `cmd->lock` and `nsock->tx_lock`, specifically in terms of lock acquisition order. I'm noting that `nbd_queue_rq` grabs `cmd->lock` and that this is followed by a call to `nbd_handle_cmd`, which then acquires `nsock->tx_lock`. So, the lock acquisition sequence is `cmd->lock` followed by `nsock->tx_lock`.
I'm thinking, I need to take a closer look at the actual implementation of `nbd_queue_rq` now to be absolutely sure. Let's see how that one is written.
|
| 47/2 |
2026/05/20 07:09 |
tool |
codesearch-definition-source |
0m
Args: map[ContextFile:drivers/block/nbd.c IncludeLines:true Name:nbd_queue_rq]
Results: map[SourceCode:1184: static blk_status_t nbd_queue_rq(struct blk_mq_hw_ctx *hctx,
1185: const struct blk_mq_queue_data *bd)
1186: {
1187: struct nbd_cmd *cmd = blk_mq_rq_to_pdu(bd->rq);
1188: blk_status_t ret;
1189:
1190: /*
1191: * Since we look at the bio's to send the request over the network we
1192: * need to make sure the completion work doesn't mark this request done
1193: * before we are done doing our send. This keeps us from dereferencing
1194: * freed data if we have particularly fast completions (ie we get the
1195: * completion before we exit sock_xmit on the last bvec) or in the case
1196: * that the server is misbehaving (or there was an error) before we're
1197: * done sending everything over the wire.
1198: */
1199: mutex_lock(&cmd->lock);
1200: clear_bit(NBD_CMD_REQUEUED, &cmd->flags);
1201:
1202: /* We can be called directly from the user space process, which means we
1203: * could possibly have signals pending so our sendmsg will fail. In
1204: * this case we need to return that we are busy, otherwise error out as
1205: * appropriate.
1206: */
1207: ret = nbd_handle_cmd(cmd, hctx->queue_num);
1208: mutex_unlock(&cmd->lock);
1209:
1210: return ret;
1211: }
SourceFile:drivers/block/nbd.c]
|
| 48/2 |
2026/05/20 07:09 |
llm |
expert |
0m
Model:
Tokens:
input: 42883
output: 43
thoughts: 18
Thoughts: Okay, here's my interpretation of that thought process, assuming I'm an expert in network block devices:
**Internal Monologue: Concurrency Control in Network Block Device Operations**
Right, so I'm focusing on the `nbd_handle_cmd` function. My brain immediately jumps to concurrency. We're dealing with network I/O, which means multiple operations can happen concurrently. Specifically, I'm noting that `nbd_handle_cmd` is acquiring `nsock->tx_lock`. That lock...that's key. It tells me that we're talking about a critical section related to the network socket, `nsock`, particularly around the transmission side of things (the `tx` part). It indicates that the code is structured to protect data integrity and avoid race conditions when sending commands or responses over the network connection. This must mean that `nsock->tx_lock` will likely synchronize access to shared resources like the transmit buffer, or perhaps even the socket itself. The fact that the code explicitly acquires it before proceeding tells me that they've recognized a need to control access to this shared resource and prevent inconsistent or corrupted data from being sent over the network.
|
| 49/2 |
2026/05/20 07:09 |
tool |
codesearch-definition-source |
0m
Args: map[ContextFile:drivers/block/nbd.c IncludeLines:true Name:nbd_handle_cmd]
Results: map[SourceCode:1117: static blk_status_t nbd_handle_cmd(struct nbd_cmd *cmd, int index)
1118: {
1119: struct request *req = blk_mq_rq_from_pdu(cmd);
1120: struct nbd_device *nbd = cmd->nbd;
1121: struct nbd_config *config;
1122: struct nbd_sock *nsock;
1123: blk_status_t ret;
1124:
1125: lockdep_assert_held(&cmd->lock);
1126:
1127: config = nbd_get_config_unlocked(nbd);
1128: if (!config) {
1129: dev_err_ratelimited(disk_to_dev(nbd->disk),
1130: "Socks array is empty\n");
1131: return BLK_STS_IOERR;
1132: }
1133:
1134: if (index >= config->num_connections) {
1135: dev_err_ratelimited(disk_to_dev(nbd->disk),
1136: "Attempted send on invalid socket\n");
1137: nbd_config_put(nbd);
1138: return BLK_STS_IOERR;
1139: }
1140: cmd->status = BLK_STS_OK;
1141: again:
1142: nsock = config->socks[index];
1143: mutex_lock(&nsock->tx_lock);
1144: if (nsock->dead) {
1145: int old_index = index;
1146: index = find_fallback(nbd, index);
1147: mutex_unlock(&nsock->tx_lock);
1148: if (index < 0) {
1149: if (wait_for_reconnect(nbd)) {
1150: index = old_index;
1151: goto again;
1152: }
1153: /* All the sockets should already be down at this point,
1154: * we just want to make sure that DISCONNECTED is set so
1155: * any requests that come in that were queue'ed waiting
1156: * for the reconnect timer don't trigger the timer again
1157: * and instead just error out.
1158: */
1159: sock_shutdown(nbd);
1160: nbd_config_put(nbd);
1161: return BLK_STS_IOERR;
1162: }
1163: goto again;
1164: }
1165:
1166: /* Handle the case that we have a pending request that was partially
1167: * transmitted that _has_ to be serviced first. We need to call requeue
1168: * here so that it gets put _after_ the request that is already on the
1169: * dispatch list.
1170: */
1171: blk_mq_start_request(req);
1172: if (unlikely(nsock->pending && nsock->pending != req)) {
1173: nbd_requeue_cmd(cmd);
1174: ret = BLK_STS_OK;
1175: goto out;
1176: }
1177: ret = nbd_send_cmd(nbd, cmd, index);
1178: out:
1179: mutex_unlock(&nsock->tx_lock);
1180: nbd_config_put(nbd);
1181: return ret;
1182: }
SourceFile:drivers/block/nbd.c]
|
| 50/2 |
2026/05/20 07:09 |
llm |
expert |
0m
Model:
Tokens:
input: 44236
output: 41
thoughts: 432
Thoughts: **Locking Hierarchy Deep Dive**
Okay, so I'm tracing a potential locking issue here within the NBD driver. My initial thought is that `nbd_handle_cmd` grabs `nsock->tx_lock`. Standard. Then, the report points from `nsock->tx_lock` to `sk_lock-AF_INET` comes from the `nbd_send_cmd` function, specifically when it calls `sock_sendmsg`, which of course acquires `sk_lock`. Right. Now I need to remind myself of the call chain and make sure that this is the correct behavior. `nbd_send_cmd` calls `sock_xmit`, which then in turn calls `sock_sendmsg`. Got it.
But... hang on. The lockdep report shows this specific sequence, indicating:
1. `lock_sock_nested` (within `net/core/sock.c`)
2. Which calls `lock_sock` (from `include/net/sock.h`),
3. Which is then a part of `tcp_sendmsg` (within `net/ipv4/tcp.c`),
4. Then `inet_sendmsg` (within `net/ipv4/af_inet.c`)
5. Then `sock_sendmsg_nosec` (within `net/socket.c`)
6. Then `__sock_sendmsg` (within `net/socket.c`)
7. Then `sock_sendmsg` (within `net/socket.c`)
8. Which leads to `__sock_xmit` (within `drivers/block/nbd.c`)
9. Which goes to `sock_xmit` (within `drivers/block/nbd.c`)
10. Which calls `send_disconnects` (within `drivers/block/nbd.c`)
11. Which finally, is a part of `nbd_disconnect` (within `drivers/block/nbd.c`)
Now here's the kicker: the report mentions `send_disconnects` also potentially acquiring `nsock->tx_lock`! That's what I want to verify, so I should look into the code of `nbd_disconnect` to confirm the code path there. I need to make sure there isn't a lock ordering issue with `nsock->tx_lock` and the socket lock in that context.
|
| 51/2 |
2026/05/20 07:09 |
tool |
codesearch-definition-source |
0m
Args: map[ContextFile:drivers/block/nbd.c IncludeLines:true Name:nbd_disconnect]
Results: map[SourceCode:1414: static int nbd_disconnect(struct nbd_device *nbd)
1415: {
1416: struct nbd_config *config = nbd->config;
1417:
1418: dev_info(disk_to_dev(nbd->disk), "NBD_DISCONNECT\n");
1419: set_bit(NBD_RT_DISCONNECT_REQUESTED, &config->runtime_flags);
1420: set_bit(NBD_DISCONNECT_REQUESTED, &nbd->flags);
1421: send_disconnects(nbd);
1422: return 0;
1423: }
SourceFile:drivers/block/nbd.c]
|
| 52/2 |
2026/05/20 07:09 |
llm |
expert |
0m
Model:
Tokens:
input: 45447
output: 41
thoughts: 7
Thoughts: Okay, I'm ready to delve into this. Let's see... the topic is "And `send_disconnects`." Right, I understand. I need to summarize my *thoughts* on the subject, as though it's my internal process. Here's how I'd approach it:
**Analyzing Disconnect Signals: The `send_disconnects` Perspective**
Okay, so we're talking about handling disconnection signals. My initial thought is, `send_disconnects` likely refers to a function, method, or perhaps a component responsible for actively sending disconnection notifications or instructions. Now, what's crucial here is the *context*. Without more information, I'm immediately running through several potential scenarios: is this related to network protocols? Communication libraries? Application-level signaling?
If it's network related, the specifics matter. Is this a graceful shutdown, a forced termination, or error handling after a link failure? What's the target system's expected response to receiving these disconnect signals? I need to consider potential race conditions, ensure data integrity before sending a disconnect message, and possibly implement retry mechanisms if the initial attempt fails.
If this is more application-level, I'm thinking about how the disconnect propagates. Does the application close all open resources, inform other processes or threads, and clean up its state? Are there any dependencies on external systems that need to be notified? Crucially, what's the impact of a disconnected entity on the overall system's functionality? I also need to make sure the disconnect process is asynchronous to avoid blocking other operations. Error handling of the sending mechanism is also important.
Furthermore, are there any security implications? Are these signals authenticated or encrypted? Can malicious actors exploit vulnerabilities in the disconnect process to cause denial-of-service or data corruption? I also need to be mindful of resources used to generate the signals.
Ultimately, I'm going to consider edge cases, error conditions, and the potential impact of a disconnect on the overall system, whether it is an established network or application architecture. `send_disconnects` requires robust design and thorough testing to ensure reliability and maintainability.
|
| 53/2 |
2026/05/20 07:09 |
tool |
codesearch-definition-source |
0m
Args: map[ContextFile:drivers/block/nbd.c IncludeLines:true Name:send_disconnects]
Results: map[SourceCode:1390: static void send_disconnects(struct nbd_device *nbd)
1391: {
1392: struct nbd_config *config = nbd->config;
1393: struct nbd_request request = {
1394: .magic = htonl(NBD_REQUEST_MAGIC),
1395: .type = htonl(NBD_CMD_DISC),
1396: };
1397: struct kvec iov = {.iov_base = &request, .iov_len = sizeof(request)};
1398: struct iov_iter from;
1399: int i, ret;
1400:
1401: for (i = 0; i < config->num_connections; i++) {
1402: struct nbd_sock *nsock = config->socks[i];
1403:
1404: iov_iter_kvec(&from, ITER_SOURCE, &iov, 1, sizeof(request));
1405: mutex_lock(&nsock->tx_lock);
1406: ret = sock_xmit(nbd, i, 1, &from, 0, NULL);
1407: if (ret < 0)
1408: dev_err(disk_to_dev(nbd->disk),
1409: "Send disconnect failed %d\n", ret);
1410: mutex_unlock(&nsock->tx_lock);
1411: }
1412: }
SourceFile:drivers/block/nbd.c]
|
| 54/2 |
2026/05/20 07:09 |
llm |
expert |
0m
Model:
Tokens:
input: 46368
output: 44
thoughts: 358
Thoughts: **Analyzing the Lock Ordering**
Okay, so I'm tracing this disconnect process. It looks like `send_disconnects` grabs `nsock->tx_lock`. From there, it calls `sock_xmit`, which in turn locks the `sk_lock`. So the lock order is `nsock->tx_lock` before `sk_lock`.
Now, where does `sk_lock` become an issue? Looking at the trace, it appears `sk_lock` -> `cpu_hotplug_lock` is the problem: specifically through this path: `percpu_down_read_internal` -> `cpus_read_lock` -> `static_key_disable` -> `__inet_hash_connect` -> `tcp_v4_connect` -> `__inet_stream_connect` -> `inet_stream_connect`.
Hmm, hold on. `inet_stream_connect` also acquires `sk_lock`? That's the link. I need to confirm that. Let me double check the source for `inet_stream_connect` to make sure I'm seeing this correctly.
|
| 55/2 |
2026/05/20 07:09 |
tool |
codesearch-definition-source |
0m
Args: map[ContextFile:net/ipv4/af_inet.c IncludeLines:true Name:inet_stream_connect]
Results: map[SourceCode: 749: int inet_stream_connect(struct socket *sock, struct sockaddr_unsized *uaddr,
750: int addr_len, int flags)
751: {
752: int err;
753:
754: lock_sock(sock->sk);
755: err = __inet_stream_connect(sock, uaddr, addr_len, flags, 0);
756: release_sock(sock->sk);
757: return err;
758: }
SourceFile:net/ipv4/af_inet.c]
|
| 56/2 |
2026/05/20 07:09 |
llm |
expert |
0m
Model:
Tokens:
input: 47189
output: 42
thoughts: 2743
Thoughts: **Locking Order Investigation**
Okay, so I'm tracing this locking order, and it looks like `inet_stream_connect` initially acquires `sk_lock`, then calls `__inet_stream_connect`, which in turn calls `cpus_read_lock`. The sequence I have so far is clearly `sk_lock` -> `cpu_hotplug_lock`.
Now, the lockdep report shows a dependency `cpu_hotplug_lock` -> `slab_mutex` emerging from the `p9_client_destroy` call, eventually ending up in `deactivate_locked_super` -> `v9fs_session_close`, and so on, terminating at `kmem_cache_destroy`, in the slab allocator. Hmm, interesting...
But where is `cpu_hotplug_lock` acquired in this chain? The lockdep report shows the call stack for acquiring `slab_mutex`, but it doesn't immediately reveal where `cpu_hotplug_lock` is being held *before* calling into the slab allocator code. I'm getting lost in the chain. Is it perhaps during a mount operation? I see `vfs_get_tree` and other filesystem-related functions in the stack trace for `slab_mutex`. I'm starting to think `cpu_hotplug_lock` is acquired somewhere *within* a mount-related function. But the stack trace itself doesn't show `cpu_hotplug_lock`.
Okay, the report points out that `slab_mutex` is lock #8.
After closer examination, I find that the chain is really: `fs_reclaim` -> `q_usage_counter` -> `elevator_lock` -> `srcu` -> `cmd->lock` -> `tx_lock` -> `sk_lock` -> `cpu_hotplug_lock` -> `slab_mutex`.
And hey, I see a report from syzbot, it says there is a chain of: `fs_reclaim --> cpu_hotplug_lock --> slab_mutex`. It appears *multiple times* in the report. This suggests a potential deadlock scenario.
Wait... syzbot's report *explicitly* lists a potential deadlock involving those locks: `fs_reclaim` -> `cpu_hotplug_lock` -> `slab_mutex` forming a loop! Now it's clear. The syzbot report confirms this sequence.
So, the dependency is `fs_reclaim` -> ... -> `cpu_hotplug_lock` -> `slab_mutex`. And the new dependency is `slab_mutex` -> `fs_reclaim`.
So the key question is still where is the `cpu_hotplug_lock` held? Is it being held during `do_new_mount`, `vfs_get_tree`, or related functions, *before* calling into `kmem_cache_destroy` where `slab_mutex` is eventually acquired?
Wait, aha! It seems `slab_mutex` is acquired in `kmem_cache_destroy`, and then I remember `kmem_cache_destroy` calls `cpus_read_lock()`!
|
| 57/2 |
2026/05/20 07:09 |
tool |
codesearch-definition-source |
0m
Args: map[ContextFile:mm/slab_common.c IncludeLines:true Name:kmem_cache_destroy]
Results: map[SourceCode: 527: void kmem_cache_destroy(struct kmem_cache *s)
528: {
529: int err;
530:
531: if (unlikely(!s) || !kasan_check_byte(s))
532: return;
533:
534: /* in-flight kfree_rcu()'s may include objects from our cache */
535: kvfree_rcu_barrier_on_cache(s);
536:
537: if (IS_ENABLED(CONFIG_SLUB_RCU_DEBUG) &&
538: (s->flags & SLAB_TYPESAFE_BY_RCU)) {
539: /*
540: * Under CONFIG_SLUB_RCU_DEBUG, when objects in a
541: * SLAB_TYPESAFE_BY_RCU slab are freed, SLUB will internally
542: * defer their freeing with call_rcu().
543: * Wait for such call_rcu() invocations here before actually
544: * destroying the cache.
545: *
546: * It doesn't matter that we haven't looked at the slab refcount
547: * yet - slabs with SLAB_TYPESAFE_BY_RCU can't be merged, so
548: * the refcount should be 1 here.
549: */
550: rcu_barrier();
551: }
552:
553: /* Wait for deferred work from kmalloc/kfree_nolock() */
554: defer_free_barrier();
555:
556: cpus_read_lock();
557: mutex_lock(&slab_mutex);
558:
559: s->refcount--;
560: if (s->refcount) {
561: mutex_unlock(&slab_mutex);
562: cpus_read_unlock();
563: return;
564: }
565:
566: /* free asan quarantined objects */
567: kasan_cache_shutdown(s);
568:
569: err = __kmem_cache_shutdown(s);
570: if (!slab_in_kunit_test())
571: WARN(err, "%s %s: Slab cache still has objects when called from %pS",
572: __func__, s->name, (void *)_RET_IP_);
573:
574: list_del(&s->list);
575:
576: mutex_unlock(&slab_mutex);
577: cpus_read_unlock();
578:
579: if (slab_state >= FULL)
580: sysfs_slab_unlink(s);
581: debugfs_slab_release(s);
582:
583: if (err)
584: return;
585:
586: if (s->flags & SLAB_TYPESAFE_BY_RCU)
587: rcu_barrier();
588:
589: kmem_cache_release(s);
590: }
SourceFile:mm/slab_common.c]
|
| 58/2 |
2026/05/20 07:09 |
llm |
expert |
0m
Model:
Tokens:
input: 51595
output: 41
thoughts: 1433
Thoughts: **Analyzing a Potential Kernel Deadlock: A Deep Dive**
Okay, let's break this down. It looks like `kmem_cache_destroy` establishes a lock dependency right off the bat, acquiring `cpu_hotplug_lock` and then `slab_mutex`. This is our starting point.
Now, let's trace the dependencies:
1. `fs_reclaim` depends on `q_usage_counter` (via `blk_alloc_queue`).
2. `q_usage_counter` depends on `elevator_lock` (from the `elevator_change` sequence).
3. `elevator_lock` depends on `srcu` (also via `elevator_change`).
4. `srcu` depends on `cmd->lock` (through `blk_mq_run_hw_queue` and `nbd_queue_rq`).
5. `cmd->lock` depends on `tx_lock` (via `nbd_queue_rq`).
6. `tx_lock` depends on `sk_lock` (through `send_disconnects` and `sock_xmit`).
7. `sk_lock` depends on `cpu_hotplug_lock` (via `inet_stream_connect`).
8. `cpu_hotplug_lock` depends on `slab_mutex` (as established by `kmem_cache_destroy`).
And the new critical dependency is: `slab_mutex` to `fs_reclaim` (seen from `__kmem_cache_create_args` and `GFP_KERNEL` allocations). This is the key.
So, this new `slab_mutex` -> `fs_reclaim` dependency is what syzbot is flagging. The big question is: is this a real deadlock? Can we actually construct a scenario where threads are blocked in a circular dependency? Let's consider a potential deadlock scenario.
Imagine:
* **Thread 1:** Holding `slab_mutex` (via `__kmem_cache_create_args`), waiting for `fs_reclaim`. This seems plausible since `__kmem_cache_create_args` calls allocation functions that could trigger memory reclaim.
* **Thread 2:** Is in the middle of memory reclaim, holding `fs_reclaim`, and is blocked waiting on an I/O completion which indirectly depends on `q_usage_counter`. Luckily, `blk_alloc_queue` explicitly tells lockdep about this dependency.
Then we need to establish the other locks in the chain:
* **Thread 3:** Holding `q_usage_counter`, blocked waiting on `elevator_lock`.
* **Thread 4:** Holding `elevator_lock`, blocked waiting on `srcu`.
* **Thread 5:** Holding `srcu`, blocked waiting on `cmd->lock`.
* **Thread 6:** Holding `cmd->lock`, blocked waiting on `tx_lock`.
* **Thread 7:** Holding `tx_lock`, blocked waiting on `sk_lock`.
* **Thread 8:** Holding `sk_lock`, blocked waiting on `cpu_hotplug_lock`.
* **Thread 9:** Holding `cpu_hotplug_lock`, blocked waiting on `slab_mutex`.
The critical point is that we confirm that `__kmem_cache_create_args` *does* hold `slab_mutex` and makes `GFP_KERNEL` allocations – specifically, calls to functions like `kstrdup_const` and `kmem_cache_zalloc`. This is confirmed. We also note that `kmem_cache_create` is called in `ubi_attach_mtd_dev`, which might give us a clue where to look.
The problem is that if `__kmem_cache_create_args` makes `GFP_KERNEL` allocations under `slab_mutex`, we have established `slab_mutex` -> `fs_reclaim`. This means that something holding `slab_mutex` cannot wait for `fs_reclaim`, because it would cause a deadlock.
So, the dependency chain becomes: `cpu_hotplug_lock` -> `slab_mutex` -> `fs_reclaim`. This circular dependency is dangerous.
The observed issue is a lockdep warning, which, by itself, isn't exploitable *directly*. However, it signals a *potential* deadlock. If this deadlock actually materializes, it would lead to a system hang, resulting in a Denial of Service.
The final question: can an unprivileged user trigger this? `inet_stream_connect` is accessible to unprivileged users. `send_disconnects` and its reliance on the NBD subsystem is worrisome. If an unprivileged user can manipulate the NBD subsystem
|
| 59/2 |
2026/05/20 07:10 |
tool |
codesearch-definition-source |
0m
Args: map[ContextFile:drivers/block/nbd.c IncludeLines:true Name:nbd_ioctl]
Results: map[SourceCode:1640: static int nbd_ioctl(struct block_device *bdev, blk_mode_t mode,
1641: unsigned int cmd, unsigned long arg)
1642: {
1643: struct nbd_device *nbd = bdev->bd_disk->private_data;
1644: struct nbd_config *config = nbd->config;
1645: int error = -EINVAL;
1646:
1647: if (!capable(CAP_SYS_ADMIN))
1648: return -EPERM;
1649:
1650: /* The block layer will pass back some non-nbd ioctls in case we have
1651: * special handling for them, but we don't so just return an error.
1652: */
1653: if (_IOC_TYPE(cmd) != 0xab)
1654: return -EINVAL;
1655:
1656: mutex_lock(&nbd->config_lock);
1657:
1658: /* Don't allow ioctl operations on a nbd device that was created with
1659: * netlink, unless it's DISCONNECT or CLEAR_SOCK, which are fine.
1660: */
1661: if (!test_bit(NBD_RT_BOUND, &config->runtime_flags) ||
1662: (cmd == NBD_DISCONNECT || cmd == NBD_CLEAR_SOCK))
1663: error = __nbd_ioctl(bdev, nbd, cmd, arg);
1664: else
1665: dev_err(nbd_to_dev(nbd), "Cannot use ioctl interface on a netlink controlled device.\n");
1666: mutex_unlock(&nbd->config_lock);
1667: return error;
1668: }
SourceFile:drivers/block/nbd.c]
|
| 60/2 |
2026/05/20 07:10 |
llm |
expert |
0m
Model:
Tokens:
input: 54624
output: 44
thoughts: 24
Thoughts: Okay, here's my interpretation of those thoughts, summarized in the first person, assuming the audience is another expert:
**NBD Access Control Nuances**
Right, so `nbd_ioctl` needs `CAP_SYS_ADMIN`. That's the established approach, and I understand the security implications there. But I'm starting to think about other ways to handle this... specifically, I'm wondering if a netlink interface for NBD could be a viable alternative. The capabilities already baked into netlink for granular access control could potentially offer a more flexible and, perhaps, more secure way to manage NBD connections and operations than relying solely on a blanket `SYS_ADMIN` requirement. I need to dig into the netlink possibilities here. What does this path look like? Is it even possible to retrofit something like that for existing NBD functionality? I need to think about that.
|
| 61/2 |
2026/05/20 07:10 |
tool |
codesearch-definition-source |
0m
Args: map[ContextFile:drivers/block/nbd.c IncludeLines:true Name:nbd_genl_connect]
Results: map[SourceCode:2073: static int nbd_genl_connect(struct sk_buff *skb, struct genl_info *info)
2074: {
2075: struct nbd_device *nbd;
2076: struct nbd_config *config;
2077: int index = -1;
2078: int ret;
2079: bool put_dev = false;
2080:
2081: if (!netlink_capable(skb, CAP_SYS_ADMIN))
2082: return -EPERM;
2083:
2084: if (info->attrs[NBD_ATTR_INDEX]) {
2085: index = nla_get_u32(info->attrs[NBD_ATTR_INDEX]);
2086:
2087: /*
2088: * Too big first_minor can cause duplicate creation of
2089: * sysfs files/links, since index << part_shift might overflow, or
2090: * MKDEV() expect that the max bits of first_minor is 20.
2091: */
2092: if (index < 0 || index > MINORMASK >> part_shift) {
2093: pr_err("illegal input index %d\n", index);
2094: return -EINVAL;
2095: }
2096: }
2097: if (GENL_REQ_ATTR_CHECK(info, NBD_ATTR_SOCKETS)) {
2098: pr_err("must specify at least one socket\n");
2099: return -EINVAL;
2100: }
2101: if (GENL_REQ_ATTR_CHECK(info, NBD_ATTR_SIZE_BYTES)) {
2102: pr_err("must specify a size in bytes for the device\n");
2103: return -EINVAL;
2104: }
2105: again:
2106: mutex_lock(&nbd_index_mutex);
2107: if (index == -1) {
2108: nbd = nbd_find_get_unused();
2109: } else {
2110: nbd = idr_find(&nbd_index_idr, index);
2111: if (nbd) {
2112: if ((test_bit(NBD_DESTROY_ON_DISCONNECT, &nbd->flags) &&
2113: test_bit(NBD_DISCONNECT_REQUESTED, &nbd->flags)) ||
2114: !refcount_inc_not_zero(&nbd->refs)) {
2115: mutex_unlock(&nbd_index_mutex);
2116: pr_err("device at index %d is going down\n",
2117: index);
2118: return -EINVAL;
2119: }
2120: }
2121: }
2122: mutex_unlock(&nbd_index_mutex);
2123:
2124: if (!nbd) {
2125: nbd = nbd_dev_add(index, 2);
2126: if (IS_ERR(nbd)) {
2127: pr_err("failed to add new device\n");
2128: return PTR_ERR(nbd);
2129: }
2130: }
2131:
2132: mutex_lock(&nbd->config_lock);
2133: if (refcount_read(&nbd->config_refs)) {
2134: mutex_unlock(&nbd->config_lock);
2135: nbd_put(nbd);
2136: if (index == -1)
2137: goto again;
2138: pr_err("nbd%d already in use\n", index);
2139: return -EBUSY;
2140: }
2141:
2142: ret = nbd_alloc_and_init_config(nbd);
2143: if (ret) {
2144: mutex_unlock(&nbd->config_lock);
2145: nbd_put(nbd);
2146: pr_err("couldn't allocate config\n");
2147: return ret;
2148: }
2149:
2150: config = nbd->config;
2151: set_bit(NBD_RT_BOUND, &config->runtime_flags);
2152: ret = nbd_genl_size_set(info, nbd);
2153: if (ret)
2154: goto out;
2155:
2156: if (info->attrs[NBD_ATTR_TIMEOUT])
2157: nbd_set_cmd_timeout(nbd,
2158: nla_get_u64(info->attrs[NBD_ATTR_TIMEOUT]));
2159: if (info->attrs[NBD_ATTR_DEAD_CONN_TIMEOUT]) {
2160: config->dead_conn_timeout =
2161: nla_get_u64(info->attrs[NBD_ATTR_DEAD_CONN_TIMEOUT]);
2162: config->dead_conn_timeout *= HZ;
2163: }
2164: if (info->attrs[NBD_ATTR_SERVER_FLAGS])
2165: config->flags =
2166: nla_get_u64(info->attrs[NBD_ATTR_SERVER_FLAGS]);
2167: if (info->attrs[NBD_ATTR_CLIENT_FLAGS]) {
2168: u64 flags = nla_get_u64(info->attrs[NBD_ATTR_CLIENT_FLAGS]);
2169: if (flags & NBD_CFLAG_DESTROY_ON_DISCONNECT) {
2170: /*
2171: * We have 1 ref to keep the device around, and then 1
2172: * ref for our current operation here, which will be
2173: * inherited by the config. If we already have
2174: * DESTROY_ON_DISCONNECT set then we know we don't have
2175: * that extra ref already held so we don't need the
2176: * put_dev.
2177: */
2178: if (!test_and_set_bit(NBD_DESTROY_ON_DISCONNECT,
2179: &nbd->flags))
2180: put_dev = true;
2181: } else {
2182: if (test_and_clear_bit(NBD_DESTROY_ON_DISCONNECT,
2183: &nbd->flags))
2184: refcount_inc(&nbd->refs);
2185: }
2186: if (flags & NBD_CFLAG_DISCONNECT_ON_CLOSE) {
2187: set_bit(NBD_RT_DISCONNECT_ON_CLOSE,
2188: &config->runtime_flags);
2189: }
2190: }
2191:
2192: if (info->attrs[NBD_ATTR_SOCKETS]) {
2193: struct nlattr *attr;
2194: int rem, fd;
2195:
2196: nla_for_each_nested(attr, info->attrs[NBD_ATTR_SOCKETS],
2197: rem) {
2198: struct nlattr *socks[NBD_SOCK_MAX+1];
2199:
2200: if (nla_type(attr) != NBD_SOCK_ITEM) {
2201: pr_err("socks must be embedded in a SOCK_ITEM attr\n");
2202: ret = -EINVAL;
2203: goto out;
2204: }
2205: ret = nla_parse_nested_deprecated(socks, NBD_SOCK_MAX,
2206: attr,
2207: nbd_sock_policy,
2208: info->extack);
2209: if (ret != 0) {
2210: pr_err("error processing sock list\n");
2211: ret = -EINVAL;
2212: goto out;
2213: }
2214: if (!socks[NBD_SOCK_FD])
2215: continue;
2216: fd = (int)nla_get_u32(socks[NBD_SOCK_FD]);
2217: ret = nbd_add_socket(nbd, fd, true);
2218: if (ret)
2219: goto out;
2220: }
2221: }
2222:
2223: if (info->attrs[NBD_ATTR_BACKEND_IDENTIFIER]) {
2224: nbd->backend = nla_strdup(info->attrs[NBD_ATTR_BACKEND_IDENTIFIER],
2225: GFP_KERNEL);
2226: if (!nbd->backend) {
2227: ret = -ENOMEM;
2228: goto out;
2229: }
2230: }
2231: ret = device_create_file(disk_to_dev(nbd->disk), &backend_attr);
2232: if (ret) {
2233: dev_err(disk_to_dev(nbd->disk),
2234: "device_create_file failed for backend!\n");
2235: goto out;
2236: }
2237: set_bit(NBD_RT_HAS_BACKEND_FILE, &config->runtime_flags);
2238:
2239: ret = nbd_start_device(nbd);
2240: out:
2241: if (!ret) {
2242: set_bit(NBD_RT_HAS_CONFIG_REF, &config->runtime_flags);
2243: refcount_inc(&nbd->config_refs);
2244: nbd_connect_reply(info, nbd->index);
2245: }
2246: mutex_unlock(&nbd->config_lock);
2247:
2248: nbd_config_put(nbd);
2249: if (put_dev)
2250: nbd_put(nbd);
2251: return ret;
2252: }
SourceFile:drivers/block/nbd.c]
|
| 62/2 |
2026/05/20 07:10 |
llm |
expert |
0m
Model:
Tokens:
input: 57764
output: 44
thoughts: 77
Thoughts: Okay, here's my interpretation of this technical snippet, expressed as if it's my own thought process:
**Diving into `nbd_genl_connect` and Capability Checks**
Alright, so `nbd_genl_connect` mandates `CAP_SYS_ADMIN` within the *initial user namespace*. The code snippet makes that pretty clear with the `if (!netlink_capable(skb, CAP_SYS_ADMIN))` check. My immediate instinct is to look at how `netlink_capable` is implemented here. It's a common pattern.
Okay, let's take a look at the `netlink_capable` function; it probably checks if the socket has sufficient permissions. Ah, wait, a key detail... it checks the capability *in the user namespace of the socket*. That's the crucial point! It isn't just a global check; it's scoped to the network namespace.
|
| 63/2 |
2026/05/20 07:10 |
tool |
codesearch-definition-source |
0m
Args: map[ContextFile:net/netlink/af_netlink.c IncludeLines:true Name:netlink_capable]
Results: map[SourceCode: 873: /**
874: * netlink_capable - Netlink global message capability test
875: * @skb: socket buffer holding a netlink command from userspace
876: * @cap: The capability to use
877: *
878: * Test to see if the opener of the socket we received the message
879: * from had when the netlink socket was created and the sender of the
880: * message has the capability @cap in all user namespaces.
881: */
882: bool netlink_capable(const struct sk_buff *skb, int cap)
883: {
884: return netlink_ns_capable(skb, &init_user_ns, cap);
885: }
SourceFile:net/netlink/af_netlink.c]
|
| 64/2 |
2026/05/20 07:10 |
llm |
expert |
0m
Model:
Tokens:
input: 58327
output: 45
thoughts: 298
Thoughts: **Analyzing NBD and UBI Access Restrictions**
Okay, so I see that `netlink_capable` does indeed check against `&init_user_ns`. That confirms it, which means that NBD requires global `CAP_SYS_ADMIN` privileges. Consequently, unprivileged users and processes within a user namespace won't be able to access it. That's a fundamental security limitation, as expected.
Now, I'm trying to remember something else related to privilege restrictions. What about `ubi_attach`? I recall a syzbot report that was a bit intriguing. Let me look it up. Right, here it is: the report mentions `syz.0.3086/17300 is trying to acquire lock: fs_reclaim but task is already holding lock: slab_mutex at: __kmem_cache_create_args+0x44/0x420 mm/slab_common.c:350`. It traces back to `alloc_ai drivers/mtd/ubi/attach.c:1464 [inline]`, ultimately leading to `ubi_attach+0x32a/0x4d30 drivers/mtd/ubi/attach.c:1560`, `ubi_attach_mtd_dev+0x139f/0x32a0 drivers/mtd/ubi/build.c:1004`, and finally `ctrl_cdev_ioctl+0x36a/0x400 drivers/mtd/ubi/cdev.c:1113`.
That's a bit of a breadcrumb trail. To understand what's going on, the best next step is definitely to investigate `ctrl_cdev_ioctl` in `drivers/mtd/ubi/cdev.c`. This could shed light on whether some privilege escalation is happening there.
|
| 65/2 |
2026/05/20 07:10 |
tool |
codesearch-definition-source |
0m
Args: map[ContextFile:drivers/mtd/ubi/cdev.c IncludeLines:true Name:ctrl_cdev_ioctl]
Results: map[SourceCode:1073: static long ctrl_cdev_ioctl(struct file *file, unsigned int cmd,
1074: unsigned long arg)
1075: {
1076: int err = 0;
1077: void __user *argp = (void __user *)arg;
1078:
1079: if (!capable(CAP_SYS_RESOURCE))
1080: return -EPERM;
1081:
1082: switch (cmd) {
1083: /* Attach an MTD device command */
1084: case UBI_IOCATT:
1085: {
1086: struct ubi_attach_req req;
1087: struct mtd_info *mtd;
1088:
1089: dbg_gen("attach MTD device");
1090: err = copy_from_user(&req, argp, sizeof(struct ubi_attach_req));
1091: if (err) {
1092: err = -EFAULT;
1093: break;
1094: }
1095:
1096: if (req.mtd_num < 0 ||
1097: (req.ubi_num < 0 && req.ubi_num != UBI_DEV_NUM_AUTO)) {
1098: err = -EINVAL;
1099: break;
1100: }
1101:
1102: mtd = get_mtd_device(NULL, req.mtd_num);
1103: if (IS_ERR(mtd)) {
1104: err = PTR_ERR(mtd);
1105: break;
1106: }
1107:
1108: /*
1109: * Note, further request verification is done by
1110: * 'ubi_attach_mtd_dev()'.
1111: */
1112: mutex_lock(&ubi_devices_mutex);
1113: err = ubi_attach_mtd_dev(mtd, req.ubi_num, req.vid_hdr_offset,
1114: req.max_beb_per1024, !!req.disable_fm,
1115: !!req.need_resv_pool);
1116: mutex_unlock(&ubi_devices_mutex);
1117: if (err < 0)
1118: put_mtd_device(mtd);
1119: else
1120: /* @err contains UBI device number */
1121: err = put_user(err, (__user int32_t *)argp);
1122:
1123: break;
1124: }
1125:
1126: /* Detach an MTD device command */
1127: case UBI_IOCDET:
1128: {
1129: int ubi_num;
1130:
1131: dbg_gen("detach MTD device");
1132: err = get_user(ubi_num, (__user int32_t *)argp);
1133: if (err) {
1134: err = -EFAULT;
1135: break;
1136: }
1137:
1138: mutex_lock(&ubi_devices_mutex);
1139: err = ubi_detach_mtd_dev(ubi_num, 0);
1140: mutex_unlock(&ubi_devices_mutex);
1141: break;
1142: }
1143:
1144: default:
1145: err = -ENOTTY;
1146: break;
1147: }
1148:
1149: return err;
1150: }
SourceFile:drivers/mtd/ubi/cdev.c]
|
| 66/2 |
2026/05/20 07:10 |
llm |
expert |
0m
Model:
Tokens:
input: 60152
output: 26
thoughts: 1621
Thoughts: **Analyzing a Potential Kernel Deadlock**
Okay, so `ctrl_cdev_ioctl` needs `CAP_SYS_RESOURCE` globally, which means `ubi_attach` is off-limits to unprivileged users and within user namespaces. That's good to know, it helps rule things out. Now, this lockdep warning… it's about a circular dependency, right? Let's trace it.
The real question is, are there other ways to create a path that results in `slab_mutex` waiting on `fs_reclaim`? Let's break this down. `__kmem_cache_create_args` gets called by `kmem_cache_create`, which means any module loading or device init that sets up a kmem cache will trigger this issue. Damn, `kmem_cache_create` is called a *lot*.
Can an unprivileged context trigger `kmem_cache_create`? Creating a new network namespace? Probably not, usually, caches are set up during module initialization. Filesystems? Some might create caches per superblock, but they're often initialized during module load too, right? Ah, wait, `ubi_attach` calls `alloc_ai`, which in turn calls `kmem_cache_create`.
Let's quickly check for other unprivileged calls to `kmem_cache_create` just to be sure. Even if one exists, the bug is just a lockdep warning. But is this a true deadlock? Let's find out!
If `kmem_cache_create` gets called, it holds `slab_mutex` and does `GFP_KERNEL` allocation. If we're low on memory, it triggers direct reclaim, which waits for `fs_reclaim`. Now, if another thread is doing memory reclaim, it holds `fs_reclaim` and potentially waits for `q_usage_counter` – this could involve doing I/O to swap. Next, if a third thread is messing with the elevator, it holds `q_usage_counter` and waits for `elevator_lock`. The fourth thread… it holds `elevator_lock` and waits for `srcu`, and then `srcu` is held by a fifth thread that's waiting on `cmd->lock`, the sixth holds `cmd->lock` and waiting on `tx_lock`, the seventh thread holds `tx_lock` while waiting for `sk_lock`, which is held by the eighth thread waiting on `cpu_hotplug_lock`. And lastly, if the ninth thread is running `kmem_cache_destroy`, then it holds `cpu_hotplug_lock` and waits for `slab_mutex`.
That's a ridiculously long chain! But it's theoretically possible. Key point: `kmem_cache_destroy` holding `cpu_hotplug_lock` and waiting on `slab_mutex` is the critical piece. Wait, `kmem_cache_destroy` is called when a cache gets destroyed. If that's the scenario, `cpu_hotplug_lock` blocks `slab_mutex` which is a problem because if `kmem_cache_create` is called and has a `slab_mutex` dependency, we have a problem. If `fs_reclaim` is trying to access `cpu_hotplug_lock`, then it could be a deadlock. But how can `fs_reclaim` get blocked by `cpu_hotplug_lock`?
Ah, it seems to go through NBD and network sockets. But NBD requires `CAP_SYS_ADMIN`. And to trigger the deadlock, you need to set up NBD, trigger `kmem_cache_create` and `kmem_cache_destroy` concurrently, and have memory reclaim happen. That's a super complex set of conditions! Plus, NBD needs `CAP_SYS_ADMIN` – which an unprivileged user wouldn't have.
Wait a second, wasn’t this `kmem_cache_create` doing `GFP_KERNEL` allocation under `slab_mutex` discussed recently on LKML? I think so. Oh, now it makes sense. The real issue is `slab_mutex` is held when we call `create_cache`, which then calls `kmem_cache_zalloc(kmem_cache, GFP_KERNEL)`. This might have been introduced recently. The point is, `kmem_cache_zalloc(kmem_cache, GFP_KERNEL)` *under* `slab_mutex` means `slab_mutex` -> `fs_reclaim`. Are there any other paths where `fs_reclaim` could depend on `slab_mutex`?
The lockdep report shows this chain: `fs_reclaim` -> `q_usage_counter` -> `elevator_lock` -> `srcu` -> `
|
| 67/2 |
2026/05/20 07:11 |
tool |
grepper |
0m
Args: map[Expression:kmem_cache_create.*nf_conntrack]
Results: map[Output:net/netfilter/nf_conntrack_core.c=2623=int nf_conntrack_init_start(void)
--
net/netfilter/nf_conntrack_core.c-2662-
net/netfilter/nf_conntrack_core.c:2663: nf_conntrack_cachep = kmem_cache_create("nf_conntrack",
net/netfilter/nf_conntrack_core.c-2664- sizeof(struct nf_conn),
]
|
| 68/2 |
2026/05/20 07:11 |
llm |
expert |
0m
Model:
Tokens:
input: 62966
output: 23
thoughts: 22
Thoughts: Here's my attempt at summarizing those thoughts, tailored for an expert audience and written in the first person:
**Kernel Memory Allocation - Global Concerns**
Okay, so I'm thinking about this issue, and the scope of it is immediately striking me. This isn't localized; it has the potential to touch the entire system. We're talking global ramifications, which means a careful, holistic approach is critical.
That leads me to a specific area of concern. I need to consider `kmem_cache_create` within the `fs/` directory. Given the widespread use of filesystems, I need to start evaluating how memory is being handled for file operations. The memory caching aspect of `kmem_cache_create` is what I need to focus on - is this area a possible contributor to the global problem?
|
| 69/2 |
2026/05/20 07:11 |
tool |
grepper |
0m
Args: map[Expression:kmem_cache_create.*_cache]
Results: map[Output:
Full output is too long, showing 500 out of 821 lines.
Use more precise expression if possible.
[Documentation/translations/zh_CN/core-api/memory-allocation.rst=76=GFP标志和回收行为
--
Documentation/translations/zh_CN/core-api/memory-allocation.rst-131-如果你需要分配许多相同的对象,你可以使用slab缓存分配器。在使用缓存之前,应该用
Documentation/translations/zh_CN/core-api/memory-allocation.rst:132:kmem_cache_create()或kmem_cache_create_usercopy()来设置缓存。如果缓存的一部分可能被复
Documentation/translations/zh_CN/core-api/memory-allocation.rst-133-制到用户空间,应该使用第二个函数。在缓存被创建后,kmem_cache_alloc()和它的封装可以从该缓
--
arch/arm64/mm/pgd.c=49=void __init pgtable_cache_init(void)
--
arch/arm64/mm/pgd.c-64- */
arch/arm64/mm/pgd.c:65: pgd_cache = kmem_cache_create("pgd_cache", PGD_SIZE, PGD_SIZE,
arch/arm64/mm/pgd.c-66- SLAB_PANIC, NULL);
--
arch/powerpc/kernel/rtas_flash.c=675=static int __init rtas_flash_init(void)
--
arch/powerpc/kernel/rtas_flash.c-687-
arch/powerpc/kernel/rtas_flash.c:688: flash_block_cache = kmem_cache_create_usercopy("rtas_flash_cache",
arch/powerpc/kernel/rtas_flash.c-689- RTAS_BLK_SIZE, RTAS_BLK_SIZE,
--
arch/powerpc/kvm/book3s_mmu_hpte.c=368=int kvmppc_mmu_hpte_sysinit(void)
--
arch/powerpc/kvm/book3s_mmu_hpte.c-370- /* init hpte slab cache */
arch/powerpc/kvm/book3s_mmu_hpte.c:371: hpte_cache = kmem_cache_create("kvm-spt", sizeof(struct hpte_cache),
arch/powerpc/kvm/book3s_mmu_hpte.c-372- sizeof(struct hpte_cache), 0, NULL);
--
arch/powerpc/platforms/cell/spufs/inode.c=762=static int __init spufs_init(void)
--
arch/powerpc/platforms/cell/spufs/inode.c-770- ret = -ENOMEM;
arch/powerpc/platforms/cell/spufs/inode.c:771: spufs_inode_cache = kmem_cache_create("spufs_inode_cache",
arch/powerpc/platforms/cell/spufs/inode.c-772- sizeof(struct spufs_inode_info), 0,
--
arch/s390/pci/pci.c=1065=static int zpci_mem_init(void)
--
arch/s390/pci/pci.c-1071-
arch/s390/pci/pci.c:1072: zdev_fmb_cache = kmem_cache_create("PCI_FMB_cache", sizeof(struct zpci_fmb),
arch/s390/pci/pci.c-1073- __alignof__(struct zpci_fmb), 0, NULL);
--
arch/sh/kernel/cpu/sh4/sq.c=372=static int __init sq_api_init(void)
--
arch/sh/kernel/cpu/sh4/sq.c-378-
arch/sh/kernel/cpu/sh4/sq.c:379: sq_cache = kmem_cache_create("store_queue_cache",
arch/sh/kernel/cpu/sh4/sq.c-380- sizeof(struct sq_mapping), 0, 0, NULL);
--
arch/sh/mm/pgtable.c=22=void pgtable_cache_init(void)
arch/sh/mm/pgtable.c-23-{
arch/sh/mm/pgtable.c:24: pgd_cachep = kmem_cache_create("pgd_cache",
arch/sh/mm/pgtable.c-25- PTRS_PER_PGD * (1<<PTE_MAGNITUDE),
--
arch/sh/mm/pgtable.c-27-#if PAGETABLE_LEVELS > 2
arch/sh/mm/pgtable.c:28: pmd_cachep = kmem_cache_create("pmd_cache",
arch/sh/mm/pgtable.c-29- PTRS_PER_PMD * (1<<PTE_MAGNITUDE),
--
arch/sparc/mm/tsb.c=341=void __init pgtable_cache_init(void)
--
arch/sparc/mm/tsb.c-344-
arch/sparc/mm/tsb.c:345: pgtable_cache = kmem_cache_create("pgtable_cache",
arch/sparc/mm/tsb.c-346- PAGE_SIZE, PAGE_SIZE,
--
block/bdev.c=447=void __init bdev_cache_init(void)
--
block/bdev.c-450-
block/bdev.c:451: bdev_cachep = kmem_cache_create("bdev_cache", sizeof(struct bdev_inode),
block/bdev.c-452- 0, (SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT|
--
block/elevator.c=498=int elv_register(struct elevator_type *e)
--
block/elevator.c-514- "%s_io_cq", e->elevator_name);
block/elevator.c:515: e->icq_cache = kmem_cache_create(e->icq_cache_name, e->icq_size,
block/elevator.c-516- e->icq_align, 0, NULL);
--
drivers/block/xen-blkback/xenbus.c=356=int __init xen_blkif_interface_init(void)
drivers/block/xen-blkback/xenbus.c-357-{
drivers/block/xen-blkback/xenbus.c:358: xen_blkif_cachep = kmem_cache_create("blkif_cache",
drivers/block/xen-blkback/xenbus.c-359- sizeof(struct xen_blkif),
--
drivers/crypto/ccp/ccp-dmaengine.c=665=int ccp_dmaengine_register(struct ccp_device *ccp)
--
drivers/crypto/ccp/ccp-dmaengine.c-689-
drivers/crypto/ccp/ccp-dmaengine.c:690: ccp->dma_cmd_cache = kmem_cache_create(dma_cmd_cache_name,
drivers/crypto/ccp/ccp-dmaengine.c-691- sizeof(struct ccp_dma_cmd),
--
drivers/crypto/ccp/ccp-dmaengine.c-704-
drivers/crypto/ccp/ccp-dmaengine.c:705: ccp->dma_desc_cache = kmem_cache_create(dma_desc_cache_name,
drivers/crypto/ccp/ccp-dmaengine.c-706- sizeof(struct ccp_dma_desc),
--
drivers/dax/super.c=644=static int dax_fs_init(void)
--
drivers/dax/super.c-647-
drivers/dax/super.c:648: dax_cache = kmem_cache_create("dax_cache", sizeof(struct dax_device), 0,
drivers/dax/super.c-649- SLAB_HWCACHE_ALIGN | SLAB_RECLAIM_ACCOUNT | SLAB_ACCOUNT,
--
drivers/dma/amd/ptdma/ptdma-dmaengine.c=562=int pt_dmaengine_register(struct pt_device *pt)
--
drivers/dma/amd/ptdma/ptdma-dmaengine.c-589-
drivers/dma/amd/ptdma/ptdma-dmaengine.c:590: pt->dma_desc_cache = kmem_cache_create(desc_cache_name,
drivers/dma/amd/ptdma/ptdma-dmaengine.c-591- sizeof(struct pt_dma_desc), 0,
--
drivers/dma/idxd/init.c=420=static int idxd_init_evl(struct idxd_device *idxd)
--
drivers/dma/idxd/init.c-443- */
drivers/dma/idxd/init.c:444: idxd->evl_cache = kmem_cache_create_usercopy(idxd_name, evl_cache_size,
drivers/dma/idxd/init.c-445- 0, 0, 0, evl_cache_size,
--
drivers/greybus/operation.c=1226=int __init gb_operation_init(void)
drivers/greybus/operation.c-1227-{
drivers/greybus/operation.c:1228: gb_message_cache = kmem_cache_create("gb_message_cache",
drivers/greybus/operation.c-1229- sizeof(struct gb_message), 0, 0,
--
drivers/greybus/operation.c-1233-
drivers/greybus/operation.c:1234: gb_operation_cache = kmem_cache_create("gb_operation_cache",
drivers/greybus/operation.c-1235- sizeof(struct gb_operation), 0,
--
drivers/iommu/omap-iommu.c=1731=static int __init omap_iommu_init(void)
--
drivers/iommu/omap-iommu.c-1744-
drivers/iommu/omap-iommu.c:1745: p = kmem_cache_create("iopte_cache", IOPTE_TABLE_SIZE, align, flags,
drivers/iommu/omap-iommu.c-1746- NULL);
--
drivers/md/dm-cache-target.c=3570=static int __init dm_cache_init(void)
--
drivers/md/dm-cache-target.c-3579-
drivers/md/dm-cache-target.c:3580: btracker_work_cache = kmem_cache_create("dm_cache_bt_work",
drivers/md/dm-cache-target.c-3581- sizeof(struct bt_work), __alignof__(struct bt_work), 0, NULL);
--
drivers/nvme/target/fcloop.c=1700=static int __init fcloop_init(void)
--
drivers/nvme/target/fcloop.c-1703-
drivers/nvme/target/fcloop.c:1704: lsreq_cache = kmem_cache_create("lsreq_cache",
drivers/nvme/target/fcloop.c-1705- sizeof(struct fcloop_lsreq), 0,
--
drivers/s390/block/dasd_devmap.c=224=static int __init dasd_parse_keyword(char *keyword)
--
drivers/s390/block/dasd_devmap.c-256- dasd_page_cache =
drivers/s390/block/dasd_devmap.c:257: kmem_cache_create("dasd_page_cache", PAGE_SIZE,
drivers/s390/block/dasd_devmap.c-258- PAGE_SIZE, SLAB_CACHE_DMA,
--
drivers/s390/cio/cmf.c=1248=static int __init init_cmbe(void)
drivers/s390/cio/cmf.c-1249-{
drivers/s390/cio/cmf.c:1250: cmbe_cache = kmem_cache_create("cmbe_cache", sizeof(struct cmbe),
drivers/s390/cio/cmf.c-1251- __alignof__(struct cmbe), 0, NULL);
--
drivers/scsi/qedf/qedf_main.c=4124=static int __init qedf_init(void)
--
drivers/scsi/qedf/qedf_main.c-4147- /* Create kmem_cache for qedf_io_work structs */
drivers/scsi/qedf/qedf_main.c:4148: qedf_io_work_cache = kmem_cache_create("qedf_io_work_cache",
drivers/scsi/qedf/qedf_main.c-4149- sizeof(struct qedf_io_work), 0, SLAB_HWCACHE_ALIGN, NULL);
--
drivers/scsi/qla2xxx/qla_target.c=8346=int __init qlt_init(void)
--
drivers/scsi/qla2xxx/qla_target.c-8361-
drivers/scsi/qla2xxx/qla_target.c:8362: qla_tgt_mgmt_cmd_cachep = kmem_cache_create("qla_tgt_mgmt_cmd_cachep",
drivers/scsi/qla2xxx/qla_target.c-8363- sizeof(struct qla_tgt_mgmt_cmd), __alignof__(struct
--
drivers/scsi/qla2xxx/qla_target.c-8366- ql_log(ql_log_fatal, NULL, 0xd04b,
drivers/scsi/qla2xxx/qla_target.c:8367: "kmem_cache_create for qla_tgt_mgmt_cmd_cachep failed\n");
drivers/scsi/qla2xxx/qla_target.c-8368- return -ENOMEM;
--
drivers/scsi/qla2xxx/qla_target.c-8370-
drivers/scsi/qla2xxx/qla_target.c:8371: qla_tgt_plogi_cachep = kmem_cache_create("qla_tgt_plogi_cachep",
drivers/scsi/qla2xxx/qla_target.c-8372- sizeof(struct qlt_plogi_ack_t), __alignof__(struct qlt_plogi_ack_t),
--
drivers/scsi/qla2xxx/qla_target.c-8376- ql_log(ql_log_fatal, NULL, 0xe06d,
drivers/scsi/qla2xxx/qla_target.c:8377: "kmem_cache_create for qla_tgt_plogi_cachep failed\n");
drivers/scsi/qla2xxx/qla_target.c-8378- ret = -ENOMEM;
--
drivers/scsi/scsi_lib.c=62=int scsi_init_sense_cache(struct Scsi_Host *shost)
--
drivers/scsi/scsi_lib.c-68- scsi_sense_cache =
drivers/scsi/scsi_lib.c:69: kmem_cache_create_usercopy("scsi_sense_cache",
drivers/scsi/scsi_lib.c-70- SCSI_SENSE_BUFFERSIZE, 0, SLAB_HWCACHE_ALIGN,
--
drivers/scsi/virtio_scsi.c=1063=static int __init virtio_scsi_init(void)
--
drivers/scsi/virtio_scsi.c-1068- if (!virtscsi_cmd_cache) {
drivers/scsi/virtio_scsi.c:1069: pr_err("kmem_cache_create() for virtscsi_cmd_cache failed\n");
drivers/scsi/virtio_scsi.c-1070- goto error;
--
drivers/staging/media/atomisp/pci/hmm/hmm_bo.c=318=int hmm_bo_device_init(struct hmm_bo_device *bdev,
--
drivers/staging/media/atomisp/pci/hmm/hmm_bo.c-346-
drivers/staging/media/atomisp/pci/hmm/hmm_bo.c:347: bdev->bo_cache = kmem_cache_create("bo_cache",
drivers/staging/media/atomisp/pci/hmm/hmm_bo.c-348- sizeof(struct hmm_buffer_object), 0, 0, NULL);
--
drivers/target/iscsi/iscsi_target.c=672=static int __init iscsi_target_init_module(void)
--
drivers/target/iscsi/iscsi_target.c-699-
drivers/target/iscsi/iscsi_target.c:700: lio_qr_cache = kmem_cache_create("lio_qr_cache",
drivers/target/iscsi/iscsi_target.c-701- sizeof(struct iscsi_queue_req),
--
drivers/target/iscsi/iscsi_target.c-708-
drivers/target/iscsi/iscsi_target.c:709: lio_dr_cache = kmem_cache_create("lio_dr_cache",
drivers/target/iscsi/iscsi_target.c-710- sizeof(struct iscsi_datain_req),
--
drivers/target/iscsi/iscsi_target.c-717-
drivers/target/iscsi/iscsi_target.c:718: lio_ooo_cache = kmem_cache_create("lio_ooo_cache",
drivers/target/iscsi/iscsi_target.c-719- sizeof(struct iscsi_ooo_cmdsn),
--
drivers/target/iscsi/iscsi_target.c-726-
drivers/target/iscsi/iscsi_target.c:727: lio_r2t_cache = kmem_cache_create("lio_r2t_cache",
drivers/target/iscsi/iscsi_target.c-728- sizeof(struct iscsi_r2t), __alignof__(struct iscsi_r2t),
--
drivers/target/loopback/tcm_loop.c=1155=static int __init tcm_loop_fabric_init(void)
--
drivers/target/loopback/tcm_loop.c-1158-
drivers/target/loopback/tcm_loop.c:1159: tcm_loop_cmd_cache = kmem_cache_create("tcm_loop_cmd_cache",
drivers/target/loopback/tcm_loop.c-1160- sizeof(struct tcm_loop_cmd),
--
drivers/target/loopback/tcm_loop.c-1163- if (!tcm_loop_cmd_cache) {
drivers/target/loopback/tcm_loop.c:1164: pr_debug("kmem_cache_create() for tcm_loop_cmd_cache failed\n");
drivers/target/loopback/tcm_loop.c-1165- goto out;
--
drivers/target/target_core_transport.c=60=int init_se_kmem_caches(void)
drivers/target/target_core_transport.c-61-{
drivers/target/target_core_transport.c:62: se_sess_cache = kmem_cache_create("se_sess_cache",
drivers/target/target_core_transport.c-63- sizeof(struct se_session), __alignof__(struct se_session),
--
drivers/target/target_core_transport.c-69- }
drivers/target/target_core_transport.c:70: se_ua_cache = kmem_cache_create("se_ua_cache",
drivers/target/target_core_transport.c-71- sizeof(struct se_ua), __alignof__(struct se_ua),
--
drivers/target/target_core_transport.c-76- }
drivers/target/target_core_transport.c:77: t10_pr_reg_cache = kmem_cache_create("t10_pr_reg_cache",
drivers/target/target_core_transport.c-78- sizeof(struct t10_pr_registration),
--
drivers/target/target_core_transport.c-84- }
drivers/target/target_core_transport.c:85: t10_alua_lu_gp_cache = kmem_cache_create("t10_alua_lu_gp_cache",
drivers/target/target_core_transport.c-86- sizeof(struct t10_alua_lu_gp), __alignof__(struct t10_alua_lu_gp),
--
drivers/target/target_core_transport.c-88- if (!t10_alua_lu_gp_cache) {
drivers/target/target_core_transport.c:89: pr_err("kmem_cache_create() for t10_alua_lu_gp_cache"
drivers/target/target_core_transport.c-90- " failed\n");
--
drivers/target/target_core_transport.c-92- }
drivers/target/target_core_transport.c:93: t10_alua_lu_gp_mem_cache = kmem_cache_create("t10_alua_lu_gp_mem_cache",
drivers/target/target_core_transport.c-94- sizeof(struct t10_alua_lu_gp_member),
--
drivers/target/target_core_transport.c-100- }
drivers/target/target_core_transport.c:101: t10_alua_tg_pt_gp_cache = kmem_cache_create("t10_alua_tg_pt_gp_cache",
drivers/target/target_core_transport.c-102- sizeof(struct t10_alua_tg_pt_gp),
--
drivers/target/target_core_user.c=3321=static int __init tcmu_module_init(void)
--
drivers/target/target_core_user.c-3328-
drivers/target/target_core_user.c:3329: tcmu_cmd_cache = kmem_cache_create("tcmu_cmd_cache",
drivers/target/target_core_user.c-3330- sizeof(struct tcmu_cmd),
--
fs/9p/v9fs.c=675=static int v9fs_init_inode_cache(void)
fs/9p/v9fs.c-676-{
fs/9p/v9fs.c:677: v9fs_inode_cache = kmem_cache_create("v9fs_inode_cache",
fs/9p/v9fs.c-678- sizeof(struct v9fs_inode),
--
fs/adfs/super.c=222=static int __init init_inodecache(void)
fs/adfs/super.c-223-{
fs/adfs/super.c:224: adfs_inode_cachep = kmem_cache_create("adfs_inode_cache",
fs/adfs/super.c-225- sizeof(struct adfs_inode_info),
--
fs/affs/super.c=130=static int __init init_inodecache(void)
fs/affs/super.c-131-{
fs/affs/super.c:132: affs_inode_cachep = kmem_cache_create("affs_inode_cache",
fs/affs/super.c-133- sizeof(struct affs_inode_info),
--
fs/afs/super.c=96=int __init afs_fs_init(void)
--
fs/afs/super.c-105- ret = -ENOMEM;
fs/afs/super.c:106: afs_inode_cachep = kmem_cache_create("afs_inode_cache",
fs/afs/super.c-107- sizeof(struct afs_vnode),
--
fs/aio.c=338=static int __init aio_setup(void)
--
fs/aio.c-345-
fs/aio.c:346: aio_inode_cachep = kmem_cache_create("aio_inode_cache",
fs/aio.c-347- sizeof(struct aio_inode_info), 0,
--
fs/befs/linuxvfs.c=435=befs_init_inodecache(void)
fs/befs/linuxvfs.c-436-{
fs/befs/linuxvfs.c:437: befs_inode_cachep = kmem_cache_create_usercopy("befs_inode_cache",
fs/befs/linuxvfs.c-438- sizeof(struct befs_inode_info), 0,
--
fs/bfs/inode.c=279=static int __init init_inodecache(void)
fs/bfs/inode.c-280-{
fs/bfs/inode.c:281: bfs_inode_cachep = kmem_cache_create("bfs_inode_cache",
fs/bfs/inode.c-282- sizeof(struct bfs_inode_info),
--
fs/coda/inode.c=71=int __init coda_init_inodecache(void)
fs/coda/inode.c-72-{
fs/coda/inode.c:73: coda_inode_cachep = kmem_cache_create("coda_inode_cache",
fs/coda/inode.c-74- sizeof(struct coda_inode_info), 0,
--
fs/configfs/mount.c=136=static int __init configfs_init(void)
--
fs/configfs/mount.c-139-
fs/configfs/mount.c:140: configfs_dir_cachep = kmem_cache_create("configfs_dir_cache",
fs/configfs/mount.c-141- sizeof(struct configfs_dirent),
--
fs/debugfs/inode.c=900=static int __init debugfs_init(void)
--
fs/debugfs/inode.c-910-
fs/debugfs/inode.c:911: debugfs_inode_cachep = kmem_cache_create("debugfs_inode_cache",
fs/debugfs/inode.c-912- sizeof(struct debugfs_inode_info), 0,
--
fs/efs/super.c=86=static int __init init_inodecache(void)
fs/efs/super.c-87-{
fs/efs/super.c:88: efs_inode_cachep = kmem_cache_create("efs_inode_cache",
fs/efs/super.c-89- sizeof(struct efs_inode_info), 0,
--
fs/exfat/cache.c=45=int exfat_cache_init(void)
fs/exfat/cache.c-46-{
fs/exfat/cache.c:47: exfat_cachep = kmem_cache_create("exfat_cache",
fs/exfat/cache.c-48- sizeof(struct exfat_cache),
--
fs/exfat/super.c=895=static int __init init_exfat_fs(void)
--
fs/exfat/super.c-902-
fs/exfat/super.c:903: exfat_inode_cachep = kmem_cache_create("exfat_inode_cache",
fs/exfat/super.c-904- sizeof(struct exfat_inode_info),
--
fs/ext2/super.c=240=static int __init init_inodecache(void)
fs/ext2/super.c-241-{
fs/ext2/super.c:242: ext2_inode_cachep = kmem_cache_create_usercopy("ext2_inode_cache",
fs/ext2/super.c-243- sizeof(struct ext2_inode_info), 0,
--
fs/ext4/super.c=1497=static int __init init_inodecache(void)
--
fs/ext4/super.c-1506-
fs/ext4/super.c:1507: ext4_inode_cachep = kmem_cache_create("ext4_inode_cache",
fs/ext4/super.c-1508- sizeof(struct ext4_inode_info),
--
fs/f2fs/super.c=5569=static int __init init_inodecache(void)
fs/f2fs/super.c-5570-{
fs/f2fs/super.c:5571: f2fs_inode_cachep = kmem_cache_create("f2fs_inode_cache",
fs/f2fs/super.c-5572- sizeof(struct f2fs_inode_info), 0,
--
fs/fat/cache.c=41=int __init fat_cache_init(void)
fs/fat/cache.c-42-{
fs/fat/cache.c:43: fat_cache_cachep = kmem_cache_create("fat_cache",
fs/fat/cache.c-44- sizeof(struct fat_cache),
--
fs/fat/inode.c=789=static int __init fat_init_inodecache(void)
fs/fat/inode.c-790-{
fs/fat/inode.c:791: fat_inode_cachep = kmem_cache_create("fat_inode_cache",
fs/fat/inode.c-792- sizeof(struct msdos_inode_info),
--
fs/fcntl.c=1165=static int __init fcntl_init(void)
--
fs/fcntl.c-1176-
fs/fcntl.c:1177: fasync_cache = kmem_cache_create("fasync_cache",
fs/fcntl.c-1178- sizeof(struct fasync_struct), 0,
--
fs/hfs/super.c=461=static int __init init_hfs_fs(void)
--
fs/hfs/super.c-464-
fs/hfs/super.c:465: hfs_inode_cachep = kmem_cache_create("hfs_inode_cache",
fs/hfs/super.c-466- sizeof(struct hfs_inode_info), 0,
--
fs/hfsplus/attributes.c=15=int __init hfsplus_create_attr_tree_cache(void)
--
fs/hfsplus/attributes.c-20- hfsplus_attr_tree_cachep =
fs/hfsplus/attributes.c:21: kmem_cache_create("hfsplus_attr_cache",
fs/hfsplus/attributes.c-22- sizeof(hfsplus_attr_entry), 0,
--
fs/hpfs/super.c=255=static int init_inodecache(void)
fs/hpfs/super.c-256-{
fs/hpfs/super.c:257: hpfs_inode_cachep = kmem_cache_create("hpfs_inode_cache",
fs/hpfs/super.c-258- sizeof(struct hpfs_inode_info),
--
fs/hugetlbfs/inode.c=1593=static int __init init_hugetlbfs_fs(void)
--
fs/hugetlbfs/inode.c-1605- error = -ENOMEM;
fs/hugetlbfs/inode.c:1606: hugetlbfs_inode_cachep = kmem_cache_create("hugetlbfs_inode_cache",
fs/hugetlbfs/inode.c-1607- sizeof(struct hugetlbfs_inode_info),
--
fs/inode.c=2592=void __init inode_init(void)
--
fs/inode.c-2594- /* inode slab cache */
fs/inode.c:2595: inode_cachep = kmem_cache_create("inode_cache",
fs/inode.c-2596- sizeof(struct inode),
--
fs/isofs/inode.c=92=static int __init init_inodecache(void)
fs/isofs/inode.c-93-{
fs/isofs/inode.c:94: isofs_inode_cachep = kmem_cache_create("isofs_inode_cache",
fs/isofs/inode.c-95- sizeof(struct iso_inode_info),
--
fs/kernfs/mount.c=460=void __init kernfs_init(void)
fs/kernfs/mount.c-461-{
fs/kernfs/mount.c:462: kernfs_node_cache = kmem_cache_create("kernfs_node_cache",
fs/kernfs/mount.c-463- sizeof(struct kernfs_node),
--
fs/kernfs/mount.c-466- /* Creates slab cache for kernfs inode attributes */
fs/kernfs/mount.c:467: kernfs_iattrs_cache = kmem_cache_create("kernfs_iattrs_cache",
fs/kernfs/mount.c-468- sizeof(struct kernfs_iattrs),
--
fs/locks.c=3074=static int __init filelock_init(void)
--
fs/locks.c-3080-
fs/locks.c:3081: filelock_cache = kmem_cache_create("file_lock_cache",
fs/locks.c-3082- sizeof(struct file_lock), 0, SLAB_PANIC, NULL);
fs/locks.c-3083-
fs/locks.c:3084: filelease_cache = kmem_cache_create("file_lease_cache",
fs/locks.c-3085- sizeof(struct file_lease), 0, SLAB_PANIC, NULL);
--
fs/minix/inode.c=105=static int __init init_inodecache(void)
fs/minix/inode.c-106-{
fs/minix/inode.c:107: minix_inode_cachep = kmem_cache_create("minix_inode_cache",
fs/minix/inode.c-108- sizeof(struct minix_inode_info),
--
fs/namei.c=132=void __init filename_init(void)
fs/namei.c-133-{
fs/namei.c:134: __names_cache = kmem_cache_create_usercopy("names_cache", sizeof(struct filename), 0,
fs/namei.c-135- SLAB_HWCACHE_ALIGN|SLAB_PANIC, offsetof(struct filename, iname),
--
fs/namespace.c=6233=void __init mnt_init(void)
--
fs/namespace.c-6236-
fs/namespace.c:6237: mnt_cache = kmem_cache_create("mnt_cache", sizeof(struct mount),
fs/namespace.c-6238- 0, SLAB_HWCACHE_ALIGN|SLAB_PANIC|SLAB_ACCOUNT, NULL);
--
fs/nfs/direct.c=1085=int __init nfs_init_directcache(void)
fs/nfs/direct.c-1086-{
fs/nfs/direct.c:1087: nfs_direct_cachep = kmem_cache_create("nfs_direct_cache",
fs/nfs/direct.c-1088- sizeof(struct nfs_direct_req),
--
fs/nfs/inode.c=2563=static int __init nfs_init_inodecache(void)
fs/nfs/inode.c-2564-{
fs/nfs/inode.c:2565: nfs_inode_cachep = kmem_cache_create("nfs_inode_cache",
fs/nfs/inode.c-2566- sizeof(struct nfs_inode),
--
fs/nfs/nfs42xattr.c=1014=int __init nfs4_xattr_cache_init(void)
--
fs/nfs/nfs42xattr.c-1017-
fs/nfs/nfs42xattr.c:1018: nfs4_xattr_cache_cachep = kmem_cache_create("nfs4_xattr_cache_cache",
fs/nfs/nfs42xattr.c-1019- sizeof(struct nfs4_xattr_cache), 0,
--
fs/nilfs2/super.c=1346=static int __init nilfs_init_cachep(void)
fs/nilfs2/super.c-1347-{
fs/nilfs2/super.c:1348: nilfs_inode_cachep = kmem_cache_create("nilfs2_inode_cache",
fs/nilfs2/super.c-1349- sizeof(struct nilfs_inode_info), 0,
--
fs/nilfs2/super.c-1354-
fs/nilfs2/super.c:1355: nilfs_transaction_cachep = kmem_cache_create("nilfs2_transaction_cache",
fs/nilfs2/super.c-1356- sizeof(struct nilfs_transaction_info), 0,
--
fs/nilfs2/super.c-1360-
fs/nilfs2/super.c:1361: nilfs_segbuf_cachep = kmem_cache_create("nilfs2_segbuf_cache",
fs/nilfs2/super.c-1362- sizeof(struct nilfs_segment_buffer), 0,
--
fs/nilfs2/super.c-1366-
fs/nilfs2/super.c:1367: nilfs_btree_path_cache = kmem_cache_create("nilfs2_btree_path_cache",
fs/nilfs2/super.c-1368- sizeof(struct nilfs_btree_path) * NILFS_BTREE_LEVEL_MAX,
--
fs/ntfs/super.c=2650=static int __init init_ntfs_fs(void)
--
fs/ntfs/super.c-2659-
fs/ntfs/super.c:2660: ntfs_index_ctx_cache = kmem_cache_create(ntfs_index_ctx_cache_name,
fs/ntfs/super.c-2661- sizeof(struct ntfs_index_context), 0 /* offset */,
--
fs/ntfs/super.c-2666- }
fs/ntfs/super.c:2667: ntfs_attr_ctx_cache = kmem_cache_create(ntfs_attr_ctx_cache_name,
fs/ntfs/super.c-2668- sizeof(struct ntfs_attr_search_ctx), 0 /* offset */,
--
fs/ntfs/super.c-2675-
fs/ntfs/super.c:2676: ntfs_name_cache = kmem_cache_create(ntfs_name_cache_name,
fs/ntfs/super.c-2677- (NTFS_MAX_NAME_LEN+2) * sizeof(__le16), 0,
--
fs/ntfs/super.c-2683-
fs/ntfs/super.c:2684: ntfs_inode_cache = kmem_cache_create(ntfs_inode_cache_name,
fs/ntfs/super.c-2685- sizeof(struct ntfs_inode), 0, SLAB_RECLAIM_ACCOUNT, NULL);
--
fs/ntfs/super.c-2690-
fs/ntfs/super.c:2691: ntfs_big_inode_cache = kmem_cache_create(ntfs_big_inode_cache_name,
fs/ntfs/super.c-2692- sizeof(struct big_ntfs_inode), 0, SLAB_HWCACHE_ALIGN |
--
fs/ntfs3/bitmap.c=41=int __init ntfs3_init_bitmap(void)
fs/ntfs3/bitmap.c-42-{
fs/ntfs3/bitmap.c:43: ntfs_enode_cachep = kmem_cache_create("ntfs3_enode_cache",
fs/ntfs3/bitmap.c-44- sizeof(struct e_node), 0,
--
fs/ocfs2/dlmfs/dlmfs.c=580=static int __init init_dlmfs_fs(void)
--
fs/ocfs2/dlmfs/dlmfs.c-584-
fs/ocfs2/dlmfs/dlmfs.c:585: dlmfs_inode_cache = kmem_cache_create("dlmfs_inode_cache",
fs/ocfs2/dlmfs/dlmfs.c-586- sizeof(struct dlmfs_inode_private),
--
fs/ocfs2/super.c=1648=static int ocfs2_initialize_mem_caches(void)
fs/ocfs2/super.c-1649-{
fs/ocfs2/super.c:1650: ocfs2_inode_cachep = kmem_cache_create("ocfs2_inode_cache",
fs/ocfs2/super.c-1651- sizeof(struct ocfs2_inode_info),
--
fs/ocfs2/super.c-1655- ocfs2_inode_init_once);
fs/ocfs2/super.c:1656: ocfs2_dquot_cachep = kmem_cache_create("ocfs2_dquot_cache",
fs/ocfs2/super.c-1657- sizeof(struct ocfs2_dquot),
--
fs/ocfs2/super.c-1660- NULL);
fs/ocfs2/super.c:1661: ocfs2_qf_chunk_cachep = kmem_cache_create("ocfs2_qf_chunk_cache",
fs/ocfs2/super.c-1662- sizeof(struct ocfs2_quota_chunk),
--
fs/openpromfs/inode.c=441=static int __init init_openprom_fs(void)
--
fs/openpromfs/inode.c-444-
fs/openpromfs/inode.c:445: op_inode_cachep = kmem_cache_create("op_inode_cache",
fs/openpromfs/inode.c-446- sizeof(struct op_inode_info),
--
]
]
|
| 70/2 |
2026/05/20 07:11 |
llm |
expert |
0m
Model:
Tokens:
input: 74370
output: 23
thoughts: 137
Thoughts: **Analyzing kmem_cache_create Usage**
Okay, so I'm digging into how `kmem_cache_create` is being used, trying to understand potential security implications. The initial thought is that a good chunk of these calls are happening within `__init` functions. This suggests that the majority of `kmem_cache_create` calls are tied to module initialization. If that's the primary location, specifically if `kmem_cache_create` is *only* called during module initialization or device attachment - which often demands `CAP_SYS_ADMIN` or `CAP_SYS_RESOURCE` - then we are likely looking at a privilege escalation vector that's not easily exploitable by an unprivileged user, right?
But that's too simplistic, I need to check my assumptions. Hold on, what about `kmem_cache_create` within the `fs/` directory? Filesystem-related code is a potential area to scrutinize. Are there any filesystems out there that dynamically create kmem caches on a per-mount basis? That would be a significantly different threat model, and definitely something an unprivileged user might be able to trigger. Okay, let's focus on the `fs/` directory and see if I can find any calls to `kmem_cache_create` *not* wrapped in an `__init` context. Time to get coding...
|
| 71/2 |
2026/05/20 07:11 |
tool |
grepper |
0m
Args: map[Expression:kmem_cache_create.*_cache]
Results: map[Output:
Full output is too long, showing 500 out of 821 lines.
Use more precise expression if possible.
[Documentation/translations/zh_CN/core-api/memory-allocation.rst=76=GFP标志和回收行为
--
Documentation/translations/zh_CN/core-api/memory-allocation.rst-131-如果你需要分配许多相同的对象,你可以使用slab缓存分配器。在使用缓存之前,应该用
Documentation/translations/zh_CN/core-api/memory-allocation.rst:132:kmem_cache_create()或kmem_cache_create_usercopy()来设置缓存。如果缓存的一部分可能被复
Documentation/translations/zh_CN/core-api/memory-allocation.rst-133-制到用户空间,应该使用第二个函数。在缓存被创建后,kmem_cache_alloc()和它的封装可以从该缓
--
arch/arm64/mm/pgd.c=49=void __init pgtable_cache_init(void)
--
arch/arm64/mm/pgd.c-64- */
arch/arm64/mm/pgd.c:65: pgd_cache = kmem_cache_create("pgd_cache", PGD_SIZE, PGD_SIZE,
arch/arm64/mm/pgd.c-66- SLAB_PANIC, NULL);
--
arch/powerpc/kernel/rtas_flash.c=675=static int __init rtas_flash_init(void)
--
arch/powerpc/kernel/rtas_flash.c-687-
arch/powerpc/kernel/rtas_flash.c:688: flash_block_cache = kmem_cache_create_usercopy("rtas_flash_cache",
arch/powerpc/kernel/rtas_flash.c-689- RTAS_BLK_SIZE, RTAS_BLK_SIZE,
--
arch/powerpc/kvm/book3s_mmu_hpte.c=368=int kvmppc_mmu_hpte_sysinit(void)
--
arch/powerpc/kvm/book3s_mmu_hpte.c-370- /* init hpte slab cache */
arch/powerpc/kvm/book3s_mmu_hpte.c:371: hpte_cache = kmem_cache_create("kvm-spt", sizeof(struct hpte_cache),
arch/powerpc/kvm/book3s_mmu_hpte.c-372- sizeof(struct hpte_cache), 0, NULL);
--
arch/powerpc/platforms/cell/spufs/inode.c=762=static int __init spufs_init(void)
--
arch/powerpc/platforms/cell/spufs/inode.c-770- ret = -ENOMEM;
arch/powerpc/platforms/cell/spufs/inode.c:771: spufs_inode_cache = kmem_cache_create("spufs_inode_cache",
arch/powerpc/platforms/cell/spufs/inode.c-772- sizeof(struct spufs_inode_info), 0,
--
arch/s390/pci/pci.c=1065=static int zpci_mem_init(void)
--
arch/s390/pci/pci.c-1071-
arch/s390/pci/pci.c:1072: zdev_fmb_cache = kmem_cache_create("PCI_FMB_cache", sizeof(struct zpci_fmb),
arch/s390/pci/pci.c-1073- __alignof__(struct zpci_fmb), 0, NULL);
--
arch/sh/kernel/cpu/sh4/sq.c=372=static int __init sq_api_init(void)
--
arch/sh/kernel/cpu/sh4/sq.c-378-
arch/sh/kernel/cpu/sh4/sq.c:379: sq_cache = kmem_cache_create("store_queue_cache",
arch/sh/kernel/cpu/sh4/sq.c-380- sizeof(struct sq_mapping), 0, 0, NULL);
--
arch/sh/mm/pgtable.c=22=void pgtable_cache_init(void)
arch/sh/mm/pgtable.c-23-{
arch/sh/mm/pgtable.c:24: pgd_cachep = kmem_cache_create("pgd_cache",
arch/sh/mm/pgtable.c-25- PTRS_PER_PGD * (1<<PTE_MAGNITUDE),
--
arch/sh/mm/pgtable.c-27-#if PAGETABLE_LEVELS > 2
arch/sh/mm/pgtable.c:28: pmd_cachep = kmem_cache_create("pmd_cache",
arch/sh/mm/pgtable.c-29- PTRS_PER_PMD * (1<<PTE_MAGNITUDE),
--
arch/sparc/mm/tsb.c=341=void __init pgtable_cache_init(void)
--
arch/sparc/mm/tsb.c-344-
arch/sparc/mm/tsb.c:345: pgtable_cache = kmem_cache_create("pgtable_cache",
arch/sparc/mm/tsb.c-346- PAGE_SIZE, PAGE_SIZE,
--
block/bdev.c=447=void __init bdev_cache_init(void)
--
block/bdev.c-450-
block/bdev.c:451: bdev_cachep = kmem_cache_create("bdev_cache", sizeof(struct bdev_inode),
block/bdev.c-452- 0, (SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT|
--
block/elevator.c=498=int elv_register(struct elevator_type *e)
--
block/elevator.c-514- "%s_io_cq", e->elevator_name);
block/elevator.c:515: e->icq_cache = kmem_cache_create(e->icq_cache_name, e->icq_size,
block/elevator.c-516- e->icq_align, 0, NULL);
--
drivers/block/xen-blkback/xenbus.c=356=int __init xen_blkif_interface_init(void)
drivers/block/xen-blkback/xenbus.c-357-{
drivers/block/xen-blkback/xenbus.c:358: xen_blkif_cachep = kmem_cache_create("blkif_cache",
drivers/block/xen-blkback/xenbus.c-359- sizeof(struct xen_blkif),
--
drivers/crypto/ccp/ccp-dmaengine.c=665=int ccp_dmaengine_register(struct ccp_device *ccp)
--
drivers/crypto/ccp/ccp-dmaengine.c-689-
drivers/crypto/ccp/ccp-dmaengine.c:690: ccp->dma_cmd_cache = kmem_cache_create(dma_cmd_cache_name,
drivers/crypto/ccp/ccp-dmaengine.c-691- sizeof(struct ccp_dma_cmd),
--
drivers/crypto/ccp/ccp-dmaengine.c-704-
drivers/crypto/ccp/ccp-dmaengine.c:705: ccp->dma_desc_cache = kmem_cache_create(dma_desc_cache_name,
drivers/crypto/ccp/ccp-dmaengine.c-706- sizeof(struct ccp_dma_desc),
--
drivers/dax/super.c=644=static int dax_fs_init(void)
--
drivers/dax/super.c-647-
drivers/dax/super.c:648: dax_cache = kmem_cache_create("dax_cache", sizeof(struct dax_device), 0,
drivers/dax/super.c-649- SLAB_HWCACHE_ALIGN | SLAB_RECLAIM_ACCOUNT | SLAB_ACCOUNT,
--
drivers/dma/amd/ptdma/ptdma-dmaengine.c=562=int pt_dmaengine_register(struct pt_device *pt)
--
drivers/dma/amd/ptdma/ptdma-dmaengine.c-589-
drivers/dma/amd/ptdma/ptdma-dmaengine.c:590: pt->dma_desc_cache = kmem_cache_create(desc_cache_name,
drivers/dma/amd/ptdma/ptdma-dmaengine.c-591- sizeof(struct pt_dma_desc), 0,
--
drivers/dma/idxd/init.c=420=static int idxd_init_evl(struct idxd_device *idxd)
--
drivers/dma/idxd/init.c-443- */
drivers/dma/idxd/init.c:444: idxd->evl_cache = kmem_cache_create_usercopy(idxd_name, evl_cache_size,
drivers/dma/idxd/init.c-445- 0, 0, 0, evl_cache_size,
--
drivers/greybus/operation.c=1226=int __init gb_operation_init(void)
drivers/greybus/operation.c-1227-{
drivers/greybus/operation.c:1228: gb_message_cache = kmem_cache_create("gb_message_cache",
drivers/greybus/operation.c-1229- sizeof(struct gb_message), 0, 0,
--
drivers/greybus/operation.c-1233-
drivers/greybus/operation.c:1234: gb_operation_cache = kmem_cache_create("gb_operation_cache",
drivers/greybus/operation.c-1235- sizeof(struct gb_operation), 0,
--
drivers/iommu/omap-iommu.c=1731=static int __init omap_iommu_init(void)
--
drivers/iommu/omap-iommu.c-1744-
drivers/iommu/omap-iommu.c:1745: p = kmem_cache_create("iopte_cache", IOPTE_TABLE_SIZE, align, flags,
drivers/iommu/omap-iommu.c-1746- NULL);
--
drivers/md/dm-cache-target.c=3570=static int __init dm_cache_init(void)
--
drivers/md/dm-cache-target.c-3579-
drivers/md/dm-cache-target.c:3580: btracker_work_cache = kmem_cache_create("dm_cache_bt_work",
drivers/md/dm-cache-target.c-3581- sizeof(struct bt_work), __alignof__(struct bt_work), 0, NULL);
--
drivers/nvme/target/fcloop.c=1700=static int __init fcloop_init(void)
--
drivers/nvme/target/fcloop.c-1703-
drivers/nvme/target/fcloop.c:1704: lsreq_cache = kmem_cache_create("lsreq_cache",
drivers/nvme/target/fcloop.c-1705- sizeof(struct fcloop_lsreq), 0,
--
drivers/s390/block/dasd_devmap.c=224=static int __init dasd_parse_keyword(char *keyword)
--
drivers/s390/block/dasd_devmap.c-256- dasd_page_cache =
drivers/s390/block/dasd_devmap.c:257: kmem_cache_create("dasd_page_cache", PAGE_SIZE,
drivers/s390/block/dasd_devmap.c-258- PAGE_SIZE, SLAB_CACHE_DMA,
--
drivers/s390/cio/cmf.c=1248=static int __init init_cmbe(void)
drivers/s390/cio/cmf.c-1249-{
drivers/s390/cio/cmf.c:1250: cmbe_cache = kmem_cache_create("cmbe_cache", sizeof(struct cmbe),
drivers/s390/cio/cmf.c-1251- __alignof__(struct cmbe), 0, NULL);
--
drivers/scsi/qedf/qedf_main.c=4124=static int __init qedf_init(void)
--
drivers/scsi/qedf/qedf_main.c-4147- /* Create kmem_cache for qedf_io_work structs */
drivers/scsi/qedf/qedf_main.c:4148: qedf_io_work_cache = kmem_cache_create("qedf_io_work_cache",
drivers/scsi/qedf/qedf_main.c-4149- sizeof(struct qedf_io_work), 0, SLAB_HWCACHE_ALIGN, NULL);
--
drivers/scsi/qla2xxx/qla_target.c=8346=int __init qlt_init(void)
--
drivers/scsi/qla2xxx/qla_target.c-8361-
drivers/scsi/qla2xxx/qla_target.c:8362: qla_tgt_mgmt_cmd_cachep = kmem_cache_create("qla_tgt_mgmt_cmd_cachep",
drivers/scsi/qla2xxx/qla_target.c-8363- sizeof(struct qla_tgt_mgmt_cmd), __alignof__(struct
--
drivers/scsi/qla2xxx/qla_target.c-8366- ql_log(ql_log_fatal, NULL, 0xd04b,
drivers/scsi/qla2xxx/qla_target.c:8367: "kmem_cache_create for qla_tgt_mgmt_cmd_cachep failed\n");
drivers/scsi/qla2xxx/qla_target.c-8368- return -ENOMEM;
--
drivers/scsi/qla2xxx/qla_target.c-8370-
drivers/scsi/qla2xxx/qla_target.c:8371: qla_tgt_plogi_cachep = kmem_cache_create("qla_tgt_plogi_cachep",
drivers/scsi/qla2xxx/qla_target.c-8372- sizeof(struct qlt_plogi_ack_t), __alignof__(struct qlt_plogi_ack_t),
--
drivers/scsi/qla2xxx/qla_target.c-8376- ql_log(ql_log_fatal, NULL, 0xe06d,
drivers/scsi/qla2xxx/qla_target.c:8377: "kmem_cache_create for qla_tgt_plogi_cachep failed\n");
drivers/scsi/qla2xxx/qla_target.c-8378- ret = -ENOMEM;
--
drivers/scsi/scsi_lib.c=62=int scsi_init_sense_cache(struct Scsi_Host *shost)
--
drivers/scsi/scsi_lib.c-68- scsi_sense_cache =
drivers/scsi/scsi_lib.c:69: kmem_cache_create_usercopy("scsi_sense_cache",
drivers/scsi/scsi_lib.c-70- SCSI_SENSE_BUFFERSIZE, 0, SLAB_HWCACHE_ALIGN,
--
drivers/scsi/virtio_scsi.c=1063=static int __init virtio_scsi_init(void)
--
drivers/scsi/virtio_scsi.c-1068- if (!virtscsi_cmd_cache) {
drivers/scsi/virtio_scsi.c:1069: pr_err("kmem_cache_create() for virtscsi_cmd_cache failed\n");
drivers/scsi/virtio_scsi.c-1070- goto error;
--
drivers/staging/media/atomisp/pci/hmm/hmm_bo.c=318=int hmm_bo_device_init(struct hmm_bo_device *bdev,
--
drivers/staging/media/atomisp/pci/hmm/hmm_bo.c-346-
drivers/staging/media/atomisp/pci/hmm/hmm_bo.c:347: bdev->bo_cache = kmem_cache_create("bo_cache",
drivers/staging/media/atomisp/pci/hmm/hmm_bo.c-348- sizeof(struct hmm_buffer_object), 0, 0, NULL);
--
drivers/target/iscsi/iscsi_target.c=672=static int __init iscsi_target_init_module(void)
--
drivers/target/iscsi/iscsi_target.c-699-
drivers/target/iscsi/iscsi_target.c:700: lio_qr_cache = kmem_cache_create("lio_qr_cache",
drivers/target/iscsi/iscsi_target.c-701- sizeof(struct iscsi_queue_req),
--
drivers/target/iscsi/iscsi_target.c-708-
drivers/target/iscsi/iscsi_target.c:709: lio_dr_cache = kmem_cache_create("lio_dr_cache",
drivers/target/iscsi/iscsi_target.c-710- sizeof(struct iscsi_datain_req),
--
drivers/target/iscsi/iscsi_target.c-717-
drivers/target/iscsi/iscsi_target.c:718: lio_ooo_cache = kmem_cache_create("lio_ooo_cache",
drivers/target/iscsi/iscsi_target.c-719- sizeof(struct iscsi_ooo_cmdsn),
--
drivers/target/iscsi/iscsi_target.c-726-
drivers/target/iscsi/iscsi_target.c:727: lio_r2t_cache = kmem_cache_create("lio_r2t_cache",
drivers/target/iscsi/iscsi_target.c-728- sizeof(struct iscsi_r2t), __alignof__(struct iscsi_r2t),
--
drivers/target/loopback/tcm_loop.c=1155=static int __init tcm_loop_fabric_init(void)
--
drivers/target/loopback/tcm_loop.c-1158-
drivers/target/loopback/tcm_loop.c:1159: tcm_loop_cmd_cache = kmem_cache_create("tcm_loop_cmd_cache",
drivers/target/loopback/tcm_loop.c-1160- sizeof(struct tcm_loop_cmd),
--
drivers/target/loopback/tcm_loop.c-1163- if (!tcm_loop_cmd_cache) {
drivers/target/loopback/tcm_loop.c:1164: pr_debug("kmem_cache_create() for tcm_loop_cmd_cache failed\n");
drivers/target/loopback/tcm_loop.c-1165- goto out;
--
drivers/target/target_core_transport.c=60=int init_se_kmem_caches(void)
drivers/target/target_core_transport.c-61-{
drivers/target/target_core_transport.c:62: se_sess_cache = kmem_cache_create("se_sess_cache",
drivers/target/target_core_transport.c-63- sizeof(struct se_session), __alignof__(struct se_session),
--
drivers/target/target_core_transport.c-69- }
drivers/target/target_core_transport.c:70: se_ua_cache = kmem_cache_create("se_ua_cache",
drivers/target/target_core_transport.c-71- sizeof(struct se_ua), __alignof__(struct se_ua),
--
drivers/target/target_core_transport.c-76- }
drivers/target/target_core_transport.c:77: t10_pr_reg_cache = kmem_cache_create("t10_pr_reg_cache",
drivers/target/target_core_transport.c-78- sizeof(struct t10_pr_registration),
--
drivers/target/target_core_transport.c-84- }
drivers/target/target_core_transport.c:85: t10_alua_lu_gp_cache = kmem_cache_create("t10_alua_lu_gp_cache",
drivers/target/target_core_transport.c-86- sizeof(struct t10_alua_lu_gp), __alignof__(struct t10_alua_lu_gp),
--
drivers/target/target_core_transport.c-88- if (!t10_alua_lu_gp_cache) {
drivers/target/target_core_transport.c:89: pr_err("kmem_cache_create() for t10_alua_lu_gp_cache"
drivers/target/target_core_transport.c-90- " failed\n");
--
drivers/target/target_core_transport.c-92- }
drivers/target/target_core_transport.c:93: t10_alua_lu_gp_mem_cache = kmem_cache_create("t10_alua_lu_gp_mem_cache",
drivers/target/target_core_transport.c-94- sizeof(struct t10_alua_lu_gp_member),
--
drivers/target/target_core_transport.c-100- }
drivers/target/target_core_transport.c:101: t10_alua_tg_pt_gp_cache = kmem_cache_create("t10_alua_tg_pt_gp_cache",
drivers/target/target_core_transport.c-102- sizeof(struct t10_alua_tg_pt_gp),
--
drivers/target/target_core_user.c=3321=static int __init tcmu_module_init(void)
--
drivers/target/target_core_user.c-3328-
drivers/target/target_core_user.c:3329: tcmu_cmd_cache = kmem_cache_create("tcmu_cmd_cache",
drivers/target/target_core_user.c-3330- sizeof(struct tcmu_cmd),
--
fs/9p/v9fs.c=675=static int v9fs_init_inode_cache(void)
fs/9p/v9fs.c-676-{
fs/9p/v9fs.c:677: v9fs_inode_cache = kmem_cache_create("v9fs_inode_cache",
fs/9p/v9fs.c-678- sizeof(struct v9fs_inode),
--
fs/adfs/super.c=222=static int __init init_inodecache(void)
fs/adfs/super.c-223-{
fs/adfs/super.c:224: adfs_inode_cachep = kmem_cache_create("adfs_inode_cache",
fs/adfs/super.c-225- sizeof(struct adfs_inode_info),
--
fs/affs/super.c=130=static int __init init_inodecache(void)
fs/affs/super.c-131-{
fs/affs/super.c:132: affs_inode_cachep = kmem_cache_create("affs_inode_cache",
fs/affs/super.c-133- sizeof(struct affs_inode_info),
--
fs/afs/super.c=96=int __init afs_fs_init(void)
--
fs/afs/super.c-105- ret = -ENOMEM;
fs/afs/super.c:106: afs_inode_cachep = kmem_cache_create("afs_inode_cache",
fs/afs/super.c-107- sizeof(struct afs_vnode),
--
fs/aio.c=338=static int __init aio_setup(void)
--
fs/aio.c-345-
fs/aio.c:346: aio_inode_cachep = kmem_cache_create("aio_inode_cache",
fs/aio.c-347- sizeof(struct aio_inode_info), 0,
--
fs/befs/linuxvfs.c=435=befs_init_inodecache(void)
fs/befs/linuxvfs.c-436-{
fs/befs/linuxvfs.c:437: befs_inode_cachep = kmem_cache_create_usercopy("befs_inode_cache",
fs/befs/linuxvfs.c-438- sizeof(struct befs_inode_info), 0,
--
fs/bfs/inode.c=279=static int __init init_inodecache(void)
fs/bfs/inode.c-280-{
fs/bfs/inode.c:281: bfs_inode_cachep = kmem_cache_create("bfs_inode_cache",
fs/bfs/inode.c-282- sizeof(struct bfs_inode_info),
--
fs/coda/inode.c=71=int __init coda_init_inodecache(void)
fs/coda/inode.c-72-{
fs/coda/inode.c:73: coda_inode_cachep = kmem_cache_create("coda_inode_cache",
fs/coda/inode.c-74- sizeof(struct coda_inode_info), 0,
--
fs/configfs/mount.c=136=static int __init configfs_init(void)
--
fs/configfs/mount.c-139-
fs/configfs/mount.c:140: configfs_dir_cachep = kmem_cache_create("configfs_dir_cache",
fs/configfs/mount.c-141- sizeof(struct configfs_dirent),
--
fs/debugfs/inode.c=900=static int __init debugfs_init(void)
--
fs/debugfs/inode.c-910-
fs/debugfs/inode.c:911: debugfs_inode_cachep = kmem_cache_create("debugfs_inode_cache",
fs/debugfs/inode.c-912- sizeof(struct debugfs_inode_info), 0,
--
fs/efs/super.c=86=static int __init init_inodecache(void)
fs/efs/super.c-87-{
fs/efs/super.c:88: efs_inode_cachep = kmem_cache_create("efs_inode_cache",
fs/efs/super.c-89- sizeof(struct efs_inode_info), 0,
--
fs/exfat/cache.c=45=int exfat_cache_init(void)
fs/exfat/cache.c-46-{
fs/exfat/cache.c:47: exfat_cachep = kmem_cache_create("exfat_cache",
fs/exfat/cache.c-48- sizeof(struct exfat_cache),
--
fs/exfat/super.c=895=static int __init init_exfat_fs(void)
--
fs/exfat/super.c-902-
fs/exfat/super.c:903: exfat_inode_cachep = kmem_cache_create("exfat_inode_cache",
fs/exfat/super.c-904- sizeof(struct exfat_inode_info),
--
fs/ext2/super.c=240=static int __init init_inodecache(void)
fs/ext2/super.c-241-{
fs/ext2/super.c:242: ext2_inode_cachep = kmem_cache_create_usercopy("ext2_inode_cache",
fs/ext2/super.c-243- sizeof(struct ext2_inode_info), 0,
--
fs/ext4/super.c=1497=static int __init init_inodecache(void)
--
fs/ext4/super.c-1506-
fs/ext4/super.c:1507: ext4_inode_cachep = kmem_cache_create("ext4_inode_cache",
fs/ext4/super.c-1508- sizeof(struct ext4_inode_info),
--
fs/f2fs/super.c=5569=static int __init init_inodecache(void)
fs/f2fs/super.c-5570-{
fs/f2fs/super.c:5571: f2fs_inode_cachep = kmem_cache_create("f2fs_inode_cache",
fs/f2fs/super.c-5572- sizeof(struct f2fs_inode_info), 0,
--
fs/fat/cache.c=41=int __init fat_cache_init(void)
fs/fat/cache.c-42-{
fs/fat/cache.c:43: fat_cache_cachep = kmem_cache_create("fat_cache",
fs/fat/cache.c-44- sizeof(struct fat_cache),
--
fs/fat/inode.c=789=static int __init fat_init_inodecache(void)
fs/fat/inode.c-790-{
fs/fat/inode.c:791: fat_inode_cachep = kmem_cache_create("fat_inode_cache",
fs/fat/inode.c-792- sizeof(struct msdos_inode_info),
--
fs/fcntl.c=1165=static int __init fcntl_init(void)
--
fs/fcntl.c-1176-
fs/fcntl.c:1177: fasync_cache = kmem_cache_create("fasync_cache",
fs/fcntl.c-1178- sizeof(struct fasync_struct), 0,
--
fs/hfs/super.c=461=static int __init init_hfs_fs(void)
--
fs/hfs/super.c-464-
fs/hfs/super.c:465: hfs_inode_cachep = kmem_cache_create("hfs_inode_cache",
fs/hfs/super.c-466- sizeof(struct hfs_inode_info), 0,
--
fs/hfsplus/attributes.c=15=int __init hfsplus_create_attr_tree_cache(void)
--
fs/hfsplus/attributes.c-20- hfsplus_attr_tree_cachep =
fs/hfsplus/attributes.c:21: kmem_cache_create("hfsplus_attr_cache",
fs/hfsplus/attributes.c-22- sizeof(hfsplus_attr_entry), 0,
--
fs/hpfs/super.c=255=static int init_inodecache(void)
fs/hpfs/super.c-256-{
fs/hpfs/super.c:257: hpfs_inode_cachep = kmem_cache_create("hpfs_inode_cache",
fs/hpfs/super.c-258- sizeof(struct hpfs_inode_info),
--
fs/hugetlbfs/inode.c=1593=static int __init init_hugetlbfs_fs(void)
--
fs/hugetlbfs/inode.c-1605- error = -ENOMEM;
fs/hugetlbfs/inode.c:1606: hugetlbfs_inode_cachep = kmem_cache_create("hugetlbfs_inode_cache",
fs/hugetlbfs/inode.c-1607- sizeof(struct hugetlbfs_inode_info),
--
fs/inode.c=2592=void __init inode_init(void)
--
fs/inode.c-2594- /* inode slab cache */
fs/inode.c:2595: inode_cachep = kmem_cache_create("inode_cache",
fs/inode.c-2596- sizeof(struct inode),
--
fs/isofs/inode.c=92=static int __init init_inodecache(void)
fs/isofs/inode.c-93-{
fs/isofs/inode.c:94: isofs_inode_cachep = kmem_cache_create("isofs_inode_cache",
fs/isofs/inode.c-95- sizeof(struct iso_inode_info),
--
fs/kernfs/mount.c=460=void __init kernfs_init(void)
fs/kernfs/mount.c-461-{
fs/kernfs/mount.c:462: kernfs_node_cache = kmem_cache_create("kernfs_node_cache",
fs/kernfs/mount.c-463- sizeof(struct kernfs_node),
--
fs/kernfs/mount.c-466- /* Creates slab cache for kernfs inode attributes */
fs/kernfs/mount.c:467: kernfs_iattrs_cache = kmem_cache_create("kernfs_iattrs_cache",
fs/kernfs/mount.c-468- sizeof(struct kernfs_iattrs),
--
fs/locks.c=3074=static int __init filelock_init(void)
--
fs/locks.c-3080-
fs/locks.c:3081: filelock_cache = kmem_cache_create("file_lock_cache",
fs/locks.c-3082- sizeof(struct file_lock), 0, SLAB_PANIC, NULL);
fs/locks.c-3083-
fs/locks.c:3084: filelease_cache = kmem_cache_create("file_lease_cache",
fs/locks.c-3085- sizeof(struct file_lease), 0, SLAB_PANIC, NULL);
--
fs/minix/inode.c=105=static int __init init_inodecache(void)
fs/minix/inode.c-106-{
fs/minix/inode.c:107: minix_inode_cachep = kmem_cache_create("minix_inode_cache",
fs/minix/inode.c-108- sizeof(struct minix_inode_info),
--
fs/namei.c=132=void __init filename_init(void)
fs/namei.c-133-{
fs/namei.c:134: __names_cache = kmem_cache_create_usercopy("names_cache", sizeof(struct filename), 0,
fs/namei.c-135- SLAB_HWCACHE_ALIGN|SLAB_PANIC, offsetof(struct filename, iname),
--
fs/namespace.c=6233=void __init mnt_init(void)
--
fs/namespace.c-6236-
fs/namespace.c:6237: mnt_cache = kmem_cache_create("mnt_cache", sizeof(struct mount),
fs/namespace.c-6238- 0, SLAB_HWCACHE_ALIGN|SLAB_PANIC|SLAB_ACCOUNT, NULL);
--
fs/nfs/direct.c=1085=int __init nfs_init_directcache(void)
fs/nfs/direct.c-1086-{
fs/nfs/direct.c:1087: nfs_direct_cachep = kmem_cache_create("nfs_direct_cache",
fs/nfs/direct.c-1088- sizeof(struct nfs_direct_req),
--
fs/nfs/inode.c=2563=static int __init nfs_init_inodecache(void)
fs/nfs/inode.c-2564-{
fs/nfs/inode.c:2565: nfs_inode_cachep = kmem_cache_create("nfs_inode_cache",
fs/nfs/inode.c-2566- sizeof(struct nfs_inode),
--
fs/nfs/nfs42xattr.c=1014=int __init nfs4_xattr_cache_init(void)
--
fs/nfs/nfs42xattr.c-1017-
fs/nfs/nfs42xattr.c:1018: nfs4_xattr_cache_cachep = kmem_cache_create("nfs4_xattr_cache_cache",
fs/nfs/nfs42xattr.c-1019- sizeof(struct nfs4_xattr_cache), 0,
--
fs/nilfs2/super.c=1346=static int __init nilfs_init_cachep(void)
fs/nilfs2/super.c-1347-{
fs/nilfs2/super.c:1348: nilfs_inode_cachep = kmem_cache_create("nilfs2_inode_cache",
fs/nilfs2/super.c-1349- sizeof(struct nilfs_inode_info), 0,
--
fs/nilfs2/super.c-1354-
fs/nilfs2/super.c:1355: nilfs_transaction_cachep = kmem_cache_create("nilfs2_transaction_cache",
fs/nilfs2/super.c-1356- sizeof(struct nilfs_transaction_info), 0,
--
fs/nilfs2/super.c-1360-
fs/nilfs2/super.c:1361: nilfs_segbuf_cachep = kmem_cache_create("nilfs2_segbuf_cache",
fs/nilfs2/super.c-1362- sizeof(struct nilfs_segment_buffer), 0,
--
fs/nilfs2/super.c-1366-
fs/nilfs2/super.c:1367: nilfs_btree_path_cache = kmem_cache_create("nilfs2_btree_path_cache",
fs/nilfs2/super.c-1368- sizeof(struct nilfs_btree_path) * NILFS_BTREE_LEVEL_MAX,
--
fs/ntfs/super.c=2650=static int __init init_ntfs_fs(void)
--
fs/ntfs/super.c-2659-
fs/ntfs/super.c:2660: ntfs_index_ctx_cache = kmem_cache_create(ntfs_index_ctx_cache_name,
fs/ntfs/super.c-2661- sizeof(struct ntfs_index_context), 0 /* offset */,
--
fs/ntfs/super.c-2666- }
fs/ntfs/super.c:2667: ntfs_attr_ctx_cache = kmem_cache_create(ntfs_attr_ctx_cache_name,
fs/ntfs/super.c-2668- sizeof(struct ntfs_attr_search_ctx), 0 /* offset */,
--
fs/ntfs/super.c-2675-
fs/ntfs/super.c:2676: ntfs_name_cache = kmem_cache_create(ntfs_name_cache_name,
fs/ntfs/super.c-2677- (NTFS_MAX_NAME_LEN+2) * sizeof(__le16), 0,
--
fs/ntfs/super.c-2683-
fs/ntfs/super.c:2684: ntfs_inode_cache = kmem_cache_create(ntfs_inode_cache_name,
fs/ntfs/super.c-2685- sizeof(struct ntfs_inode), 0, SLAB_RECLAIM_ACCOUNT, NULL);
--
fs/ntfs/super.c-2690-
fs/ntfs/super.c:2691: ntfs_big_inode_cache = kmem_cache_create(ntfs_big_inode_cache_name,
fs/ntfs/super.c-2692- sizeof(struct big_ntfs_inode), 0, SLAB_HWCACHE_ALIGN |
--
fs/ntfs3/bitmap.c=41=int __init ntfs3_init_bitmap(void)
fs/ntfs3/bitmap.c-42-{
fs/ntfs3/bitmap.c:43: ntfs_enode_cachep = kmem_cache_create("ntfs3_enode_cache",
fs/ntfs3/bitmap.c-44- sizeof(struct e_node), 0,
--
fs/ocfs2/dlmfs/dlmfs.c=580=static int __init init_dlmfs_fs(void)
--
fs/ocfs2/dlmfs/dlmfs.c-584-
fs/ocfs2/dlmfs/dlmfs.c:585: dlmfs_inode_cache = kmem_cache_create("dlmfs_inode_cache",
fs/ocfs2/dlmfs/dlmfs.c-586- sizeof(struct dlmfs_inode_private),
--
fs/ocfs2/super.c=1648=static int ocfs2_initialize_mem_caches(void)
fs/ocfs2/super.c-1649-{
fs/ocfs2/super.c:1650: ocfs2_inode_cachep = kmem_cache_create("ocfs2_inode_cache",
fs/ocfs2/super.c-1651- sizeof(struct ocfs2_inode_info),
--
fs/ocfs2/super.c-1655- ocfs2_inode_init_once);
fs/ocfs2/super.c:1656: ocfs2_dquot_cachep = kmem_cache_create("ocfs2_dquot_cache",
fs/ocfs2/super.c-1657- sizeof(struct ocfs2_dquot),
--
fs/ocfs2/super.c-1660- NULL);
fs/ocfs2/super.c:1661: ocfs2_qf_chunk_cachep = kmem_cache_create("ocfs2_qf_chunk_cache",
fs/ocfs2/super.c-1662- sizeof(struct ocfs2_quota_chunk),
--
fs/openpromfs/inode.c=441=static int __init init_openprom_fs(void)
--
fs/openpromfs/inode.c-444-
fs/openpromfs/inode.c:445: op_inode_cachep = kmem_cache_create("op_inode_cache",
fs/openpromfs/inode.c-446- sizeof(struct op_inode_info),
--
]
]
|
| 72/2 |
2026/05/20 07:11 |
llm |
expert |
0m
Model:
Tokens:
input: 86010
output: 23
thoughts: 1432
Thoughts: **Analysis of a Potential Kernel Deadlock**
Okay, let's break this down. It appears we've got a lockdep warning related to `kmem_cache_create`, and it's got me thinking. The initial report focuses on the interaction between `slab_mutex`, `fs_reclaim`, and `cpu_hotplug_lock`. Seems almost all `kmem_cache_create` calls are either in `__init` functions or require privileges, like when attaching a UBI device. However, the core of the issue is this global dependency that's created; `slab_mutex` -> `fs_reclaim`. If any process holds `fs_reclaim` and then tries to acquire `slab_mutex` – or a lock dependent on `slab_mutex` – we're looking at deadlock territory.
The syzbot report points to a chain: `fs_reclaim` -> `cpu_hotplug_lock` -> `slab_mutex`, and `fs_reclaim` to `cpu_hotplug_lock` goes through NBD. Since NBD requires `CAP_SYS_ADMIN`, an unprivileged user shouldn't be able to trigger it. So, we're relatively safe.
Now, let's play devil's advocate: is there *any* other route from `fs_reclaim` to `cpu_hotplug_lock`? I checked memory reclaim itself, and nope, it doesn't directly grab `cpu_hotplug_lock`. We might be fine. Does memory reclaim call `kmem_cache_destroy` or wait for a lock held by `kmem_cache_destroy`? No, memory reclaim doesn't destroy caches. But, if a thread doing `kmem_cache_destroy` holds `cpu_hotplug_lock` and waits for `slab_mutex` and another thread is doing memory reclaim, holding `fs_reclaim` and waiting for a lock, it could trigger a deadlock.
The lockdep chain seems to require NBD, which, again, is gated by `CAP_SYS_ADMIN`.
What's the actual impact here? It's a lockdep *warning*, which is disabled in production kernels. If it *does* happen, it's a Denial of Service – the system hangs. Can it be triggered remotely? No, not really, as far as I can tell. Is it a malicious filesystem? Not unless we're talking about a *very* intricate and improbable scenario involving concurrent operations with memory reclaim, NBD, and `kmem_cache_create`/`kmem_cache_destroy`. NBD isn't tied to any filesystem mounting, so it appears unlikely.
So, here's the summary: this is a lockdep warning about a circular locking dependency. The new dependency is `slab_mutex` -> `fs_reclaim` via `kmem_cache_create`. The existing dependency chain is `fs_reclaim` -> ... -> `cpu_hotplug_lock` -> `slab_mutex`. Triggering the existing chain *requires* NBD or similar, which demands `CAP_SYS_ADMIN` in the initial user namespace. An unprivileged user is, therefore, unable to trigger this. It's not exploitable for privilege escalation or memory corruption, but it can cause a DoS if the exact conditions are met by a privileged user, but that's not accessible from user namespaces, and it is not remotely triggerable or through a malicious filesystem.
But wait a minute... is there another way to trigger `fs_reclaim` -> `slab_mutex`? What if we get `fs_reclaim` -> `cpu_hotplug_lock` without NBD? What if it's, say, `fs_reclaim` -> `sk_lock` -> `cpu_hotplug_lock`? Does `fs_reclaim` acquire `sk_lock`? If a socket's being reclaimed? No, sockets are not reclaimed by `fs_reclaim`. Oh, wait... what about network I/O during memory reclaim? Like swapping over network or NFS? *Yes!* That means a socket I/O which could trigger the acquisition of `sk_lock`. Then `sk_lock` to `cpu_hotplug_lock` happens via `inet_stream_connect`!.
If memory reclaim acquires `sk_lock` (e.g., to send data over a socket), it might be waiting for `sk_lock`. Another thread doing `inet_stream_connect` then holds `sk_lock` and waits for `cpu_hotplug_lock`. If a *third* thread does `kmem_cache_destroy`, holding `cpu_hotplug_lock` and waits for `slab_mutex`, and a *fourth* thread, doing `kmem
|
| 73/2 |
2026/05/20 07:11 |
tool |
grepper |
0m
Error:
Args: map[Expression:kmem_cache_create.*bpf]
Results:
|
| 74/2 |
2026/05/20 07:11 |
llm |
expert |
0m
Model:
Tokens:
input: 88504
output: 23
thoughts: 8
Thoughts: Okay, here's my interpretation of that thought process, tailored for an expert audience, and presented as if it were my own internal monologue:
**Considering Scope Within a Specific Codebase Area**
Hmm, I'm thinking about the current problem... and I'm wondering if I'm neglecting a crucial aspect by focusing on the broader architecture. Is there anything relevant within the `net/` directory specifically? I know `net/` is often where the network-related logic lives, but I need to make sure I consider it, even if superficially. There could be something hidden away in the intricacies of the socket handling, connection pooling, or perhaps even in a specific protocol implementation that directly pertains to this issue. It would be a huge time saver to address any issues now, instead of later. Before I go any further, I should scan the contents and see if I need to address any items in this specific section. I need to make sure I am not missing a critical piece of the puzzle.
|
| 75/2 |
2026/05/20 07:11 |
tool |
grepper |
0m
Args: map[Expression:kmem_cache_create.*_cache]
Results: map[Output:
Full output is too long, showing 500 out of 821 lines.
Use more precise expression if possible.
[Documentation/translations/zh_CN/core-api/memory-allocation.rst=76=GFP标志和回收行为
--
Documentation/translations/zh_CN/core-api/memory-allocation.rst-131-如果你需要分配许多相同的对象,你可以使用slab缓存分配器。在使用缓存之前,应该用
Documentation/translations/zh_CN/core-api/memory-allocation.rst:132:kmem_cache_create()或kmem_cache_create_usercopy()来设置缓存。如果缓存的一部分可能被复
Documentation/translations/zh_CN/core-api/memory-allocation.rst-133-制到用户空间,应该使用第二个函数。在缓存被创建后,kmem_cache_alloc()和它的封装可以从该缓
--
arch/arm64/mm/pgd.c=49=void __init pgtable_cache_init(void)
--
arch/arm64/mm/pgd.c-64- */
arch/arm64/mm/pgd.c:65: pgd_cache = kmem_cache_create("pgd_cache", PGD_SIZE, PGD_SIZE,
arch/arm64/mm/pgd.c-66- SLAB_PANIC, NULL);
--
arch/powerpc/kernel/rtas_flash.c=675=static int __init rtas_flash_init(void)
--
arch/powerpc/kernel/rtas_flash.c-687-
arch/powerpc/kernel/rtas_flash.c:688: flash_block_cache = kmem_cache_create_usercopy("rtas_flash_cache",
arch/powerpc/kernel/rtas_flash.c-689- RTAS_BLK_SIZE, RTAS_BLK_SIZE,
--
arch/powerpc/kvm/book3s_mmu_hpte.c=368=int kvmppc_mmu_hpte_sysinit(void)
--
arch/powerpc/kvm/book3s_mmu_hpte.c-370- /* init hpte slab cache */
arch/powerpc/kvm/book3s_mmu_hpte.c:371: hpte_cache = kmem_cache_create("kvm-spt", sizeof(struct hpte_cache),
arch/powerpc/kvm/book3s_mmu_hpte.c-372- sizeof(struct hpte_cache), 0, NULL);
--
arch/powerpc/platforms/cell/spufs/inode.c=762=static int __init spufs_init(void)
--
arch/powerpc/platforms/cell/spufs/inode.c-770- ret = -ENOMEM;
arch/powerpc/platforms/cell/spufs/inode.c:771: spufs_inode_cache = kmem_cache_create("spufs_inode_cache",
arch/powerpc/platforms/cell/spufs/inode.c-772- sizeof(struct spufs_inode_info), 0,
--
arch/s390/pci/pci.c=1065=static int zpci_mem_init(void)
--
arch/s390/pci/pci.c-1071-
arch/s390/pci/pci.c:1072: zdev_fmb_cache = kmem_cache_create("PCI_FMB_cache", sizeof(struct zpci_fmb),
arch/s390/pci/pci.c-1073- __alignof__(struct zpci_fmb), 0, NULL);
--
arch/sh/kernel/cpu/sh4/sq.c=372=static int __init sq_api_init(void)
--
arch/sh/kernel/cpu/sh4/sq.c-378-
arch/sh/kernel/cpu/sh4/sq.c:379: sq_cache = kmem_cache_create("store_queue_cache",
arch/sh/kernel/cpu/sh4/sq.c-380- sizeof(struct sq_mapping), 0, 0, NULL);
--
arch/sh/mm/pgtable.c=22=void pgtable_cache_init(void)
arch/sh/mm/pgtable.c-23-{
arch/sh/mm/pgtable.c:24: pgd_cachep = kmem_cache_create("pgd_cache",
arch/sh/mm/pgtable.c-25- PTRS_PER_PGD * (1<<PTE_MAGNITUDE),
--
arch/sh/mm/pgtable.c-27-#if PAGETABLE_LEVELS > 2
arch/sh/mm/pgtable.c:28: pmd_cachep = kmem_cache_create("pmd_cache",
arch/sh/mm/pgtable.c-29- PTRS_PER_PMD * (1<<PTE_MAGNITUDE),
--
arch/sparc/mm/tsb.c=341=void __init pgtable_cache_init(void)
--
arch/sparc/mm/tsb.c-344-
arch/sparc/mm/tsb.c:345: pgtable_cache = kmem_cache_create("pgtable_cache",
arch/sparc/mm/tsb.c-346- PAGE_SIZE, PAGE_SIZE,
--
block/bdev.c=447=void __init bdev_cache_init(void)
--
block/bdev.c-450-
block/bdev.c:451: bdev_cachep = kmem_cache_create("bdev_cache", sizeof(struct bdev_inode),
block/bdev.c-452- 0, (SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT|
--
block/elevator.c=498=int elv_register(struct elevator_type *e)
--
block/elevator.c-514- "%s_io_cq", e->elevator_name);
block/elevator.c:515: e->icq_cache = kmem_cache_create(e->icq_cache_name, e->icq_size,
block/elevator.c-516- e->icq_align, 0, NULL);
--
drivers/block/xen-blkback/xenbus.c=356=int __init xen_blkif_interface_init(void)
drivers/block/xen-blkback/xenbus.c-357-{
drivers/block/xen-blkback/xenbus.c:358: xen_blkif_cachep = kmem_cache_create("blkif_cache",
drivers/block/xen-blkback/xenbus.c-359- sizeof(struct xen_blkif),
--
drivers/crypto/ccp/ccp-dmaengine.c=665=int ccp_dmaengine_register(struct ccp_device *ccp)
--
drivers/crypto/ccp/ccp-dmaengine.c-689-
drivers/crypto/ccp/ccp-dmaengine.c:690: ccp->dma_cmd_cache = kmem_cache_create(dma_cmd_cache_name,
drivers/crypto/ccp/ccp-dmaengine.c-691- sizeof(struct ccp_dma_cmd),
--
drivers/crypto/ccp/ccp-dmaengine.c-704-
drivers/crypto/ccp/ccp-dmaengine.c:705: ccp->dma_desc_cache = kmem_cache_create(dma_desc_cache_name,
drivers/crypto/ccp/ccp-dmaengine.c-706- sizeof(struct ccp_dma_desc),
--
drivers/dax/super.c=644=static int dax_fs_init(void)
--
drivers/dax/super.c-647-
drivers/dax/super.c:648: dax_cache = kmem_cache_create("dax_cache", sizeof(struct dax_device), 0,
drivers/dax/super.c-649- SLAB_HWCACHE_ALIGN | SLAB_RECLAIM_ACCOUNT | SLAB_ACCOUNT,
--
drivers/dma/amd/ptdma/ptdma-dmaengine.c=562=int pt_dmaengine_register(struct pt_device *pt)
--
drivers/dma/amd/ptdma/ptdma-dmaengine.c-589-
drivers/dma/amd/ptdma/ptdma-dmaengine.c:590: pt->dma_desc_cache = kmem_cache_create(desc_cache_name,
drivers/dma/amd/ptdma/ptdma-dmaengine.c-591- sizeof(struct pt_dma_desc), 0,
--
drivers/dma/idxd/init.c=420=static int idxd_init_evl(struct idxd_device *idxd)
--
drivers/dma/idxd/init.c-443- */
drivers/dma/idxd/init.c:444: idxd->evl_cache = kmem_cache_create_usercopy(idxd_name, evl_cache_size,
drivers/dma/idxd/init.c-445- 0, 0, 0, evl_cache_size,
--
drivers/greybus/operation.c=1226=int __init gb_operation_init(void)
drivers/greybus/operation.c-1227-{
drivers/greybus/operation.c:1228: gb_message_cache = kmem_cache_create("gb_message_cache",
drivers/greybus/operation.c-1229- sizeof(struct gb_message), 0, 0,
--
drivers/greybus/operation.c-1233-
drivers/greybus/operation.c:1234: gb_operation_cache = kmem_cache_create("gb_operation_cache",
drivers/greybus/operation.c-1235- sizeof(struct gb_operation), 0,
--
drivers/iommu/omap-iommu.c=1731=static int __init omap_iommu_init(void)
--
drivers/iommu/omap-iommu.c-1744-
drivers/iommu/omap-iommu.c:1745: p = kmem_cache_create("iopte_cache", IOPTE_TABLE_SIZE, align, flags,
drivers/iommu/omap-iommu.c-1746- NULL);
--
drivers/md/dm-cache-target.c=3570=static int __init dm_cache_init(void)
--
drivers/md/dm-cache-target.c-3579-
drivers/md/dm-cache-target.c:3580: btracker_work_cache = kmem_cache_create("dm_cache_bt_work",
drivers/md/dm-cache-target.c-3581- sizeof(struct bt_work), __alignof__(struct bt_work), 0, NULL);
--
drivers/nvme/target/fcloop.c=1700=static int __init fcloop_init(void)
--
drivers/nvme/target/fcloop.c-1703-
drivers/nvme/target/fcloop.c:1704: lsreq_cache = kmem_cache_create("lsreq_cache",
drivers/nvme/target/fcloop.c-1705- sizeof(struct fcloop_lsreq), 0,
--
drivers/s390/block/dasd_devmap.c=224=static int __init dasd_parse_keyword(char *keyword)
--
drivers/s390/block/dasd_devmap.c-256- dasd_page_cache =
drivers/s390/block/dasd_devmap.c:257: kmem_cache_create("dasd_page_cache", PAGE_SIZE,
drivers/s390/block/dasd_devmap.c-258- PAGE_SIZE, SLAB_CACHE_DMA,
--
drivers/s390/cio/cmf.c=1248=static int __init init_cmbe(void)
drivers/s390/cio/cmf.c-1249-{
drivers/s390/cio/cmf.c:1250: cmbe_cache = kmem_cache_create("cmbe_cache", sizeof(struct cmbe),
drivers/s390/cio/cmf.c-1251- __alignof__(struct cmbe), 0, NULL);
--
drivers/scsi/qedf/qedf_main.c=4124=static int __init qedf_init(void)
--
drivers/scsi/qedf/qedf_main.c-4147- /* Create kmem_cache for qedf_io_work structs */
drivers/scsi/qedf/qedf_main.c:4148: qedf_io_work_cache = kmem_cache_create("qedf_io_work_cache",
drivers/scsi/qedf/qedf_main.c-4149- sizeof(struct qedf_io_work), 0, SLAB_HWCACHE_ALIGN, NULL);
--
drivers/scsi/qla2xxx/qla_target.c=8346=int __init qlt_init(void)
--
drivers/scsi/qla2xxx/qla_target.c-8361-
drivers/scsi/qla2xxx/qla_target.c:8362: qla_tgt_mgmt_cmd_cachep = kmem_cache_create("qla_tgt_mgmt_cmd_cachep",
drivers/scsi/qla2xxx/qla_target.c-8363- sizeof(struct qla_tgt_mgmt_cmd), __alignof__(struct
--
drivers/scsi/qla2xxx/qla_target.c-8366- ql_log(ql_log_fatal, NULL, 0xd04b,
drivers/scsi/qla2xxx/qla_target.c:8367: "kmem_cache_create for qla_tgt_mgmt_cmd_cachep failed\n");
drivers/scsi/qla2xxx/qla_target.c-8368- return -ENOMEM;
--
drivers/scsi/qla2xxx/qla_target.c-8370-
drivers/scsi/qla2xxx/qla_target.c:8371: qla_tgt_plogi_cachep = kmem_cache_create("qla_tgt_plogi_cachep",
drivers/scsi/qla2xxx/qla_target.c-8372- sizeof(struct qlt_plogi_ack_t), __alignof__(struct qlt_plogi_ack_t),
--
drivers/scsi/qla2xxx/qla_target.c-8376- ql_log(ql_log_fatal, NULL, 0xe06d,
drivers/scsi/qla2xxx/qla_target.c:8377: "kmem_cache_create for qla_tgt_plogi_cachep failed\n");
drivers/scsi/qla2xxx/qla_target.c-8378- ret = -ENOMEM;
--
drivers/scsi/scsi_lib.c=62=int scsi_init_sense_cache(struct Scsi_Host *shost)
--
drivers/scsi/scsi_lib.c-68- scsi_sense_cache =
drivers/scsi/scsi_lib.c:69: kmem_cache_create_usercopy("scsi_sense_cache",
drivers/scsi/scsi_lib.c-70- SCSI_SENSE_BUFFERSIZE, 0, SLAB_HWCACHE_ALIGN,
--
drivers/scsi/virtio_scsi.c=1063=static int __init virtio_scsi_init(void)
--
drivers/scsi/virtio_scsi.c-1068- if (!virtscsi_cmd_cache) {
drivers/scsi/virtio_scsi.c:1069: pr_err("kmem_cache_create() for virtscsi_cmd_cache failed\n");
drivers/scsi/virtio_scsi.c-1070- goto error;
--
drivers/staging/media/atomisp/pci/hmm/hmm_bo.c=318=int hmm_bo_device_init(struct hmm_bo_device *bdev,
--
drivers/staging/media/atomisp/pci/hmm/hmm_bo.c-346-
drivers/staging/media/atomisp/pci/hmm/hmm_bo.c:347: bdev->bo_cache = kmem_cache_create("bo_cache",
drivers/staging/media/atomisp/pci/hmm/hmm_bo.c-348- sizeof(struct hmm_buffer_object), 0, 0, NULL);
--
drivers/target/iscsi/iscsi_target.c=672=static int __init iscsi_target_init_module(void)
--
drivers/target/iscsi/iscsi_target.c-699-
drivers/target/iscsi/iscsi_target.c:700: lio_qr_cache = kmem_cache_create("lio_qr_cache",
drivers/target/iscsi/iscsi_target.c-701- sizeof(struct iscsi_queue_req),
--
drivers/target/iscsi/iscsi_target.c-708-
drivers/target/iscsi/iscsi_target.c:709: lio_dr_cache = kmem_cache_create("lio_dr_cache",
drivers/target/iscsi/iscsi_target.c-710- sizeof(struct iscsi_datain_req),
--
drivers/target/iscsi/iscsi_target.c-717-
drivers/target/iscsi/iscsi_target.c:718: lio_ooo_cache = kmem_cache_create("lio_ooo_cache",
drivers/target/iscsi/iscsi_target.c-719- sizeof(struct iscsi_ooo_cmdsn),
--
drivers/target/iscsi/iscsi_target.c-726-
drivers/target/iscsi/iscsi_target.c:727: lio_r2t_cache = kmem_cache_create("lio_r2t_cache",
drivers/target/iscsi/iscsi_target.c-728- sizeof(struct iscsi_r2t), __alignof__(struct iscsi_r2t),
--
drivers/target/loopback/tcm_loop.c=1155=static int __init tcm_loop_fabric_init(void)
--
drivers/target/loopback/tcm_loop.c-1158-
drivers/target/loopback/tcm_loop.c:1159: tcm_loop_cmd_cache = kmem_cache_create("tcm_loop_cmd_cache",
drivers/target/loopback/tcm_loop.c-1160- sizeof(struct tcm_loop_cmd),
--
drivers/target/loopback/tcm_loop.c-1163- if (!tcm_loop_cmd_cache) {
drivers/target/loopback/tcm_loop.c:1164: pr_debug("kmem_cache_create() for tcm_loop_cmd_cache failed\n");
drivers/target/loopback/tcm_loop.c-1165- goto out;
--
drivers/target/target_core_transport.c=60=int init_se_kmem_caches(void)
drivers/target/target_core_transport.c-61-{
drivers/target/target_core_transport.c:62: se_sess_cache = kmem_cache_create("se_sess_cache",
drivers/target/target_core_transport.c-63- sizeof(struct se_session), __alignof__(struct se_session),
--
drivers/target/target_core_transport.c-69- }
drivers/target/target_core_transport.c:70: se_ua_cache = kmem_cache_create("se_ua_cache",
drivers/target/target_core_transport.c-71- sizeof(struct se_ua), __alignof__(struct se_ua),
--
drivers/target/target_core_transport.c-76- }
drivers/target/target_core_transport.c:77: t10_pr_reg_cache = kmem_cache_create("t10_pr_reg_cache",
drivers/target/target_core_transport.c-78- sizeof(struct t10_pr_registration),
--
drivers/target/target_core_transport.c-84- }
drivers/target/target_core_transport.c:85: t10_alua_lu_gp_cache = kmem_cache_create("t10_alua_lu_gp_cache",
drivers/target/target_core_transport.c-86- sizeof(struct t10_alua_lu_gp), __alignof__(struct t10_alua_lu_gp),
--
drivers/target/target_core_transport.c-88- if (!t10_alua_lu_gp_cache) {
drivers/target/target_core_transport.c:89: pr_err("kmem_cache_create() for t10_alua_lu_gp_cache"
drivers/target/target_core_transport.c-90- " failed\n");
--
drivers/target/target_core_transport.c-92- }
drivers/target/target_core_transport.c:93: t10_alua_lu_gp_mem_cache = kmem_cache_create("t10_alua_lu_gp_mem_cache",
drivers/target/target_core_transport.c-94- sizeof(struct t10_alua_lu_gp_member),
--
drivers/target/target_core_transport.c-100- }
drivers/target/target_core_transport.c:101: t10_alua_tg_pt_gp_cache = kmem_cache_create("t10_alua_tg_pt_gp_cache",
drivers/target/target_core_transport.c-102- sizeof(struct t10_alua_tg_pt_gp),
--
drivers/target/target_core_user.c=3321=static int __init tcmu_module_init(void)
--
drivers/target/target_core_user.c-3328-
drivers/target/target_core_user.c:3329: tcmu_cmd_cache = kmem_cache_create("tcmu_cmd_cache",
drivers/target/target_core_user.c-3330- sizeof(struct tcmu_cmd),
--
fs/9p/v9fs.c=675=static int v9fs_init_inode_cache(void)
fs/9p/v9fs.c-676-{
fs/9p/v9fs.c:677: v9fs_inode_cache = kmem_cache_create("v9fs_inode_cache",
fs/9p/v9fs.c-678- sizeof(struct v9fs_inode),
--
fs/adfs/super.c=222=static int __init init_inodecache(void)
fs/adfs/super.c-223-{
fs/adfs/super.c:224: adfs_inode_cachep = kmem_cache_create("adfs_inode_cache",
fs/adfs/super.c-225- sizeof(struct adfs_inode_info),
--
fs/affs/super.c=130=static int __init init_inodecache(void)
fs/affs/super.c-131-{
fs/affs/super.c:132: affs_inode_cachep = kmem_cache_create("affs_inode_cache",
fs/affs/super.c-133- sizeof(struct affs_inode_info),
--
fs/afs/super.c=96=int __init afs_fs_init(void)
--
fs/afs/super.c-105- ret = -ENOMEM;
fs/afs/super.c:106: afs_inode_cachep = kmem_cache_create("afs_inode_cache",
fs/afs/super.c-107- sizeof(struct afs_vnode),
--
fs/aio.c=338=static int __init aio_setup(void)
--
fs/aio.c-345-
fs/aio.c:346: aio_inode_cachep = kmem_cache_create("aio_inode_cache",
fs/aio.c-347- sizeof(struct aio_inode_info), 0,
--
fs/befs/linuxvfs.c=435=befs_init_inodecache(void)
fs/befs/linuxvfs.c-436-{
fs/befs/linuxvfs.c:437: befs_inode_cachep = kmem_cache_create_usercopy("befs_inode_cache",
fs/befs/linuxvfs.c-438- sizeof(struct befs_inode_info), 0,
--
fs/bfs/inode.c=279=static int __init init_inodecache(void)
fs/bfs/inode.c-280-{
fs/bfs/inode.c:281: bfs_inode_cachep = kmem_cache_create("bfs_inode_cache",
fs/bfs/inode.c-282- sizeof(struct bfs_inode_info),
--
fs/coda/inode.c=71=int __init coda_init_inodecache(void)
fs/coda/inode.c-72-{
fs/coda/inode.c:73: coda_inode_cachep = kmem_cache_create("coda_inode_cache",
fs/coda/inode.c-74- sizeof(struct coda_inode_info), 0,
--
fs/configfs/mount.c=136=static int __init configfs_init(void)
--
fs/configfs/mount.c-139-
fs/configfs/mount.c:140: configfs_dir_cachep = kmem_cache_create("configfs_dir_cache",
fs/configfs/mount.c-141- sizeof(struct configfs_dirent),
--
fs/debugfs/inode.c=900=static int __init debugfs_init(void)
--
fs/debugfs/inode.c-910-
fs/debugfs/inode.c:911: debugfs_inode_cachep = kmem_cache_create("debugfs_inode_cache",
fs/debugfs/inode.c-912- sizeof(struct debugfs_inode_info), 0,
--
fs/efs/super.c=86=static int __init init_inodecache(void)
fs/efs/super.c-87-{
fs/efs/super.c:88: efs_inode_cachep = kmem_cache_create("efs_inode_cache",
fs/efs/super.c-89- sizeof(struct efs_inode_info), 0,
--
fs/exfat/cache.c=45=int exfat_cache_init(void)
fs/exfat/cache.c-46-{
fs/exfat/cache.c:47: exfat_cachep = kmem_cache_create("exfat_cache",
fs/exfat/cache.c-48- sizeof(struct exfat_cache),
--
fs/exfat/super.c=895=static int __init init_exfat_fs(void)
--
fs/exfat/super.c-902-
fs/exfat/super.c:903: exfat_inode_cachep = kmem_cache_create("exfat_inode_cache",
fs/exfat/super.c-904- sizeof(struct exfat_inode_info),
--
fs/ext2/super.c=240=static int __init init_inodecache(void)
fs/ext2/super.c-241-{
fs/ext2/super.c:242: ext2_inode_cachep = kmem_cache_create_usercopy("ext2_inode_cache",
fs/ext2/super.c-243- sizeof(struct ext2_inode_info), 0,
--
fs/ext4/super.c=1497=static int __init init_inodecache(void)
--
fs/ext4/super.c-1506-
fs/ext4/super.c:1507: ext4_inode_cachep = kmem_cache_create("ext4_inode_cache",
fs/ext4/super.c-1508- sizeof(struct ext4_inode_info),
--
fs/f2fs/super.c=5569=static int __init init_inodecache(void)
fs/f2fs/super.c-5570-{
fs/f2fs/super.c:5571: f2fs_inode_cachep = kmem_cache_create("f2fs_inode_cache",
fs/f2fs/super.c-5572- sizeof(struct f2fs_inode_info), 0,
--
fs/fat/cache.c=41=int __init fat_cache_init(void)
fs/fat/cache.c-42-{
fs/fat/cache.c:43: fat_cache_cachep = kmem_cache_create("fat_cache",
fs/fat/cache.c-44- sizeof(struct fat_cache),
--
fs/fat/inode.c=789=static int __init fat_init_inodecache(void)
fs/fat/inode.c-790-{
fs/fat/inode.c:791: fat_inode_cachep = kmem_cache_create("fat_inode_cache",
fs/fat/inode.c-792- sizeof(struct msdos_inode_info),
--
fs/fcntl.c=1165=static int __init fcntl_init(void)
--
fs/fcntl.c-1176-
fs/fcntl.c:1177: fasync_cache = kmem_cache_create("fasync_cache",
fs/fcntl.c-1178- sizeof(struct fasync_struct), 0,
--
fs/hfs/super.c=461=static int __init init_hfs_fs(void)
--
fs/hfs/super.c-464-
fs/hfs/super.c:465: hfs_inode_cachep = kmem_cache_create("hfs_inode_cache",
fs/hfs/super.c-466- sizeof(struct hfs_inode_info), 0,
--
fs/hfsplus/attributes.c=15=int __init hfsplus_create_attr_tree_cache(void)
--
fs/hfsplus/attributes.c-20- hfsplus_attr_tree_cachep =
fs/hfsplus/attributes.c:21: kmem_cache_create("hfsplus_attr_cache",
fs/hfsplus/attributes.c-22- sizeof(hfsplus_attr_entry), 0,
--
fs/hpfs/super.c=255=static int init_inodecache(void)
fs/hpfs/super.c-256-{
fs/hpfs/super.c:257: hpfs_inode_cachep = kmem_cache_create("hpfs_inode_cache",
fs/hpfs/super.c-258- sizeof(struct hpfs_inode_info),
--
fs/hugetlbfs/inode.c=1593=static int __init init_hugetlbfs_fs(void)
--
fs/hugetlbfs/inode.c-1605- error = -ENOMEM;
fs/hugetlbfs/inode.c:1606: hugetlbfs_inode_cachep = kmem_cache_create("hugetlbfs_inode_cache",
fs/hugetlbfs/inode.c-1607- sizeof(struct hugetlbfs_inode_info),
--
fs/inode.c=2592=void __init inode_init(void)
--
fs/inode.c-2594- /* inode slab cache */
fs/inode.c:2595: inode_cachep = kmem_cache_create("inode_cache",
fs/inode.c-2596- sizeof(struct inode),
--
fs/isofs/inode.c=92=static int __init init_inodecache(void)
fs/isofs/inode.c-93-{
fs/isofs/inode.c:94: isofs_inode_cachep = kmem_cache_create("isofs_inode_cache",
fs/isofs/inode.c-95- sizeof(struct iso_inode_info),
--
fs/kernfs/mount.c=460=void __init kernfs_init(void)
fs/kernfs/mount.c-461-{
fs/kernfs/mount.c:462: kernfs_node_cache = kmem_cache_create("kernfs_node_cache",
fs/kernfs/mount.c-463- sizeof(struct kernfs_node),
--
fs/kernfs/mount.c-466- /* Creates slab cache for kernfs inode attributes */
fs/kernfs/mount.c:467: kernfs_iattrs_cache = kmem_cache_create("kernfs_iattrs_cache",
fs/kernfs/mount.c-468- sizeof(struct kernfs_iattrs),
--
fs/locks.c=3074=static int __init filelock_init(void)
--
fs/locks.c-3080-
fs/locks.c:3081: filelock_cache = kmem_cache_create("file_lock_cache",
fs/locks.c-3082- sizeof(struct file_lock), 0, SLAB_PANIC, NULL);
fs/locks.c-3083-
fs/locks.c:3084: filelease_cache = kmem_cache_create("file_lease_cache",
fs/locks.c-3085- sizeof(struct file_lease), 0, SLAB_PANIC, NULL);
--
fs/minix/inode.c=105=static int __init init_inodecache(void)
fs/minix/inode.c-106-{
fs/minix/inode.c:107: minix_inode_cachep = kmem_cache_create("minix_inode_cache",
fs/minix/inode.c-108- sizeof(struct minix_inode_info),
--
fs/namei.c=132=void __init filename_init(void)
fs/namei.c-133-{
fs/namei.c:134: __names_cache = kmem_cache_create_usercopy("names_cache", sizeof(struct filename), 0,
fs/namei.c-135- SLAB_HWCACHE_ALIGN|SLAB_PANIC, offsetof(struct filename, iname),
--
fs/namespace.c=6233=void __init mnt_init(void)
--
fs/namespace.c-6236-
fs/namespace.c:6237: mnt_cache = kmem_cache_create("mnt_cache", sizeof(struct mount),
fs/namespace.c-6238- 0, SLAB_HWCACHE_ALIGN|SLAB_PANIC|SLAB_ACCOUNT, NULL);
--
fs/nfs/direct.c=1085=int __init nfs_init_directcache(void)
fs/nfs/direct.c-1086-{
fs/nfs/direct.c:1087: nfs_direct_cachep = kmem_cache_create("nfs_direct_cache",
fs/nfs/direct.c-1088- sizeof(struct nfs_direct_req),
--
fs/nfs/inode.c=2563=static int __init nfs_init_inodecache(void)
fs/nfs/inode.c-2564-{
fs/nfs/inode.c:2565: nfs_inode_cachep = kmem_cache_create("nfs_inode_cache",
fs/nfs/inode.c-2566- sizeof(struct nfs_inode),
--
fs/nfs/nfs42xattr.c=1014=int __init nfs4_xattr_cache_init(void)
--
fs/nfs/nfs42xattr.c-1017-
fs/nfs/nfs42xattr.c:1018: nfs4_xattr_cache_cachep = kmem_cache_create("nfs4_xattr_cache_cache",
fs/nfs/nfs42xattr.c-1019- sizeof(struct nfs4_xattr_cache), 0,
--
fs/nilfs2/super.c=1346=static int __init nilfs_init_cachep(void)
fs/nilfs2/super.c-1347-{
fs/nilfs2/super.c:1348: nilfs_inode_cachep = kmem_cache_create("nilfs2_inode_cache",
fs/nilfs2/super.c-1349- sizeof(struct nilfs_inode_info), 0,
--
fs/nilfs2/super.c-1354-
fs/nilfs2/super.c:1355: nilfs_transaction_cachep = kmem_cache_create("nilfs2_transaction_cache",
fs/nilfs2/super.c-1356- sizeof(struct nilfs_transaction_info), 0,
--
fs/nilfs2/super.c-1360-
fs/nilfs2/super.c:1361: nilfs_segbuf_cachep = kmem_cache_create("nilfs2_segbuf_cache",
fs/nilfs2/super.c-1362- sizeof(struct nilfs_segment_buffer), 0,
--
fs/nilfs2/super.c-1366-
fs/nilfs2/super.c:1367: nilfs_btree_path_cache = kmem_cache_create("nilfs2_btree_path_cache",
fs/nilfs2/super.c-1368- sizeof(struct nilfs_btree_path) * NILFS_BTREE_LEVEL_MAX,
--
fs/ntfs/super.c=2650=static int __init init_ntfs_fs(void)
--
fs/ntfs/super.c-2659-
fs/ntfs/super.c:2660: ntfs_index_ctx_cache = kmem_cache_create(ntfs_index_ctx_cache_name,
fs/ntfs/super.c-2661- sizeof(struct ntfs_index_context), 0 /* offset */,
--
fs/ntfs/super.c-2666- }
fs/ntfs/super.c:2667: ntfs_attr_ctx_cache = kmem_cache_create(ntfs_attr_ctx_cache_name,
fs/ntfs/super.c-2668- sizeof(struct ntfs_attr_search_ctx), 0 /* offset */,
--
fs/ntfs/super.c-2675-
fs/ntfs/super.c:2676: ntfs_name_cache = kmem_cache_create(ntfs_name_cache_name,
fs/ntfs/super.c-2677- (NTFS_MAX_NAME_LEN+2) * sizeof(__le16), 0,
--
fs/ntfs/super.c-2683-
fs/ntfs/super.c:2684: ntfs_inode_cache = kmem_cache_create(ntfs_inode_cache_name,
fs/ntfs/super.c-2685- sizeof(struct ntfs_inode), 0, SLAB_RECLAIM_ACCOUNT, NULL);
--
fs/ntfs/super.c-2690-
fs/ntfs/super.c:2691: ntfs_big_inode_cache = kmem_cache_create(ntfs_big_inode_cache_name,
fs/ntfs/super.c-2692- sizeof(struct big_ntfs_inode), 0, SLAB_HWCACHE_ALIGN |
--
fs/ntfs3/bitmap.c=41=int __init ntfs3_init_bitmap(void)
fs/ntfs3/bitmap.c-42-{
fs/ntfs3/bitmap.c:43: ntfs_enode_cachep = kmem_cache_create("ntfs3_enode_cache",
fs/ntfs3/bitmap.c-44- sizeof(struct e_node), 0,
--
fs/ocfs2/dlmfs/dlmfs.c=580=static int __init init_dlmfs_fs(void)
--
fs/ocfs2/dlmfs/dlmfs.c-584-
fs/ocfs2/dlmfs/dlmfs.c:585: dlmfs_inode_cache = kmem_cache_create("dlmfs_inode_cache",
fs/ocfs2/dlmfs/dlmfs.c-586- sizeof(struct dlmfs_inode_private),
--
fs/ocfs2/super.c=1648=static int ocfs2_initialize_mem_caches(void)
fs/ocfs2/super.c-1649-{
fs/ocfs2/super.c:1650: ocfs2_inode_cachep = kmem_cache_create("ocfs2_inode_cache",
fs/ocfs2/super.c-1651- sizeof(struct ocfs2_inode_info),
--
fs/ocfs2/super.c-1655- ocfs2_inode_init_once);
fs/ocfs2/super.c:1656: ocfs2_dquot_cachep = kmem_cache_create("ocfs2_dquot_cache",
fs/ocfs2/super.c-1657- sizeof(struct ocfs2_dquot),
--
fs/ocfs2/super.c-1660- NULL);
fs/ocfs2/super.c:1661: ocfs2_qf_chunk_cachep = kmem_cache_create("ocfs2_qf_chunk_cache",
fs/ocfs2/super.c-1662- sizeof(struct ocfs2_quota_chunk),
--
fs/openpromfs/inode.c=441=static int __init init_openprom_fs(void)
--
fs/openpromfs/inode.c-444-
fs/openpromfs/inode.c:445: op_inode_cachep = kmem_cache_create("op_inode_cache",
fs/openpromfs/inode.c-446- sizeof(struct op_inode_info),
--
]
]
|
| 76/2 |
2026/05/20 07:11 |
llm |
expert |
0m
Model:
Tokens:
input: 99928
output: 20
thoughts: 489
Thoughts: **My Analysis of the Potential Deadlock**
Okay, let's break this down. My initial observation is that `kmem_cache_create` appears to be almost exclusively invoked during initialization routines like module loading or device attachment. This means an unprivileged user can't directly trigger it. This is good news, eliminating the most obvious attack vector.
But, I need to be thorough. What about `kmem_cache_destroy`? Could an unprivileged user somehow trigger that? Nope, it seems that's also limited to cleanup procedures, mirroring the restricted use of `kmem_cache_create`.
So, we're dealing with a lockdep warning, which, at worst, represents a deadlock. But the fact remains it can *only* be triggered by a privileged user with `CAP_SYS_ADMIN` and `CAP_SYS_RESOURCE`. Specifically, I know that `ubi_attach` needs `CAP_SYS_RESOURCE` and NBD needs `CAP_SYS_ADMIN`. This is critical.
This immediately rules out unprivileged users. Furthermore, user namespaces are also out of the question because both `netlink_capable` and `capable(CAP_SYS_RESOURCE)` check `init_user_ns`.
So:
* **Exploitable: False.** This isn't a memory corruption vulnerability; it's a deadlock.
* **DenialOfService: True.** A deadlock will cause a system hang. But, given that it requires root privileges, the question then becomes, does it qualify as a true DoS, since it's limited to a privileged user? The prompt states "Most bugs can, since they cause system crash, hangs, deadlocks, or resource leaks," so I must rate this as a DoS vulnerability.
* **Unprivileged: False.** Requires root.
* **UserNamespace: False.**
* **VMGuestTrigger: False.**
* **VMHostTrigger: False.**
* **NetworkTrigger: False.**
* **RemoteTrigger: False.**
* **PeripheralTrigger: False.**
* **FilesystemTrigger: False.**
Just to be absolutely certain, let me quickly revisit other paths to `kmem_cache_create`. I'm thinking... could BPF somehow be involved? Let me quickly check the `kernel/bpf/` directory.
|
| 77/2 |
2026/05/20 07:11 |
tool |
grepper |
0m
Args: map[Expression:kmem_cache_create]
Results: map[Output:
Full output is too long, showing 500 out of 2753 lines.
Use more precise expression if possible.
[Documentation/core-api/memory-allocation.rst=169=If you need to allocate many identical objects you can use the slab
Documentation/core-api/memory-allocation.rst:170:cache allocator. The cache should be set up with kmem_cache_create() or
Documentation/core-api/memory-allocation.rst:171:kmem_cache_create_usercopy() before it can be used. The second function
Documentation/core-api/memory-allocation.rst-172-should be used if a part of the cache might be copied to the userspace.
--
Documentation/core-api/memory-allocation.rst=186=Memory allocated by `kvmalloc` can be freed with `kvfree`.
Documentation/core-api/memory-allocation.rst:187:Caches created by `kmem_cache_create` should be freed with
Documentation/core-api/memory-allocation.rst-188-`kmem_cache_destroy` only after freeing all the allocated objects first.
--
Documentation/trace/ftrace.rst=3030=listed in:
--
Documentation/trace/ftrace.rst-3037- put_prev_task_idle
Documentation/trace/ftrace.rst:3038: kmem_cache_create
Documentation/trace/ftrace.rst-3039- pick_next_task_rt
--
Documentation/translations/zh_CN/core-api/memory-allocation.rst=76=GFP标志和回收行为
--
Documentation/translations/zh_CN/core-api/memory-allocation.rst-131-如果你需要分配许多相同的对象,你可以使用slab缓存分配器。在使用缓存之前,应该用
Documentation/translations/zh_CN/core-api/memory-allocation.rst:132:kmem_cache_create()或kmem_cache_create_usercopy()来设置缓存。如果缓存的一部分可能被复
Documentation/translations/zh_CN/core-api/memory-allocation.rst-133-制到用户空间,应该使用第二个函数。在缓存被创建后,kmem_cache_alloc()和它的封装可以从该缓
--
arch/arm64/mm/pgd.c=49=void __init pgtable_cache_init(void)
--
arch/arm64/mm/pgd.c-64- */
arch/arm64/mm/pgd.c:65: pgd_cache = kmem_cache_create("pgd_cache", PGD_SIZE, PGD_SIZE,
arch/arm64/mm/pgd.c-66- SLAB_PANIC, NULL);
--
arch/powerpc/kernel/rtas_flash.c=675=static int __init rtas_flash_init(void)
--
arch/powerpc/kernel/rtas_flash.c-687-
arch/powerpc/kernel/rtas_flash.c:688: flash_block_cache = kmem_cache_create_usercopy("rtas_flash_cache",
arch/powerpc/kernel/rtas_flash.c-689- RTAS_BLK_SIZE, RTAS_BLK_SIZE,
--
arch/powerpc/kvm/book3s_64_mmu_radix.c=1453=int kvmppc_radix_init(void)
--
arch/powerpc/kvm/book3s_64_mmu_radix.c-1456-
arch/powerpc/kvm/book3s_64_mmu_radix.c:1457: kvm_pte_cache = kmem_cache_create("kvm-pte", size, size, 0, pte_ctor);
arch/powerpc/kvm/book3s_64_mmu_radix.c-1458- if (!kvm_pte_cache)
--
arch/powerpc/kvm/book3s_64_mmu_radix.c-1462-
arch/powerpc/kvm/book3s_64_mmu_radix.c:1463: kvm_pmd_cache = kmem_cache_create("kvm-pmd", size, size, 0, pmd_ctor);
arch/powerpc/kvm/book3s_64_mmu_radix.c-1464- if (!kvm_pmd_cache) {
--
arch/powerpc/kvm/book3s_mmu_hpte.c=368=int kvmppc_mmu_hpte_sysinit(void)
--
arch/powerpc/kvm/book3s_mmu_hpte.c-370- /* init hpte slab cache */
arch/powerpc/kvm/book3s_mmu_hpte.c:371: hpte_cache = kmem_cache_create("kvm-spt", sizeof(struct hpte_cache),
arch/powerpc/kvm/book3s_mmu_hpte.c-372- sizeof(struct hpte_cache), 0, NULL);
--
arch/powerpc/mm/init-common.c=118=void pgtable_cache_add(unsigned int shift)
--
arch/powerpc/mm/init-common.c-142- if (name)
arch/powerpc/mm/init-common.c:143: new = kmem_cache_create(name, table_size, align, 0, ctor(shift));
arch/powerpc/mm/init-common.c-144- if (!new)
--
arch/powerpc/perf/hv-24x7.c=1692=static int hv_24x7_init(void)
--
arch/powerpc/perf/hv-24x7.c-1722-
arch/powerpc/perf/hv-24x7.c:1723: hv_page_cache = kmem_cache_create("hv-page-4096", 4096, 4096, 0, NULL);
arch/powerpc/perf/hv-24x7.c-1724- if (!hv_page_cache)
--
arch/powerpc/platforms/cell/spufs/inode.c=762=static int __init spufs_init(void)
--
arch/powerpc/platforms/cell/spufs/inode.c-770- ret = -ENOMEM;
arch/powerpc/platforms/cell/spufs/inode.c:771: spufs_inode_cache = kmem_cache_create("spufs_inode_cache",
arch/powerpc/platforms/cell/spufs/inode.c-772- sizeof(struct spufs_inode_info), 0,
--
arch/powerpc/platforms/pseries/setup.c=340=static int alloc_dispatch_log_kmem_cache(void)
--
arch/powerpc/platforms/pseries/setup.c-343-
arch/powerpc/platforms/pseries/setup.c:344: dtl_cache = kmem_cache_create_usercopy("dtl", DISPATCH_LOG_BYTES,
arch/powerpc/platforms/pseries/setup.c-345- DISPATCH_LOG_BYTES, 0, 0, DISPATCH_LOG_BYTES, ctor);
--
arch/powerpc/sysdev/xive/native.c=495=static bool __init xive_parse_provisioning(struct device_node *np)
--
arch/powerpc/sysdev/xive/native.c-523-
arch/powerpc/sysdev/xive/native.c:524: xive_provision_cache = kmem_cache_create("xive-provision",
arch/powerpc/sysdev/xive/native.c-525- xive_provision_size,
--
arch/riscv/kernel/vector.c=64=void __init riscv_v_setup_ctx_cache(void)
--
arch/riscv/kernel/vector.c-70-
arch/riscv/kernel/vector.c:71: riscv_v_user_cachep = kmem_cache_create_usercopy("riscv_vector_ctx",
arch/riscv/kernel/vector.c-72- riscv_v_vsize, 16, SLAB_PANIC,
--
arch/riscv/kernel/vector.c-74-#ifdef CONFIG_RISCV_ISA_V_PREEMPTIVE
arch/riscv/kernel/vector.c:75: riscv_v_kernel_cachep = kmem_cache_create("riscv_vector_kctx",
arch/riscv/kernel/vector.c-76- riscv_v_vsize, 16,
--
arch/s390/mm/pgalloc.c=390=static int base_pgt_cache_init(void)
--
arch/s390/mm/pgalloc.c-398- if (!base_pgt_cache)
arch/s390/mm/pgalloc.c:399: base_pgt_cache = kmem_cache_create("base_pgt", sz, sz, 0, NULL);
arch/s390/mm/pgalloc.c-400- mutex_unlock(&base_pgt_cache_mutex);
--
arch/s390/pci/pci.c=1065=static int zpci_mem_init(void)
--
arch/s390/pci/pci.c-1071-
arch/s390/pci/pci.c:1072: zdev_fmb_cache = kmem_cache_create("PCI_FMB_cache", sizeof(struct zpci_fmb),
arch/s390/pci/pci.c-1073- __alignof__(struct zpci_fmb), 0, NULL);
--
arch/sh/kernel/cpu/sh4/sq.c=372=static int __init sq_api_init(void)
--
arch/sh/kernel/cpu/sh4/sq.c-378-
arch/sh/kernel/cpu/sh4/sq.c:379: sq_cache = kmem_cache_create("store_queue_cache",
arch/sh/kernel/cpu/sh4/sq.c-380- sizeof(struct sq_mapping), 0, 0, NULL);
--
arch/sh/kernel/dwarf.c=1167=static int __init dwarf_unwinder_init(void)
--
arch/sh/kernel/dwarf.c-1170-
arch/sh/kernel/dwarf.c:1171: dwarf_frame_cachep = kmem_cache_create("dwarf_frames",
arch/sh/kernel/dwarf.c-1172- sizeof(struct dwarf_frame), 0,
--
arch/sh/kernel/dwarf.c-1174-
arch/sh/kernel/dwarf.c:1175: dwarf_reg_cachep = kmem_cache_create("dwarf_regs",
arch/sh/kernel/dwarf.c-1176- sizeof(struct dwarf_reg), 0,
--
arch/sh/kernel/process.c=53=void arch_task_cache_init(void)
--
arch/sh/kernel/process.c-57-
arch/sh/kernel/process.c:58: task_xstate_cachep = kmem_cache_create("task_xstate", xstate_size,
arch/sh/kernel/process.c-59- __alignof__(union thread_xstate),
--
arch/sh/mm/pgtable.c=22=void pgtable_cache_init(void)
arch/sh/mm/pgtable.c-23-{
arch/sh/mm/pgtable.c:24: pgd_cachep = kmem_cache_create("pgd_cache",
arch/sh/mm/pgtable.c-25- PTRS_PER_PGD * (1<<PTE_MAGNITUDE),
--
arch/sh/mm/pgtable.c-27-#if PAGETABLE_LEVELS > 2
arch/sh/mm/pgtable.c:28: pmd_cachep = kmem_cache_create("pmd_cache",
arch/sh/mm/pgtable.c-29- PTRS_PER_PMD * (1<<PTE_MAGNITUDE),
--
arch/sparc/mm/tsb.c=341=void __init pgtable_cache_init(void)
--
arch/sparc/mm/tsb.c-344-
arch/sparc/mm/tsb.c:345: pgtable_cache = kmem_cache_create("pgtable_cache",
arch/sparc/mm/tsb.c-346- PAGE_SIZE, PAGE_SIZE,
--
arch/sparc/mm/tsb.c-357-
arch/sparc/mm/tsb.c:358: tsb_caches[i] = kmem_cache_create(name,
arch/sparc/mm/tsb.c-359- size, size,
--
arch/x86/events/intel/lbr.c=1418=create_lbr_kmem_cache(size_t size, size_t align)
arch/x86/events/intel/lbr.c-1419-{
arch/x86/events/intel/lbr.c:1420: return kmem_cache_create("x86_lbr", size, align, 0, NULL);
arch/x86/events/intel/lbr.c-1421-}
--
arch/x86/kvm/mmu/mmu.c=7599=int kvm_mmu_vendor_module_init(void)
--
arch/x86/kvm/mmu/mmu.c-7618-
arch/x86/kvm/mmu/mmu.c:7619: mmu_page_header_cache = kmem_cache_create("kvm_mmu_page_header",
arch/x86/kvm/mmu/mmu.c-7620- sizeof(struct kvm_mmu_page),
--
arch/x86/kvm/x86.c=566=static struct kmem_cache *kvm_alloc_emulator_cache(void)
--
arch/x86/kvm/x86.c-570-
arch/x86/kvm/x86.c:571: return kmem_cache_create_usercopy("x86_emulator", size,
arch/x86/kvm/x86.c-572- __alignof__(struct x86_emulate_ctxt),
--
block/bdev.c=447=void __init bdev_cache_init(void)
--
block/bdev.c-450-
block/bdev.c:451: bdev_cachep = kmem_cache_create("bdev_cache", sizeof(struct bdev_inode),
block/bdev.c-452- 0, (SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT|
--
block/bio-integrity-auto.c=114=static int __init blk_integrity_auto_init(void)
block/bio-integrity-auto.c-115-{
block/bio-integrity-auto.c:116: bid_slab = kmem_cache_create("bio_integrity_data",
block/bio-integrity-auto.c-117- sizeof(struct bio_integrity_data), 0,
--
block/bio-integrity-fs.c=71=static int __init fs_bio_integrity_init(void)
block/bio-integrity-fs.c-72-{
block/bio-integrity-fs.c:73: fs_bio_integrity_cache = kmem_cache_create("fs_bio_integrity",
block/bio-integrity-fs.c-74- sizeof(struct fs_bio_integrity_buf), 0,
--
block/bio.c=88=static struct bio_slab *create_bio_slab(unsigned int size)
--
block/bio.c-95- snprintf(bslab->name, sizeof(bslab->name), "bio-%d", size);
block/bio.c:96: bslab->slab = kmem_cache_create(bslab->name, size,
block/bio.c-97- ARCH_KMALLOC_MINALIGN,
--
block/bio.c=1980=static int __init init_bio(void)
--
block/bio.c-1988-
block/bio.c:1989: bvs->slab = kmem_cache_create(bvs->name,
block/bio.c-1990- bvs->nr_vecs * sizeof(struct bio_vec), 0,
--
block/blk-ioc.c=436=static int __init blk_ioc_init(void)
block/blk-ioc.c-437-{
block/blk-ioc.c:438: iocontext_cachep = kmem_cache_create("blkdev_ioc",
block/blk-ioc.c-439- sizeof(struct io_context), 0, SLAB_PANIC, NULL);
--
block/elevator.c=498=int elv_register(struct elevator_type *e)
--
block/elevator.c-514- "%s_io_cq", e->elevator_name);
block/elevator.c:515: e->icq_cache = kmem_cache_create(e->icq_cache_name, e->icq_size,
block/elevator.c-516- e->icq_align, 0, NULL);
--
drivers/acpi/osl.c=1599=acpi_os_create_cache(char *name, u16 size, u16 depth, acpi_cache_t **cache)
drivers/acpi/osl.c-1600-{
drivers/acpi/osl.c:1601: *cache = kmem_cache_create(name, size, 0, 0, NULL);
drivers/acpi/osl.c-1602- if (*cache == NULL)
--
drivers/block/aoe/aoeblk.c=443=aoeblk_init(void)
drivers/block/aoe/aoeblk.c-444-{
drivers/block/aoe/aoeblk.c:445: buf_pool_cache = kmem_cache_create("aoe_bufs",
drivers/block/aoe/aoeblk.c-446- sizeof(struct buf),
--
drivers/block/drbd/drbd_main.c=2077=static int drbd_create_mempools(void)
--
drivers/block/drbd/drbd_main.c-2082- /* caches */
drivers/block/drbd/drbd_main.c:2083: drbd_request_cache = kmem_cache_create(
drivers/block/drbd/drbd_main.c-2084- "drbd_req", sizeof(struct drbd_request), 0, 0, NULL);
--
drivers/block/drbd/drbd_main.c-2087-
drivers/block/drbd/drbd_main.c:2088: drbd_ee_cache = kmem_cache_create(
drivers/block/drbd/drbd_main.c-2089- "drbd_ee", sizeof(struct drbd_peer_request), 0, 0, NULL);
--
drivers/block/drbd/drbd_main.c-2092-
drivers/block/drbd/drbd_main.c:2093: drbd_bm_ext_cache = kmem_cache_create(
drivers/block/drbd/drbd_main.c-2094- "drbd_bm", sizeof(struct bm_extent), 0, 0, NULL);
--
drivers/block/drbd/drbd_main.c-2097-
drivers/block/drbd/drbd_main.c:2098: drbd_al_ext_cache = kmem_cache_create(
drivers/block/drbd/drbd_main.c-2099- "drbd_al", sizeof(struct lc_element), 0, 0, NULL);
--
drivers/block/xen-blkback/xenbus.c=356=int __init xen_blkif_interface_init(void)
drivers/block/xen-blkback/xenbus.c-357-{
drivers/block/xen-blkback/xenbus.c:358: xen_blkif_cachep = kmem_cache_create("blkif_cache",
drivers/block/xen-blkback/xenbus.c-359- sizeof(struct xen_blkif),
--
drivers/bus/mhi/ep/main.c=1445=int mhi_ep_register_controller(struct mhi_ep_cntrl *mhi_cntrl,
--
drivers/bus/mhi/ep/main.c-1467-
drivers/bus/mhi/ep/main.c:1468: mhi_cntrl->ev_ring_el_cache = kmem_cache_create("mhi_ep_event_ring_el",
drivers/bus/mhi/ep/main.c-1469- sizeof(struct mhi_ring_element), 0,
--
drivers/bus/mhi/ep/main.c-1475-
drivers/bus/mhi/ep/main.c:1476: mhi_cntrl->tre_buf_cache = kmem_cache_create("mhi_ep_tre_buf", MHI_EP_DEFAULT_MTU, 0,
drivers/bus/mhi/ep/main.c-1477- 0, NULL);
--
drivers/bus/mhi/ep/main.c-1482-
drivers/bus/mhi/ep/main.c:1483: mhi_cntrl->ring_item_cache = kmem_cache_create("mhi_ep_ring_item",
drivers/bus/mhi/ep/main.c-1484- sizeof(struct mhi_ep_ring_item), 0,
--
drivers/crypto/axis/artpec6_crypto.c=2840=static int artpec6_crypto_probe(struct platform_device *pdev)
--
drivers/crypto/axis/artpec6_crypto.c-2878-
drivers/crypto/axis/artpec6_crypto.c:2879: ac->dma_cache = kmem_cache_create("artpec6_crypto_dma",
drivers/crypto/axis/artpec6_crypto.c-2880- sizeof(struct artpec6_crypto_dma_descriptors),
--
drivers/crypto/caam/caamalg_qi2.c=5194=static int dpaa2_caam_probe(struct fsl_mc_device *dpseci_dev)
--
drivers/crypto/caam/caamalg_qi2.c-5220-
drivers/crypto/caam/caamalg_qi2.c:5221: qi_cache = kmem_cache_create("dpaa2_caamqicache", CAAM_QI_MEMCACHE_SIZE,
drivers/crypto/caam/caamalg_qi2.c-5222- 0, 0, NULL);
--
drivers/crypto/caam/qi.c=730=int caam_qi_init(struct platform_device *caam_pdev)
--
drivers/crypto/caam/qi.c-782-
drivers/crypto/caam/qi.c:783: qi_cache = kmem_cache_create("caamqicache", CAAM_QI_MEMCACHE_SIZE,
drivers/crypto/caam/qi.c-784- dma_get_cache_alignment(), 0, NULL);
--
drivers/crypto/ccp/ccp-dmaengine.c=665=int ccp_dmaengine_register(struct ccp_device *ccp)
--
drivers/crypto/ccp/ccp-dmaengine.c-689-
drivers/crypto/ccp/ccp-dmaengine.c:690: ccp->dma_cmd_cache = kmem_cache_create(dma_cmd_cache_name,
drivers/crypto/ccp/ccp-dmaengine.c-691- sizeof(struct ccp_dma_cmd),
--
drivers/crypto/ccp/ccp-dmaengine.c-704-
drivers/crypto/ccp/ccp-dmaengine.c:705: ccp->dma_desc_cache = kmem_cache_create(dma_desc_cache_name,
drivers/crypto/ccp/ccp-dmaengine.c-706- sizeof(struct ccp_dma_desc),
--
drivers/dax/super.c=644=static int dax_fs_init(void)
--
drivers/dax/super.c-647-
drivers/dax/super.c:648: dax_cache = kmem_cache_create("dax_cache", sizeof(struct dax_device), 0,
drivers/dax/super.c-649- SLAB_HWCACHE_ALIGN | SLAB_RECLAIM_ACCOUNT | SLAB_ACCOUNT,
--
drivers/dma/amd/ptdma/ptdma-dmaengine.c=562=int pt_dmaengine_register(struct pt_device *pt)
--
drivers/dma/amd/ptdma/ptdma-dmaengine.c-589-
drivers/dma/amd/ptdma/ptdma-dmaengine.c:590: pt->dma_desc_cache = kmem_cache_create(desc_cache_name,
drivers/dma/amd/ptdma/ptdma-dmaengine.c-591- sizeof(struct pt_dma_desc), 0,
--
drivers/dma/dmaengine.c=1430=static int __init dmaengine_init_unmap_pool(void)
--
drivers/dma/dmaengine.c-1440-
drivers/dma/dmaengine.c:1441: p->cache = kmem_cache_create(p->name, size, 0,
drivers/dma/dmaengine.c-1442- SLAB_HWCACHE_ALIGN, NULL);
--
drivers/dma/idxd/init.c=420=static int idxd_init_evl(struct idxd_device *idxd)
--
drivers/dma/idxd/init.c-443- */
drivers/dma/idxd/init.c:444: idxd->evl_cache = kmem_cache_create_usercopy(idxd_name, evl_cache_size,
drivers/dma/idxd/init.c-445- 0, 0, 0, evl_cache_size,
--
drivers/dma/ioat/init.c=1417=static int __init ioat_init_module(void)
--
drivers/dma/ioat/init.c-1423-
drivers/dma/ioat/init.c:1424: ioat_cache = kmem_cache_create("ioat", sizeof(struct ioat_ring_ent),
drivers/dma/ioat/init.c-1425- 0, SLAB_HWCACHE_ALIGN, NULL);
--
drivers/dma/ste_dma40.c=3123=static int __init d40_hw_detect_init(struct platform_device *pdev,
--
drivers/dma/ste_dma40.c-3285-
drivers/dma/ste_dma40.c:3286: base->desc_slab = kmem_cache_create(D40_NAME, sizeof(struct d40_desc),
drivers/dma/ste_dma40.c-3287- 0, SLAB_HWCACHE_ALIGN,
--
drivers/firewire/net.c=1658=static int __init fwnet_init(void)
--
drivers/firewire/net.c-1671-
drivers/firewire/net.c:1672: fwnet_packet_task_cache = kmem_cache_create("packet_task",
drivers/firewire/net.c-1673- sizeof(struct fwnet_packet_task), 0, 0, NULL);
--
drivers/firmware/google/gsmi.c=898=static __init int gsmi_init(void)
--
drivers/firmware/google/gsmi.c-938- */
drivers/firmware/google/gsmi.c:939: gsmi_dev.mem_pool = kmem_cache_create("gsmi", GSMI_BUF_SIZE,
drivers/firmware/google/gsmi.c-940- GSMI_BUF_ALIGN,
--
drivers/gpu/drm/amd/amdgpu/amdgpu_userq_fence.c=40=int amdgpu_userq_fence_slab_init(void)
drivers/gpu/drm/amd/amdgpu/amdgpu_userq_fence.c-41-{
drivers/gpu/drm/amd/amdgpu/amdgpu_userq_fence.c:42: amdgpu_userq_fence_slab = kmem_cache_create("amdgpu_userq_fence",
drivers/gpu/drm/amd/amdgpu/amdgpu_userq_fence.c-43- sizeof(struct amdgpu_userq_fence),
--
drivers/gpu/drm/exynos/exynos_drm_g2d.c=1449=static int g2d_probe(struct platform_device *pdev)
--
drivers/gpu/drm/exynos/exynos_drm_g2d.c-1458-
drivers/gpu/drm/exynos/exynos_drm_g2d.c:1459: g2d->runqueue_slab = kmem_cache_create("g2d_runqueue_slab",
drivers/gpu/drm/exynos/exynos_drm_g2d.c-1460- sizeof(struct g2d_runqueue_node), 0, 0, NULL);
--
drivers/gpu/drm/i915/gvt/scheduler.c=1391=int intel_vgpu_setup_submission(struct intel_vgpu *vgpu)
--
drivers/gpu/drm/i915/gvt/scheduler.c-1430-
drivers/gpu/drm/i915/gvt/scheduler.c:1431: s->workloads = kmem_cache_create_usercopy("gvt-g_vgpu_workload",
drivers/gpu/drm/i915/gvt/scheduler.c-1432- sizeof(struct intel_vgpu_workload), 0,
--
drivers/gpu/drm/i915/i915_request.c=2290=int __init i915_request_module_init(void)
--
drivers/gpu/drm/i915/i915_request.c-2292- slab_requests =
drivers/gpu/drm/i915/i915_request.c:2293: kmem_cache_create("i915_request",
drivers/gpu/drm/i915/i915_request.c-2294- sizeof(struct i915_request),
--
drivers/gpu/drm/lima/lima_gp.c=353=int lima_gp_pipe_init(struct lima_device *dev)
--
drivers/gpu/drm/lima/lima_gp.c-358- if (!lima_gp_task_slab) {
drivers/gpu/drm/lima/lima_gp.c:359: lima_gp_task_slab = kmem_cache_create_usercopy(
drivers/gpu/drm/lima/lima_gp.c-360- "lima_gp_task", sizeof(struct lima_sched_task) + frame_size,
--
drivers/gpu/drm/lima/lima_pp.c=464=int lima_pp_pipe_init(struct lima_device *dev)
--
drivers/gpu/drm/lima/lima_pp.c-474- if (!lima_pp_task_slab) {
drivers/gpu/drm/lima/lima_pp.c:475: lima_pp_task_slab = kmem_cache_create_usercopy(
drivers/gpu/drm/lima/lima_pp.c-476- "lima_pp_task", sizeof(struct lima_sched_task) + frame_size,
--
drivers/gpu/drm/lima/lima_sched.c=30=int lima_sched_slab_init(void)
--
drivers/gpu/drm/lima/lima_sched.c-32- if (!lima_fence_slab) {
drivers/gpu/drm/lima/lima_sched.c:33: lima_fence_slab = kmem_cache_create(
drivers/gpu/drm/lima/lima_sched.c-34- "lima_fence", sizeof(struct lima_fence), 0,
--
drivers/gpu/drm/msm/msm_iommu.c=773=struct msm_mmu *msm_iommu_gpu_new(struct device *dev, struct msm_gpu *gpu, unsigned long quirks)
--
drivers/gpu/drm/msm/msm_iommu.c-789- iommu->pt_cache =
drivers/gpu/drm/msm/msm_iommu.c:790: kmem_cache_create("msm-mmu-pt", tblsz, tblsz, 0, NULL);
drivers/gpu/drm/msm/msm_iommu.c-791- }
--
drivers/gpu/drm/panthor/panthor_mmu.c=2966=int panthor_mmu_pt_cache_init(void)
drivers/gpu/drm/panthor/panthor_mmu.c-2967-{
drivers/gpu/drm/panthor/panthor_mmu.c:2968: pt_cache = kmem_cache_create("panthor-mmu-pt", SZ_4K, SZ_4K, 0, NULL);
drivers/gpu/drm/panthor/panthor_mmu.c-2969- if (!pt_cache)
--
drivers/gpu/drm/virtio/virtgpu_vq.c=73=int virtio_gpu_alloc_vbufs(struct virtio_gpu_device *vgdev)
drivers/gpu/drm/virtio/virtgpu_vq.c-74-{
drivers/gpu/drm/virtio/virtgpu_vq.c:75: vgdev->vbufs = kmem_cache_create("virtio-gpu-vbufs",
drivers/gpu/drm/virtio/virtgpu_vq.c-76- VBUFFER_SIZE,
--
drivers/gpu/drm/xe/xe_hw_fence.c=19=int __init xe_hw_fence_module_init(void)
drivers/gpu/drm/xe/xe_hw_fence.c-20-{
drivers/gpu/drm/xe/xe_hw_fence.c:21: xe_hw_fence_slab = kmem_cache_create("xe_hw_fence",
drivers/gpu/drm/xe/xe_hw_fence.c-22- sizeof(struct xe_hw_fence), 0,
--
drivers/gpu/drm/xe/xe_sched_job.c=27=int __init xe_sched_job_module_init(void)
--
drivers/gpu/drm/xe/xe_sched_job.c-29- xe_sched_job_slab =
drivers/gpu/drm/xe/xe_sched_job.c:30: kmem_cache_create("xe_sched_job",
drivers/gpu/drm/xe/xe_sched_job.c-31- sizeof(struct xe_sched_job) +
--
drivers/gpu/drm/xe/xe_sched_job.c-37- xe_sched_job_parallel_slab =
drivers/gpu/drm/xe/xe_sched_job.c:38: kmem_cache_create("xe_sched_job_parallel",
drivers/gpu/drm/xe/xe_sched_job.c-39- sizeof(struct xe_sched_job) +
--
drivers/greybus/operation.c=1226=int __init gb_operation_init(void)
drivers/greybus/operation.c-1227-{
drivers/greybus/operation.c:1228: gb_message_cache = kmem_cache_create("gb_message_cache",
drivers/greybus/operation.c-1229- sizeof(struct gb_message), 0, 0,
--
drivers/greybus/operation.c-1233-
drivers/greybus/operation.c:1234: gb_operation_cache = kmem_cache_create("gb_operation_cache",
drivers/greybus/operation.c-1235- sizeof(struct gb_operation), 0,
--
drivers/infiniband/hw/hfi1/user_sdma.c=106=int hfi1_user_sdma_alloc_queues(struct hfi1_ctxtdata *uctxt,
--
drivers/infiniband/hw/hfi1/user_sdma.c-147- fd->subctxt);
drivers/infiniband/hw/hfi1/user_sdma.c:148: pq->txreq_cache = kmem_cache_create(buf,
drivers/infiniband/hw/hfi1/user_sdma.c-149- sizeof(struct user_sdma_txreq),
--
drivers/infiniband/hw/hfi1/verbs_txreq.c=80=int verbs_txreq_init(struct hfi1_ibdev *dev)
--
drivers/infiniband/hw/hfi1/verbs_txreq.c-85- snprintf(buf, sizeof(buf), "hfi1_%u_vtxreq_cache", dd->unit);
drivers/infiniband/hw/hfi1/verbs_txreq.c:86: dev->verbs_txreq_cache = kmem_cache_create(buf,
drivers/infiniband/hw/hfi1/verbs_txreq.c-87- sizeof(struct verbs_txreq),
--
drivers/infiniband/ulp/iser/iscsi_iser.c=1011=static int __init iser_init(void)
--
drivers/infiniband/ulp/iser/iscsi_iser.c-1018-
drivers/infiniband/ulp/iser/iscsi_iser.c:1019: ig.desc_cache = kmem_cache_create("iser_descriptors",
drivers/infiniband/ulp/iser/iscsi_iser.c-1020- sizeof(struct iser_tx_desc),
--
drivers/infiniband/ulp/srpt/ib_srpt.c=117=static struct kmem_cache *srpt_cache_get(unsigned int object_size)
--
drivers/infiniband/ulp/srpt/ib_srpt.c-133- refcount_set(&e->ref, 1);
drivers/infiniband/ulp/srpt/ib_srpt.c:134: e->c = kmem_cache_create(name, object_size, /*align=*/512, 0, NULL);
drivers/infiniband/ulp/srpt/ib_srpt.c-135- if (!e->c)
--
drivers/iommu/exynos-iommu.c=1492=static int __init exynos_iommu_init(void)
--
drivers/iommu/exynos-iommu.c-1502-
drivers/iommu/exynos-iommu.c:1503: lv2table_kmem_cache = kmem_cache_create("exynos-iommu-lv2table",
drivers/iommu/exynos-iommu.c-1504- LV2TABLE_SIZE, LV2TABLE_SIZE, 0, NULL);
--
drivers/iommu/fsl_pamu_domain.c=32=static int __init iommu_init_mempool(void)
drivers/iommu/fsl_pamu_domain.c-33-{
drivers/iommu/fsl_pamu_domain.c:34: fsl_pamu_domain_cache = kmem_cache_create("fsl_pamu_domain",
drivers/iommu/fsl_pamu_domain.c-35- sizeof(struct fsl_dma_domain),
--
drivers/iommu/fsl_pamu_domain.c-43-
drivers/iommu/fsl_pamu_domain.c:44: iommu_devinfo_cache = kmem_cache_create("iommu_devinfo",
drivers/iommu/fsl_pamu_domain.c-45- sizeof(struct device_domain_info),
--
drivers/iommu/io-pgtable-arm-v7s.c=667=static struct io_pgtable *arm_v7s_alloc_pgtable(struct io_pgtable_cfg *cfg,
--
drivers/iommu/io-pgtable-arm-v7s.c-705-
drivers/iommu/io-pgtable-arm-v7s.c:706: data->l2_tables = kmem_cache_create("io-pgtable_armv7s_l2",
drivers/iommu/io-pgtable-arm-v7s.c-707- ARM_V7S_TABLE_SIZE(2, cfg),
--
drivers/iommu/iova.c=953=int iova_cache_get(void)
--
drivers/iommu/iova.c-958- if (!iova_cache_users) {
drivers/iommu/iova.c:959: iova_cache = kmem_cache_create("iommu_iova", sizeof(struct iova), 0,
drivers/iommu/iova.c-960- SLAB_HWCACHE_ALIGN, NULL);
--
drivers/iommu/iova.c-963-
drivers/iommu/iova.c:964: iova_magazine_cache = kmem_cache_create("iommu_iova_magazine",
drivers/iommu/iova.c-965- sizeof(struct iova_magazine),
--
drivers/iommu/omap-iommu.c=1731=static int __init omap_iommu_init(void)
--
drivers/iommu/omap-iommu.c-1744-
drivers/iommu/omap-iommu.c:1745: p = kmem_cache_create("iopte_cache", IOPTE_TABLE_SIZE, align, flags,
drivers/iommu/omap-iommu.c-1746- NULL);
--
drivers/iommu/s390-iommu.c=196=static int __init dma_alloc_cpu_table_caches(void)
drivers/iommu/s390-iommu.c-197-{
drivers/iommu/s390-iommu.c:198: dma_region_table_cache = kmem_cache_create("PCI_DMA_region_tables",
drivers/iommu/s390-iommu.c-199- ZPCI_TABLE_SIZE,
--
drivers/iommu/s390-iommu.c-204-
drivers/iommu/s390-iommu.c:205: dma_page_table_cache = kmem_cache_create("PCI_DMA_page_tables",
drivers/iommu/s390-iommu.c-206- ZPCI_PT_SIZE,
--
drivers/iommu/sun50i-iommu.c=999=static int sun50i_iommu_probe(struct platform_device *pdev)
--
drivers/iommu/sun50i-iommu.c-1011-
drivers/iommu/sun50i-iommu.c:1012: iommu->pt_pool = kmem_cache_create(dev_name(&pdev->dev),
drivers/iommu/sun50i-iommu.c-1013- PT_SIZE, PT_SIZE,
--
drivers/md/dm-bufio.c=2495=struct dm_bufio_client *dm_bufio_client_create(struct block_device *bdev, unsigned int block_size,
--
drivers/md/dm-bufio.c-2556- block_size, atomic_inc_return(&seqno));
drivers/md/dm-bufio.c:2557: c->slab_cache = kmem_cache_create(slab_name, block_size, align,
drivers/md/dm-bufio.c-2558- SLAB_RECLAIM_ACCOUNT, NULL);
--
drivers/md/dm-bufio.c-2569- atomic_inc_return(&seqno));
drivers/md/dm-bufio.c:2570: c->slab_buffer = kmem_cache_create(slab_name, sizeof(struct dm_buffer) + aux_size,
drivers/md/dm-bufio.c-2571- 0, SLAB_RECLAIM_ACCOUNT, NULL);
--
drivers/md/dm-cache-target.c=3570=static int __init dm_cache_init(void)
--
drivers/md/dm-cache-target.c-3579-
drivers/md/dm-cache-target.c:3580: btracker_work_cache = kmem_cache_create("dm_cache_bt_work",
drivers/md/dm-cache-target.c-3581- sizeof(struct bt_work), __alignof__(struct bt_work), 0, NULL);
--
drivers/md/dm-integrity.c=5443=static int __init dm_integrity_init(void)
--
drivers/md/dm-integrity.c-5446-
drivers/md/dm-integrity.c:5447: journal_io_cache = kmem_cache_create("integrity_journal_io",
drivers/md/dm-integrity.c-5448- sizeof(struct journal_io), 0, 0, NULL);
--
]
]
|
| 78/2 |
2026/05/20 07:11 |
llm |
expert |
0m
Model:
Tokens:
input: 112922
output: 22
thoughts: 301
Thoughts: **My Assessment of the Vulnerability**
Okay, I'm pretty sure, based on my understanding of the code, that `kmem_cache_create` isn't something an unprivileged user can just call directly. The deadlock here hinges on `kmem_cache_create` and `kmem_cache_destroy` happening at the same time as memory reclaim and NBD network operations. But NBD requires `CAP_SYS_ADMIN`, and since an unprivileged user can't trigger `kmem_cache_create` directly, this seems beyond their reach. It's a Denial of Service, specifically a deadlock, and only a privileged user could potentially trigger it.
So, here's my initial assessment:
* **Exploitable:** False
* **DenialOfService:** True
* **Unprivileged:** False
* **UserNamespace:** False
* **VMGuestTrigger:** False
* **VMHostTrigger:** False
* **NetworkTrigger:** False
* **RemoteTrigger:** False
* **PeripheralTrigger:** False
* **FilesystemTrigger:** False
But wait, hold on a second! What if `kmem_cache_create` is called indirectly, maybe when mounting a filesystem? And what if that filesystem is mounted by an unprivileged user within a user namespace? That's a different scenario altogether! I need to consider all the filesystems that *can* be mounted within a user namespace. Let's see... `tmpfs`, `ramfs`, `devpts`, `sysfs`, `proc`, `cgroup`, `mqueue`, `bpf`, `overlayfs`, and `fuse` are likely candidates. And sometimes even `ext4`, though that's less common. Do any of these, on mount, call `kmem_cache_create`? I need to check the code. Let's start with `fuse`.
|
| 79/2 |
2026/05/20 07:11 |
tool |
grepper |
0m
Args: map[Expression:kmem_cache_create.*fuse]
Results: map[Output:fs/fuse/dev.c=2730=int __init fuse_dev_init(void)
--
fs/fuse/dev.c-2732- int err = -ENOMEM;
fs/fuse/dev.c:2733: fuse_req_cachep = kmem_cache_create("fuse_request",
fs/fuse/dev.c-2734- sizeof(struct fuse_req),
--
fs/fuse/inode.c=2212=static int __init fuse_fs_init(void)
--
fs/fuse/inode.c-2215-
fs/fuse/inode.c:2216: fuse_inode_cachep = kmem_cache_create("fuse_inode",
fs/fuse/inode.c-2217- sizeof(struct fuse_inode), 0,
]
|
| 80/2 |
2026/05/20 07:12 |
llm |
expert |
0m
Model:
Tokens:
input: 113872
output: 23
thoughts: 18
Thoughts: Okay, here's my interpretation of those thoughts, presented as a personal thought process, as requested:
**Navigating Filesystem Implementations**
Right, so I'm thinking about the way these filesystems are constructed, and I'm focusing on how they're *initialized*. Specifically, the `fuse` filesystem calls some function, let's say `fuse` to set up the filesystem within its `__init__` method. That's a crucial starting point. Now, what's got me thinking is another filesystem implementation I've been working with, `overlayfs`. This one, as I recall, has its own peculiarities and initialization procedures. I need to refresh my memory on that, because its approach will definitely influence any comparisons or integrations I'm considering. Perhaps I can see if the `overlayfs` has any similarities.
|
| 81/2 |
2026/05/20 07:12 |
tool |
grepper |
0m
Args: map[Expression:kmem_cache_create.*ovl]
Results: map[Output:fs/overlayfs/super.c=1588=static int __init ovl_init(void)
--
fs/overlayfs/super.c-1591-
fs/overlayfs/super.c:1592: ovl_inode_cachep = kmem_cache_create("ovl_inode",
fs/overlayfs/super.c-1593- sizeof(struct ovl_inode), 0,
]
|
| 82/2 |
2026/05/20 07:12 |
llm |
expert |
0m
Model:
Tokens:
input: 114209
output: 66
thoughts: 72
Thoughts: Okay, here's my understanding, formulated as though I'm thinking it:
**Analysis of Privilege Escalation Vectors**
Alright, let's nail this down. Looking back at the code, it's pretty clear that even within a user namespace, an unprivileged user just *cannot* trigger that `kmem_cache_create` function. That's a fundamental barrier. And even if they somehow managed to get around that – which, again, seems impossible from what I'm seeing in `__init` – the NBD-related deadlock they're trying to exploit *still* requires global `CAP_SYS_ADMIN`. That's a hard requirement, not something they can finagle with user namespaces. Therefore, based on this analysis, I'm confident in saying that the attack vector is completely inaccessible to an unprivileged user. That's a good and solid conclusion. I'm ready to craft the final response.
|
| 83/2 |
2026/05/20 07:12 |
tool |
set-results |
0m
Args: map[DenialOfService:true Exploitable:false FilesystemTrigger:false NetworkTrigger:false PeripheralTrigger:false RemoteTrigger:false Unprivileged:false UserNamespace:false VMGuestTrigger:false VMHostTrigger:false]
Results: map[DenialOfService:true Exploitable:false FilesystemTrigger:false NetworkTrigger:false PeripheralTrigger:false RemoteTrigger:false Unprivileged:false UserNamespace:false VMGuestTrigger:false VMHostTrigger:false]
|
| 84/2 |
2026/05/20 07:12 |
llm |
expert |
0m
Model:
Tokens:
input: 114608
output: 768
thoughts: 10
Thoughts: Okay, here's the summary, formatted as requested:
**Final Response Readiness**
Right, let's get down to brass tacks. I've analyzed the inputs, considered the nuances, and parsed the implications. I’m at the point where I have a well-formed understanding of the request and the context. The gears are turning, and the necessary frameworks are in place. The data is processed, the angles are assessed, and I'm ready to craft the definitive response. This is the moment to synthesize all that analysis into a coherent and insightful deliverable.
|
| 85/1 |
2026/05/20 07:12 |
action |
format-explanation |
0m
Results: map[Explanation:The bug report indicates a lockdep warning about a possible circular locking
dependency (deadlock) involving `slab_mutex`, `fs_reclaim`, `cpu_hotplug_lock`,
and several locks related to the Network Block Device (NBD) and network sockets.
### Analysis of the Dependency Chain
The lockdep report shows the following existing dependency chain:
1. `fs_reclaim` -> `q_usage_counter` (established during `blk_alloc_queue`)
2. `q_usage_counter` -> `elevator_lock` (from `elevator_change` calling
`blk_mq_freeze_queue`)
3. `elevator_lock` -> `srcu` (from `elevator_change` calling
`blk_mq_quiesce_queue`)
4. `srcu` -> `cmd->lock` (from `blk_mq_run_hw_queue` dispatching requests to
NBD)
5. `cmd->lock` -> `tx_lock` (from `nbd_queue_rq` calling `nbd_handle_cmd`)
6. `tx_lock` -> `sk_lock` (from `send_disconnects` calling `sock_xmit`)
7. `sk_lock` -> `cpu_hotplug_lock` (from `inet_stream_connect` calling
`cpus_read_lock`)
8. `cpu_hotplug_lock` -> `slab_mutex` (from `kmem_cache_destroy` acquiring both)
The new dependency that triggers the warning is:
`slab_mutex` -> `fs_reclaim`
This new dependency is established because `__kmem_cache_create_args` holds
`slab_mutex` and then performs memory allocations with `GFP_KERNEL` (which can
enter direct memory reclaim and acquire `fs_reclaim`). In the syzbot report,
this happens during `ubi_attach_mtd_dev` which dynamically creates a kmem cache
for the attached device.
### Security Impact
* **Exploitable**: No. This is a locking issue (deadlock) and does not result in
memory corruption, out-of-bounds access, or use-after-free. It cannot be
exploited for privilege escalation.
* **Denial of Service**: Yes. If the exact timing conditions are met, the
circular dependency can lead to a system deadlock (hang), resulting in a Denial
of Service.
* **Accessible From Unprivileged Processes / User Namespaces**: No. Triggering
this deadlock requires setting up the entire dependency chain. The chain heavily
relies on the Network Block Device (NBD) subsystem (`cmd->lock`, `tx_lock`).
Configuring NBD devices and sending netlink commands to them requires global
`CAP_SYS_ADMIN` (checked via `netlink_capable(skb, CAP_SYS_ADMIN)` which
verifies capabilities in the `init_user_ns`). Additionally, dynamically creating
kmem caches (which triggers the `slab_mutex` -> `fs_reclaim` link) is typically
restricted to module initialization or privileged operations like `ubi_attach`
(which requires global `CAP_SYS_RESOURCE`). Thus, unprivileged users (even
within user namespaces) cannot set up the required environment or trigger the
deadlock.
### Conclusion
This is a complex lockdep warning involving NBD, networking, and slab cache
creation. It represents a theoretical deadlock that could cause a Denial of
Service, but it is strictly limited to highly privileged users
(root/CAP_SYS_ADMIN) who can configure NBD devices and attach UBI devices. It
poses no security risk to unprivileged users.]
|