vdso_restorer.c 2.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * vdso_restorer.c - tests vDSO-based signal restore
  4. * Copyright (c) 2015 Andrew Lutomirski
  5. *
  6. * This makes sure that sa_restorer == NULL keeps working on 32-bit
  7. * configurations. Modern glibc doesn't use it under any circumstances,
  8. * so it's easy to overlook breakage.
  9. *
  10. * 64-bit userspace has never supported sa_restorer == NULL, so this is
  11. * 32-bit only.
  12. */
  13. #define _GNU_SOURCE
  14. #include <err.h>
  15. #include <stdio.h>
  16. #include <dlfcn.h>
  17. #include <string.h>
  18. #include <signal.h>
  19. #include <unistd.h>
  20. #include <syscall.h>
  21. #include <sys/syscall.h>
  22. /* Open-code this -- the headers are too messy to easily use them. */
  23. struct real_sigaction {
  24. void *handler;
  25. unsigned long flags;
  26. void *restorer;
  27. unsigned int mask[2];
  28. };
  29. static volatile sig_atomic_t handler_called;
  30. static void handler_with_siginfo(int sig, siginfo_t *info, void *ctx_void)
  31. {
  32. handler_called = 1;
  33. }
  34. static void handler_without_siginfo(int sig)
  35. {
  36. handler_called = 1;
  37. }
  38. int main()
  39. {
  40. int nerrs = 0;
  41. struct real_sigaction sa;
  42. void *vdso = dlopen("linux-vdso.so.1",
  43. RTLD_LAZY | RTLD_LOCAL | RTLD_NOLOAD);
  44. if (!vdso)
  45. vdso = dlopen("linux-gate.so.1",
  46. RTLD_LAZY | RTLD_LOCAL | RTLD_NOLOAD);
  47. if (!vdso) {
  48. printf("[SKIP]\tFailed to find vDSO. Tests are not expected to work.\n");
  49. return 0;
  50. }
  51. memset(&sa, 0, sizeof(sa));
  52. sa.handler = handler_with_siginfo;
  53. sa.flags = SA_SIGINFO;
  54. sa.restorer = NULL; /* request kernel-provided restorer */
  55. printf("[RUN]\tRaise a signal, SA_SIGINFO, sa.restorer == NULL\n");
  56. if (syscall(SYS_rt_sigaction, SIGUSR1, &sa, NULL, 8) != 0)
  57. err(1, "raw rt_sigaction syscall");
  58. raise(SIGUSR1);
  59. if (handler_called) {
  60. printf("[OK]\tSA_SIGINFO handler returned successfully\n");
  61. } else {
  62. printf("[FAIL]\tSA_SIGINFO handler was not called\n");
  63. nerrs++;
  64. }
  65. printf("[RUN]\tRaise a signal, !SA_SIGINFO, sa.restorer == NULL\n");
  66. sa.flags = 0;
  67. sa.handler = handler_without_siginfo;
  68. if (syscall(SYS_sigaction, SIGUSR1, &sa, 0) != 0)
  69. err(1, "raw sigaction syscall");
  70. handler_called = 0;
  71. raise(SIGUSR1);
  72. if (handler_called) {
  73. printf("[OK]\t!SA_SIGINFO handler returned successfully\n");
  74. } else {
  75. printf("[FAIL]\t!SA_SIGINFO handler was not called\n");
  76. nerrs++;
  77. }
  78. return nerrs;
  79. }