// { dg-do run } #include #include #include #include #include #include using std::ofstream; using std::ifstream; using std::ios; struct A { A():value(123) {} int value; virtual int access() { return this->value; } }; struct B { B():value(456) {} int value; virtual int access() { return this->value; } }; struct C : public A, public B { C():better_value(789) {} int better_value; virtual int access() { return this->better_value; } }; struct D: public C { D():other_value(987) {} int other_value; virtual int access() { return this->other_value; } }; volatile static int signal_count = 0; sigjmp_buf before_segv; static void handler(int sig, siginfo_t *si, void *unused) { /* printf("Got SIGSEGV at address: 0x%lx\n", (long) si->si_addr); */ signal_count++; /* You are not supposed to longjmp out of a signal handler but it seems to work for this test case and it simplifies it */ siglongjmp(before_segv, 1); /* exit(1); */ } /* Access one of the vtable_map variables generated by this .o */ extern void * _ZN4_VTVI1BE12__vtable_mapE; /* Access one of the vtable_map variables generated by libstdc++ */ extern void * _ZN4_VTVISt8ios_baseE12__vtable_mapE; int use(B *b) { int ret; ret = sigsetjmp(before_segv, 1); if (ret == 0) { /* This should generate a segmentation violation. ie: at this point it should be protected */ _ZN4_VTVI1BE12__vtable_mapE = 0; } assert(ret == 1 && signal_count == 1); ret = sigsetjmp(before_segv, 1); if (ret == 0) { /* Try to modify one of the vtable_map variables in the stdc++ library. This should generate a segmentation violation. ie: at this point it should be protected */ _ZN4_VTVISt8ios_baseE12__vtable_mapE = 0; } assert(ret == 1 && signal_count == 2); return b->access(); } void myread(std::istream * in) { char input_str[50] = "\0"; if (in->good()) (*in) >> input_str; std::cout << input_str << std::endl; delete in; } int main() { ifstream * infile = new ifstream("./thunk_vtable_map_attack.cpp"); myread(infile); /* Set up handler for SIGSEGV. */ struct sigaction sa; sa.sa_flags = SA_SIGINFO; sigemptyset(&sa.sa_mask); sa.sa_sigaction = handler; if (sigaction(SIGSEGV, &sa, NULL) == -1) assert(0); C c; assert(use(&c) == 789); return 0; }