stack_expansion_signal.c 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Test that signal delivery is able to expand the stack segment without
  4. * triggering a SEGV.
  5. *
  6. * Based on test code by Tom Lane.
  7. */
  8. #include <err.h>
  9. #include <stdio.h>
  10. #include <stdlib.h>
  11. #include <signal.h>
  12. #include <sys/types.h>
  13. #include <unistd.h>
  14. #include "../pmu/lib.h"
  15. #include "utils.h"
  16. #define _KB (1024)
  17. #define _MB (1024 * 1024)
  18. static char *stack_base_ptr;
  19. static char *stack_top_ptr;
  20. static volatile sig_atomic_t sig_occurred = 0;
  21. static void sigusr1_handler(int signal_arg)
  22. {
  23. sig_occurred = 1;
  24. }
  25. static int consume_stack(unsigned int stack_size, union pipe write_pipe)
  26. {
  27. char stack_cur;
  28. if ((stack_base_ptr - &stack_cur) < stack_size)
  29. return consume_stack(stack_size, write_pipe);
  30. else {
  31. stack_top_ptr = &stack_cur;
  32. FAIL_IF(notify_parent(write_pipe));
  33. while (!sig_occurred)
  34. barrier();
  35. }
  36. return 0;
  37. }
  38. static int child(unsigned int stack_size, union pipe write_pipe)
  39. {
  40. struct sigaction act;
  41. char stack_base;
  42. act.sa_handler = sigusr1_handler;
  43. sigemptyset(&act.sa_mask);
  44. act.sa_flags = 0;
  45. if (sigaction(SIGUSR1, &act, NULL) < 0)
  46. err(1, "sigaction");
  47. stack_base_ptr = (char *) (((size_t) &stack_base + 65535) & ~65535UL);
  48. FAIL_IF(consume_stack(stack_size, write_pipe));
  49. printf("size 0x%06x: OK, stack base %p top %p (%zx used)\n",
  50. stack_size, stack_base_ptr, stack_top_ptr,
  51. stack_base_ptr - stack_top_ptr);
  52. return 0;
  53. }
  54. static int test_one_size(unsigned int stack_size)
  55. {
  56. union pipe read_pipe, write_pipe;
  57. pid_t pid;
  58. FAIL_IF(pipe(read_pipe.fds) == -1);
  59. FAIL_IF(pipe(write_pipe.fds) == -1);
  60. pid = fork();
  61. if (pid == 0) {
  62. close(read_pipe.read_fd);
  63. close(write_pipe.write_fd);
  64. exit(child(stack_size, read_pipe));
  65. }
  66. close(read_pipe.write_fd);
  67. close(write_pipe.read_fd);
  68. FAIL_IF(sync_with_child(read_pipe, write_pipe));
  69. kill(pid, SIGUSR1);
  70. FAIL_IF(wait_for_child(pid));
  71. close(read_pipe.read_fd);
  72. close(write_pipe.write_fd);
  73. return 0;
  74. }
  75. int test(void)
  76. {
  77. unsigned int i, size;
  78. // Test with used stack from 1MB - 64K to 1MB + 64K
  79. // Increment by 64 to get more coverage of odd sizes
  80. for (i = 0; i < (128 * _KB); i += 64) {
  81. size = i + (1 * _MB) - (64 * _KB);
  82. FAIL_IF(test_one_size(size));
  83. }
  84. return 0;
  85. }
  86. int main(void)
  87. {
  88. return test_harness(test, "stack_expansion_signal");
  89. }