GCC how to detect stack buffer overflow
Asked Answered
V

4

10

Since there is an option -fstack-protector-strong in gcc to detect stack smashing. However, it can not always detect stack buffer overflow. For the first function func, when I input a 10 char more string, the program does not always crash. My question is where there is a way to detect stack buffer overflow.

void func()
{
    char array[10];
    gets(array);
}

void func2()
{
    char buffer[10];
    int n = sprintf(buffer, "%s", "abcdefghpapeas");
    printf("aaaa [%d], [%s]\n", n, buffer);
}

int main ()
{
   func();
   func2();
}
Voltammeter answered 30/9, 2013 at 10:12 Comment(7)
Why you are tagging the question C++, and then writing code like that?Sohn
wouldn't it be more logical to avoid that in first place? For example, using snprintf(buffer, sizeof(buffer), "%s", ...)Monostylous
It is there to detect if the stack is smashed, not to detect if you overflowed the buffer. Use more characters.Gateway
since it occurs in a legacy code, to minimize the impact of code change, it is better to let the program crash when overflow occursVoltammeter
Do you think there's an undocumented -fstack-protector-strong-but-i-mean-for-real-now option or something?Samba
The stack and a buffer are two completely unrelated things.Urina
@Adam: not quite, because the buffer is allocated on the stack.Barmecide
C
9

Overflows on the stack are either hard to detect or very expensive to detect - chose your poison.

In a nutshell, when you have this:

 char a,b;
 char *ptr=&a;
 ptr[1] = 0;

then this is technically legal: There is space allocated on the stack which belongs to the function. It's just very dangerous.

So the solution might be to add a gap between a and b and fill that with a pattern. But, well, some people actually write code as above. So your compiler needs to detect that.

Alternatively, we could create a bit-map of all bytes that your code has really allocated and then instrument all the code to check against this map. Very safe, pretty slow, bloats your memory usage. On the positive side, there are tools to help with this (like Valgrind).

See where I'm going?

Conclusion: In C, there is no good way to automatically detect many memory problems because the language and the API is often too sloppy. The solution is to move code into helper functions that check their parameters rigorously, always to the right thing and have good unit test coverage.

Always use snprintf() versions of functions if you have a choice. If old code uses the unsafe versions, change it.

Coot answered 30/9, 2013 at 11:49 Comment(2)
The language isn't sloppy, programmers are. :)Internode
The programmers who wrote the language and the libraries were sloppy, which is reflected in the product.Coot
M
2

You can use a tool called Valgrind

http://valgrind.org/

Mathura answered 30/9, 2013 at 11:48 Comment(3)
This is incorrect. Valgrind is a nice tool, but it does not detect stack-based buffer overflows. See here: https://mcmap.net/q/815319/-valgrind-won-39-t-detect-buffer-overflow.Trinee
AddressSanitizer would be a better choice, it's much more precise e.g. can do stack overflows.Chiropteran
Valgrind can detect stack overflows, e.g., stack overflow in thread #1: cant't grow stack... maybe you need debug info.Dodona
C
2

My question is where there is a way to detect stack buffer overflow...

void func()
{
    char array[10];
    gets(array);
}

void func2()
{
    char buffer[10];
    int n = sprintf(buffer, "%s", "abcdefghpapeas");
    printf("aaaa [%d], [%s]\n", n, buffer);
}

Because you are using GCC, you can use FORTIFY_SOURCES.

FORTIFY_SOURCE uses "safer" variants of high risk functions like memcpy, strcpy and gets. The compiler uses the safer variants when it can deduce the destination buffer size. If the copy would exceed the destination buffer size, then the program calls abort(). If the compiler cannot deduce the destination buffer size, then the "safer" variants are not used.

To disable FORTIFY_SOURCE for testing, you should compile the program with -U_FORTIFY_SOURCE or -D_FORTIFY_SOURCE=0.


The C Standard has "safer" functions via ISO/IEC TR 24731-1, Bounds Checking Interfaces. On conforming platforms, you can simply call gets_s and sprintf_s. They offer consistent behavior (like always ensuring a string is NULL terminated) and consistent return values (like 0 on success or an errno_t).

Unfortunately, gcc and glibc does not conform to the C Standard. Ulrich Drepper (one of the glibc maintainers) called bounds checking interfaces "horribly inefficient BSD crap", and they were never added. Hopefully it will change in the future.

Cosmopolite answered 12/9, 2014 at 15:14 Comment(0)
F
0

First of all Do Not Use gets. By now almost everyone knows the all the security and reliability problems that can occur with gets. But it's included here for historical reasons as well because it's a very good example of bad programming.

Let's look at all the problems with the code:

// Really bad code
char line[100];
gets(line);

Because gets does not do bounds checking a string longer than 100 characters will overwrite memory. If you're lucky the program will just crash Or it might exhibit strange behavior.

The gets function is so bad that the GNU gcc linker issues a warning whenever it's used.

/tmp/ccI5WJ5m.o(.text+0x24): In function `main':
: warning: the `gets' function is dangerous and should not be used.

Protect array accesses with assert

C/C++ does not do bound checking.

for example:

int data[10]

i = 20
data[20] = 100 //Memory Corruption

Use the assert function for above code

#include<assert.h>


int data[10];
i=20

assert((i >= 0) && (i < sizeof(data) / sizeof(data[0]))); // throws 

data[i] = 100

Array overflows are one of the most common programming errors and are extremely frustrating to try and locate. This code doesn't eliminate them, but it does cause buggy code to abort early in a way that makes the problem tremendously easier to find.

And use snprintf(buffer, sizeof(buffer), "%s", "abcdefghpapeas") and some tools like valgrind or GDB.

Hope this helps you..

Ferbam answered 12/9, 2014 at 15:55 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.