1// { dg-do run } 2 3#include <assert.h> 4#include <signal.h> 5#include <setjmp.h> 6#include <stdio.h> 7 8#include <iostream> 9#include <fstream> 10 11using std::ofstream; 12using std::ifstream; 13using std::ios; 14 15struct A { 16 A():value(123) {} 17 int value; 18 virtual int access() { return this->value; } 19}; 20struct B { 21 B():value(456) {} 22 int value; 23 virtual int access() { return this->value; } 24}; 25struct C : public A, public B { 26 C():better_value(789) {} 27 int better_value; 28 virtual int access() { return this->better_value; } 29}; 30struct D: public C { 31 D():other_value(987) {} 32 int other_value; 33 virtual int access() { return this->other_value; } 34}; 35 36volatile static int signal_count = 0; 37 38sigjmp_buf before_segv; 39 40static void 41handler(int sig, siginfo_t *si, void *unused) 42{ 43 /* 44 printf("Got SIGSEGV at address: 0x%lx\n", 45 (long) si->si_addr); 46 */ 47 48 signal_count++; 49 /* You are not supposed to longjmp out of a signal handler but it seems 50 to work for this test case and it simplifies it */ 51 siglongjmp(before_segv, 1); 52 /* exit(1); */ 53} 54 55/* Access one of the vtable_map variables generated by this .o */ 56extern void * _ZN4_VTVI1BE12__vtable_mapE; 57 58/* Access one of the vtable_map variables generated by libstdc++ */ 59extern void * _ZN4_VTVISt8ios_baseE12__vtable_mapE; 60 61int use(B *b) 62{ 63 int ret; 64 65 ret = sigsetjmp(before_segv, 1); 66 if (ret == 0) 67 { 68 /* This should generate a segmentation violation. ie: at this point it should 69 be protected */ 70 _ZN4_VTVI1BE12__vtable_mapE = 0; 71 } 72 assert(ret == 1 && signal_count == 1); 73 74 ret = sigsetjmp(before_segv, 1); 75 if (ret == 0) 76 { 77 /* Try to modify one of the vtable_map variables in the stdc++ library. 78 This should generate a segmentation violation. ie: at this point it 79 should be protected */ 80 _ZN4_VTVISt8ios_baseE12__vtable_mapE = 0; 81 } 82 assert(ret == 1 && signal_count == 2); 83 84 return b->access(); 85} 86 87void myread(std::istream * in) 88{ 89 char input_str[50] = "\0"; 90 if (in->good()) 91 (*in) >> input_str; 92 std::cout << input_str << std::endl; 93 delete in; 94} 95 96int main() 97{ 98 ifstream * infile = new ifstream("./thunk_vtable_map_attack.cpp"); 99 myread(infile); 100 101 /* Set up handler for SIGSEGV. */ 102 struct sigaction sa; 103 sa.sa_flags = SA_SIGINFO; 104 sigemptyset(&sa.sa_mask); 105 sa.sa_sigaction = handler; 106 if (sigaction(SIGSEGV, &sa, NULL) == -1) 107 assert(0); 108 109 C c; 110 assert(use(&c) == 789); 111 112 return 0; 113} 114