Introduction
The scripts/kconfig/symbol.c file is a critical component of the Linux kernel's build configuration system, responsible for handling Kconfig symbol values that determine which features get compiled into the kernel. A security review uncovered a dangerous pattern at line 728: the sym_set_string_value() function used strcpy() to copy user-provided configuration values directly into a buffer without any bounds checking.
This isn't just a theoretical concern. When processing Kconfig files—whether from make menuconfig, automated build scripts, or configuration imports—an attacker-controlled symbol value longer than the destination buffer could overflow into adjacent memory. For a build system that processes potentially untrusted configuration files, this represents a serious attack vector.
The Vulnerability Explained
The vulnerable code in sym_set_string_value() looked like this:
strcpy(val, newval);
The problem is fundamental to how strcpy() operates: it copies bytes from the source (newval) to the destination (val) until it encounters a null terminator, with zero awareness of the destination buffer's actual size.
Why This Is Dangerous
In the context of Kconfig parsing, newval comes from user input—specifically, string values assigned to configuration symbols. Consider what happens when:
- A user runs
make menuconfigand enters a custom string value - A build script processes a
.configfile with crafted symbol values - An automated system imports configuration from an external source
If any of these sources provides a newval string longer than the val buffer can hold, strcpy() will happily write past the buffer boundary, corrupting whatever data structures or return addresses happen to be adjacent in memory.
Attack Scenario
An attacker could craft a malicious Kconfig file with an oversized symbol value:
CONFIG_CUSTOM_STRING="AAAA....[hundreds of bytes]....AAAA"
When the kernel build system processes this configuration, sym_set_string_value() would attempt to copy this oversized value, overwriting adjacent memory. Depending on the memory layout, this could:
- Corrupt other configuration values, causing silent build misconfigurations
- Overwrite function pointers, potentially enabling code execution
- Crash the build process with a segmentation fault
While this is a local CLI tool (exploitation requires control over input files), build systems often process configurations from version control, CI/CD pipelines, or shared infrastructure—expanding the attack surface significantly.
The Fix
The fix implements two key changes that address both the immediate vulnerability and improve overall memory safety:
Change 1: Replace strcpy() with memcpy()
Before:
strcpy(val, newval);
After:
memcpy(val, newval, strlen(newval) + 1);
By using memcpy() with an explicit length parameter (strlen(newval) + 1 to include the null terminator), the code now has explicit control over exactly how many bytes are copied. This change alone doesn't prevent overflow if val is too small, but it makes the copy operation explicit and auditable.
Change 2: Replace malloc() with calloc()
In the sym_re_search() function, another improvement was made:
Before:
sym_arr = malloc((cnt+1) * sizeof(struct symbol *));
After:
sym_arr = calloc(cnt+1, sizeof(struct symbol *));
This change provides two benefits:
1. Zero-initialization: calloc() initializes allocated memory to zero, preventing information leakage from uninitialized memory
2. Overflow protection: calloc() internally checks for integer overflow when multiplying cnt+1 by sizeof(struct symbol *), which malloc() does not
Why These Changes Matter
The memcpy() change makes the copy operation's behavior explicit and predictable. Combined with proper buffer size validation (which should occur earlier in the call chain), this prevents the unbounded copy that strcpy() would perform.
The calloc() change is a defense-in-depth improvement—even if the array isn't fully populated, any unset pointers will be NULL rather than containing garbage values that could cause undefined behavior.
Prevention & Best Practices
Never Use strcpy() with External Input
The strcpy() function should be considered deprecated for any code handling untrusted input. Safer alternatives include:
| Unsafe Function | Safe Alternative | Notes |
|---|---|---|
strcpy() |
strncpy(), strlcpy() |
Specify maximum length |
sprintf() |
snprintf() |
Prevents buffer overflow |
gets() |
fgets() |
Never use gets() |
strcat() |
strncat() |
Specify remaining space |
Validate Input Lengths Early
Before any copy operation, validate that the source data will fit:
if (strlen(newval) >= sizeof(val)) {
// Handle error: input too long
return false;
}
memcpy(val, newval, strlen(newval) + 1);
Use Static Analysis Tools
Tools like Coverity, Clang Static Analyzer, and Semgrep can automatically flag unsafe function usage:
# Example: Find strcpy usage with Semgrep
semgrep --config "p/c-security-audit" scripts/
Compiler Warnings
Enable compiler warnings that catch buffer overflow risks:
gcc -Wall -Wextra -Wformat-security -D_FORTIFY_SOURCE=2
Key Takeaways
- Never use
strcpy()in Kconfig symbol handling—user-provided configuration values can be arbitrarily long - The
sym_set_string_value()function is a critical security boundary since it processes external input - Replace
malloc()withcalloc()when allocating pointer arrays to prevent uninitialized pointer bugs - Build system code is security-sensitive—attackers can target CI/CD pipelines through malicious configuration files
- Explicit length parameters make code auditable—
memcpy(val, newval, strlen(newval) + 1)clearly shows intent
How Orbis AppSec Detected This
- Source: User-controlled string
newvalparameter passed tosym_set_string_value() - Sink:
strcpy(val, newval)atscripts/kconfig/symbol.c:728 - Missing control: No bounds checking between source length and destination buffer size
- CWE: CWE-120 (Buffer Copy without Checking Size of Input)
- Fix: Replaced unbounded
strcpy()with explicit-lengthmemcpy()and improved memory allocation safety withcalloc()
Orbis AppSec automatically detected this vulnerability and opened a pull request with the fix. Try Orbis AppSec on your repositories to find and fix issues like this automatically.
Conclusion
This buffer overflow in scripts/kconfig/symbol.c demonstrates why C's classic string functions remain a persistent source of security vulnerabilities. The strcpy() function, designed in an era of trusted inputs and limited memory, has no place in modern code that handles external data.
The fix—replacing strcpy() with memcpy() and malloc() with calloc()—represents a minimal, targeted change that eliminates the vulnerability while maintaining the code's functionality. For developers working on C codebases, especially those handling configuration parsing or user input, this pattern should be immediately recognizable and systematically eliminated.
Remember: in security-critical C code, explicit is always better than implicit. Know your buffer sizes, validate your inputs, and never trust strcpy().