sigaltstack.c 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. #define _GNU_SOURCE
  3. #include <signal.h>
  4. #include <stdio.h>
  5. #include <stdbool.h>
  6. #include <string.h>
  7. #include <err.h>
  8. #include <errno.h>
  9. #include <limits.h>
  10. #include <sys/mman.h>
  11. #include <sys/auxv.h>
  12. #include <sys/prctl.h>
  13. #include <sys/resource.h>
  14. #include <setjmp.h>
  15. #include "helpers.h"
  16. /* sigaltstack()-enforced minimum stack */
  17. #define ENFORCED_MINSIGSTKSZ 2048
  18. #ifndef AT_MINSIGSTKSZ
  19. # define AT_MINSIGSTKSZ 51
  20. #endif
  21. static int nerrs;
  22. static bool sigalrm_expected;
  23. static unsigned long at_minstack_size;
  24. static int setup_altstack(void *start, unsigned long size)
  25. {
  26. stack_t ss;
  27. memset(&ss, 0, sizeof(ss));
  28. ss.ss_size = size;
  29. ss.ss_sp = start;
  30. return sigaltstack(&ss, NULL);
  31. }
  32. static jmp_buf jmpbuf;
  33. static void sigsegv(int sig, siginfo_t *info, void *ctx_void)
  34. {
  35. if (sigalrm_expected) {
  36. printf("[FAIL]\tWrong signal delivered: SIGSEGV (expected SIGALRM).");
  37. nerrs++;
  38. } else {
  39. printf("[OK]\tSIGSEGV signal delivered.\n");
  40. }
  41. siglongjmp(jmpbuf, 1);
  42. }
  43. static void sigalrm(int sig, siginfo_t *info, void *ctx_void)
  44. {
  45. if (!sigalrm_expected) {
  46. printf("[FAIL]\tWrong signal delivered: SIGALRM (expected SIGSEGV).");
  47. nerrs++;
  48. } else {
  49. printf("[OK]\tSIGALRM signal delivered.\n");
  50. }
  51. }
  52. static void test_sigaltstack(void *altstack, unsigned long size)
  53. {
  54. if (setup_altstack(altstack, size))
  55. err(1, "sigaltstack()");
  56. sigalrm_expected = (size > at_minstack_size) ? true : false;
  57. sethandler(SIGSEGV, sigsegv, 0);
  58. sethandler(SIGALRM, sigalrm, SA_ONSTACK);
  59. if (!sigsetjmp(jmpbuf, 1)) {
  60. printf("[RUN]\tTest an alternate signal stack of %ssufficient size.\n",
  61. sigalrm_expected ? "" : "in");
  62. printf("\tRaise SIGALRM. %s is expected to be delivered.\n",
  63. sigalrm_expected ? "It" : "SIGSEGV");
  64. raise(SIGALRM);
  65. }
  66. clearhandler(SIGALRM);
  67. clearhandler(SIGSEGV);
  68. }
  69. int main(void)
  70. {
  71. void *altstack;
  72. at_minstack_size = getauxval(AT_MINSIGSTKSZ);
  73. altstack = mmap(NULL, at_minstack_size + SIGSTKSZ, PROT_READ | PROT_WRITE,
  74. MAP_PRIVATE | MAP_ANONYMOUS | MAP_STACK, -1, 0);
  75. if (altstack == MAP_FAILED)
  76. err(1, "mmap()");
  77. if ((ENFORCED_MINSIGSTKSZ + 1) < at_minstack_size)
  78. test_sigaltstack(altstack, ENFORCED_MINSIGSTKSZ + 1);
  79. test_sigaltstack(altstack, at_minstack_size + SIGSTKSZ);
  80. return nerrs == 0 ? 0 : 1;
  81. }