blob: 428023a06665d47fda66c2a7a504f5d839ecc864 [file] [log] [blame]
// WARNING: bad unlock balance in migration_cpu_stop
// https://syzkaller.appspot.com/bug?id=6eea1643991c65d0b6e48335439cca795de4592d
// status:open
// autogenerated by syzkaller (https://github.com/google/syzkaller)
#define _GNU_SOURCE
#include <dirent.h>
#include <endian.h>
#include <errno.h>
#include <fcntl.h>
#include <setjmp.h>
#include <signal.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/mount.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/loop.h>
unsigned long long procid;
static __thread int skip_segv;
static __thread jmp_buf segv_env;
static void segv_handler(int sig, siginfo_t* info, void* ctx)
{
uintptr_t addr = (uintptr_t)info->si_addr;
const uintptr_t prog_start = 1 << 20;
const uintptr_t prog_end = 100 << 20;
if (__atomic_load_n(&skip_segv, __ATOMIC_RELAXED) &&
(addr < prog_start || addr > prog_end)) {
_longjmp(segv_env, 1);
}
exit(sig);
}
static void install_segv_handler(void)
{
struct sigaction sa;
memset(&sa, 0, sizeof(sa));
sa.sa_handler = SIG_IGN;
syscall(SYS_rt_sigaction, 0x20, &sa, NULL, 8);
syscall(SYS_rt_sigaction, 0x21, &sa, NULL, 8);
memset(&sa, 0, sizeof(sa));
sa.sa_sigaction = segv_handler;
sa.sa_flags = SA_NODEFER | SA_SIGINFO;
sigaction(SIGSEGV, &sa, NULL);
sigaction(SIGBUS, &sa, NULL);
}
#define NONFAILING(...) \
{ \
__atomic_fetch_add(&skip_segv, 1, __ATOMIC_SEQ_CST); \
if (_setjmp(segv_env) == 0) { \
__VA_ARGS__; \
} \
__atomic_fetch_sub(&skip_segv, 1, __ATOMIC_SEQ_CST); \
}
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;
}
#define BITMASK(bf_off, bf_len) (((1ull << (bf_len)) - 1) << (bf_off))
#define STORE_BY_BITMASK(type, htobe, addr, val, bf_off, bf_len) \
*(type*)(addr) = \
htobe((htobe(*(type*)(addr)) & ~BITMASK((bf_off), (bf_len))) | \
(((type)(val) << (bf_off)) & BITMASK((bf_off), (bf_len))))
struct fs_image_segment {
void* data;
uintptr_t size;
uintptr_t offset;
};
#define IMAGE_MAX_SEGMENTS 4096
#define IMAGE_MAX_SIZE (129 << 20)
#define SYZ_memfd_create 319
static long syz_mount_image(long fsarg, long dir, unsigned long size,
unsigned long nsegs, long segments, long flags,
long optsarg)
{
char loopname[64], fs[32], opts[256];
int loopfd, err = 0, res = -1;
unsigned long i;
struct fs_image_segment* segs = (struct fs_image_segment*)segments;
if (nsegs > IMAGE_MAX_SEGMENTS)
nsegs = IMAGE_MAX_SEGMENTS;
for (i = 0; i < nsegs; i++) {
if (segs[i].size > IMAGE_MAX_SIZE)
segs[i].size = IMAGE_MAX_SIZE;
segs[i].offset %= IMAGE_MAX_SIZE;
if (segs[i].offset > IMAGE_MAX_SIZE - segs[i].size)
segs[i].offset = IMAGE_MAX_SIZE - segs[i].size;
if (size < segs[i].offset + segs[i].offset)
size = segs[i].offset + segs[i].offset;
}
if (size > IMAGE_MAX_SIZE)
size = IMAGE_MAX_SIZE;
int memfd = syscall(SYZ_memfd_create, "syz_mount_image", 0);
if (memfd == -1) {
err = errno;
goto error;
}
if (ftruncate(memfd, size)) {
err = errno;
goto error_close_memfd;
}
for (i = 0; i < nsegs; i++) {
if (pwrite(memfd, segs[i].data, segs[i].size, segs[i].offset) < 0) {
}
}
snprintf(loopname, sizeof(loopname), "/dev/loop%llu", procid);
loopfd = open(loopname, O_RDWR);
if (loopfd == -1) {
err = errno;
goto error_close_memfd;
}
if (ioctl(loopfd, LOOP_SET_FD, memfd)) {
if (errno != EBUSY) {
err = errno;
goto error_close_loop;
}
ioctl(loopfd, LOOP_CLR_FD, 0);
usleep(1000);
if (ioctl(loopfd, LOOP_SET_FD, memfd)) {
err = errno;
goto error_close_loop;
}
}
mkdir((char*)dir, 0777);
memset(fs, 0, sizeof(fs));
NONFAILING(strncpy(fs, (char*)fsarg, sizeof(fs) - 1));
memset(opts, 0, sizeof(opts));
NONFAILING(strncpy(opts, (char*)optsarg, sizeof(opts) - 32));
if (strcmp(fs, "iso9660") == 0) {
flags |= MS_RDONLY;
} else if (strncmp(fs, "ext", 3) == 0) {
if (strstr(opts, "errors=panic") || strstr(opts, "errors=remount-ro") == 0)
strcat(opts, ",errors=continue");
} else if (strcmp(fs, "xfs") == 0) {
strcat(opts, ",nouuid");
}
if (mount(loopname, (char*)dir, fs, flags, opts)) {
err = errno;
goto error_clear_loop;
}
res = 0;
error_clear_loop:
ioctl(loopfd, LOOP_CLR_FD, 0);
error_close_loop:
close(loopfd);
error_close_memfd:
close(memfd);
error:
errno = err;
return res;
}
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_RESET_LOOP 1
static void reset_loop()
{
char buf[64];
snprintf(buf, sizeof(buf), "/dev/loop%llu", procid);
int loopfd = open(buf, O_RDWR);
if (loopfd != -1) {
ioctl(loopfd, LOOP_CLR_FD, 0);
close(loopfd);
}
}
#define SYZ_HAVE_SETUP_TEST 1
static void setup_test()
{
prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0);
setpgrp();
}
#define SYZ_HAVE_RESET_TEST 1
static void reset_test()
{
int fd;
for (fd = 3; fd < 30; fd++)
close(fd);
}
static void execute_one(void);
#define WAIT_FLAGS __WALL
static void loop(void)
{
int iter;
for (iter = 0;; iter++) {
reset_loop();
int pid = fork();
if (pid < 0)
exit(1);
if (pid == 0) {
setup_test();
execute_one();
reset_test();
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;
}
}
}
uint64_t r[3] = {0xffffffffffffffff, 0xffffffffffffffff, 0x0};
void execute_one(void)
{
long res = 0;
syscall(__NR_getresuid, 0x20000300, 0, 0);
syscall(__NR_socket, 2, 0x808, 5);
NONFAILING(*(uint32_t*)0x20000040 = 1);
NONFAILING(*(uint32_t*)0x20000044 = 0x70);
NONFAILING(*(uint8_t*)0x20000048 = 0);
NONFAILING(*(uint8_t*)0x20000049 = 0);
NONFAILING(*(uint8_t*)0x2000004a = 0);
NONFAILING(*(uint8_t*)0x2000004b = 0);
NONFAILING(*(uint32_t*)0x2000004c = 0);
NONFAILING(*(uint64_t*)0x20000050 = 0x50d);
NONFAILING(*(uint64_t*)0x20000058 = 0);
NONFAILING(*(uint64_t*)0x20000060 = 0);
NONFAILING(STORE_BY_BITMASK(uint64_t, , 0x20000068, 0, 0, 1));
NONFAILING(STORE_BY_BITMASK(uint64_t, , 0x20000068, 0, 1, 1));
NONFAILING(STORE_BY_BITMASK(uint64_t, , 0x20000068, 0, 2, 1));
NONFAILING(STORE_BY_BITMASK(uint64_t, , 0x20000068, 0, 3, 1));
NONFAILING(STORE_BY_BITMASK(uint64_t, , 0x20000068, 0, 4, 1));
NONFAILING(STORE_BY_BITMASK(uint64_t, , 0x20000068, 0, 5, 1));
NONFAILING(STORE_BY_BITMASK(uint64_t, , 0x20000068, 0, 6, 1));
NONFAILING(STORE_BY_BITMASK(uint64_t, , 0x20000068, 0, 7, 1));
NONFAILING(STORE_BY_BITMASK(uint64_t, , 0x20000068, 0, 8, 1));
NONFAILING(STORE_BY_BITMASK(uint64_t, , 0x20000068, 0, 9, 1));
NONFAILING(STORE_BY_BITMASK(uint64_t, , 0x20000068, 0, 10, 1));
NONFAILING(STORE_BY_BITMASK(uint64_t, , 0x20000068, 0, 11, 1));
NONFAILING(STORE_BY_BITMASK(uint64_t, , 0x20000068, 0, 12, 1));
NONFAILING(STORE_BY_BITMASK(uint64_t, , 0x20000068, 0, 13, 1));
NONFAILING(STORE_BY_BITMASK(uint64_t, , 0x20000068, 0, 14, 1));
NONFAILING(STORE_BY_BITMASK(uint64_t, , 0x20000068, 0, 15, 2));
NONFAILING(STORE_BY_BITMASK(uint64_t, , 0x20000068, 0, 17, 1));
NONFAILING(STORE_BY_BITMASK(uint64_t, , 0x20000068, 0, 18, 1));
NONFAILING(STORE_BY_BITMASK(uint64_t, , 0x20000068, 0, 19, 1));
NONFAILING(STORE_BY_BITMASK(uint64_t, , 0x20000068, 0, 20, 1));
NONFAILING(STORE_BY_BITMASK(uint64_t, , 0x20000068, 0, 21, 1));
NONFAILING(STORE_BY_BITMASK(uint64_t, , 0x20000068, 0, 22, 1));
NONFAILING(STORE_BY_BITMASK(uint64_t, , 0x20000068, 0, 23, 1));
NONFAILING(STORE_BY_BITMASK(uint64_t, , 0x20000068, 0, 24, 1));
NONFAILING(STORE_BY_BITMASK(uint64_t, , 0x20000068, 0, 25, 1));
NONFAILING(STORE_BY_BITMASK(uint64_t, , 0x20000068, 0, 26, 1));
NONFAILING(STORE_BY_BITMASK(uint64_t, , 0x20000068, 0, 27, 1));
NONFAILING(STORE_BY_BITMASK(uint64_t, , 0x20000068, 0, 28, 1));
NONFAILING(STORE_BY_BITMASK(uint64_t, , 0x20000068, 0, 29, 35));
NONFAILING(*(uint32_t*)0x20000070 = 0);
NONFAILING(*(uint32_t*)0x20000074 = 0);
NONFAILING(*(uint64_t*)0x20000078 = 0);
NONFAILING(*(uint64_t*)0x20000080 = 0);
NONFAILING(*(uint64_t*)0x20000088 = 0);
NONFAILING(*(uint64_t*)0x20000090 = 0);
NONFAILING(*(uint32_t*)0x20000098 = 0);
NONFAILING(*(uint32_t*)0x2000009c = 0);
NONFAILING(*(uint64_t*)0x200000a0 = 0);
NONFAILING(*(uint32_t*)0x200000a8 = 0);
NONFAILING(*(uint16_t*)0x200000ac = 0);
NONFAILING(*(uint16_t*)0x200000ae = 0);
res = syscall(__NR_perf_event_open, 0x20000040, 0, 0, -1, 0);
if (res != -1)
r[0] = res;
res = syscall(__NR_socket, 0xa, 2, 0);
if (res != -1)
r[1] = res;
res = syscall(__NR_gettid);
if (res != -1)
r[2] = res;
NONFAILING(*(uint32_t*)0x20000100 = 7);
NONFAILING(*(uint32_t*)0x20000104 = 0x70);
NONFAILING(*(uint8_t*)0x20000108 = 4);
NONFAILING(*(uint8_t*)0x20000109 = 0xc8);
NONFAILING(*(uint8_t*)0x2000010a = 2);
NONFAILING(*(uint8_t*)0x2000010b = 9);
NONFAILING(*(uint32_t*)0x2000010c = 0);
NONFAILING(*(uint64_t*)0x20000110 = 0x1f);
NONFAILING(*(uint64_t*)0x20000118 = 0x2600);
NONFAILING(*(uint64_t*)0x20000120 = 8);
NONFAILING(STORE_BY_BITMASK(uint64_t, , 0x20000128, 0x80, 0, 1));
NONFAILING(STORE_BY_BITMASK(uint64_t, , 0x20000128, 1, 1, 1));
NONFAILING(
STORE_BY_BITMASK(uint64_t, , 0x20000128, 0xfffffffffffffff8, 2, 1));
NONFAILING(STORE_BY_BITMASK(uint64_t, , 0x20000128, 0, 3, 1));
NONFAILING(STORE_BY_BITMASK(uint64_t, , 0x20000128, 0x1000, 4, 1));
NONFAILING(STORE_BY_BITMASK(uint64_t, , 0x20000128, 0x10001, 5, 1));
NONFAILING(STORE_BY_BITMASK(uint64_t, , 0x20000128, 0xffffffff, 6, 1));
NONFAILING(STORE_BY_BITMASK(uint64_t, , 0x20000128, 9, 7, 1));
NONFAILING(STORE_BY_BITMASK(uint64_t, , 0x20000128, 8, 8, 1));
NONFAILING(STORE_BY_BITMASK(uint64_t, , 0x20000128, 9, 9, 1));
NONFAILING(STORE_BY_BITMASK(uint64_t, , 0x20000128, 9, 10, 1));
NONFAILING(STORE_BY_BITMASK(uint64_t, , 0x20000128, 0x100000001, 11, 1));
NONFAILING(STORE_BY_BITMASK(uint64_t, , 0x20000128, 0xff, 12, 1));
NONFAILING(STORE_BY_BITMASK(uint64_t, , 0x20000128, 1, 13, 1));
NONFAILING(STORE_BY_BITMASK(uint64_t, , 0x20000128, 0xe4f, 14, 1));
NONFAILING(STORE_BY_BITMASK(uint64_t, , 0x20000128, 0, 15, 2));
NONFAILING(STORE_BY_BITMASK(uint64_t, , 0x20000128, 0, 17, 1));
NONFAILING(
STORE_BY_BITMASK(uint64_t, , 0x20000128, 0xfffffffffffeffff, 18, 1));
NONFAILING(STORE_BY_BITMASK(uint64_t, , 0x20000128, 0x7fffffff, 19, 1));
NONFAILING(STORE_BY_BITMASK(uint64_t, , 0x20000128, 7, 20, 1));
NONFAILING(STORE_BY_BITMASK(uint64_t, , 0x20000128, 0x72, 21, 1));
NONFAILING(STORE_BY_BITMASK(uint64_t, , 0x20000128, 5, 22, 1));
NONFAILING(STORE_BY_BITMASK(uint64_t, , 0x20000128, 0x4d999846, 23, 1));
NONFAILING(STORE_BY_BITMASK(uint64_t, , 0x20000128, 7, 24, 1));
NONFAILING(STORE_BY_BITMASK(uint64_t, , 0x20000128, 0xb6f, 25, 1));
NONFAILING(STORE_BY_BITMASK(uint64_t, , 0x20000128, 2, 26, 1));
NONFAILING(STORE_BY_BITMASK(uint64_t, , 0x20000128, 0xffff, 27, 1));
NONFAILING(STORE_BY_BITMASK(uint64_t, , 0x20000128, 0xffff, 28, 1));
NONFAILING(STORE_BY_BITMASK(uint64_t, , 0x20000128, 0, 29, 35));
NONFAILING(*(uint32_t*)0x20000130 = 0x3f);
NONFAILING(*(uint32_t*)0x20000134 = 6);
NONFAILING(*(uint64_t*)0x20000138 = 0x200000c0);
NONFAILING(*(uint64_t*)0x20000140 = 0xf);
NONFAILING(*(uint64_t*)0x20000148 = 0x8008);
NONFAILING(*(uint64_t*)0x20000150 = 0x39);
NONFAILING(*(uint32_t*)0x20000158 = 0);
NONFAILING(*(uint32_t*)0x2000015c = 7);
NONFAILING(*(uint64_t*)0x20000160 = 5);
NONFAILING(*(uint32_t*)0x20000168 = 8);
NONFAILING(*(uint16_t*)0x2000016c = 6);
NONFAILING(*(uint16_t*)0x2000016e = 0);
syscall(__NR_perf_event_open, 0x20000100, r[2], 6, r[0], 0xa);
NONFAILING(memcpy((void*)0x20000200, "ext4\000", 5));
NONFAILING(memcpy((void*)0x20000240, "./file0\000", 8));
NONFAILING(*(uint64_t*)0x200002c0 = 0x20000280);
NONFAILING(memcpy((void*)0x20000280,
"\x08\x68\xdb\xee\x5d\x5b\x6d\xcc\x83\xc9\xff\x60\xf6\x13",
14));
NONFAILING(*(uint64_t*)0x200002c8 = 0xe);
NONFAILING(*(uint64_t*)0x200002d0 = 6);
syz_mount_image(0x20000200, 0x20000240, 4, 1, 0x200002c0, 0, 0);
NONFAILING(*(uint16_t*)0x20000000 = 0xa);
NONFAILING(*(uint16_t*)0x20000002 = htobe16(0));
NONFAILING(*(uint32_t*)0x20000004 = htobe32(0));
NONFAILING(*(uint8_t*)0x20000008 = -1);
NONFAILING(*(uint8_t*)0x20000009 = 2);
NONFAILING(*(uint8_t*)0x2000000a = 0);
NONFAILING(*(uint8_t*)0x2000000b = 0);
NONFAILING(*(uint8_t*)0x2000000c = 0);
NONFAILING(*(uint8_t*)0x2000000d = 0);
NONFAILING(*(uint8_t*)0x2000000e = 0);
NONFAILING(*(uint8_t*)0x2000000f = 0);
NONFAILING(*(uint8_t*)0x20000010 = 0);
NONFAILING(*(uint8_t*)0x20000011 = 0);
NONFAILING(*(uint8_t*)0x20000012 = 0);
NONFAILING(*(uint8_t*)0x20000013 = 0);
NONFAILING(*(uint8_t*)0x20000014 = 0);
NONFAILING(*(uint8_t*)0x20000015 = 0);
NONFAILING(*(uint8_t*)0x20000016 = 0);
NONFAILING(*(uint8_t*)0x20000017 = 1);
NONFAILING(*(uint32_t*)0x20000018 = 6);
syscall(__NR_connect, r[1], 0x20000000, 0x1c);
syscall(__NR_sendmmsg, r[1], 0, 0, 0x7ffd);
NONFAILING(*(uint8_t*)0x200001c0 = 6);
NONFAILING(*(uint8_t*)0x200001c1 = 1);
NONFAILING(*(uint16_t*)0x200001c2 = 4);
syscall(__NR_ioctl, -1, 0x4b48, 0x200001c0);
}
int main(void)
{
syscall(__NR_mmap, 0x20000000, 0x1000000, 3, 0x32, -1, 0);
install_segv_handler();
loop();
return 0;
}