panda-re / lava

LAVA: Large-scale Automated Vulnerability Addition
Other
371 stars 60 forks source link

Function Pointers and Dataflow #15

Open AndrewFasano opened 5 years ago

AndrewFasano commented 5 years ago

Injecting the data_flow argument into function definitions and declarations currently can generate code that will cause crashes due to function pointers. Here are a few possible scenarios.

Scenario 1

Only one function can ever be assigned the function pointer

int inc(int arg) {
     return arg+1;
}

int main() {
    int (*fn)(int);
    fn = inc;
    return fn(1);
}

Here inc is safe to instrument, so we can rewrite both it and fn to add data_flow and everything should continue to work:

int inc(int *data_flow, int arg) {
     return arg+1;
}

int main() {
    // [Some code to initialize data_flow]
    int (*fn)(int*, int);
    fn = inc;
    return fn(data_flow, 1);
}

Scenario 2

Two functions can be assigned to a function pointer, only one can be instrumented

#include <stdlib.h>
#include <stdio.h>

// Custom 'allocator' function used instead of
// malloc, but only sometimes
void *my_allocator(int size) {
     return malloc(4);
}

int main(int argc, char* argv[]) {
    void* (*allocator)(int);
    int i;
    int allocsize = 64;

    // When given an argument, use my_allocator
    // instead of malloc
    if (argc >1) {
        allocator = my_allocator;
    } else {
        allocator = (void*)malloc;
    }

    // Allocate a buffer
    char *a = (char*)allocator(allocsize);

    // Set values in buffer
    for (i=0;i<allocsize;i++){
        a[i] = 0xff;
    }

    // Print buffer
    for (i=0;i<allocsize;i++){
        printf("%02x", a[i]);
    }
    printf("\n");
}

Since we can't instrument malloc, we can't change the signature of allocator. Since allocator can't be changed, we can't instrument my_allocator. Thus we can't add data_flow to anything here.

Possible Solutions

  1. Refuse to instrument any function that is ever assigned to a function pointer
  2. Use blacklist to config files where a user can specify functions that should not be instrumented. Code to do this is has been around since 931795e340189f40005962b5790ff679d24917ae, but it might be broken though.
  3. Analyze which functions can possible be assigned to a function pointer. If any of the functions cannot be instrumented, instrument none of them. Otherwise, instrument all of them.

@tleek Do you have anything else to say about the problem or thoughts on how to approach this?