0

Situation - I am using a third party stack. I have a source code of the third party. This code is quite clumsy and a there are a lot of problems related to buffer over-run.

My Solution - In order to trace down this issue, I am overriding the existing functions like sprintf and memcpy to check if there is a buffer overrun.

Here is what I have done so far to override malloc and sprintf.

#define memcpy my_memcpy
void * my_memcpy(void *s1, const void *s2, size_t n)
    {
      void *(*libc_memcpy)(void*,const void*,size_t) = dlsym(RTLD_NEXT, "memcpy");

      return libc_memcpy(s1,s2,n);
    }

Next, I have used sprintf -

#define sprintf  mysprintf

int mysprintf(char *str, const char *format, ...)
{
  va_list args;
  va_start(args, format);
  vsprintf(str,format, args);
  va_end(args);
  return 0;

}

My problem - I want the overridden function to print when the buffer - destination is of less capacity, then what we are writing to it.

I need the solution, which will work for stack allocated memory like char buff[5]; and char *buff = (char *) malloc(5);

So, let's say, when we do memcpy on the buff with the string size 6 bytes, then the overriden memcpy should throw an error. Similarly, when we sprintf, the overriden sprintf should throw an error. The major problem is sprintf. I want to use snprintf rather than sprintf. It's difficult to look into every piece of code and change to snprintf. So, What I want to do here is to override sprintf with my version and internally call snprintf, where I will compute 'n' based on the size of the arg. Also, I will compare if the n is less than buffer size or not. The bottleneck is how to find the size of the buffer based on the pointer passed.

dexterous
  • 6,422
  • 12
  • 51
  • 99
  • It isn't clear to me what your problem is. Your condition in the 'wish' section needs to be more complex: `if (from_malloc(s1) && malloc_usable_size(s1) < n)` (which checks that you're copying to allocated memory). If you've got the data structure sorted, what is the problem? How to convert the value in `s1` into a pointer to a `struct malloc_chunk`? If so, then `((struct malloc_chunk *)((char *)s1 - sizeof(struct malloc_chunk)))->size` should give you the answer (provided `s1` actually points to space allocated by `malloc()` et al). – Jonathan Leffler Sep 28 '15 at 05:46
  • I have just rephrased my question to get better response. – dexterous Sep 28 '15 at 07:27
  • No can do. There is no way for a `memcpy()` surrogate to know how big a stack allocated chunk of memory is. It might be possible to handle it off the heap with support from the `malloc()` library, but to manage stack allocated memory, you'd need compiler support. – Jonathan Leffler Sep 28 '15 at 07:30

1 Answers1

1

Well, the best you could do is to keep track elsewhere of the required size of all blocks allocated through your own copy of malloc, and then have your copies of memcpy and sprintf test if the pointer is one coming from that special allocation function, and then if size is compatible.

You have basically two ways of build such a system:

  • your malloc add 2 * sizeof(int) to the required size, puts a signature in first int, and the required size int second and returns a pointer just after that. Then memcpy and sprintf controls that *(((int *) p) - 2) is the signature and then get usable length in *(((int *) p) - 1). Limit: the signature could be in a wrong place in memory giving false positive, and anyway doing so on a non specially allocated pointer would invoke undefined behaviour, because you could access outside of an array. But it is simple to implement
  • you build a data structure (kind of hash) to store allocated pointers with their sizes. Then memcpy and sprintf look for their pointer in that data struct. No undefined behaviour here, but you have to implement the correct data structure in C

Anyway, both solutions suffer a common flaw: you only test buffer overruns for direct allocated memory - if you allocate a 2D array of char and the buffer overun occurs when doing a sprintf on an element other than first, you will not detect it. Second solution could if you test if a pointer is in the range start - end of an allocated block, but it would be more expensive. And you cannot control stack allocated memory, nor static buffers.

Serge Ballesta
  • 143,923
  • 11
  • 122
  • 252