1*053f45beSAndroid Build Coastguard WorkerFrom 3fce534596d950ce2524275e90eaf9c949a81423 Mon Sep 17 00:00:00 2001 2*053f45beSAndroid Build Coastguard WorkerFrom: Edward Liaw <[email protected]> 3*053f45beSAndroid Build Coastguard WorkerDate: Wed, 20 Apr 2022 00:29:06 +0000 4*053f45beSAndroid Build Coastguard WorkerSubject: [PATCH 18/20] userfaultfd: Fix arm issues and Android compatibility 5*053f45beSAndroid Build Coastguard Worker 6*053f45beSAndroid Build Coastguard WorkerFix ARM related issues in userfaultfd selftest 7*053f45beSAndroid Build Coastguard Worker 8*053f45beSAndroid Build Coastguard WorkerFollowing issues were observed while running userfaultfd selftest on ARM 9*053f45beSAndroid Build Coastguard Workerdevices. On x86_64 no issues were detected: 10*053f45beSAndroid Build Coastguard Worker 11*053f45beSAndroid Build Coastguard Worker1) posix_memalign returned tagged pointer, which isn't handled well by 12*053f45beSAndroid Build Coastguard Workerthe kernel. So replace its use with mmap 13*053f45beSAndroid Build Coastguard Worker2) pthread_create followed by fork caused deadlock in certain cases 14*053f45beSAndroid Build Coastguard Workerwherein fork required some work to be completed by the created thread. 15*053f45beSAndroid Build Coastguard WorkerUsed synchronization to ensure that created thread's start funtion has 16*053f45beSAndroid Build Coastguard Workerstarted before invoking fork. 17*053f45beSAndroid Build Coastguard Worker 18*053f45beSAndroid Build Coastguard Worker(cherry picked from commit 9b11d1b6ab483cb451b102a30d996dc180330161) 19*053f45beSAndroid Build Coastguard WorkerBug: 160737021 20*053f45beSAndroid Build Coastguard WorkerBug: 169683130 21*053f45beSAndroid Build Coastguard WorkerTest: atest vts_linux_kselftest_arm_64 22*053f45beSAndroid Build Coastguard Worker 23*053f45beSAndroid Build Coastguard WorkerEnable userfaultfd selftest 24*053f45beSAndroid Build Coastguard Worker 25*053f45beSAndroid Build Coastguard WorkerNow that the userfaultfd feature is enabled in the Android kernel, it 26*053f45beSAndroid Build Coastguard Workermakes sense to have its selftest enabled in the test infra. 27*053f45beSAndroid Build Coastguard Worker 28*053f45beSAndroid Build Coastguard WorkerThe test source code required the following changes: 29*053f45beSAndroid Build Coastguard Worker1) Use UFFD_USER_MODE_ONLY as unprivileged processes are not allowed 30*053f45beSAndroid Build Coastguard Workeruserfaults from kernel space on Android 31*053f45beSAndroid Build Coastguard Worker2) Use random/initstate instead of random_r/initstate_r as bionic 32*053f45beSAndroid Build Coastguard Workerdoesn't support the latter. 33*053f45beSAndroid Build Coastguard Worker3) Since bionic doesn't have pthread_cancel() implemented, we 34*053f45beSAndroid Build Coastguard Workerimplemented the same functionality using pthread_kill() and longjmp(). 35*053f45beSAndroid Build Coastguard Worker 36*053f45beSAndroid Build Coastguard Worker(cherry picked from commit 599ed29be16f2612c1ca1bc2cab1b95e1ae0e6f7) 37*053f45beSAndroid Build Coastguard WorkerBug: 160737021 38*053f45beSAndroid Build Coastguard WorkerBug: 169683130 39*053f45beSAndroid Build Coastguard WorkerTest: treehugger 40*053f45beSAndroid Build Coastguard Worker--- 41*053f45beSAndroid Build Coastguard Worker tools/testing/selftests/vm/userfaultfd.c | 57 ++++++++++++++++++++++-- 42*053f45beSAndroid Build Coastguard Worker 1 file changed, 53 insertions(+), 4 deletions(-) 43*053f45beSAndroid Build Coastguard Worker 44*053f45beSAndroid Build Coastguard Workerdiff --git a/tools/testing/selftests/vm/userfaultfd.c b/tools/testing/selftests/vm/userfaultfd.c 45*053f45beSAndroid Build Coastguard Workerindex 297f250c1d95..28230a57fedd 100644 46*053f45beSAndroid Build Coastguard Worker--- a/tools/testing/selftests/vm/userfaultfd.c 47*053f45beSAndroid Build Coastguard Worker+++ b/tools/testing/selftests/vm/userfaultfd.c 48*053f45beSAndroid Build Coastguard Worker@@ -100,9 +100,11 @@ static int huge_fd; 49*053f45beSAndroid Build Coastguard Worker static unsigned long long *count_verify; 50*053f45beSAndroid Build Coastguard Worker static int uffd = -1; 51*053f45beSAndroid Build Coastguard Worker static int uffd_flags, finished, *pipefd; 52*053f45beSAndroid Build Coastguard Worker+static volatile bool ready_for_fork; 53*053f45beSAndroid Build Coastguard Worker static char *area_src, *area_src_alias, *area_dst, *area_dst_alias, *area_remap; 54*053f45beSAndroid Build Coastguard Worker static char *zeropage; 55*053f45beSAndroid Build Coastguard Worker pthread_attr_t attr; 56*053f45beSAndroid Build Coastguard Worker+pthread_key_t long_jmp_key; 57*053f45beSAndroid Build Coastguard Worker static bool test_collapse; 58*053f45beSAndroid Build Coastguard Worker 59*053f45beSAndroid Build Coastguard Worker /* Userfaultfd test statistics */ 60*053f45beSAndroid Build Coastguard Worker@@ -821,6 +823,9 @@ static void *uffd_poll_thread(void *arg) 61*053f45beSAndroid Build Coastguard Worker pollfd[1].fd = pipefd[cpu*2]; 62*053f45beSAndroid Build Coastguard Worker pollfd[1].events = POLLIN; 63*053f45beSAndroid Build Coastguard Worker 64*053f45beSAndroid Build Coastguard Worker+ // Notify the main thread that it can now fork. 65*053f45beSAndroid Build Coastguard Worker+ ready_for_fork = true; 66*053f45beSAndroid Build Coastguard Worker+ 67*053f45beSAndroid Build Coastguard Worker for (;;) { 68*053f45beSAndroid Build Coastguard Worker ret = poll(pollfd, 2, -1); 69*053f45beSAndroid Build Coastguard Worker if (ret <= 0) { 70*053f45beSAndroid Build Coastguard Worker@@ -868,15 +873,27 @@ static void *uffd_poll_thread(void *arg) 71*053f45beSAndroid Build Coastguard Worker 72*053f45beSAndroid Build Coastguard Worker pthread_mutex_t uffd_read_mutex = PTHREAD_MUTEX_INITIALIZER; 73*053f45beSAndroid Build Coastguard Worker 74*053f45beSAndroid Build Coastguard Worker+static void sigusr1_handler(int signum, siginfo_t *siginfo, void *ptr) 75*053f45beSAndroid Build Coastguard Worker+{ 76*053f45beSAndroid Build Coastguard Worker+ jmp_buf *env; 77*053f45beSAndroid Build Coastguard Worker+ env = pthread_getspecific(long_jmp_key); 78*053f45beSAndroid Build Coastguard Worker+ longjmp(*env, 1); 79*053f45beSAndroid Build Coastguard Worker+} 80*053f45beSAndroid Build Coastguard Worker+ 81*053f45beSAndroid Build Coastguard Worker static void *uffd_read_thread(void *arg) 82*053f45beSAndroid Build Coastguard Worker { 83*053f45beSAndroid Build Coastguard Worker struct uffd_stats *stats = (struct uffd_stats *)arg; 84*053f45beSAndroid Build Coastguard Worker struct uffd_msg msg; 85*053f45beSAndroid Build Coastguard Worker+ jmp_buf env; 86*053f45beSAndroid Build Coastguard Worker+ int setjmp_ret; 87*053f45beSAndroid Build Coastguard Worker 88*053f45beSAndroid Build Coastguard Worker- pthread_mutex_unlock(&uffd_read_mutex); 89*053f45beSAndroid Build Coastguard Worker- /* from here cancellation is ok */ 90*053f45beSAndroid Build Coastguard Worker+ pthread_setspecific(long_jmp_key, &env); 91*053f45beSAndroid Build Coastguard Worker 92*053f45beSAndroid Build Coastguard Worker- for (;;) { 93*053f45beSAndroid Build Coastguard Worker+ pthread_mutex_unlock(&uffd_read_mutex); 94*053f45beSAndroid Build Coastguard Worker+ // One first return setjmp return 0. On second (fake) return from 95*053f45beSAndroid Build Coastguard Worker+ // longjmp() it returns the provided value, which will be 1 in our case. 96*053f45beSAndroid Build Coastguard Worker+ setjmp_ret = setjmp(env); 97*053f45beSAndroid Build Coastguard Worker+ while (!setjmp_ret) { 98*053f45beSAndroid Build Coastguard Worker if (uffd_read_msg(uffd, &msg)) 99*053f45beSAndroid Build Coastguard Worker continue; 100*053f45beSAndroid Build Coastguard Worker uffd_handle_page_fault(&msg, stats); 101*053f45beSAndroid Build Coastguard Worker@@ -974,7 +991,7 @@ static int stress(struct uffd_stats *uffd_stats) 102*053f45beSAndroid Build Coastguard Worker (void *)&uffd_stats[cpu])) 103*053f45beSAndroid Build Coastguard Worker return 1; 104*053f45beSAndroid Build Coastguard Worker } else { 105*053f45beSAndroid Build Coastguard Worker- if (pthread_cancel(uffd_threads[cpu])) 106*053f45beSAndroid Build Coastguard Worker+ if (pthread_kill(uffd_threads[cpu], SIGUSR1)) 107*053f45beSAndroid Build Coastguard Worker return 1; 108*053f45beSAndroid Build Coastguard Worker if (pthread_join(uffd_threads[cpu], NULL)) 109*053f45beSAndroid Build Coastguard Worker return 1; 110*053f45beSAndroid Build Coastguard Worker@@ -1208,6 +1225,10 @@ static int userfaultfd_events_test(void) 111*053f45beSAndroid Build Coastguard Worker char c; 112*053f45beSAndroid Build Coastguard Worker struct uffd_stats stats = { 0 }; 113*053f45beSAndroid Build Coastguard Worker 114*053f45beSAndroid Build Coastguard Worker+ // All the syscalls below up to pthread_create will ensure that this 115*053f45beSAndroid Build Coastguard Worker+ // write is completed before, the uffd_thread sets it to true. 116*053f45beSAndroid Build Coastguard Worker+ ready_for_fork = false; 117*053f45beSAndroid Build Coastguard Worker+ 118*053f45beSAndroid Build Coastguard Worker printf("testing events (fork, remap, remove): "); 119*053f45beSAndroid Build Coastguard Worker fflush(stdout); 120*053f45beSAndroid Build Coastguard Worker 121*053f45beSAndroid Build Coastguard Worker@@ -1231,6 +1252,11 @@ static int userfaultfd_events_test(void) 122*053f45beSAndroid Build Coastguard Worker if (pthread_create(&uffd_mon, &attr, uffd_poll_thread, &stats)) 123*053f45beSAndroid Build Coastguard Worker err("uffd_poll_thread create"); 124*053f45beSAndroid Build Coastguard Worker 125*053f45beSAndroid Build Coastguard Worker+ // Wait for the poll_thread to start executing before forking. This is 126*053f45beSAndroid Build Coastguard Worker+ // required to avoid a deadlock, which can happen if poll_thread doesn't 127*053f45beSAndroid Build Coastguard Worker+ // start getting executed by the time fork is invoked. 128*053f45beSAndroid Build Coastguard Worker+ while (!ready_for_fork); 129*053f45beSAndroid Build Coastguard Worker+ 130*053f45beSAndroid Build Coastguard Worker pid = fork(); 131*053f45beSAndroid Build Coastguard Worker if (pid < 0) 132*053f45beSAndroid Build Coastguard Worker err("fork"); 133*053f45beSAndroid Build Coastguard Worker@@ -1261,6 +1287,10 @@ static int userfaultfd_sig_test(void) 134*053f45beSAndroid Build Coastguard Worker char c; 135*053f45beSAndroid Build Coastguard Worker struct uffd_stats stats = { 0 }; 136*053f45beSAndroid Build Coastguard Worker 137*053f45beSAndroid Build Coastguard Worker+ // All the syscalls below up to pthread_create will ensure that this 138*053f45beSAndroid Build Coastguard Worker+ // write is completed before, the uffd_thread sets it to true. 139*053f45beSAndroid Build Coastguard Worker+ ready_for_fork = false; 140*053f45beSAndroid Build Coastguard Worker+ 141*053f45beSAndroid Build Coastguard Worker printf("testing signal delivery: "); 142*053f45beSAndroid Build Coastguard Worker fflush(stdout); 143*053f45beSAndroid Build Coastguard Worker 144*053f45beSAndroid Build Coastguard Worker@@ -1288,6 +1318,11 @@ static int userfaultfd_sig_test(void) 145*053f45beSAndroid Build Coastguard Worker if (pthread_create(&uffd_mon, &attr, uffd_poll_thread, &stats)) 146*053f45beSAndroid Build Coastguard Worker err("uffd_poll_thread create"); 147*053f45beSAndroid Build Coastguard Worker 148*053f45beSAndroid Build Coastguard Worker+ // Wait for the poll_thread to start executing before forking. This is 149*053f45beSAndroid Build Coastguard Worker+ // required to avoid a deadlock, which can happen if poll_thread doesn't 150*053f45beSAndroid Build Coastguard Worker+ // start getting executed by the time fork is invoked. 151*053f45beSAndroid Build Coastguard Worker+ while (!ready_for_fork); 152*053f45beSAndroid Build Coastguard Worker+ 153*053f45beSAndroid Build Coastguard Worker pid = fork(); 154*053f45beSAndroid Build Coastguard Worker if (pid < 0) 155*053f45beSAndroid Build Coastguard Worker err("fork"); 156*053f45beSAndroid Build Coastguard Worker@@ -1540,6 +1575,7 @@ static int userfaultfd_stress(void) 157*053f45beSAndroid Build Coastguard Worker void *area; 158*053f45beSAndroid Build Coastguard Worker unsigned long nr; 159*053f45beSAndroid Build Coastguard Worker struct uffdio_register uffdio_register; 160*053f45beSAndroid Build Coastguard Worker+ struct sigaction act; 161*053f45beSAndroid Build Coastguard Worker struct uffd_stats uffd_stats[nr_cpus]; 162*053f45beSAndroid Build Coastguard Worker 163*053f45beSAndroid Build Coastguard Worker uffd_test_ctx_init(0); 164*053f45beSAndroid Build Coastguard Worker@@ -1554,6 +1590,17 @@ static int userfaultfd_stress(void) 165*053f45beSAndroid Build Coastguard Worker pthread_attr_init(&attr); 166*053f45beSAndroid Build Coastguard Worker pthread_attr_setstacksize(&attr, 16*1024*1024); 167*053f45beSAndroid Build Coastguard Worker 168*053f45beSAndroid Build Coastguard Worker+ // For handling thread termination of read thread in the absence of 169*053f45beSAndroid Build Coastguard Worker+ // pthread_cancel(). 170*053f45beSAndroid Build Coastguard Worker+ pthread_key_create(&long_jmp_key, NULL); 171*053f45beSAndroid Build Coastguard Worker+ memset(&act, 0, sizeof(act)); 172*053f45beSAndroid Build Coastguard Worker+ act.sa_sigaction = sigusr1_handler; 173*053f45beSAndroid Build Coastguard Worker+ act.sa_flags = SA_SIGINFO; 174*053f45beSAndroid Build Coastguard Worker+ if (sigaction(SIGUSR1, &act, 0)) { 175*053f45beSAndroid Build Coastguard Worker+ perror("sigaction"); 176*053f45beSAndroid Build Coastguard Worker+ return 1; 177*053f45beSAndroid Build Coastguard Worker+ } 178*053f45beSAndroid Build Coastguard Worker+ 179*053f45beSAndroid Build Coastguard Worker while (bounces--) { 180*053f45beSAndroid Build Coastguard Worker printf("bounces: %d, mode:", bounces); 181*053f45beSAndroid Build Coastguard Worker if (bounces & BOUNCE_RANDOM) 182*053f45beSAndroid Build Coastguard Worker@@ -1670,6 +1717,8 @@ static int userfaultfd_stress(void) 183*053f45beSAndroid Build Coastguard Worker userfaultfd_pagemap_test(page_size * 512); 184*053f45beSAndroid Build Coastguard Worker } 185*053f45beSAndroid Build Coastguard Worker 186*053f45beSAndroid Build Coastguard Worker+ pthread_key_delete(long_jmp_key); 187*053f45beSAndroid Build Coastguard Worker+ 188*053f45beSAndroid Build Coastguard Worker return userfaultfd_zeropage_test() || userfaultfd_sig_test() 189*053f45beSAndroid Build Coastguard Worker || userfaultfd_events_test() || userfaultfd_minor_test(); 190*053f45beSAndroid Build Coastguard Worker } 191*053f45beSAndroid Build Coastguard Worker-- 192*053f45beSAndroid Build Coastguard Worker2.42.0.609.gbb76f46606-goog 193*053f45beSAndroid Build Coastguard Worker 194