diff options
| author | ilnaz <[email protected]> | 2022-12-13 16:01:38 +0300 |
|---|---|---|
| committer | ilnaz <[email protected]> | 2022-12-13 16:01:38 +0300 |
| commit | f2bea70bea01921ec43846224d100f2c70dd5719 (patch) | |
| tree | eead917572063b63adc1c9a76284c8fbd10f25a3 /contrib/libs/liburing/test/sqpoll-disable-exit.c | |
| parent | 1ab9ee3dfe0ab4023a3a57bf55de31dff3eac908 (diff) | |
Add cross-link
Diffstat (limited to 'contrib/libs/liburing/test/sqpoll-disable-exit.c')
| -rw-r--r-- | contrib/libs/liburing/test/sqpoll-disable-exit.c | 197 |
1 files changed, 197 insertions, 0 deletions
diff --git a/contrib/libs/liburing/test/sqpoll-disable-exit.c b/contrib/libs/liburing/test/sqpoll-disable-exit.c new file mode 100644 index 00000000000..b2a4160c589 --- /dev/null +++ b/contrib/libs/liburing/test/sqpoll-disable-exit.c @@ -0,0 +1,197 @@ +#include "../config-host.h" +/* SPDX-License-Identifier: MIT */ +// https://syzkaller.appspot.com/bug?id=99f4ea77bb9b9ef24cefb66469be319f4aa9f162 +// autogenerated by syzkaller (https://github.com/google/syzkaller) + +#include <dirent.h> +#include <endian.h> +#include <errno.h> +#include <fcntl.h> +#include <signal.h> +#include <stdarg.h> +#include <stdbool.h> +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/mman.h> +#include <sys/prctl.h> +#include <sys/stat.h> +#include <sys/types.h> +#include <sys/wait.h> +#include <time.h> +#include <unistd.h> + +#include "liburing.h" +#include "../src/syscall.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 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; +} + +#define SIZEOF_IO_URING_SQE 64 +#define SIZEOF_IO_URING_CQE 16 +#define SQ_HEAD_OFFSET 0 +#define SQ_TAIL_OFFSET 64 +#define SQ_RING_MASK_OFFSET 256 +#define SQ_RING_ENTRIES_OFFSET 264 +#define SQ_FLAGS_OFFSET 276 +#define SQ_DROPPED_OFFSET 272 +#define CQ_HEAD_OFFSET 128 +#define CQ_TAIL_OFFSET 192 +#define CQ_RING_MASK_OFFSET 260 +#define CQ_RING_ENTRIES_OFFSET 268 +#define CQ_RING_OVERFLOW_OFFSET 284 +#define CQ_FLAGS_OFFSET 280 +#define CQ_CQES_OFFSET 320 + +static long syz_io_uring_setup(volatile long a0, volatile long a1, + volatile long a2, volatile long a3, + volatile long a4, volatile long a5) +{ + uint32_t entries = (uint32_t)a0; + struct io_uring_params* setup_params = (struct io_uring_params*)a1; + void* vma1 = (void*)a2; + void* vma2 = (void*)a3; + void** ring_ptr_out = (void**)a4; + void** sqes_ptr_out = (void**)a5; + uint32_t fd_io_uring = __sys_io_uring_setup(entries, setup_params); + uint32_t sq_ring_sz = + setup_params->sq_off.array + setup_params->sq_entries * sizeof(uint32_t); + uint32_t cq_ring_sz = setup_params->cq_off.cqes + + setup_params->cq_entries * SIZEOF_IO_URING_CQE; + uint32_t ring_sz = sq_ring_sz > cq_ring_sz ? sq_ring_sz : cq_ring_sz; + *ring_ptr_out = mmap(vma1, ring_sz, PROT_READ | PROT_WRITE, + MAP_SHARED | MAP_POPULATE | MAP_FIXED, fd_io_uring, + IORING_OFF_SQ_RING); + uint32_t sqes_sz = setup_params->sq_entries * SIZEOF_IO_URING_SQE; + *sqes_ptr_out = + mmap(vma2, sqes_sz, PROT_READ | PROT_WRITE, + MAP_SHARED | MAP_POPULATE | MAP_FIXED, fd_io_uring, IORING_OFF_SQES); + return fd_io_uring; +} + +static void kill_and_wait(int pid, int* status) +{ + kill(-pid, SIGKILL); + kill(pid, SIGKILL); + for (int 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) { + } +} + +static void setup_test() +{ + prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0); + setpgrp(); + write_file("/proc/self/oom_score_adj", "1000"); +} + +static void execute_one(void); + +#define WAIT_FLAGS __WALL + +static void loop(void) +{ + int iter = 0; + for (; iter < 100; 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 < 5000) { + continue; + } + kill_and_wait(pid, &status); + break; + } + } +} + +void execute_one(void) +{ + *(uint32_t*)0x20000044 = 0; + *(uint32_t*)0x20000048 = 0x42; + *(uint32_t*)0x2000004c = 0; + *(uint32_t*)0x20000050 = 0; + *(uint32_t*)0x20000058 = -1; + *(uint32_t*)0x2000005c = 0; + *(uint32_t*)0x20000060 = 0; + *(uint32_t*)0x20000064 = 0; + syz_io_uring_setup(0x74bc, 0x20000040, 0x20ffb000, 0x20ffc000, 0, 0); +} +int main(void) +{ + mmap((void *)0x1ffff000ul, 0x1000ul, 0ul, 0x32ul, -1, 0ul); + mmap((void *)0x20000000ul, 0x1000000ul, 7ul, 0x32ul, -1, 0ul); + mmap((void *)0x21000000ul, 0x1000ul, 0ul, 0x32ul, -1, 0ul); + loop(); + return 0; +} |
