thunk_vtable_map_attack.cc 2.4 KB

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