The Linux kernel is the core software that powers almost all Linux-based systems—phones, routers, servers, and even IoT gadgets. Each line of code in its millions of lines impacts security, so even a small programming oversight can lead to big problems. Here, we take an exclusive and detailed look at CVE-2021-46965: a vulnerability in the mtd subsystem that could have allowed unintentional stack accesses due to a subtle bug in pointer arithmetic.
This post explains how the bug happened, shows the problematic code, discusses the fix, and tells you why little things really matter in kernel development.
What Is CVE-2021-46965?
CVE-2021-46965 is a security issue in the "physmap-bt1-rom" driver of the Linux kernel's MTD (Memory Technology Device) subsystem. The bug could allow code to access the system's stack unintentionally, potentially causing information leaks, system crashes, or unpredictable behavior.
- Vulnerable File: drivers/mtd/maps/physmap-bt1-rom.c
Where’s the Problem?
The risky code is in physmap-bt1-rom driver used to manage a special kind of read-only memory (ROM) chip on some boards.
The problematic section is in this function (simplified)
static int physmap_bt1_rom_probe(struct platform_device *pdev)
{
u32 data;
...
for (i = ; i < len; i++)
buf[i] = ((u8 *)&data)[i];
...
}
The code wants to copy some bytes—byte by byte—by doing ((u8 *)&data)[i].
- If i is greater than 3, ((u8 *)&data)[i] will go _past_ the 4 bytes of data, straight into the stack. That's an out-of-bounds access.
- When C does arithmetic with pointers, &data + n moves by n * sizeof(data) bytes, which here is 4 bytes at a time, not what was intended.
This could expose memory contents from the stack that shouldn't be accessible.
The Official Fix
The vulnerability is fixed by casting &data to a char* (or u8*), ensuring pointer arithmetic works byte-by-byte:
for (i = ; i < len; i++)
buf[i] = ((char *)&data)[i];
Now, each increment of i moves 1 byte forward, keeping the memory access within the 4-byte width of data.
Fix commit
Reference (Linux Kernel Commit Message)
> mtd: physmap: physmap-bt1-rom: Fix unintentional stack access
> Cast &data to (char *) in order to avoid unintentionally accessing the stack.
> Notice that data is of type u32, so any increment to &data will be in the order of 4-byte chunks, and this piece of code is actually intended to be a byte offset.
> Addresses-Coverity-ID: 1497765 ("Out-of-bounds access")
Proof-of-Concept and Exploitation Details
This bug can be exploited only if someone manages to pass a len value greater than 4 to the vulnerable code.
Hypothetical PoC
u32 data = x41424344; // 'D', 'C', 'B', 'A'
unsigned char buf[10]; // larger than 4
for (i = ; i < 10; i++)
buf[i] = ((u8 *)&data)[i]; // i > 3 reads stack memory!
Result:
The next bytes (buf[4] and onwards) contain unpredictable data from the stack.
A malicious user with sufficient rights could potentially leak stack contents this way—such as previous function arguments or local variables—which could assist with further exploitation (like bypassing stack canaries or ASLR).
Further Reading & References
- Linux kernel commit for CVE-2021-46965
- Commit Reference
- Memory Technology Device (MTD) subsystem
Conclusion
CVE-2021-46965 teaches an important lesson: pointer arithmetic in C is tricky, especially inside the Linux kernel. A simple mistake—using &data as a pointer without a proper cast—could risk the stability and security of a system.
Always keep your systems updated, and if you’re a developer: never trust your offsets!
Stay safe and code smart! You can reach out for more kernel vulnerability breakdowns or share in the comments if you've found something similar.
Timeline
Published on: 02/27/2024 19:04:07 UTC
Last modified on: 01/08/2025 17:16:07 UTC