1 /* SPDX-License-Identifier: MIT */
2 // autogenerated by syzkaller (https://github.com/google/syzkaller)
3
4 #include <dirent.h>
5 #include <endian.h>
6 #include <errno.h>
7 #include <fcntl.h>
8 #include <pthread.h>
9 #include <signal.h>
10 #include <stdarg.h>
11 #include <stdbool.h>
12 #include <stdint.h>
13 #include <stdio.h>
14 #include <stdlib.h>
15 #include <string.h>
16 #include <sys/prctl.h>
17 #include <sys/stat.h>
18 #include <sys/syscall.h>
19 #include <sys/types.h>
20 #include <sys/wait.h>
21 #include <time.h>
22 #include <unistd.h>
23 #include <sys/mman.h>
24
25 #include <linux/futex.h>
26
27 #include "liburing.h"
28 #include "helpers.h"
29 #include "../src/syscall.h"
30
31 #if !defined(SYS_futex) && defined(SYS_futex_time64)
32 # define SYS_futex SYS_futex_time64
33 #endif
34
sleep_ms(uint64_t ms)35 static void sleep_ms(uint64_t ms)
36 {
37 usleep(ms * 1000);
38 }
39
current_time_ms(void)40 static uint64_t current_time_ms(void)
41 {
42 struct timespec ts;
43 if (clock_gettime(CLOCK_MONOTONIC, &ts))
44 exit(1);
45 return (uint64_t)ts.tv_sec * 1000 + (uint64_t)ts.tv_nsec / 1000000;
46 }
47
thread_start(void * (* fn)(void *),void * arg)48 static void thread_start(void* (*fn)(void*), void* arg)
49 {
50 pthread_t th;
51 pthread_attr_t attr;
52 pthread_attr_init(&attr);
53 pthread_attr_setstacksize(&attr, 128 << 10);
54 int i;
55 for (i = 0; i < 100; i++) {
56 if (pthread_create(&th, &attr, fn, arg) == 0) {
57 pthread_attr_destroy(&attr);
58 return;
59 }
60 if (errno == EAGAIN) {
61 usleep(50);
62 continue;
63 }
64 break;
65 }
66 exit(1);
67 }
68
69 typedef struct {
70 int state;
71 } event_t;
72
event_init(event_t * ev)73 static void event_init(event_t* ev)
74 {
75 ev->state = 0;
76 }
77
event_reset(event_t * ev)78 static void event_reset(event_t* ev)
79 {
80 ev->state = 0;
81 }
82
event_set(event_t * ev)83 static void event_set(event_t* ev)
84 {
85 if (ev->state)
86 exit(1);
87 __atomic_store_n(&ev->state, 1, __ATOMIC_RELEASE);
88 syscall(SYS_futex, &ev->state, FUTEX_WAKE | FUTEX_PRIVATE_FLAG);
89 }
90
event_wait(event_t * ev)91 static void event_wait(event_t* ev)
92 {
93 while (!__atomic_load_n(&ev->state, __ATOMIC_ACQUIRE))
94 syscall(SYS_futex, &ev->state, FUTEX_WAIT | FUTEX_PRIVATE_FLAG, 0, 0);
95 }
96
event_isset(event_t * ev)97 static int event_isset(event_t* ev)
98 {
99 return __atomic_load_n(&ev->state, __ATOMIC_ACQUIRE);
100 }
101
event_timedwait(event_t * ev,uint64_t timeout)102 static int event_timedwait(event_t* ev, uint64_t timeout)
103 {
104 uint64_t start = current_time_ms();
105 uint64_t now = start;
106 for (;;) {
107 uint64_t remain = timeout - (now - start);
108 struct timespec ts;
109 ts.tv_sec = remain / 1000;
110 ts.tv_nsec = (remain % 1000) * 1000 * 1000;
111 syscall(SYS_futex, &ev->state, FUTEX_WAIT | FUTEX_PRIVATE_FLAG, 0, &ts);
112 if (__atomic_load_n(&ev->state, __ATOMIC_RELAXED))
113 return 1;
114 now = current_time_ms();
115 if (now - start > timeout)
116 return 0;
117 }
118 }
119
write_file(const char * file,const char * what,...)120 static bool write_file(const char* file, const char* what, ...)
121 {
122 char buf[1024];
123 va_list args;
124 va_start(args, what);
125 vsnprintf(buf, sizeof(buf), what, args);
126 va_end(args);
127 buf[sizeof(buf) - 1] = 0;
128 int len = strlen(buf);
129 int fd = open(file, O_WRONLY | O_CLOEXEC);
130 if (fd == -1)
131 return false;
132 if (write(fd, buf, len) != len) {
133 int err = errno;
134 close(fd);
135 errno = err;
136 return false;
137 }
138 close(fd);
139 return true;
140 }
141
kill_and_wait(int pid,int * status)142 static void kill_and_wait(int pid, int* status)
143 {
144 kill(-pid, SIGKILL);
145 kill(pid, SIGKILL);
146 int i;
147 for (i = 0; i < 100; i++) {
148 if (waitpid(-1, status, WNOHANG | __WALL) == pid)
149 return;
150 usleep(1000);
151 }
152 DIR* dir = opendir("/sys/fs/fuse/connections");
153 if (dir) {
154 for (;;) {
155 struct dirent* ent = readdir(dir);
156 if (!ent)
157 break;
158 if (strcmp(ent->d_name, ".") == 0 || strcmp(ent->d_name, "..") == 0)
159 continue;
160 char abort[300];
161 snprintf(abort, sizeof(abort), "/sys/fs/fuse/connections/%s/abort",
162 ent->d_name);
163 int fd = open(abort, O_WRONLY);
164 if (fd == -1) {
165 continue;
166 }
167 if (write(fd, abort, 1) < 0) {
168 }
169 close(fd);
170 }
171 closedir(dir);
172 } else {
173 }
174 while (waitpid(-1, status, __WALL) != pid) {
175 }
176 }
177
178 #define SYZ_HAVE_SETUP_TEST 1
setup_test(void)179 static void setup_test(void)
180 {
181 prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0);
182 setpgrp();
183 write_file("/proc/self/oom_score_adj", "1000");
184 }
185
186 struct thread_t {
187 int created, call;
188 event_t ready, done;
189 };
190
191 static struct thread_t threads[16];
192 static void execute_call(int call);
193 static int running;
194
thr(void * arg)195 static void* thr(void* arg)
196 {
197 struct thread_t* th = (struct thread_t*)arg;
198 for (;;) {
199 event_wait(&th->ready);
200 event_reset(&th->ready);
201 execute_call(th->call);
202 __atomic_fetch_sub(&running, 1, __ATOMIC_RELAXED);
203 event_set(&th->done);
204 }
205 return 0;
206 }
207
execute_one(void)208 static void execute_one(void)
209 {
210 int i, call, thread;
211 for (call = 0; call < 3; call++) {
212 for (thread = 0; thread < (int)(sizeof(threads) / sizeof(threads[0]));
213 thread++) {
214 struct thread_t* th = &threads[thread];
215 if (!th->created) {
216 th->created = 1;
217 event_init(&th->ready);
218 event_init(&th->done);
219 event_set(&th->done);
220 thread_start(thr, th);
221 }
222 if (!event_isset(&th->done))
223 continue;
224 event_reset(&th->done);
225 th->call = call;
226 __atomic_fetch_add(&running, 1, __ATOMIC_RELAXED);
227 event_set(&th->ready);
228 event_timedwait(&th->done, 45);
229 break;
230 }
231 }
232 for (i = 0; i < 100 && __atomic_load_n(&running, __ATOMIC_RELAXED); i++)
233 sleep_ms(1);
234 }
235
236 static void execute_one(void);
237
238 #define WAIT_FLAGS __WALL
239
loop(void)240 static void loop(void)
241 {
242 for (;;) {
243 int pid = fork();
244 if (pid < 0)
245 exit(1);
246 if (pid == 0) {
247 setup_test();
248 execute_one();
249 exit(0);
250 }
251 int status = 0;
252 uint64_t start = current_time_ms();
253 for (;;) {
254 if (waitpid(-1, &status, WNOHANG | WAIT_FLAGS) == pid)
255 break;
256 sleep_ms(1);
257 if (current_time_ms() - start < 5 * 1000)
258 continue;
259 kill_and_wait(pid, &status);
260 break;
261 }
262 }
263 }
264
265 static uint64_t r[1] = {0xffffffffffffffff};
266
execute_call(int call)267 void execute_call(int call)
268 {
269 long res;
270 switch (call) {
271 case 0:
272 *(uint32_t*)0x20000040 = 0;
273 *(uint32_t*)0x20000044 = 0;
274 *(uint32_t*)0x20000048 = 0;
275 *(uint32_t*)0x2000004c = 0;
276 *(uint32_t*)0x20000050 = 0;
277 *(uint32_t*)0x20000054 = 0;
278 *(uint32_t*)0x20000058 = 0;
279 *(uint32_t*)0x2000005c = 0;
280 *(uint32_t*)0x20000060 = 0;
281 *(uint32_t*)0x20000064 = 0;
282 *(uint32_t*)0x20000068 = 0;
283 *(uint32_t*)0x2000006c = 0;
284 *(uint32_t*)0x20000070 = 0;
285 *(uint32_t*)0x20000074 = 0;
286 *(uint32_t*)0x20000078 = 0;
287 *(uint32_t*)0x2000007c = 0;
288 *(uint32_t*)0x20000080 = 0;
289 *(uint32_t*)0x20000084 = 0;
290 *(uint64_t*)0x20000088 = 0;
291 *(uint32_t*)0x20000090 = 0;
292 *(uint32_t*)0x20000094 = 0;
293 *(uint32_t*)0x20000098 = 0;
294 *(uint32_t*)0x2000009c = 0;
295 *(uint32_t*)0x200000a0 = 0;
296 *(uint32_t*)0x200000a4 = 0;
297 *(uint32_t*)0x200000a8 = 0;
298 *(uint32_t*)0x200000ac = 0;
299 *(uint64_t*)0x200000b0 = 0;
300 res = __sys_io_uring_setup(0x64, (struct io_uring_params *) 0x20000040UL);
301 if (res != -1)
302 r[0] = res;
303 break;
304 case 1:
305 __sys_io_uring_register((long)r[0], 0, 0, 0);
306 break;
307 case 2:
308 __sys_io_uring_register((long)r[0], 0, 0, 0);
309 break;
310 }
311 }
312
sig_int(int sig)313 static void sig_int(int sig)
314 {
315 exit(0);
316 }
317
main(int argc,char * argv[])318 int main(int argc, char *argv[])
319 {
320 if (argc > 1)
321 return T_EXIT_SKIP;
322 signal(SIGINT, sig_int);
323 mmap((void *) 0x20000000, 0x1000000, 3, MAP_ANON|MAP_PRIVATE, -1, 0);
324 signal(SIGALRM, sig_int);
325 alarm(5);
326
327 loop();
328 return T_EXIT_PASS;
329 }
330