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