tst-longjmp_chk2.c 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. /* Verify longjmp fortify checking does not reject signal stacks. */
  2. #include <assert.h>
  3. #include <setjmp.h>
  4. #include <signal.h>
  5. #include <stdio.h>
  6. #include <stdlib.h>
  7. #include <string.h>
  8. #include <sys/types.h>
  9. #include <sys/time.h>
  10. #include <sys/resource.h>
  11. #include <unistd.h>
  12. #include <support/support.h>
  13. static jmp_buf mainloop;
  14. static sigset_t mainsigset;
  15. static volatile sig_atomic_t pass;
  16. static void
  17. write_indented (const char *str)
  18. {
  19. for (int i = 0; i < pass; ++i)
  20. write_message (" ");
  21. write_message (str);
  22. }
  23. static void
  24. stackoverflow_handler (int sig)
  25. {
  26. stack_t altstack;
  27. /* Sanity check to keep test from looping forever (in case the longjmp
  28. chk code is slightly broken). */
  29. pass++;
  30. sigaltstack (NULL, &altstack);
  31. write_indented ("in signal handler\n");
  32. if (altstack.ss_flags & SS_ONSTACK)
  33. write_indented ("on alternate stack\n");
  34. siglongjmp (mainloop, pass);
  35. }
  36. static volatile int *
  37. recurse_1 (int n, volatile int *p)
  38. {
  39. if (n >= 0)
  40. *recurse_1 (n + 1, p) += n;
  41. return p;
  42. }
  43. static int
  44. recurse (int n)
  45. {
  46. int sum = 0;
  47. return *recurse_1 (n, &sum);
  48. }
  49. static int
  50. do_test (void)
  51. {
  52. char mystack[SIGSTKSZ];
  53. stack_t altstack;
  54. struct sigaction action;
  55. sigset_t emptyset;
  56. /* Before starting the endless recursion, try to be friendly to the user's
  57. machine. On some Linux 2.2.x systems, there is no stack limit for user
  58. processes at all. We don't want to kill such systems. */
  59. struct rlimit rl;
  60. rl.rlim_cur = rl.rlim_max = 0x100000; /* 1 MB */
  61. setrlimit (RLIMIT_STACK, &rl);
  62. /* Install the alternate stack. */
  63. altstack.ss_sp = mystack;
  64. altstack.ss_size = sizeof (mystack);
  65. altstack.ss_flags = 0; /* no SS_DISABLE */
  66. if (sigaltstack (&altstack, NULL) < 0)
  67. {
  68. puts ("first sigaltstack failed");
  69. return 0;
  70. }
  71. /* Install the SIGSEGV handler. */
  72. sigemptyset (&action.sa_mask);
  73. action.sa_handler = &stackoverflow_handler;
  74. action.sa_flags = SA_ONSTACK;
  75. sigaction (SIGSEGV, &action, (struct sigaction *) NULL);
  76. sigaction (SIGBUS, &action, (struct sigaction *) NULL);
  77. /* Save the current signal mask. */
  78. sigemptyset (&emptyset);
  79. sigprocmask (SIG_BLOCK, &emptyset, &mainsigset);
  80. /* Provoke two stack overflows in a row. */
  81. if (sigsetjmp (mainloop, 1) != 0)
  82. {
  83. assert (pass != 0);
  84. printf ("%*sout of signal handler\n", pass, "");
  85. }
  86. else
  87. assert (pass == 0);
  88. sigaltstack (NULL, &altstack);
  89. if (altstack.ss_flags & SS_ONSTACK)
  90. printf ("%*son alternate stack\n", pass, "");
  91. else
  92. printf ("%*snot on alternate stack\n", pass, "");
  93. if (pass < 2)
  94. {
  95. recurse (0);
  96. puts ("recurse call returned");
  97. return 2;
  98. }
  99. altstack.ss_flags |= SS_DISABLE;
  100. if (sigaltstack (&altstack, NULL) == -1)
  101. printf ("disabling alternate stack failed\n");
  102. else
  103. printf ("disabling alternate stack succeeded \n");
  104. /* Restore the signal handlers, in case we trigger a crash after the
  105. tests above. */
  106. signal (SIGBUS, SIG_DFL);
  107. signal (SIGSEGV, SIG_DFL);
  108. return 0;
  109. }
  110. #include <support/test-driver.c>