In 2022, a significant vulnerability was identified and patched in the Linux kernel's Network Block Device (NBD) subsystem. Tagged as CVE-2022-49295, this flaw centers around unsafe cleanup order in the NBD module, resulting in a race condition that could cause the kernel to panic due to a NULL pointer dereference.
This long-read dives deep into the bug, breaking down how it happens, references, minimal PoC insights, and real-world implications.
What is NBD and What Went Wrong?
NBD (Network Block Device) allows Linux boxes to use block devices over a network, as if they were local disks. It's widely used for virtual storage, distributed filesystems, and testing.
Core Issue
The vulnerability exists in the order of operations inside nbd_cleanup(). This function performs cleanup when the NBD module unloads. Originally, the module first performed various internal resource cleanups before unregistering its Generic Netlink family with genl_unregister_family().
This cleanup sequence is unsafe. After internal teardown but *before* the Netlink family unregistration, userland can still send Netlink commands to the module, which may access freed resources – leading to a crash.
In Short
- Vulnerability: Use-after-free / NULL pointer dereference in NBD cleanup
Here’s the Oops trace caused by the bug
BUG: kernel NULL pointer dereference, address: 0000000000000098
Oops: 0002 [#1] SMP PTI
CPU: 1 PID: 31299 Comm: nbd-client Tainted: G E 5.14.-rc4
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996)
RIP: 001:down_write+x1a/x50
Call Trace:
start_creating+x89/x130
debugfs_create_dir+x1b/x130
nbd_start_device+x13d/x390 [nbd]
nbd_genl_connect+x42f/x748 [nbd]
genl_family_rcv_msg_doit.isra.+xec/x150
genl_rcv_msg+xe5/x1e
netlink_rcv_skb+x55/x100
genl_rcv+x29/x40
netlink_unicast+x1a8/x250
netlink_sendmsg+x21b/x430
____sys_sendmsg+x2a4/x2d
___sys_sendmsg+x81/xc
__sys_sendmsg+x62/xb
__x64_sys_sendmsg+x1f/x30
do_syscall_64+x3b/xc
entry_SYSCALL_64_after_hwframe+x44/xae
Modules linked in: nbd(E-)
This boils down to: _NBD module resources gone, but userspace can still talk to the family. Kaboom._
The Bad Cleanup Order
// UNVULNERABLE: Clean up first, unregister later
static void nbd_cleanup(void)
{
// ...resource cleanup
genl_unregister_family(&nbd_genl_family); // <-- Should come first!
// ...more cleanup
}
The Fix: Unregister Early
The correct (and now committed) fix is to unregister the Netlink family before freeing other resources:
static void nbd_cleanup(void)
{
genl_unregister_family(&nbd_genl_family); // Prevent further entry points
// Now safe to clean up resources
// ...other cleanup steps
}
This way, no new Netlink messages can enter after data structures are destroyed.
Kernel Patch
- Commit: nbd: call genl_unregister_family() first in nbd_cleanup (Linux)
Bug Type: Race condition leading to potential NULL dereference or use-after-free
- Privilege Required: LOCAL (ability to load/unload modules or communicate via Netlink)
The module’s resources are gone, but Netlink messages are still being processed.
4. Kernel dereferences freed (or NULL) pointers => panic / Oops.
Minimal Repro Steps (Proof of Concept)
*Requires privilege to load/unload modules and access to NBD.*
# In terminal 1, repeatedly invoke nbd-client:
while true; do
nbd-client -C $(head -c 8 /dev/urandom | od -An -tx1 | tr -d ' \n') /dev/nbd
done
# In terminal 2, repeatedly unload the NBD module:
while true; do
sudo rmmod nbd
sudo modprobe nbd
done
This stresses the race, and on a vulnerable kernel, it may crash.
Note: May result in system instability; do *NOT* try on production machines.
Links, References, and Further Reading
- Linux Kernel Patch for CVE-2022-49295
- NBD subsystem in kernel source
- oss-sec mailing list discussion
- CVE-2022-49295 at cve.org
- Generic Netlink Documentation
- nbd-client tool
Conclusion
- CVE-2022-49295 is a classic example of why kernel resource teardown order matters, especially with asynchronous interfaces like Netlink.
Stay safe, and keep your kernel up to date!
*Exclusive long-form summary by your friendly security explainer. Copying discouraged—share the link instead!*
Timeline
Published on: 02/26/2025 07:01:06 UTC
Last modified on: 04/14/2025 20:08:12 UTC