CVE-2022-49300 - Exploiting and Fixing the NBD Race Condition in Linux Kernel

In 2022, a critical race condition was found and fixed in the Linux kernel’s nbd (Network Block Device) driver. This bug, tracked as CVE-2022-49300, could allow a NULL pointer dereference and resource leak, leading to kernel panics ("oopses") if exploited. This post will walk through how this bug happens, the potential dangers, and what changes were made to fix it—with code snippets and original references.

Introduction to NBD and Its Danger Zone

NBD is a kernel module that lets you treat a remote block device like a local disk. It’s handy for all sorts of things in cloud and storage systems.

But, because it lives in the kernel and handles user I/O at high speed, even small mistakes can cause very bad problems—like crashes, info leaks, or DoS.

The main issue was a race between two activities

- A user or system process is connecting to the NBD device (via nbd_genl_connect(), which calls nbd_alloc_config() to set things up).
- At the same time, the nbd kernel module is being unloaded/removed (via rmmod nbd or similar).

If both actions happen at the same time, the connection code (nbd_alloc_config()) might still proceed—even though the module is halfway out the door. This leads to leaked memory (never-freed nbd_config structs and workqueues), and worse, to the module’s code being accessed even after it was technically gone. That triggers classic kernel errors like:

BUG: kernel NULL pointer dereference, address: 000000000000004
Oops: 000 [#1] SMP PTI
...
RIP: 001:nbd_read_stat.cold+x130/x1a4 [nbd]
Call Trace:
  recv_work+x3b/xb [nbd]
  process_one_work+x1ed/x390
...

In plain English:
A workqueue created while the module is still alive can try to use code that has already been unloaded. That’s an instant crash.

The Root Cause: Misusing try_module_get()

The kernel’s try_module_get() function is there to count module references: if it returns true, you can use the code, and the module won’t be unloaded until you’re done; if it returns false, the module is being torn down, so you shouldn’t try to do anything.

Pseudo-Exploit: Triggering the Race

An actual exploit would require kernel access and precise timing, but here’s a simplified version that shows the scenario:

# On one terminal, rapidly create NBD devices
for i in {1..100}
do
    nbd-client localhost 10809 /dev/nbd &
    sleep .01
    pkill nbd-client
done

# On another terminal, repeatedly remove module (may require root)
for i in {1..100}
do
    rmmod nbd 2>/dev/null
    modprobe nbd 2>/dev/null
done

If unlucky (or lucky?), the race hits and you might see a kernel oops like above.

Less dangerous POC in C (if you can run kernel modules)

// This is not a full exploit, but illustrates the dangerous call:
if (!try_module_get(module)) {
    // The right thing is to abort here!
    // The buggy code didn't do that.
}
// else, proceed as normal

The Fix: Defensive Programming

With the patch, the kernel does the right thing: it checks if try_module_get() succeeded. If not, it bails out early and does NOT create configs that will be left dangling.

The fixed code added

static struct nbd_config *nbd_alloc_config(struct nbd_device *nbd) {
    ...
    if (!try_module_get(THIS_MODULE)) {
        pr_err("nbd: try_module_get failed, can't allocate config.\n");
        return ERR_PTR(-ENODEV);
    }
    ...
    // Only assign nbd->config if we succeeded
    nbd->config = config;
    ...
}

Now, nbd->config is only set if everything is good: valid or NULL, never left dangling.

Debugging Aid

The developers even added a debug message to help track down leftover references when removing the module, making future bug hunts easier.

Bug report, discussion, and patch:

- lkml.org kernel mailing list
- Linux kernel commit 21510a8f4

NBD documentation:

- NBD docs on kernel.org

CVE page:

- CVE-2022-49300 on cve.mitre.org

Proper cleanup and defensive checks prevent crashes and keep systems reliable.

This bug could be abused for denial of service (crash the box), and in theory, maybe worse if someone managed to wedge in malicious code during the race.

Conclusion

CVE-2022-49300 shows how subtle races can trip up even mature kernel code.

Thanks to careful review and patching, Linux users are now safer. If you run kernels with NBD enabled, make sure your distro includes the patch!

Stay Safe & Up to Date

Always run updated kernels, and check your modules if you build out-of-tree drivers!

Timeline

Published on: 02/26/2025 07:01:06 UTC
Last modified on: 04/14/2025 20:08:41 UTC