blob: 7cdfdd70d5bdb93bc32ae4fa079f38ac16f476ee [file] [log] [blame]
Jens Axboee5024352020-02-11 20:34:12 -07001/* SPDX-License-Identifier: MIT */
Jens Axboe78f59df2019-04-23 12:05:18 -06002// 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>
Jens Axboe459e8952020-04-24 07:39:24 -060023#include <sys/mman.h>
Jens Axboe78f59df2019-04-23 12:05:18 -060024
25#include <linux/futex.h>
26
27static void sleep_ms(uint64_t ms)
28{
29 usleep(ms * 1000);
30}
31
32static uint64_t current_time_ms(void)
33{
34 struct timespec ts;
35 if (clock_gettime(CLOCK_MONOTONIC, &ts))
36 exit(1);
37 return (uint64_t)ts.tv_sec * 1000 + (uint64_t)ts.tv_nsec / 1000000;
38}
39
40static void thread_start(void* (*fn)(void*), void* arg)
41{
42 pthread_t th;
43 pthread_attr_t attr;
44 pthread_attr_init(&attr);
45 pthread_attr_setstacksize(&attr, 128 << 10);
46 int i;
47 for (i = 0; i < 100; i++) {
48 if (pthread_create(&th, &attr, fn, arg) == 0) {
49 pthread_attr_destroy(&attr);
50 return;
51 }
52 if (errno == EAGAIN) {
53 usleep(50);
54 continue;
55 }
56 break;
57 }
58 exit(1);
59}
60
61typedef struct {
62 int state;
63} event_t;
64
65static void event_init(event_t* ev)
66{
67 ev->state = 0;
68}
69
70static void event_reset(event_t* ev)
71{
72 ev->state = 0;
73}
74
75static void event_set(event_t* ev)
76{
77 if (ev->state)
78 exit(1);
79 __atomic_store_n(&ev->state, 1, __ATOMIC_RELEASE);
80 syscall(SYS_futex, &ev->state, FUTEX_WAKE | FUTEX_PRIVATE_FLAG);
81}
82
83static void event_wait(event_t* ev)
84{
85 while (!__atomic_load_n(&ev->state, __ATOMIC_ACQUIRE))
86 syscall(SYS_futex, &ev->state, FUTEX_WAIT | FUTEX_PRIVATE_FLAG, 0, 0);
87}
88
89static int event_isset(event_t* ev)
90{
91 return __atomic_load_n(&ev->state, __ATOMIC_ACQUIRE);
92}
93
94static int event_timedwait(event_t* ev, uint64_t timeout)
95{
96 uint64_t start = current_time_ms();
97 uint64_t now = start;
98 for (;;) {
99 uint64_t remain = timeout - (now - start);
100 struct timespec ts;
101 ts.tv_sec = remain / 1000;
102 ts.tv_nsec = (remain % 1000) * 1000 * 1000;
103 syscall(SYS_futex, &ev->state, FUTEX_WAIT | FUTEX_PRIVATE_FLAG, 0, &ts);
104 if (__atomic_load_n(&ev->state, __ATOMIC_RELAXED))
105 return 1;
106 now = current_time_ms();
107 if (now - start > timeout)
108 return 0;
109 }
110}
111
112static bool write_file(const char* file, const char* what, ...)
113{
114 char buf[1024];
115 va_list args;
116 va_start(args, what);
117 vsnprintf(buf, sizeof(buf), what, args);
118 va_end(args);
119 buf[sizeof(buf) - 1] = 0;
120 int len = strlen(buf);
121 int fd = open(file, O_WRONLY | O_CLOEXEC);
122 if (fd == -1)
123 return false;
124 if (write(fd, buf, len) != len) {
125 int err = errno;
126 close(fd);
127 errno = err;
128 return false;
129 }
130 close(fd);
131 return true;
132}
133
134static void kill_and_wait(int pid, int* status)
135{
136 kill(-pid, SIGKILL);
137 kill(pid, SIGKILL);
138 int i;
139 for (i = 0; i < 100; i++) {
140 if (waitpid(-1, status, WNOHANG | __WALL) == pid)
141 return;
142 usleep(1000);
143 }
144 DIR* dir = opendir("/sys/fs/fuse/connections");
145 if (dir) {
146 for (;;) {
147 struct dirent* ent = readdir(dir);
148 if (!ent)
149 break;
150 if (strcmp(ent->d_name, ".") == 0 || strcmp(ent->d_name, "..") == 0)
151 continue;
152 char abort[300];
153 snprintf(abort, sizeof(abort), "/sys/fs/fuse/connections/%s/abort",
154 ent->d_name);
155 int fd = open(abort, O_WRONLY);
156 if (fd == -1) {
157 continue;
158 }
159 if (write(fd, abort, 1) < 0) {
160 }
161 close(fd);
162 }
163 closedir(dir);
164 } else {
165 }
166 while (waitpid(-1, status, __WALL) != pid) {
167 }
168}
169
170#define SYZ_HAVE_SETUP_TEST 1
171static void setup_test()
172{
173 prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0);
174 setpgrp();
175 write_file("/proc/self/oom_score_adj", "1000");
176}
177
178struct thread_t {
179 int created, call;
180 event_t ready, done;
181};
182
183static struct thread_t threads[16];
184static void execute_call(int call);
185static int running;
186
187static void* thr(void* arg)
188{
189 struct thread_t* th = (struct thread_t*)arg;
190 for (;;) {
191 event_wait(&th->ready);
192 event_reset(&th->ready);
193 execute_call(th->call);
194 __atomic_fetch_sub(&running, 1, __ATOMIC_RELAXED);
195 event_set(&th->done);
196 }
197 return 0;
198}
199
200static void execute_one(void)
201{
202 int i, call, thread;
203 for (call = 0; call < 3; call++) {
204 for (thread = 0; thread < (int)(sizeof(threads) / sizeof(threads[0]));
205 thread++) {
206 struct thread_t* th = &threads[thread];
207 if (!th->created) {
208 th->created = 1;
209 event_init(&th->ready);
210 event_init(&th->done);
211 event_set(&th->done);
212 thread_start(thr, th);
213 }
214 if (!event_isset(&th->done))
215 continue;
216 event_reset(&th->done);
217 th->call = call;
218 __atomic_fetch_add(&running, 1, __ATOMIC_RELAXED);
219 event_set(&th->ready);
220 event_timedwait(&th->done, 45);
221 break;
222 }
223 }
224 for (i = 0; i < 100 && __atomic_load_n(&running, __ATOMIC_RELAXED); i++)
225 sleep_ms(1);
226}
227
228static void execute_one(void);
229
230#define WAIT_FLAGS __WALL
231
232static void loop(void)
233{
234 int iter;
235 for (iter = 0;; iter++) {
236 int pid = fork();
237 if (pid < 0)
238 exit(1);
239 if (pid == 0) {
240 setup_test();
241 execute_one();
242 exit(0);
243 }
244 int status = 0;
245 uint64_t start = current_time_ms();
246 for (;;) {
247 if (waitpid(-1, &status, WNOHANG | WAIT_FLAGS) == pid)
248 break;
249 sleep_ms(1);
250 if (current_time_ms() - start < 5 * 1000)
251 continue;
252 kill_and_wait(pid, &status);
253 break;
254 }
255 }
256}
257
258#ifndef __NR_io_uring_register
259#define __NR_io_uring_register 427
260#endif
261#ifndef __NR_io_uring_setup
262#define __NR_io_uring_setup 425
263#endif
Jens Axboe78f59df2019-04-23 12:05:18 -0600264
265uint64_t r[1] = {0xffffffffffffffff};
266
267void 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 = syscall(__NR_io_uring_setup, 0x64, 0x20000040);
301 if (res != -1)
302 r[0] = res;
303 break;
304 case 1:
305 syscall(__NR_io_uring_register, (long)r[0], 0, 0, 0);
306 break;
307 case 2:
308 syscall(__NR_io_uring_register, (long)r[0], 0, 0, 0);
309 break;
310 }
311}
Jens Axboeb00ba562019-10-08 12:23:38 -0600312
313static void sig_int(int sig)
314{
315 exit(0);
316}
317
Jens Axboe78f59df2019-04-23 12:05:18 -0600318int main(void)
319{
Jens Axboeb00ba562019-10-08 12:23:38 -0600320 signal(SIGINT, sig_int);
Jens Axboe459e8952020-04-24 07:39:24 -0600321 mmap((void *) 0x20000000, 0x1000000, 3, 0x32, -1, 0);
Jens Axboe78f59df2019-04-23 12:05:18 -0600322 loop();
323 return 0;
324}