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