1From 3fce534596d950ce2524275e90eaf9c949a81423 Mon Sep 17 00:00:00 2001 2From: Edward Liaw <[email protected]> 3Date: Wed, 20 Apr 2022 00:29:06 +0000 4Subject: [PATCH 18/20] userfaultfd: Fix arm issues and Android compatibility 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 | 57 ++++++++++++++++++++++-- 42 1 file changed, 53 insertions(+), 4 deletions(-) 43 44diff --git a/tools/testing/selftests/vm/userfaultfd.c b/tools/testing/selftests/vm/userfaultfd.c 45index 297f250c1d95..28230a57fedd 100644 46--- a/tools/testing/selftests/vm/userfaultfd.c 47+++ b/tools/testing/selftests/vm/userfaultfd.c 48@@ -100,9 +100,11 @@ static int huge_fd; 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, *area_remap; 54 static char *zeropage; 55 pthread_attr_t attr; 56+pthread_key_t long_jmp_key; 57 static bool test_collapse; 58 59 /* Userfaultfd test statistics */ 60@@ -821,6 +823,9 @@ static void *uffd_poll_thread(void *arg) 61 pollfd[1].fd = pipefd[cpu*2]; 62 pollfd[1].events = POLLIN; 63 64+ // Notify the main thread that it can now fork. 65+ ready_for_fork = true; 66+ 67 for (;;) { 68 ret = poll(pollfd, 2, -1); 69 if (ret <= 0) { 70@@ -868,15 +873,27 @@ static void *uffd_poll_thread(void *arg) 71 72 pthread_mutex_t uffd_read_mutex = PTHREAD_MUTEX_INITIALIZER; 73 74+static void sigusr1_handler(int signum, siginfo_t *siginfo, void *ptr) 75+{ 76+ jmp_buf *env; 77+ env = pthread_getspecific(long_jmp_key); 78+ longjmp(*env, 1); 79+} 80+ 81 static void *uffd_read_thread(void *arg) 82 { 83 struct uffd_stats *stats = (struct uffd_stats *)arg; 84 struct uffd_msg msg; 85+ jmp_buf env; 86+ int setjmp_ret; 87 88- pthread_mutex_unlock(&uffd_read_mutex); 89- /* from here cancellation is ok */ 90+ pthread_setspecific(long_jmp_key, &env); 91 92- for (;;) { 93+ pthread_mutex_unlock(&uffd_read_mutex); 94+ // One first return setjmp return 0. On second (fake) return from 95+ // longjmp() it returns the provided value, which will be 1 in our case. 96+ setjmp_ret = setjmp(env); 97+ while (!setjmp_ret) { 98 if (uffd_read_msg(uffd, &msg)) 99 continue; 100 uffd_handle_page_fault(&msg, stats); 101@@ -974,7 +991,7 @@ static int stress(struct uffd_stats *uffd_stats) 102 (void *)&uffd_stats[cpu])) 103 return 1; 104 } else { 105- if (pthread_cancel(uffd_threads[cpu])) 106+ if (pthread_kill(uffd_threads[cpu], SIGUSR1)) 107 return 1; 108 if (pthread_join(uffd_threads[cpu], NULL)) 109 return 1; 110@@ -1208,6 +1225,10 @@ static int userfaultfd_events_test(void) 111 char c; 112 struct uffd_stats stats = { 0 }; 113 114+ // All the syscalls below up to pthread_create will ensure that this 115+ // write is completed before, the uffd_thread sets it to true. 116+ ready_for_fork = false; 117+ 118 printf("testing events (fork, remap, remove): "); 119 fflush(stdout); 120 121@@ -1231,6 +1252,11 @@ static int userfaultfd_events_test(void) 122 if (pthread_create(&uffd_mon, &attr, uffd_poll_thread, &stats)) 123 err("uffd_poll_thread create"); 124 125+ // Wait for the poll_thread to start executing before forking. This is 126+ // required to avoid a deadlock, which can happen if poll_thread doesn't 127+ // start getting executed by the time fork is invoked. 128+ while (!ready_for_fork); 129+ 130 pid = fork(); 131 if (pid < 0) 132 err("fork"); 133@@ -1261,6 +1287,10 @@ static int userfaultfd_sig_test(void) 134 char c; 135 struct uffd_stats stats = { 0 }; 136 137+ // All the syscalls below up to pthread_create will ensure that this 138+ // write is completed before, the uffd_thread sets it to true. 139+ ready_for_fork = false; 140+ 141 printf("testing signal delivery: "); 142 fflush(stdout); 143 144@@ -1288,6 +1318,11 @@ static int userfaultfd_sig_test(void) 145 if (pthread_create(&uffd_mon, &attr, uffd_poll_thread, &stats)) 146 err("uffd_poll_thread create"); 147 148+ // Wait for the poll_thread to start executing before forking. This is 149+ // required to avoid a deadlock, which can happen if poll_thread doesn't 150+ // start getting executed by the time fork is invoked. 151+ while (!ready_for_fork); 152+ 153 pid = fork(); 154 if (pid < 0) 155 err("fork"); 156@@ -1540,6 +1575,7 @@ static int userfaultfd_stress(void) 157 void *area; 158 unsigned long nr; 159 struct uffdio_register uffdio_register; 160+ struct sigaction act; 161 struct uffd_stats uffd_stats[nr_cpus]; 162 163 uffd_test_ctx_init(0); 164@@ -1554,6 +1590,17 @@ static int userfaultfd_stress(void) 165 pthread_attr_init(&attr); 166 pthread_attr_setstacksize(&attr, 16*1024*1024); 167 168+ // For handling thread termination of read thread in the absence of 169+ // pthread_cancel(). 170+ pthread_key_create(&long_jmp_key, NULL); 171+ memset(&act, 0, sizeof(act)); 172+ act.sa_sigaction = sigusr1_handler; 173+ act.sa_flags = SA_SIGINFO; 174+ if (sigaction(SIGUSR1, &act, 0)) { 175+ perror("sigaction"); 176+ return 1; 177+ } 178+ 179 while (bounces--) { 180 printf("bounces: %d, mode:", bounces); 181 if (bounces & BOUNCE_RANDOM) 182@@ -1670,6 +1717,8 @@ static int userfaultfd_stress(void) 183 userfaultfd_pagemap_test(page_size * 512); 184 } 185 186+ pthread_key_delete(long_jmp_key); 187+ 188 return userfaultfd_zeropage_test() || userfaultfd_sig_test() 189 || userfaultfd_events_test() || userfaultfd_minor_test(); 190 } 191-- 1922.42.0.609.gbb76f46606-goog 193 194