The Linux kernel is the core of most modern operating systems, so vulnerabilities in it can have far-reaching consequences. One such issue is CVE-2024-39482, which revolved around an out-of-bounds (OOB) variable length array abuse in the bcache subsystem, specifically inside the btree_iter structure. In this long read, we break down how this vulnerability worked, why it’s dangerous, how it was fixed, and what a potential exploit might look like.
[Further Reading and References](#further-reading)
What is bcache?
Bcache is a popular block layer cache that lets you use an SSD as a cache for slower hard drives. By caching frequent reads/writes, performance improves dramatically.
About the Vulnerability: CVE-2024-39482
CVE-2024-39482 revolves around how the kernel's bcache code managed iterators (btree_iter) for traversing btrees, which are essential to how bcache manages cached data. The problem was that a fixed-size array inside this structure wasn't always used correctly: sometimes the structure was allocated with a dynamic size to match the cache set — but code would then access the array with indexes beyond its actual size, leading to out-of-bounds (OOB) memory access.
Such bugs can trigger stability issues, memory leaks, cross-object corruption, or, in the worst cases, privilege escalation.
In most situations, it was used as intended: a stack-allocated object with that fixed size.
- But sometimes the code would allocate a bigger chunk of memory from a mempool to handle a larger btree_iter for some cache sets — and the code would index this with numbers larger than MAX_BSETS, thinking it was safe.
- That means the array was accessed beyond its declared range, leading to undefined behavior (corruption, kernel panic, etc.).
Example
#define MAX_BSETS 16
struct btree_iter {
int idx;
int data[MAX_BSETS];
};
// ...Somewhere...
struct btree_iter *iter = allocate_btree_iter(longer_len); // len > MAX_BSETS
iter->data[i] = ...; // i > MAX_BSETS? Uh-oh!
Vulnerable Code
#define MAX_BSETS 16
struct btree_iter {
int idx;
int data[MAX_BSETS]; // Fixed-length
};
// Allocated dynamically, but still uses MAX_BSETS
struct btree_iter *iter = kmalloc(sizeof(struct btree_iter) + extra, GFP_KERNEL);
for (int i = ; i < cache_set_bsets; ++i) {
iter->data[i] = ...; // OOB if cache_set_bsets > MAX_BSETS
}
A btree_iter_stack that embeds btree_iter and a fixed-length data array for stack use.
struct btree_iter {
int idx;
int data[]; // Flexible array member!
};
struct btree_iter_stack {
struct btree_iter iter;
int data[MAX_BSETS];
};
// Stack use:
struct btree_iter_stack stack_iter;
stack_iter.iter = ...;
stack_iter.data[...] = ...;
// Heap use (proper size):
struct btree_iter *iter = kmalloc(sizeof(*iter) + bsets * sizeof(int), GFP_KERNEL);
This beautifully matches allocation and access. No more OOB.
Exploiting the Bug: How an Attacker Could Abuse It
An attacker with local privileges (i.e., with the ability to run code on the affected system) could, in theory:
1. Craft a large enough cache set to get bcache to allocate a large btree_iter from the pool. The attacker could control how many bsets get created.
2. Trigger operations (scheduled or forced btree operations) that use the buggy iterator implementation.
3. Exploit out-of-bounds writes into adjacent kernel memory, leading to corruption or (if skillful) code execution in kernel space.
While tricky, the attack path is realistic in some shared hosting or container scenarios, where the attacker can configure bcache.
Simple Exploit Skeleton (Conceptual)
// Pseudocode: Create a cache set with many BSETS
system("make-bcache --bsets 100");
// Wait for kernel to allocate btree_iter with dynamic length
// Trigger bcache operations (writes/deletes) to hit the OOB access
// Monitor dmesg or use a crafted payload to try to influence adjacent memory
Note: No full PoC is disclosed here for safety, but this illustrates the flow.
Patch Details and Fix
The patch separates stack and dynamic allocation use, as detailed above, making it impossible for the kernel to index past the end of the actual allocated array, no matter the variant used.
Patch link (official):
- Linux kernel commit fixing CVE-2024-39482
Main takeaway: Always ensure your struct member arrays match your dynamic allocations!
Kernel patch and commit:
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=5b16dbfcbb2f
Linux bcache manual:
https://wiki.kernel.org/index.php/LinuxBcache
NIST NVD:
https://nvd.nist.gov/vuln/detail/CVE-2024-39482 *(May update over time)*
Upstream bcache github:
Conclusion
CVE-2024-39482 is a subtle but impactful Linux kernel vulnerability from poor struct array management. It serves as a powerful reminder that array sizes and allocation boundaries must always match. If you use bcache, update your kernel to the latest version without delay!
*More exclusive content: Have questions on kernel security? Ask us below or request a deeper dive into similar bugs!*
Timeline
Published on: 07/05/2024 07:15:10 UTC
Last modified on: 07/15/2024 06:50:18 UTC