CVE-2024-26883 - Linux Kernel stackmap Overflow on 32-bit Systems Explained

Linux security is always crucial, especially around the eBPF (extended Berkeley Packet Filter) subsystem, which powers things like tracing and performance monitoring. On 32-bit chips, an overlooked bug in the *stackmap* code could have led to exploit opportunities until a recent fix. Known as CVE-2024-26883, here’s a deep-dive breakdown so you can understand what happened, what the dangers were, and how it was handled.

What is CVE-2024-26883?

A flaw was discovered in the Linux kernel’s stackmap implementation for the eBPF subsystem on 32-bit architectures (like old ARM, MIPS, etc). The issue boiled down to the way the code allocated hash buckets for maps—a calculation that could overflow, specifically *before* the intended safety check ever ran.

This could allow attackers to trigger buggy kernel behavior, possibly leading to crashes or maybe more serious issues (with enough skill and know-how).

Let’s look at the code logic

The vulnerable code wanted to calculate the number of hash buckets for a *stackmap* safely, preventing values that would be too big for available memory. It used this helper:

unsigned long buckets = roundup_pow_of_two(user_value);
if (buckets == )
    return -EINVAL; // error: overflow

It seemed fine—if the result is zero, it would signal an unsafe overflow, and the system would refuse the request.

But here’s the kicker: on 32-bit architectures (where values like unsigned long are only 32 bits), doing big left shifts in roundup_pow_of_two() is undefined behavior. The language standard means the shift could do anything; maybe it’ll nicely give zero, maybe something weird, or maybe nothing helpful at all.

A simplified version of such a rounding might look like

unsigned long roundup_pow_of_two(unsigned long x) {
    if (x == )
        return 1;
    x--;
    x |= x >> 1;
    x |= x >> 2;
    x |= x >> 4;
    x |= x >> 8;
    x |= x >> 16; // On 32-bit this is fine, but adding another shift can break
    x++;
    return x;
}

If someone requested a huge stackmap size by providing a near-overflowing value, the calculation inside roundup_pow_of_two() can overflow internally—*before* the buckets == safety check gets a chance to catch anything.

Public Discovery

The bug was actually caught by syzkaller (aka syzbot), Google’s excellent Linux kernel fuzzing robot, smashing strange inputs into system calls to see what breaks. syzbot found that specifically the DEVMAP_HASH eBPF map type reproduced the problem, but the bug’s logic was from older hash map code.

Commit with Fix:
Fixes were merged into the Linux kernel mainline:
commit (see also lore.kernel.org message)

Calculation overflows inside roundup_pow_of_two():

Instead of failing safely (returning zero), internal math overflows, resulting in a small value, causing allocation of a much-too-small hash table.

Kernel allocates buffer too small:

Later BPF operations, trusted size calculations, or writes may corrupt kernel memory following the small buffer.

Result:

Likely a kernel oops (crash), but with expert manipulation and luck, possible privilege escalation paths might exist.

Proof-of-Concept Pseudocode (for illustration)

(Do NOT use for malicious purposes; this is a redacted teaching example.)

// User space: bpf syscall to make a huge stackmap
struct bpf_attr attr;
memset(&attr, , sizeof(attr));
attr.map_type = BPF_MAP_TYPE_STACK_TRACE;
attr.key_size = 4;
attr.value_size = 128;
attr.max_entries = xFFFFFFFF; // triggers overflow on 32-bit

int fd = syscall(__NR_bpf, BPF_MAP_CREATE, &attr, sizeof(attr));
if (fd < )
    perror("bpf create failed");

This would either “crash” or expose the kernel to attack, especially if the attacker could later write past the actual buffer.

The Fix: Simple and Clean

Instead of checking *after* rounding (where overflow might have already happened), the fix just checks *before*:

if (user_value > MAX_SAFE_ENTRIES)
    return -EINVAL;

buckets = roundup_pow_of_two(user_value);
// No more dangerous overflows

This way, we guarantee no wild overflows or undefined shifts.

Upstream commit:

Linux git commit 689ac01d6c65 (kernel.org)

syzkaller bug report:

syzkaller dashboard entry *(note: actual URL may differ)*
- BPF documentation (kernel.org)
- roundup_pow_of_two() discussion on Stack Overflow

Conclusion

CVE-2024-26883 is a classic example where architectures matter: stuff that’s harmless on 64-bit chips can go badly wrong on 32-bit, and all it takes is the wrong kind of input. Fixes like these keep our core systems safer. If you run custom kernels on 32-bit hardware (think embedded, old Raspberry Pis, etc.), update as soon as possible.

Stay patched! And if you’re developing kernel code, remember: always validate *before* doing any operation that could overflow, especially on systems with smaller word sizes.


*Got more questions about eBPF, kernel security, or want live tutorials? Drop a comment!*

Timeline

Published on: 04/17/2024 11:15:10 UTC
Last modified on: 06/27/2024 12:15:21 UTC