The Linux kernel is the heart of most modern servers and devices. Keeping it secure is a top priority. In this post, we take a deep dive into CVE-2021-46956, a memory leak vulnerability found in the virtiofs subsystem, specifically in the virtio_fs_probe() function. This issue could potentially lead to crashes, memory exhaustion, or resource leaks on affected systems.

What is virtiofs?

virtiofs provides a way for virtual machines (VMs) to efficiently share filesystems with the host, enabling fast file operations between guests and the host. It’s widely used in modern virtualization setups with QEMU/KVM.

When does CVE-2021-46956 Happen?

This flaw occurs if you accidentally pass the same tag twice to QEMU while configuring virtiofs devices. When this happens, the kernel tries to register both with the same identifier (tag). The first registration works fine, but the second one fails with error -17 (-EEXIST) and, crucially, fails to clean up the memory that was just allocated. This results in a memory leak.

Real-World Example

Imagine you’re configuring your VM and accidentally specify the same tag for two separate virtiofs mounts in your QEMU command line:

# Incorrect QEMU usage: Duplicate tag "mymount"
qemu-system-x86_64 \
    -drive file=$IMG,format=qcow2 \
    -device vhost-user-fs-pci,chardev=char1,tag=mymount \
    -device vhost-user-fs-pci,chardev=char2,tag=mymount

kmemleak, the Linux kernel memory leak detector, flagged an unreferenced memory object

unreferenced object xffff888103d47800 (size 1024):
  comm "systemd-udevd", pid 118, jiffies 429489378 (age 18.340s)
  ...
backtrace:
  [<000000000ebb87c1>] virtio_fs_probe+x171/x7ae [virtiofs]
  [<00000000f8aca419>] virtio_dev_probe+x15f/x210
    ...

It shows the memory object is allocated via virtio_fs_probe() but was never freed after the duplicate tag error.

You might also see something like this in your logs

virtiofs: probe of virtio5 failed with error -17

The Fix

The bug was that the error (duplicate tag) path in virtio_fs_probe() did not free the memory it just allocated for the (failed) device. The fix is simple: clean up on failure.

Here’s the essence of the fix (from the official patch)

static int virtio_fs_probe(struct virtio_device *vdev)
{
    struct virtio_fs *fs;
    ...
    fs = kzalloc(sizeof(*fs), GFP_KERNEL);
    if (!fs)
        return -ENOMEM;
    ...
    ret = register_filesystem(fs);
    if (ret) {
        kfree(fs);   // <-- The fix: Free fs on failure!
        return ret;
    }
    ...
}

In the real patch, the exact logic may check for where/when to free, but the key is to ensure free is always called upon failure.

Reference:

virtiofs: fix memory leak in virtio_fs_probe() (kernel.org patch)

Can it be Exploited?

This vulnerability is not directly exploitable for privilege escalation or arbitrary code execution. However, a malicious actor with ability to influence QEMU config could intentionally cause repeated leaks, eventually exhausting kernel memory. This can lead to DoS (Denial of Service) on the VM host.

Potential attack vectors

- VM tenants setting up their own VMs could misconfigure (or purposely abuse) tags for resource exhaustion.

How to Detect

- Use kmemleak to monitor your kernel for leaks (kmemleak documentation)

References

- Original patch commit on kernel.org
- Red Hat Bugzilla entry #2045988
- Virtiofs Home

Summary

CVE-2021-46956 is a memory leak in the virtiofs virtio_fs_probe() function, triggered by accidentally passing the same tag twice. It’s been fixed in the Linux kernel; be sure to use unique tags and upgrade your systems to stay safe from memory exhaustion attacks!

Timeline

Published on: 02/27/2024 19:04:06 UTC
Last modified on: 12/06/2024 17:54:34 UTC