The stack is frequently used for convenient temporary storage, because allocated memory is automatically freed when the function returns. Generally, the operating system will grow the stack as needed. However, this can fail due to a lack of memory or collision with other allocated areas of the address space (depending on the architecture). When this occurs, the operating system may terminate the program abnormally. If user input is able to This condition can be exploited to cause a denial-of-service attack in cases where an attacker can control or influence the amount of stack memory allocated, then an attacker could use this in a denial-of-service attack.
Non-Compliant Code Example
C99 includes support for variable length arrays. If the value used for the length of the array is influenced by user inputarray length is derived from an untrusted data source, an attacker could cause the program to use a large number of stack pages, possibly resulting in the process being killed due to lack of memory, or simply cause the stack pointer to point to a different region of memory. The latter could be used to write to an arbitrary memory location.to perform an excessive allocation on the stack.
This The following non-compliant code copies a file. It allocates a buffer of user-defined size on the stack to temporarily store data read from the source fileexample temporarily stores data read from a source file into a buffer. The buffer is allocated on the stack as a variable length array of size bufsize
.
Code Block | ||
---|---|---|
| ||
int copy_file(FILE *src, FILE *dst, size_t bufsize) { char buf[bufsize]; while (fgets(buf, bufsize, src)) { fputs(buf, dst); } return 0; } |
If the size of the buffer is not constrained, a malicious user could specify a buffer of several gigabytes which might cause a crash. If the architecture is set up in a way that the heap exists "below" the stack in memory, a buffer exactly long enough to place the stack pointer into the heap could be used to overwrite memory there with what fputs()
and fgets()
store on the stack bufsize
can be controlled by a malicious user, this code could be exploited to cause a denial-of-service attack.
Compliant Solution
This compliant solution replaces the dynamic variable length array with a call to malloc()
. A If malloc()
failure should not cause a program to terminate abnormally, and fails, the return value of malloc()
can be checked for success to see if it is safe to continueto prevent the program from terminating abnormally.
Code Block | ||
---|---|---|
| ||
int copy_file(FILE *src, FILE *dst, size_t bufsize) { char *buf = malloc(bufsize); if (!buf) { return -1; } while (fgets(buf, bufsize, src)) { fputs(buf, dst); } return 0; } |
Non-Compliant Code Example
Using recursion Recursion can also lead to large stack allocations. It needs to be ensured that functions which are recursive do not recurse so deep that the stack grows too large.Recursive functions must ensures they they do not exhaust the stack due to excessive recursions.
This non-compliant The following implementation of the Fibonacci function uses recursion.
...
Stack overflow caused by excessive stack allocations or recursion could lead to abnormal termination and denial-of-service attacks.
use a large number of stack pages, possibly resulting in the process being killed due to lack of memory, or simply cause the stack pointer to point to a different region of memory. The latter could be used to write to an arbitrary memory location.
Recommendation | Severity | Likelihood | Remediation Cost | Priority | Level |
---|---|---|---|---|---|
MEM05-A | 1 (low) | 1 (unlikely) | 2 (medium) | P2 | L3 |
...