New To Programming? Say Hello To Memory Corruption

By | 01/07/2013

So, we got a crash and that was theoretically and clearly due to stack corruption caused by the local string buffer going out of bound. The local variable ‘aBuf’ in ‘cpyPrint()’ is capable of storing only 6 characters, however the program forces 8 characters(including null character) to it. One can try passing a 6-character string to ‘cpyPrint()’ and re-build/re-run again.

However, if we see, there was no error as such saying the destination buffer was not sufficient, or anything like that. We just see a segmentation fault secretive of anything related to what caused it. A point to observe is, the crash happened even after the copied buffer got printed, precisely at the exit of the method. Hence, the effects are not immediate, just as the stack gets corrupted, rather much later than that.

Imagine, when this buffer overrun happens as a silent bug in a huge code infrastructure. No doubt, that will give anyone a hard time debugging the crash.

Another vital perspective these buffer overruns make the programs vulnerable to many attacks. In fact, there are pretty popular techniques to exploit an elf binary by injecting infectious code. These techniques use the loop holes which are created if there are buffer overflows in the code.

It basically uses the buffer overrun memory to inject the malicious code or a pointer to the address of a malicious function code. This is altogether a different topic, which we shall discuss in a separate article.

Moving on to stack overflows, by which I meant if the process need to use stack memory beyond stack limits, it may lead to stack corruption. One good example is a lot of nested calls where each function variables, parameters and return address are in the form of activation records in the stack. As the function call returns, the activation record memory frees. However, in case of nested function calls, a lot of activation records would be created without freeing them, hence filling up the stack space.

As a basic example, lets try following extensive recursive example.

#include <stdio.h>
int recur(long int var)
{
   if (var > 0)
   {
       recur (var--);
   }

   printf("the var is %ld\n", var);
   return var;
}

int main()
{
   recur (3000);
   return 0;
}

On compiling and running the source on my system, I get

$ gcc -Wall stkoverflow.c -o stkoverflow
$ ./stkoverflow
Segmentation fault (core dumped)

Note that, the value may vary to get a crash from system to system. It depends upon the size of stack available for each process. Here is how one can know the size of stack,

$ulimit -a

Check out what you get on your system, I get the following

core file size          (blocks, -c) unlimited
data seg size           (kbytes, -d) unlimited
scheduling priority             (-e) 20
file size               (blocks, -f) unlimited
pending signals                 (-i) 16382
max locked memory       (kbytes, -l) 64
max memory size         (kbytes, -m) unlimited
open files                      (-n) 1024
pipe size            (512 bytes, -p) 8
POSIX message queues     (bytes, -q) 819200
real-time priority              (-r) 0
stack size              (kbytes, -s) 8192
cpu time               (seconds, -t) unlimited
max user processes              (-u) unlimited
virtual memory          (kbytes, -v) unlimited
file locks                      (-x) unlimited

or to be specific,

$ ulimit -s

The output as expected is

8192

One can even set the stack size as per any special need by,

$ ulimit -s <value>

With gcc, an amazing thing is it comes with the latest stack smashing protector (SSP). We shall learn more about it in the later part.

3. Heap Corruption

Heap corruption is corrupting the heap memory of the process image in the RAM. Since, it is the memory used to dynamic memory allocation, it is caused to memory allocated by ‘malloc()’ method or ‘new’ operator. It is even harder to detect, with following plausible reasons

  • Attempting to write to a memory already freed
  • Attempting to write out of bounds of a dynamically allocated memory
  • Attempting to write to a memory which was never allocated.

As an example, we are writing a code which will try to write to a memory which has already been freed.

#include <stdio.h>
#include <stdlib.h>
int main()
{
   int *pData = NULL;
   int num = 12;
   pData = (int*) malloc (num * sizeof (int));
   //...do stuff use the memory
   free(pData);

   pData[0] = -1;
   pData = (int*) malloc (num * sizeof (int));
   //...do stuff use the memory
   free(pData);
   return 0;
}

On compiling and running, we get a segmentation fault, which is due to heap corruption.

$ gcc -Wall heapcorrupt.c -o heapcorrupt
$ ./heapcorrupt
Segmentation fault (core dumped)

However, one may check the seg fault never happened when we did the write onto the invalid already freed memory.

The most obvious heap corruption is by writing outside the bounds of the allocated memory. However, again it might be hard to detect as the segmentation violation fault will occur at a later point of time, giving no hints about when the corruption took place.

Conclusion

With this part of article, we learned about the various memory corruption ways and some simple debugging techniques to detect and resolve them. However, when the code is huge (involves abundance of arrays, methods and dynamically allocated memories), we have Linux tools available, which leverage detecting the memory corruption and the exact location. We shall discuss what all tools with hands on experience in the next part of the article.

4 thoughts on “New To Programming? Say Hello To Memory Corruption

  1. hackerspace

    The problem you mention here is a problem with the code.

    What does Linux have to do with it ? It’ll be the same in any OS in the world.

    Nothing more than a article bait. I wonder who edits the articles here.

    Reply
    1. Rupali Post author

      Thanks for the comment.
      Well, the purpose of this article is to make the readers understand the memory corruption before we learn about the various tools aiding to tackle it. Memory corruption is a crucial issue during programming on any OS. That does not mean, Linux users need not know it.
      The article still tries to give it a linux flavor by debugging using linux utilities, before we move on to the memory corruption tools in part II

      Hope you like the part II of this article which is http://mylinuxbook.com/debugging-linux-memory-corruption/

      Thanks,

      Reply
  2. dothebart

    You should definitely mention valgrind.org, which is one of the best tools around to detect & fix such corruptions.

    Reply
    1. Rupali Post author

      Thanks for the suggestion.
      Apologize if it wasn’t clear, but the article mentions in the ‘conclusion’ that memory corruption tools will be discussed in the next part.

      The part II which is http://mylinuxbook.com/debugging-linux-memory-corruption/ discusses about a few of the memory corruption detection tools including valgrind.
      Hope you like it.

      Thanks,

      Reply

Leave a Reply

Your email address will not be published. Required fields are marked *