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