vdso_restorer.c 2.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. /*
  2. * vdso_restorer.c - tests vDSO-based signal restore
  3. * Copyright (c) 2015 Andrew Lutomirski
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms and conditions of the GNU General Public License,
  7. * version 2, as published by the Free Software Foundation.
  8. *
  9. * This program is distributed in the hope it will be useful, but
  10. * WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12. * General Public License for more details.
  13. *
  14. * This makes sure that sa_restorer == NULL keeps working on 32-bit
  15. * configurations. Modern glibc doesn't use it under any circumstances,
  16. * so it's easy to overlook breakage.
  17. *
  18. * 64-bit userspace has never supported sa_restorer == NULL, so this is
  19. * 32-bit only.
  20. */
  21. #define _GNU_SOURCE
  22. #include <err.h>
  23. #include <stdio.h>
  24. #include <string.h>
  25. #include <signal.h>
  26. #include <unistd.h>
  27. #include <syscall.h>
  28. #include <sys/syscall.h>
  29. /* Open-code this -- the headers are too messy to easily use them. */
  30. struct real_sigaction {
  31. void *handler;
  32. unsigned long flags;
  33. void *restorer;
  34. unsigned int mask[2];
  35. };
  36. static volatile sig_atomic_t handler_called;
  37. static void handler_with_siginfo(int sig, siginfo_t *info, void *ctx_void)
  38. {
  39. handler_called = 1;
  40. }
  41. static void handler_without_siginfo(int sig)
  42. {
  43. handler_called = 1;
  44. }
  45. int main()
  46. {
  47. int nerrs = 0;
  48. struct real_sigaction sa;
  49. memset(&sa, 0, sizeof(sa));
  50. sa.handler = handler_with_siginfo;
  51. sa.flags = SA_SIGINFO;
  52. sa.restorer = NULL; /* request kernel-provided restorer */
  53. if (syscall(SYS_rt_sigaction, SIGUSR1, &sa, NULL, 8) != 0)
  54. err(1, "raw rt_sigaction syscall");
  55. raise(SIGUSR1);
  56. if (handler_called) {
  57. printf("[OK]\tSA_SIGINFO handler returned successfully\n");
  58. } else {
  59. printf("[FAIL]\tSA_SIGINFO handler was not called\n");
  60. nerrs++;
  61. }
  62. sa.flags = 0;
  63. sa.handler = handler_without_siginfo;
  64. if (syscall(SYS_sigaction, SIGUSR1, &sa, 0) != 0)
  65. err(1, "raw sigaction syscall");
  66. handler_called = 0;
  67. raise(SIGUSR1);
  68. if (handler_called) {
  69. printf("[OK]\t!SA_SIGINFO handler returned successfully\n");
  70. } else {
  71. printf("[FAIL]\t!SA_SIGINFO handler was not called\n");
  72. nerrs++;
  73. }
  74. }