summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJens Axboe <axboe@kernel.dk>2019-04-23 12:05:18 -0600
committerJens Axboe <axboe@kernel.dk>2019-04-23 12:06:18 -0600
commit78f59df3339191a500d9a27e2fe9d2eea888a2e0 (patch)
treefb2dbc860f04220d8547791959a6a8bbfb1460f2
parentad45ed1d67833ccea7f20c60c0cd503e52998a56 (diff)
downloadliburing-78f59df3339191a500d9a27e2fe9d2eea888a2e0.tar.gz
liburing-78f59df3339191a500d9a27e2fe9d2eea888a2e0.tar.bz2
Add regression test cases for three recent issues
Signed-off-by: Jens Axboe <axboe@kernel.dk>
-rw-r--r--test/35fa71a030ca-test.c318
-rw-r--r--test/917257daa0fe-test.c50
-rw-r--r--test/Makefile12
-rw-r--r--test/b19062a56726-test.c50
4 files changed, 428 insertions, 2 deletions
diff --git a/test/35fa71a030ca-test.c b/test/35fa71a030ca-test.c
new file mode 100644
index 0000000..17e062b
--- /dev/null
+++ b/test/35fa71a030ca-test.c
@@ -0,0 +1,318 @@
+// autogenerated by syzkaller (https://github.com/google/syzkaller)
+
+#include <dirent.h>
+#include <endian.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <pthread.h>
+#include <signal.h>
+#include <stdarg.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/prctl.h>
+#include <sys/stat.h>
+#include <sys/syscall.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <time.h>
+#include <unistd.h>
+
+#include <linux/futex.h>
+
+static void sleep_ms(uint64_t ms)
+{
+ usleep(ms * 1000);
+}
+
+static uint64_t current_time_ms(void)
+{
+ struct timespec ts;
+ if (clock_gettime(CLOCK_MONOTONIC, &ts))
+ exit(1);
+ return (uint64_t)ts.tv_sec * 1000 + (uint64_t)ts.tv_nsec / 1000000;
+}
+
+static void thread_start(void* (*fn)(void*), void* arg)
+{
+ pthread_t th;
+ pthread_attr_t attr;
+ pthread_attr_init(&attr);
+ pthread_attr_setstacksize(&attr, 128 << 10);
+ int i;
+ for (i = 0; i < 100; i++) {
+ if (pthread_create(&th, &attr, fn, arg) == 0) {
+ pthread_attr_destroy(&attr);
+ return;
+ }
+ if (errno == EAGAIN) {
+ usleep(50);
+ continue;
+ }
+ break;
+ }
+ exit(1);
+}
+
+typedef struct {
+ int state;
+} event_t;
+
+static void event_init(event_t* ev)
+{
+ ev->state = 0;
+}
+
+static void event_reset(event_t* ev)
+{
+ ev->state = 0;
+}
+
+static void event_set(event_t* ev)
+{
+ if (ev->state)
+ exit(1);
+ __atomic_store_n(&ev->state, 1, __ATOMIC_RELEASE);
+ syscall(SYS_futex, &ev->state, FUTEX_WAKE | FUTEX_PRIVATE_FLAG);
+}
+
+static void event_wait(event_t* ev)
+{
+ while (!__atomic_load_n(&ev->state, __ATOMIC_ACQUIRE))
+ syscall(SYS_futex, &ev->state, FUTEX_WAIT | FUTEX_PRIVATE_FLAG, 0, 0);
+}
+
+static int event_isset(event_t* ev)
+{
+ return __atomic_load_n(&ev->state, __ATOMIC_ACQUIRE);
+}
+
+static int event_timedwait(event_t* ev, uint64_t timeout)
+{
+ uint64_t start = current_time_ms();
+ uint64_t now = start;
+ for (;;) {
+ uint64_t remain = timeout - (now - start);
+ struct timespec ts;
+ ts.tv_sec = remain / 1000;
+ ts.tv_nsec = (remain % 1000) * 1000 * 1000;
+ syscall(SYS_futex, &ev->state, FUTEX_WAIT | FUTEX_PRIVATE_FLAG, 0, &ts);
+ if (__atomic_load_n(&ev->state, __ATOMIC_RELAXED))
+ return 1;
+ now = current_time_ms();
+ if (now - start > timeout)
+ return 0;
+ }
+}
+
+static bool write_file(const char* file, const char* what, ...)
+{
+ char buf[1024];
+ va_list args;
+ va_start(args, what);
+ vsnprintf(buf, sizeof(buf), what, args);
+ va_end(args);
+ buf[sizeof(buf) - 1] = 0;
+ int len = strlen(buf);
+ int fd = open(file, O_WRONLY | O_CLOEXEC);
+ if (fd == -1)
+ return false;
+ if (write(fd, buf, len) != len) {
+ int err = errno;
+ close(fd);
+ errno = err;
+ return false;
+ }
+ close(fd);
+ return true;
+}
+
+static void kill_and_wait(int pid, int* status)
+{
+ kill(-pid, SIGKILL);
+ kill(pid, SIGKILL);
+ int i;
+ for (i = 0; i < 100; i++) {
+ if (waitpid(-1, status, WNOHANG | __WALL) == pid)
+ return;
+ usleep(1000);
+ }
+ DIR* dir = opendir("/sys/fs/fuse/connections");
+ if (dir) {
+ for (;;) {
+ struct dirent* ent = readdir(dir);
+ if (!ent)
+ break;
+ if (strcmp(ent->d_name, ".") == 0 || strcmp(ent->d_name, "..") == 0)
+ continue;
+ char abort[300];
+ snprintf(abort, sizeof(abort), "/sys/fs/fuse/connections/%s/abort",
+ ent->d_name);
+ int fd = open(abort, O_WRONLY);
+ if (fd == -1) {
+ continue;
+ }
+ if (write(fd, abort, 1) < 0) {
+ }
+ close(fd);
+ }
+ closedir(dir);
+ } else {
+ }
+ while (waitpid(-1, status, __WALL) != pid) {
+ }
+}
+
+#define SYZ_HAVE_SETUP_TEST 1
+static void setup_test()
+{
+ prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0);
+ setpgrp();
+ write_file("/proc/self/oom_score_adj", "1000");
+}
+
+struct thread_t {
+ int created, call;
+ event_t ready, done;
+};
+
+static struct thread_t threads[16];
+static void execute_call(int call);
+static int running;
+
+static void* thr(void* arg)
+{
+ struct thread_t* th = (struct thread_t*)arg;
+ for (;;) {
+ event_wait(&th->ready);
+ event_reset(&th->ready);
+ execute_call(th->call);
+ __atomic_fetch_sub(&running, 1, __ATOMIC_RELAXED);
+ event_set(&th->done);
+ }
+ return 0;
+}
+
+static void execute_one(void)
+{
+ int i, call, thread;
+ for (call = 0; call < 3; call++) {
+ for (thread = 0; thread < (int)(sizeof(threads) / sizeof(threads[0]));
+ thread++) {
+ struct thread_t* th = &threads[thread];
+ if (!th->created) {
+ th->created = 1;
+ event_init(&th->ready);
+ event_init(&th->done);
+ event_set(&th->done);
+ thread_start(thr, th);
+ }
+ if (!event_isset(&th->done))
+ continue;
+ event_reset(&th->done);
+ th->call = call;
+ __atomic_fetch_add(&running, 1, __ATOMIC_RELAXED);
+ event_set(&th->ready);
+ event_timedwait(&th->done, 45);
+ break;
+ }
+ }
+ for (i = 0; i < 100 && __atomic_load_n(&running, __ATOMIC_RELAXED); i++)
+ sleep_ms(1);
+}
+
+static void execute_one(void);
+
+#define WAIT_FLAGS __WALL
+
+static void loop(void)
+{
+ int iter;
+ for (iter = 0;; iter++) {
+ int pid = fork();
+ if (pid < 0)
+ exit(1);
+ if (pid == 0) {
+ setup_test();
+ execute_one();
+ exit(0);
+ }
+ int status = 0;
+ uint64_t start = current_time_ms();
+ for (;;) {
+ if (waitpid(-1, &status, WNOHANG | WAIT_FLAGS) == pid)
+ break;
+ sleep_ms(1);
+ if (current_time_ms() - start < 5 * 1000)
+ continue;
+ kill_and_wait(pid, &status);
+ break;
+ }
+ }
+}
+
+#ifndef __NR_io_uring_register
+#define __NR_io_uring_register 427
+#endif
+#ifndef __NR_io_uring_setup
+#define __NR_io_uring_setup 425
+#endif
+#ifndef __NR_mmap
+#define __NR_mmap 192
+#endif
+
+uint64_t r[1] = {0xffffffffffffffff};
+
+void execute_call(int call)
+{
+ long res;
+ switch (call) {
+ case 0:
+ *(uint32_t*)0x20000040 = 0;
+ *(uint32_t*)0x20000044 = 0;
+ *(uint32_t*)0x20000048 = 0;
+ *(uint32_t*)0x2000004c = 0;
+ *(uint32_t*)0x20000050 = 0;
+ *(uint32_t*)0x20000054 = 0;
+ *(uint32_t*)0x20000058 = 0;
+ *(uint32_t*)0x2000005c = 0;
+ *(uint32_t*)0x20000060 = 0;
+ *(uint32_t*)0x20000064 = 0;
+ *(uint32_t*)0x20000068 = 0;
+ *(uint32_t*)0x2000006c = 0;
+ *(uint32_t*)0x20000070 = 0;
+ *(uint32_t*)0x20000074 = 0;
+ *(uint32_t*)0x20000078 = 0;
+ *(uint32_t*)0x2000007c = 0;
+ *(uint32_t*)0x20000080 = 0;
+ *(uint32_t*)0x20000084 = 0;
+ *(uint64_t*)0x20000088 = 0;
+ *(uint32_t*)0x20000090 = 0;
+ *(uint32_t*)0x20000094 = 0;
+ *(uint32_t*)0x20000098 = 0;
+ *(uint32_t*)0x2000009c = 0;
+ *(uint32_t*)0x200000a0 = 0;
+ *(uint32_t*)0x200000a4 = 0;
+ *(uint32_t*)0x200000a8 = 0;
+ *(uint32_t*)0x200000ac = 0;
+ *(uint64_t*)0x200000b0 = 0;
+ res = syscall(__NR_io_uring_setup, 0x64, 0x20000040);
+ if (res != -1)
+ r[0] = res;
+ break;
+ case 1:
+ syscall(__NR_io_uring_register, (long)r[0], 0, 0, 0);
+ break;
+ case 2:
+ syscall(__NR_io_uring_register, (long)r[0], 0, 0, 0);
+ break;
+ }
+}
+int main(void)
+{
+ syscall(__NR_mmap, 0x20000000, 0x1000000, 3, 0x32, -1, 0);
+ loop();
+ return 0;
+}
diff --git a/test/917257daa0fe-test.c b/test/917257daa0fe-test.c
new file mode 100644
index 0000000..a5378a7
--- /dev/null
+++ b/test/917257daa0fe-test.c
@@ -0,0 +1,50 @@
+// autogenerated by syzkaller (https://github.com/google/syzkaller)
+
+#include <endian.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/syscall.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#ifndef __NR_io_uring_setup
+#define __NR_io_uring_setup 425
+#endif
+
+int main(void)
+{
+ syscall(__NR_mmap, 0x20000000, 0x1000000, 3, 0x32, -1, 0);
+
+ *(uint32_t*)0x20000000 = 0;
+ *(uint32_t*)0x20000004 = 0;
+ *(uint32_t*)0x20000008 = 6;
+ *(uint32_t*)0x2000000c = 0;
+ *(uint32_t*)0x20000010 = 0x3af;
+ *(uint32_t*)0x20000014 = 0;
+ *(uint32_t*)0x20000018 = 0;
+ *(uint32_t*)0x2000001c = 0;
+ *(uint32_t*)0x20000020 = 0;
+ *(uint32_t*)0x20000024 = 0;
+ *(uint32_t*)0x20000028 = 0;
+ *(uint32_t*)0x2000002c = 0;
+ *(uint32_t*)0x20000030 = 0;
+ *(uint32_t*)0x20000034 = 0;
+ *(uint32_t*)0x20000038 = 0;
+ *(uint32_t*)0x2000003c = 0;
+ *(uint32_t*)0x20000040 = 0;
+ *(uint32_t*)0x20000044 = 0;
+ *(uint64_t*)0x20000048 = 0;
+ *(uint32_t*)0x20000050 = 0;
+ *(uint32_t*)0x20000054 = 0;
+ *(uint32_t*)0x20000058 = 0;
+ *(uint32_t*)0x2000005c = 0;
+ *(uint32_t*)0x20000060 = 0;
+ *(uint32_t*)0x20000064 = 0;
+ *(uint32_t*)0x20000068 = 0;
+ *(uint32_t*)0x2000006c = 0;
+ *(uint64_t*)0x20000070 = 0;
+ syscall(__NR_io_uring_setup, 0x7a6, 0x20000000);
+ return 0;
+}
diff --git a/test/Makefile b/test/Makefile
index 08b0c42..d2a3cc4 100644
--- a/test/Makefile
+++ b/test/Makefile
@@ -1,12 +1,14 @@
CFLAGS ?= -g -O2 -Wall -D_GNU_SOURCE -L../src/
all_targets += poll poll-cancel ring-leak fsync io_uring_setup io_uring_register \
- io_uring_enter nop sq-full cq-full
+ io_uring_enter nop sq-full cq-full 35fa71a030ca-test \
+ 917257daa0fe-test b19062a56726-test
all: $(all_targets)
test_srcs := poll.c poll-cancel.c ring-leak.c fsync.c io_uring_setup.c \
- io_uring_register.c io_uring_enter.c nop.c sq-full.c cq-full.c
+ io_uring_register.c io_uring_enter.c nop.c sq-full.c cq-full.c \
+ 35fa71a030ca-test.c 917257daa0fe-test.c b19062a56726-test.c
test_objs := $(patsubst %.c,%.ol,$(test_srcs))
@@ -30,6 +32,12 @@ sq-full: sq-full.c
$(CC) $(CFLAGS) -o $@ sq-full.c -luring
cq-full: cq-full.c
$(CC) $(CFLAGS) -o $@ cq-full.c -luring
+35fa71a030ca-test: 35fa71a030ca-test.c
+ $(CC) $(CFLAGS) -o $@ 35fa71a030ca-test.c -lpthread
+917257daa0fe-test: 917257daa0fe-test.c
+ $(CC) $(CFLAGS) -o $@ 917257daa0fe-test.c
+b19062a56726-test: b19062a56726-test.c
+ $(CC) $(CFLAGS) -o $@ b19062a56726-test.c
clean:
rm -f $(all_targets) $(test_objs)
diff --git a/test/b19062a56726-test.c b/test/b19062a56726-test.c
new file mode 100644
index 0000000..62d4645
--- /dev/null
+++ b/test/b19062a56726-test.c
@@ -0,0 +1,50 @@
+// autogenerated by syzkaller (https://github.com/google/syzkaller)
+
+#include <endian.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/syscall.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#ifndef __NR_io_uring_setup
+#define __NR_io_uring_setup 425
+#endif
+
+int main(void)
+{
+ syscall(__NR_mmap, 0x20000000, 0x1000000, 3, 0x32, -1, 0);
+
+ *(uint32_t*)0x20000200 = 0;
+ *(uint32_t*)0x20000204 = 0;
+ *(uint32_t*)0x20000208 = 5;
+ *(uint32_t*)0x2000020c = 0x400;
+ *(uint32_t*)0x20000210 = 0;
+ *(uint32_t*)0x20000214 = 0;
+ *(uint32_t*)0x20000218 = 0;
+ *(uint32_t*)0x2000021c = 0;
+ *(uint32_t*)0x20000220 = 0;
+ *(uint32_t*)0x20000224 = 0;
+ *(uint32_t*)0x20000228 = 0;
+ *(uint32_t*)0x2000022c = 0;
+ *(uint32_t*)0x20000230 = 0;
+ *(uint32_t*)0x20000234 = 0;
+ *(uint32_t*)0x20000238 = 0;
+ *(uint32_t*)0x2000023c = 0;
+ *(uint32_t*)0x20000240 = 0;
+ *(uint32_t*)0x20000244 = 0;
+ *(uint64_t*)0x20000248 = 0;
+ *(uint32_t*)0x20000250 = 0;
+ *(uint32_t*)0x20000254 = 0;
+ *(uint32_t*)0x20000258 = 0;
+ *(uint32_t*)0x2000025c = 0;
+ *(uint32_t*)0x20000260 = 0;
+ *(uint32_t*)0x20000264 = 0;
+ *(uint32_t*)0x20000268 = 0;
+ *(uint32_t*)0x2000026c = 0;
+ *(uint64_t*)0x20000270 = 0;
+ syscall(__NR_io_uring_setup, 0xc9f, 0x20000200);
+ return 0;
+}