简体   繁体   中英

Stack smashing not fires. Why?

I'm trying to make glibc detect stack smashing, and I use the following code:

 #include <stdio.h>
 #include <string.h>

 static const int n = 5;

 int main(int argc, char *argv[])
 {
  if (argc != 2)
  {
     printf("usage: %s string\n", argv[0]);
     return -1;
  }
  printf("%s, len = %d\n", argv[1], strlen(argv[1]));
  unsigned char a[n][n];
  unsigned char * b = a[n - 1];
  memcpy(b, argv[1], (strlen(argv[1]) + 1) * sizeof(unsigned char));
  return 0;
 }

If argv[1] length greater than 5, I expect detection of stack smashing error, however, I do not, and valgrind detects no errors. What I should change to get this error? (array a must be two-dimensional)

By default, GCC only adds code to detect stack smashing when you do something particularly dangerous like alloca (or gets , as you mention in a comment), or declare a large automatic array.

If you want to enable protection for all functions, use the -fstack-protector-all option. You can also request a warning about unprotected functions with -Wstack-protector .

It seems like the logic in gcc which decides when to enable stack protection is slightly tricky. First note from the docs:

-fstack-protector

Emit extra code to check for buffer overflows, such as stack smashing attacks. This is done by adding a guard variable to functions with vulnerable objects. This includes functions that call alloca, and functions with buffers larger than 8 bytes . The guards are initialized when a function is entered and then checked when the function exits. If a guard check fails, an error message is printed and the program exits

So, we should expect a function with local buffers smaller than 8 bytes to be unprotected. For example, this:

int unprotected() {
    char a[5];
    strcpy(a, "this is much too long");
    return a[0];
}

compiled with gcc -fstack-protector -Wstack-protector , gives a warning like

warning: stack protector not protecting function: all local arrays are less than 8 bytes long [-Wstack-protector]

So, you might think your char[5][5] will be protected, since it is more than 8 bytes long. However, when I compile that to assembler, I get no warning or stack protection (you can find the assembler to look for in this Dr. Dobbs article ). It seems that gcc treats it as 5 buffers of 5 bytes each instead of a single buffer of 25 bytes.

You can persuade gcc to enable stack protection either by showing it a single buffer larger than 8 bytes:

void protected(char *arg) {
    union {
        char dummy[5 * 5];
        char a[5][5];
    } u;
    memcpy(u.a[4], arg, (strlen(arg) + 1));
}

or by simply using -fstack-protector-all .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM