tm-signal-stack.c 1.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Copyright 2015, Michael Neuling, IBM Corp.
  4. *
  5. * Test the kernel's signal delievery code to ensure that we don't
  6. * trelaim twice in the kernel signal delivery code. This can happen
  7. * if we trigger a signal when in a transaction and the stack pointer
  8. * is bogus.
  9. *
  10. * This test case registers a SEGV handler, sets the stack pointer
  11. * (r1) to NULL, starts a transaction and then generates a SEGV. The
  12. * SEGV should be handled but we exit here as the stack pointer is
  13. * invalid and hance we can't sigreturn. We only need to check that
  14. * this flow doesn't crash the kernel.
  15. */
  16. #include <unistd.h>
  17. #include <sys/types.h>
  18. #include <sys/wait.h>
  19. #include <stdlib.h>
  20. #include <stdio.h>
  21. #include <signal.h>
  22. #include "utils.h"
  23. #include "tm.h"
  24. void signal_segv(int signum)
  25. {
  26. /* This should never actually run since stack is foobar */
  27. exit(1);
  28. }
  29. int tm_signal_stack()
  30. {
  31. int pid;
  32. SKIP_IF(!have_htm());
  33. SKIP_IF(htm_is_synthetic());
  34. pid = fork();
  35. if (pid < 0)
  36. exit(1);
  37. if (pid) { /* Parent */
  38. /*
  39. * It's likely the whole machine will crash here so if
  40. * the child ever exits, we are good.
  41. */
  42. wait(NULL);
  43. return 0;
  44. }
  45. /*
  46. * The flow here is:
  47. * 1) register a signal handler (so signal delievery occurs)
  48. * 2) make stack pointer (r1) = NULL
  49. * 3) start transaction
  50. * 4) cause segv
  51. */
  52. if (signal(SIGSEGV, signal_segv) == SIG_ERR)
  53. exit(1);
  54. asm volatile("li 1, 0 ;" /* stack ptr == NULL */
  55. "1:"
  56. "tbegin.;"
  57. "beq 1b ;" /* retry forever */
  58. "tsuspend.;"
  59. "ld 2, 0(1) ;" /* trigger segv" */
  60. : : : "memory");
  61. /* This should never get here due to above segv */
  62. return 1;
  63. }
  64. int main(void)
  65. {
  66. return test_harness(tm_signal_stack, "tm_signal_stack");
  67. }