In the world of open source tooling, security vulnerabilities can sometimes stay hidden in classic components. Today, let's dig into CVE-2021-32256, a stack-overflow bug discovered in GNU libiberty’s rust-demangle.c—specifically in the demangle_type function, as shipped with GNU Binutils 2.36. This exclusive article breaks down what happened, shows relevant code, and explains the vulnerability in simple, clear terms.
What is GNU libiberty and Why Should You Care?
GNU libiberty is a helper library distributed with GNU Binutils and GCC. It contains numerous utility functions, including code for symbol demangling, which is crucial for debugging in languages like C++ and Rust. The rust-demangle.c file helps with unmangling Rust symbols.
Symbol demangling is usually safe, but if not implemented carefully, it can be used to trigger crashes—sometimes even more serious exploits.
The Vulnerability: Stack Overflow via demangle_type
The main problem resides in the demangle_type function inside rust-demangle.c. This function can be triggered into infinite recursion—eventually overflowing the stack—if crafted input is provided.
Here is a simplified vulnerable code snippet (from original GNU Binutils repository):
static int
demangle_type(struct rust_demangler *rdm)
{
char c = peek(rdm);
switch (c) {
// ... various type cases
case 'P':
advance(rdm);
// * Recursive call, but no depth check! *
if (!demangle_type(rdm))
return ;
break;
// ... other cases
}
return 1;
}
Here, a type with the P prefix leads to a recursive call to demangle_type—but there’s no limit to how deeply this recursion can go!
An attacker can craft a symbol containing a long chain of pointer types (P), like this
_PPPPPPPPPPPPPPPPPPP..._ // (hundreds or thousands of P's)
If this symbol is fed to a tool that calls rust_demangle()—for example, via c++filt or a binutils-based disassembler—it will recursively call demangle_type for each P, no matter how many. Eventually, the stack runs out, causing a stack-overflow and crash.
Sample Exploit Input
rustfilt <<< "_PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP"
Where rustfilt is a tool that uses the vulnerable routine.
What Happens?
An unprivileged user can remotely or locally crash any tool using the affected code by providing maliciously crafted Rust-mangled symbols. This is a denial of service (DoS) vulnerability.
Reported: May 2021
- Patched: See binutils bugzilla #27839
Commit Fix:
- Git diff for fix
- NVD Entry: CVE-2021-32256
The fix limits recursion by tracking depth and failing if the symbol nesting gets too deep.
Patch example
static int
demangle_type(struct rust_demangler *rdm, int depth)
{
if (depth > MAX_DEPTH)
return ;
// ...rest unchanged
case 'P':
advance(rdm);
if (!demangle_type(rdm, depth + 1))
return ;
break;
// ...
}
Try this
# Create a mangled symbol with 10,000 P's
with open("evil.txt", "w") as f:
f.write("_" + "P" * 10000)
# Pipe it into a vulnerable demangler
os.system("cat evil.txt | rustfilt")
Impact Summary
- Who is affected: Anyone using GNU Binutils ≤2.36, or other tools using libiberty's rust-demangle.
What can happen: Crash via crafted input (Denial of Service).
- How to fix: Upgrade Binutils/libiberty or use a package containing the patch.
Follow upstream security notices for your toolchain.
Linux distros have picked up this patch, but double-check yours if you use custom or embedded toolchains.
Further Reading
- CVE-2021-32256 at NVD
- binutils bug report & patch
- GNU Binutils sourceware.org
In Summary
The notorious CVE-2021-32256 is a classic example of how even simple recursive functions, if left unchecked, can create serious security risks. Always validate untrusted inputs and cap recursion in parsers. Stay alerted—sometimes the next exploit hides in the oldest, dustiest corner of your codebase!
Stay safe, keep your toolchains up to date!
*This write-up is exclusive and aims to help engineers, students, and security professionals understand and mitigate such stack vulnerabilities in C/C++ codebases. For hands-on demo or further technical questions, reach out or leave a comment below.*
Timeline
Published on: 07/18/2023 14:15:00 UTC
Last modified on: 08/24/2023 19:15:00 UTC