llvm / llvm-project

The LLVM Project is a collection of modular and reusable compiler and toolchain technologies.
http://llvm.org
Other
29.1k stars 12.01k forks source link

[CodeGen] Improving the buffer overflow detection ability #81653

Open vojkan99 opened 9 months ago

vojkan99 commented 9 months ago

Currently, LLVM's ability to detect buffer overflows is based on two things:

There are a lot of cases which are not covered by the -Wfortify-source warning and the run time error only happens when FORTIFY_SOURCE concept is enabled with the -D_FORTIFY_SOURCE={1, 2, 3} flag (even then not all cases are caught). Therefore, there is room for improvement regarding the detection of buffer overflows.

This issue proposes the addition of a new LLVM CodeGen pass which would attempt to detect buffer overflows in calls to memcpy/memmove/memset/strncpy/bcopy/bzero functions at compile time and issue appropriate warnings/errors if successfull. This should be an improvement on both of the already existing ways to detect buffer overflows as it does the warning/error generation in compile time (better than at run time) and it covers some cases which -Wfortify-source does not. One of those cases is given in the example below which contains a buffer overflow (memcpy.c).

#include <string.h>

#define STATIC_BUF_SIZE 10

char th_dst[STATIC_BUF_SIZE];            /* Destination buffer */
char th_src[STATIC_BUF_SIZE];            /* Source buffer */

int main() {
  int size = STATIC_BUF_SIZE + 1;

  bzero(th_dst, STATIC_BUF_SIZE);
  for (int i = 0; i < STATIC_BUF_SIZE; i++)
    th_src[i] = (unsigned char)(i + 1);

  memcpy(th_dst, th_src, size);

  return 0;
}

Compiling this test case into executable and its execution looks like this:

bash-4.4$ clang -O2 memcpy.c -o a.out // no compile-time warning bash-4.4$ ./a.out bash-4.4$

If -D_FORTIFY_SOURCE=2 option is also specified, there will be a run time error which is:

buffer overflow detected : terminated Aborted (core dumped)

Note that the overflow is either not caught (without FORTIFY_SOURCE) or caught at run time only (with FORTIFY_SOURCE). However, in this case, we should be able to detect it at compile time as both the length and size of the destination pointer is known at compile time, when compiled with optimizations.

I implemented a pass as discussed above and can now report a compile time warning for mentioned test case:

bash-4.4$ clang -O2 memcpy.c -o a.out warning: 'llvm.memcpy.p0i8.p0i8.i64' writing 11 bytes into a region of size 10 bytes (80 bits) overflows the destination

Note that the warning message is not the same as the warnings issued by Clang, for example, as the optimizer lacks the proper infrastructure to generate warnings (at least to my knowledge). This can definitely be further improved.

Detecting such issues at compile time (even if not enabled by default) would be greatly desirable rather than at run time. If this is agreeable, I would be interested in working more on a patch which improves buffer overflow detection at compile time.

nikic commented 9 months ago

We do not allow warnings to be emitting during optimization as a matter of policy. There are some exceptions, but they don't apply here.