tm-signal-pagefault.c 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Copyright 2020, Gustavo Luiz Duarte, IBM Corp.
  4. *
  5. * This test starts a transaction and triggers a signal, forcing a pagefault to
  6. * happen when the kernel signal handling code touches the user signal stack.
  7. *
  8. * In order to avoid pre-faulting the signal stack memory and to force the
  9. * pagefault to happen precisely in the kernel signal handling code, the
  10. * pagefault handling is done in userspace using the userfaultfd facility.
  11. *
  12. * Further pagefaults are triggered by crafting the signal handler's ucontext
  13. * to point to additional memory regions managed by the userfaultfd, so using
  14. * the same mechanism used to avoid pre-faulting the signal stack memory.
  15. *
  16. * On failure (bug is present) kernel crashes or never returns control back to
  17. * userspace. If bug is not present, tests completes almost immediately.
  18. */
  19. #include <stdio.h>
  20. #include <stdlib.h>
  21. #include <string.h>
  22. #include <linux/userfaultfd.h>
  23. #include <poll.h>
  24. #include <unistd.h>
  25. #include <sys/ioctl.h>
  26. #include <sys/syscall.h>
  27. #include <fcntl.h>
  28. #include <sys/mman.h>
  29. #include <pthread.h>
  30. #include <signal.h>
  31. #include <errno.h>
  32. #include "tm.h"
  33. #define UF_MEM_SIZE 655360 /* 10 x 64k pages */
  34. /* Memory handled by userfaultfd */
  35. static char *uf_mem;
  36. static size_t uf_mem_offset = 0;
  37. /*
  38. * Data that will be copied into the faulting pages (instead of zero-filled
  39. * pages). This is used to make the test more reliable and avoid segfaulting
  40. * when we return from the signal handler. Since we are making the signal
  41. * handler's ucontext point to newly allocated memory, when that memory is
  42. * paged-in it will contain the expected content.
  43. */
  44. static char backing_mem[UF_MEM_SIZE];
  45. static size_t pagesize;
  46. /*
  47. * Return a chunk of at least 'size' bytes of memory that will be handled by
  48. * userfaultfd. If 'backing_data' is not NULL, its content will be save to
  49. * 'backing_mem' and then copied into the faulting pages when the page fault
  50. * is handled.
  51. */
  52. void *get_uf_mem(size_t size, void *backing_data)
  53. {
  54. void *ret;
  55. if (uf_mem_offset + size > UF_MEM_SIZE) {
  56. fprintf(stderr, "Requesting more uf_mem than expected!\n");
  57. exit(EXIT_FAILURE);
  58. }
  59. ret = &uf_mem[uf_mem_offset];
  60. /* Save the data that will be copied into the faulting page */
  61. if (backing_data != NULL)
  62. memcpy(&backing_mem[uf_mem_offset], backing_data, size);
  63. /* Reserve the requested amount of uf_mem */
  64. uf_mem_offset += size;
  65. /* Keep uf_mem_offset aligned to the page size (round up) */
  66. uf_mem_offset = (uf_mem_offset + pagesize - 1) & ~(pagesize - 1);
  67. return ret;
  68. }
  69. void *fault_handler_thread(void *arg)
  70. {
  71. struct uffd_msg msg; /* Data read from userfaultfd */
  72. long uffd; /* userfaultfd file descriptor */
  73. struct uffdio_copy uffdio_copy;
  74. struct pollfd pollfd;
  75. ssize_t nread, offset;
  76. uffd = (long) arg;
  77. for (;;) {
  78. pollfd.fd = uffd;
  79. pollfd.events = POLLIN;
  80. if (poll(&pollfd, 1, -1) == -1) {
  81. perror("poll() failed");
  82. exit(EXIT_FAILURE);
  83. }
  84. nread = read(uffd, &msg, sizeof(msg));
  85. if (nread == 0) {
  86. fprintf(stderr, "read(): EOF on userfaultfd\n");
  87. exit(EXIT_FAILURE);
  88. }
  89. if (nread == -1) {
  90. perror("read() failed");
  91. exit(EXIT_FAILURE);
  92. }
  93. /* We expect only one kind of event */
  94. if (msg.event != UFFD_EVENT_PAGEFAULT) {
  95. fprintf(stderr, "Unexpected event on userfaultfd\n");
  96. exit(EXIT_FAILURE);
  97. }
  98. /*
  99. * We need to handle page faults in units of pages(!).
  100. * So, round faulting address down to page boundary.
  101. */
  102. uffdio_copy.dst = msg.arg.pagefault.address & ~(pagesize-1);
  103. offset = (char *) uffdio_copy.dst - uf_mem;
  104. uffdio_copy.src = (unsigned long) &backing_mem[offset];
  105. uffdio_copy.len = pagesize;
  106. uffdio_copy.mode = 0;
  107. uffdio_copy.copy = 0;
  108. if (ioctl(uffd, UFFDIO_COPY, &uffdio_copy) == -1) {
  109. perror("ioctl-UFFDIO_COPY failed");
  110. exit(EXIT_FAILURE);
  111. }
  112. }
  113. }
  114. void setup_uf_mem(void)
  115. {
  116. long uffd; /* userfaultfd file descriptor */
  117. pthread_t thr;
  118. struct uffdio_api uffdio_api;
  119. struct uffdio_register uffdio_register;
  120. int ret;
  121. pagesize = sysconf(_SC_PAGE_SIZE);
  122. /* Create and enable userfaultfd object */
  123. uffd = syscall(__NR_userfaultfd, O_CLOEXEC | O_NONBLOCK);
  124. if (uffd == -1) {
  125. perror("userfaultfd() failed");
  126. exit(EXIT_FAILURE);
  127. }
  128. uffdio_api.api = UFFD_API;
  129. uffdio_api.features = 0;
  130. if (ioctl(uffd, UFFDIO_API, &uffdio_api) == -1) {
  131. perror("ioctl-UFFDIO_API failed");
  132. exit(EXIT_FAILURE);
  133. }
  134. /*
  135. * Create a private anonymous mapping. The memory will be demand-zero
  136. * paged, that is, not yet allocated. When we actually touch the memory
  137. * the related page will be allocated via the userfaultfd mechanism.
  138. */
  139. uf_mem = mmap(NULL, UF_MEM_SIZE, PROT_READ | PROT_WRITE,
  140. MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
  141. if (uf_mem == MAP_FAILED) {
  142. perror("mmap() failed");
  143. exit(EXIT_FAILURE);
  144. }
  145. /*
  146. * Register the memory range of the mapping we've just mapped to be
  147. * handled by the userfaultfd object. In 'mode' we request to track
  148. * missing pages (i.e. pages that have not yet been faulted-in).
  149. */
  150. uffdio_register.range.start = (unsigned long) uf_mem;
  151. uffdio_register.range.len = UF_MEM_SIZE;
  152. uffdio_register.mode = UFFDIO_REGISTER_MODE_MISSING;
  153. if (ioctl(uffd, UFFDIO_REGISTER, &uffdio_register) == -1) {
  154. perror("ioctl-UFFDIO_REGISTER");
  155. exit(EXIT_FAILURE);
  156. }
  157. /* Create a thread that will process the userfaultfd events */
  158. ret = pthread_create(&thr, NULL, fault_handler_thread, (void *) uffd);
  159. if (ret != 0) {
  160. fprintf(stderr, "pthread_create(): Error. Returned %d\n", ret);
  161. exit(EXIT_FAILURE);
  162. }
  163. }
  164. /*
  165. * Assumption: the signal was delivered while userspace was in transactional or
  166. * suspended state, i.e. uc->uc_link != NULL.
  167. */
  168. void signal_handler(int signo, siginfo_t *si, void *uc)
  169. {
  170. ucontext_t *ucp = uc;
  171. /* Skip 'trap' after returning, otherwise we get a SIGTRAP again */
  172. ucp->uc_link->uc_mcontext.regs->nip += 4;
  173. ucp->uc_mcontext.v_regs =
  174. get_uf_mem(sizeof(elf_vrreg_t), ucp->uc_mcontext.v_regs);
  175. ucp->uc_link->uc_mcontext.v_regs =
  176. get_uf_mem(sizeof(elf_vrreg_t), ucp->uc_link->uc_mcontext.v_regs);
  177. ucp->uc_link = get_uf_mem(sizeof(ucontext_t), ucp->uc_link);
  178. }
  179. bool have_userfaultfd(void)
  180. {
  181. long rc;
  182. errno = 0;
  183. rc = syscall(__NR_userfaultfd, -1);
  184. return rc == 0 || errno != ENOSYS;
  185. }
  186. int tm_signal_pagefault(void)
  187. {
  188. struct sigaction sa;
  189. stack_t ss;
  190. SKIP_IF(!have_htm());
  191. SKIP_IF(htm_is_synthetic());
  192. SKIP_IF(!have_userfaultfd());
  193. setup_uf_mem();
  194. /*
  195. * Set an alternative stack that will generate a page fault when the
  196. * signal is raised. The page fault will be treated via userfaultfd,
  197. * i.e. via fault_handler_thread.
  198. */
  199. ss.ss_sp = get_uf_mem(SIGSTKSZ, NULL);
  200. ss.ss_size = SIGSTKSZ;
  201. ss.ss_flags = 0;
  202. if (sigaltstack(&ss, NULL) == -1) {
  203. perror("sigaltstack() failed");
  204. exit(EXIT_FAILURE);
  205. }
  206. sa.sa_flags = SA_SIGINFO | SA_ONSTACK;
  207. sa.sa_sigaction = signal_handler;
  208. if (sigaction(SIGTRAP, &sa, NULL) == -1) {
  209. perror("sigaction() failed");
  210. exit(EXIT_FAILURE);
  211. }
  212. /* Trigger a SIGTRAP in transactional state */
  213. asm __volatile__(
  214. "tbegin.;"
  215. "beq 1f;"
  216. "trap;"
  217. "1: ;"
  218. : : : "memory");
  219. /* Trigger a SIGTRAP in suspended state */
  220. asm __volatile__(
  221. "tbegin.;"
  222. "beq 1f;"
  223. "tsuspend.;"
  224. "trap;"
  225. "tresume.;"
  226. "1: ;"
  227. : : : "memory");
  228. return EXIT_SUCCESS;
  229. }
  230. int main(int argc, char **argv)
  231. {
  232. /*
  233. * Depending on kernel config, the TM Bad Thing might not result in a
  234. * crash, instead the kernel never returns control back to userspace, so
  235. * set a tight timeout. If the test passes it completes almost
  236. * immediately.
  237. */
  238. test_harness_set_timeout(2);
  239. return test_harness(tm_signal_pagefault, "tm_signal_pagefault");
  240. }