1From 6387912710bf3762635e5bd6ddb4be59f50d9b78 Mon Sep 17 00:00:00 2001 2From: Edward Liaw <edliaw@google.com> 3Date: Wed, 20 Apr 2022 00:29:06 +0000 4Subject: [PATCH 16/24] userfaultfd 5 6Fix ARM related issues in userfaultfd selftest 7 8Following issues were observed while running userfaultfd selftest on ARM 9devices. On x86_64 no issues were detected: 10 111) posix_memalign returned tagged pointer, which isn't handled well by 12the kernel. So replace its use with mmap 132) pthread_create followed by fork caused deadlock in certain cases 14wherein fork required some work to be completed by the created thread. 15Used synchronization to ensure that created thread's start funtion has 16started before invoking fork. 17 18(cherry picked from commit 9b11d1b6ab483cb451b102a30d996dc180330161) 19Bug: 160737021 20Bug: 169683130 21Test: atest vts_linux_kselftest_arm_64 22 23Enable userfaultfd selftest 24 25Now that the userfaultfd feature is enabled in the Android kernel, it 26makes sense to have its selftest enabled in the test infra. 27 28The test source code required the following changes: 291) Use UFFD_USER_MODE_ONLY as unprivileged processes are not allowed 30userfaults from kernel space on Android 312) Use random/initstate instead of random_r/initstate_r as bionic 32doesn't support the latter. 333) Since bionic doesn't have pthread_cancel() implemented, we 34implemented the same functionality using pthread_kill() and longjmp(). 35 36(cherry picked from commit 599ed29be16f2612c1ca1bc2cab1b95e1ae0e6f7) 37Bug: 160737021 38Bug: 169683130 39Test: treehugger 40--- 41 tools/testing/selftests/vm/userfaultfd.c | 74 ++++++++++++++++++++++-- 42 1 file changed, 69 insertions(+), 5 deletions(-) 43 44diff --git a/tools/testing/selftests/vm/userfaultfd.c b/tools/testing/selftests/vm/userfaultfd.c 45index 3fc1d2ee29485..e7a79f120cbde 100644 46--- a/tools/testing/selftests/vm/userfaultfd.c 47+++ b/tools/testing/selftests/vm/userfaultfd.c 48@@ -93,9 +93,11 @@ static char *huge_fd_off0; 49 static unsigned long long *count_verify; 50 static int uffd = -1; 51 static int uffd_flags, finished, *pipefd; 52+static volatile bool ready_for_fork; 53 static char *area_src, *area_src_alias, *area_dst, *area_dst_alias; 54 static char *zeropage; 55 pthread_attr_t attr; 56+pthread_key_t long_jmp_key; 57 58 /* Userfaultfd test statistics */ 59 struct uffd_stats { 60@@ -377,8 +379,13 @@ static void userfaultfd_open(uint64_t *features) 61 struct uffdio_api uffdio_api; 62 63 uffd = syscall(__NR_userfaultfd, O_CLOEXEC | O_NONBLOCK | UFFD_USER_MODE_ONLY); 64- if (uffd < 0) 65- err("userfaultfd syscall not available in this kernel"); 66+ if (uffd < 0) { 67+ if (errno == ENOSYS) { 68+ printf("userfaultfd syscall not available in this kernel\n"); 69+ exit(KSFT_SKIP); 70+ } 71+ err("userfaultfd syscall failed with errno: %d\n", errno); 72+ } 73 uffd_flags = fcntl(uffd, F_GETFD, NULL); 74 75 uffdio_api.api = UFFD_API; 76@@ -720,6 +727,9 @@ static void *uffd_poll_thread(void *arg) 77 pollfd[1].fd = pipefd[cpu*2]; 78 pollfd[1].events = POLLIN; 79 80+ // Notify the main thread that it can now fork. 81+ ready_for_fork = true; 82+ 83 for (;;) { 84 ret = poll(pollfd, 2, -1); 85 if (ret <= 0) { 86@@ -766,15 +776,28 @@ static void *uffd_poll_thread(void *arg) 87 88 pthread_mutex_t uffd_read_mutex = PTHREAD_MUTEX_INITIALIZER; 89 90+static void sigusr1_handler(int signum, siginfo_t *siginfo, void *ptr) 91+{ 92+ jmp_buf *env; 93+ env = pthread_getspecific(long_jmp_key); 94+ longjmp(*env, 1); 95+} 96+ 97 static void *uffd_read_thread(void *arg) 98 { 99 struct uffd_stats *stats = (struct uffd_stats *)arg; 100 struct uffd_msg msg; 101+ jmp_buf env; 102+ int setjmp_ret; 103+ 104+ pthread_setspecific(long_jmp_key, &env); 105 106 pthread_mutex_unlock(&uffd_read_mutex); 107- /* from here cancellation is ok */ 108 109- for (;;) { 110+ // One first return setjmp return 0. On second (fake) return from 111+ // longjmp() it returns the provided value, which will be 1 in our case. 112+ setjmp_ret = setjmp(env); 113+ while (!setjmp_ret) { 114 if (uffd_read_msg(uffd, &msg)) 115 continue; 116 uffd_handle_page_fault(&msg, stats); 117@@ -872,7 +895,7 @@ static int stress(struct uffd_stats *uffd_stats) 118 (void *)&uffd_stats[cpu])) 119 return 1; 120 } else { 121- if (pthread_cancel(uffd_threads[cpu])) 122+ if (pthread_kill(uffd_threads[cpu], SIGUSR1)) 123 return 1; 124 if (pthread_join(uffd_threads[cpu], NULL)) 125 return 1; 126@@ -1112,6 +1135,10 @@ static int userfaultfd_events_test(void) 127 char c; 128 struct uffd_stats stats = { 0 }; 129 130+ // All the syscalls below up to pthread_create will ensure that this 131+ // write is completed before, the uffd_thread sets it to true. 132+ ready_for_fork = false; 133+ 134 printf("testing events (fork, remap, remove): "); 135 fflush(stdout); 136 137@@ -1135,6 +1162,11 @@ static int userfaultfd_events_test(void) 138 if (pthread_create(&uffd_mon, &attr, uffd_poll_thread, &stats)) 139 err("uffd_poll_thread create"); 140 141+ // Wait for the poll_thread to start executing before forking. This is 142+ // required to avoid a deadlock, which can happen if poll_thread doesn't 143+ // start getting executed by the time fork is invoked. 144+ while (!ready_for_fork); 145+ 146 pid = fork(); 147 if (pid < 0) 148 err("fork"); 149@@ -1165,6 +1197,10 @@ static int userfaultfd_sig_test(void) 150 char c; 151 struct uffd_stats stats = { 0 }; 152 153+ // All the syscalls below up to pthread_create will ensure that this 154+ // write is completed before, the uffd_thread sets it to true. 155+ ready_for_fork = false; 156+ 157 printf("testing signal delivery: "); 158 fflush(stdout); 159 160@@ -1192,6 +1228,11 @@ static int userfaultfd_sig_test(void) 161 if (pthread_create(&uffd_mon, &attr, uffd_poll_thread, &stats)) 162 err("uffd_poll_thread create"); 163 164+ // Wait for the poll_thread to start executing before forking. This is 165+ // required to avoid a deadlock, which can happen if poll_thread doesn't 166+ // start getting executed by the time fork is invoked. 167+ while (!ready_for_fork); 168+ 169 pid = fork(); 170 if (pid < 0) 171 err("fork"); 172@@ -1421,6 +1462,7 @@ static int userfaultfd_stress(void) 173 char *tmp_area; 174 unsigned long nr; 175 struct uffdio_register uffdio_register; 176+ struct sigaction act; 177 struct uffd_stats uffd_stats[nr_cpus]; 178 179 uffd_test_ctx_init(0); 180@@ -1435,6 +1477,17 @@ static int userfaultfd_stress(void) 181 pthread_attr_init(&attr); 182 pthread_attr_setstacksize(&attr, 16*1024*1024); 183 184+ // For handling thread termination of read thread in the absense of 185+ // pthread_cancel(). 186+ pthread_key_create(&long_jmp_key, NULL); 187+ memset(&act, 0, sizeof(act)); 188+ act.sa_sigaction = sigusr1_handler; 189+ act.sa_flags = SA_SIGINFO; 190+ if (sigaction(SIGUSR1, &act, 0)) { 191+ perror("sigaction"); 192+ return 1; 193+ } 194+ 195 while (bounces--) { 196 printf("bounces: %d, mode:", bounces); 197 if (bounces & BOUNCE_RANDOM) 198@@ -1555,6 +1608,8 @@ static int userfaultfd_stress(void) 199 userfaultfd_pagemap_test(page_size * 512); 200 } 201 202+ pthread_key_delete(long_jmp_key); 203+ 204 return userfaultfd_zeropage_test() || userfaultfd_sig_test() 205 || userfaultfd_events_test() || userfaultfd_minor_test(); 206 } 207@@ -1649,6 +1704,9 @@ static void sigalrm(int sig) 208 209 int main(int argc, char **argv) 210 { 211+ char randstate[64]; 212+ unsigned int seed; 213+ 214 if (argc < 4) 215 usage(); 216 217@@ -1692,6 +1750,12 @@ int main(int argc, char **argv) 218 nr_pages * page_size * 2)) 219 err("fallocate"); 220 } 221+ 222+ seed = (unsigned int) time(NULL); 223+ bzero(&randstate, sizeof(randstate)); 224+ if (!initstate(seed, randstate, sizeof(randstate))) 225+ fprintf(stderr, "srandom_r error\n"), exit(1); 226+ 227 printf("nr_pages: %lu, nr_pages_per_cpu: %lu\n", 228 nr_pages, nr_pages_per_cpu); 229 return userfaultfd_stress(); 230-- 2312.36.0.550.gb090851708-goog 232 233