CVE-2022-49381 - Memory Leak Fixed in Linux Kernel JFFS2 Filesystem (jffs2_do_fill_super)

In early 2022, a subtle but impactful memory leak vulnerability was discovered and fixed in the Linux kernel's JFFS2 (Journaling Flash File System version 2) implementation. Tracked as CVE-2022-49381, this issue affects the jffs2_do_fill_super function and could allow local attackers (or even standard users mounting JFFS2 images) to trigger a kernel memory leak, eventually exhausting system resources.

This post will break down what happened, show you where the problem was, the fix, and explain with real kernel code and links for further details.

What Happened? (Technical Analysis)

JFFS2 is a filesystem for flash memory devices, commonly used in embedded Linux systems.

When you mount a JFFS2 filesystem, the kernel runs a function called jffs2_do_fill_super(). This function sets up all the in-memory data structures required to operate on the filesystem.

d_make_root(): Creates the root directory entry.

If one of these steps fails (for example, because of a corrupt filesystem), the code would prematurely return but forget to clean up resources allocated earlier, especially those initialized by jffs2_sum_init().

Kmemleak Report

Linux's kmemleak detected unreferenced memory (memory that was allocated but not freed, and lost all pointers to it):

unreferenced object xffff888105a65340 (size 64): ...
  backtrace:
    kmem_cache_alloc_trace
    jffs2_sum_init
    jffs2_do_mount_fs
    jffs2_do_fill_super
    jffs2_fill_super
    [...]

and

unreferenced object xffff8881bd7f000 (size 65536):
  backtrace:
    kmalloc_order
    __kmalloc
    jffs2_sum_init
    jffs2_do_mount_fs
    jffs2_do_fill_super
    jffs2_fill_super
    [...]

Meaning: leaked memory if mount fails in the middle.

Let's look at the problematic code (simplified)

int jffs2_do_fill_super(...)
{
    // ... some init code ...
    err = jffs2_sum_init(c);
    if (err)
        goto free_something;

    root_inode = jffs2_iget(...);
    if (IS_ERR(root_inode)) {
        err = PTR_ERR(root_inode);
        goto free_c; // <-- This doesn't free jffs2_sum_init allocations!
    }

    sb->s_root = d_make_root(root_inode);
    if (!sb->s_root) {
        iput(root_inode);
        err = -ENOMEM;
        goto free_c; // <-- same issue here!
    }

    return ;

// ... error handling labels ...
}

Here, if jffs2_iget() or d_make_root() fail, the function jumps to free_c, which didn't actually clean up the allocations made by jffs2_sum_init(). These allocations include substantial kernel memory.

The Fix

The solution is to properly clean up these allocations by calling jffs2_sum_exit() in the error handling paths—everywhere between a successful jffs2_sum_init() and a completed mount.

Patched code snippet:

free_c:
    jffs2_sum_exit(c);   // <--- FIX ADDED
    kfree(c);
    return err;

Or, in the larger context, the fix is simply to add a call to jffs2_sum_exit() along every premature exit after a successful jffs2_sum_init().

Related Commit diff:
Linux kernel git commit

Who is affected?

Any Linux system running JFFS2 and allowing mounting of potentially invalid or maliciously crafted JFFS2 images.

How can it be abused?

A local user (even with standard user capabilities, if they can mount) can repeatedly attempt to mount a corrupted JFFS2 image. With each failed mount, a chunk of kernel memory is leaked. Repeating this can potentially exhaust kernel memory, leading to system instability or a full denial-of-service (DoS).

Sample Exploit Steps

1. Create a corrupted JFFS2 filesystem image or use a fuzzed/truncated one.

while true; do

mount -t jffs2 /path/to/corrupted.img /mnt/test || true
umount /mnt/test 2>/dev/null

Monitor memory:

- Watch /proc/meminfo or use dmesg to see OOM (Out Of Memory) or kernel messages.

Why is this a big deal?

Leaked kernel memory is not returned until reboot. On embedded devices with little RAM, this may brick the system or require a hard reset—all triggered by user-level operations.

Security Impact

- CVE-2022-49381 is a classic example of a *local denial-of-service* vulnerability due to kernel memory leak.

References

- Linux Kernel Commit Fixing the Issue
- Kmemleak Documentation
- CVE-2022-49381 at NVD
- LKML Patch Submission

Summary

*CVE-2022-49381* teaches us that every exit path after resource allocation must be checked for proper cleanup. Small mistakes in kernel code can have major system stability and security impacts, even without enablement of network or remote attack vectors.

Developers: Always review error paths after allocations.

- Security teams: Monitor for excessive mounts or OOM situations, especially on embedded or multi-user systems.

Timeline

Published on: 02/26/2025 07:01:14 UTC
Last modified on: 04/14/2025 20:38:11 UTC