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)

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.

- 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