I am executing my a.out file. After execution the program runs for some time then exits with the message:
**** stack smashing detected ***: ./a.out terminated*
*======= Backtrace: =========*
*/lib/tls/i686/cmov/libc.so.6(__fortify_fail+0x48)Aborted*
What could be the possible reasons for this and how do I rectify it?
It means that you wrote to some variables on the stack in an illegal way, most likely as the result of a Buffer overflow.
You could try to debug the problem using valgrind:
Minimal example with disassembly analysis
a.c:
Compile and run:
fails as desired:
Tested on Ubuntu 16.04, GCC 6.4.0.
Disassembly
Now we look at the disassembly:
which contains:
Notice the handy comments automatically added by
objdump
's artificial intelligence module.If you run this program multiple times through GDB, you will see that:
myfunc
is exactly what modifies the address of the canaryThe canary randomized by setting it with
%fs:0x28
, which contains a random value as explained at:Debug attempts
From now on, we modify the code:
to be instead:
to be more interesting.
We will then try to see if we can pinpoint the culprit
+ 1
call with a method more automated than just reading and understanding the entire source code.gcc -fsanitize=address
If you recompile with this flag and run the program, it outputs:
followed by some more colored output.
This clearly pinpoints the problematic line 12.
Thank Google.
Valgrind SGCheck
As mentioned by others, Valgrind is not good at solving this kind of problem.
It does have an experimental tool called SGCheck:
So I was not very surprised when it did not find the error:
The error message should look like this apparently: Valgrind missing error
GDB
An important observation is that if you run the program through GDB, or examine the
core
file after the fact:then, as we saw on the assembly, GDB should point you to the end of the function that did the canary check:
And therefore the problem is likely in one of the calls that this function made.
Next we try to pinpoint the exact failing call by first single stepping up just after the canary is set:
and watching the address:
Now, this does leaves us at the right offending instruction:
len = 5
andi = 4
, and in this particular case, did point us to the culprit line 12.However, the backtrace is corrupted, and contains some trash. A correct backtrace would look like:
so maybe this could corrupt the stack and prevent you from seeing the trace.
Also, this method requires knowing what is the last call of the canary checking function otherwise you will have false positives, which will not always be feasible, unless you use reverse debugging.