// autogenerated by syzkaller (https://github.com/google/syzkaller)

#define _GNU_SOURCE 

#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/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>

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;
}

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");
}

#define KMEMLEAK_FILE "/sys/kernel/debug/kmemleak"

static const char* setup_leak()
{
	if (!write_file(KMEMLEAK_FILE, "scan=off")) {
		if (errno == EBUSY)
			return "KMEMLEAK disabled: increase CONFIG_DEBUG_KMEMLEAK_EARLY_LOG_SIZE"
			       " or unset CONFIG_DEBUG_KMEMLEAK_DEFAULT_OFF";
		return "failed to write(kmemleak, \"scan=off\")";
	}
	if (!write_file(KMEMLEAK_FILE, "scan"))
		return "failed to write(kmemleak, \"scan\")";
	sleep(5);
	if (!write_file(KMEMLEAK_FILE, "scan"))
		return "failed to write(kmemleak, \"scan\")";
	if (!write_file(KMEMLEAK_FILE, "clear"))
		return "failed to write(kmemleak, \"clear\")";
	return NULL;
}

static void check_leaks(void)
{
	int fd = open(KMEMLEAK_FILE, O_RDWR);
	if (fd == -1)
	exit(1);
	uint64_t start = current_time_ms();
	if (write(fd, "scan", 4) != 4)
	exit(1);
	sleep(1);
	while (current_time_ms() - start < 4 * 1000)
		sleep(1);
	if (write(fd, "scan", 4) != 4)
	exit(1);
	static char buf[128 << 10];
	ssize_t n = read(fd, buf, sizeof(buf) - 1);
	if (n < 0)
	exit(1);
	int nleaks = 0;
	if (n != 0) {
		sleep(1);
		if (write(fd, "scan", 4) != 4)
	exit(1);
		if (lseek(fd, 0, SEEK_SET) < 0)
	exit(1);
		n = read(fd, buf, sizeof(buf) - 1);
		if (n < 0)
	exit(1);
		buf[n] = 0;
		char* pos = buf;
		char* end = buf + n;
		while (pos < end) {
			char* next = strstr(pos + 1, "unreferenced object");
			if (!next)
				next = end;
			char prev = *next;
			*next = 0;
			fprintf(stderr, "BUG: memory leak\n%s\n", pos);
			*next = prev;
			pos = next;
			nleaks++;
		}
	}
	if (write(fd, "clear", 5) != 5)
	exit(1);
	close(fd);
	if (nleaks)
		exit(1);
}

static void execute_one(void);

#define WAIT_FLAGS __WALL

static void loop(void)
{
	int iter = 0;
	for (;; 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 (;;) {
			sleep_ms(10);
			if (waitpid(-1, &status, WNOHANG | WAIT_FLAGS) == pid)
				break;
			if (current_time_ms() - start < 5000)
				continue;
			kill_and_wait(pid, &status);
			break;
		}
		check_leaks();
	}
}

uint64_t r[1] = {0xffffffffffffffff};

void execute_one(void)
{
		intptr_t res = 0;
	if (write(1, "executing program\n", sizeof("executing program\n") - 1)) {}
//  openat$bsg arguments: [
//    fd: const = 0xffffffffffffff9c (8 bytes)
//    file: ptr[in, buffer] {
//      buffer: {2f 64 65 76 2f 62 73 67 2f 31 3a 30 3a 30 3a 30 00} (length 0x11)
//    }
//    flags: open_flags = 0x8881 (4 bytes)
//    mode: const = 0x0 (2 bytes)
//  ]
//  returns fd_bsg
memcpy((void*)0x200000000080, "/dev/bsg/1:0:0:0\000", 17);
	res = syscall(__NR_openat, /*fd=*/0xffffffffffffff9cul, /*file=*/0x200000000080ul, /*flags=O_NONBLOCK|O_LARGEFILE|O_EXCL|O_WRONLY*/0x8881, /*mode=*/0);
	if (res != -1)
		r[0] = res;
//  ioctl$BSG_IO arguments: [
//    fd: fd_bsg (resource)
//    cmd: const = 0x2285 (4 bytes)
//    arg: ptr[inout, sg_io_v4] {
//      sg_io_v4 {
//        guard: bsg_guard = 0x51 (4 bytes)
//        prot: const = 0x0 (4 bytes)
//        subprot: bsg_sub_protocols = 0x0 (4 bytes)
//        req_len: len = 0x0 (4 bytes)
//        req: nil
//        req_tag: int64 = 0x1 (8 bytes)
//        req_attr: const = 0x0 (4 bytes)
//        req_prio: int32 = 0x80000001 (4 bytes)
//        req_extra: int32 = 0x10001 (4 bytes)
//        max_resp_len: bytesize = 0x0 (4 bytes)
//        resp: nil
//        dout_iovec_count: const = 0x0 (4 bytes)
//        dout_xfer_len: len = 0x0 (4 bytes)
//        din_iovec_count: const = 0x0 (4 bytes)
//        din_xfer_len: len = 0xfffffffffffffff9 (4 bytes)
//        dout_xferp: nil
//        din_xferp: nil
//        timeout: int32 = 0x8 (4 bytes)
//        flags: bsg_flags = 0x20 (4 bytes)
//        usr_ptr: nil
//        spare_in: int32 = 0xffffffff (4 bytes)
//        drv_status: const = 0x0 (4 bytes)
//        trans_status: const = 0x0 (4 bytes)
//        dev_status: const = 0x0 (4 bytes)
//        retry_delay: const = 0x0 (4 bytes)
//        info: const = 0x0 (4 bytes)
//        dur: const = 0x0 (4 bytes)
//        resp_len: const = 0x0 (4 bytes)
//        din_resid: const = 0x0 (4 bytes)
//        dout_resid: const = 0x0 (4 bytes)
//        gen_tag: const = 0x0 (8 bytes)
//        spare_out: const = 0x0 (4 bytes)
//        pad: const = 0x0 (4 bytes)
//      }
//    }
//  ]
*(uint32_t*)0x2000000000c0 = 0x51;
*(uint32_t*)0x2000000000c4 = 0;
*(uint32_t*)0x2000000000c8 = 0;
*(uint32_t*)0x2000000000cc = 0;
*(uint64_t*)0x2000000000d0 = 0;
*(uint64_t*)0x2000000000d8 = 1;
*(uint32_t*)0x2000000000e0 = 0;
*(uint32_t*)0x2000000000e4 = 0x80000001;
*(uint32_t*)0x2000000000e8 = 0x10001;
*(uint32_t*)0x2000000000ec = 0;
*(uint64_t*)0x2000000000f0 = 0;
*(uint32_t*)0x2000000000f8 = 0;
*(uint32_t*)0x2000000000fc = 0;
*(uint32_t*)0x200000000100 = 0;
*(uint32_t*)0x200000000104 = 0xfffffff9;
*(uint64_t*)0x200000000108 = 0;
*(uint64_t*)0x200000000110 = 0;
*(uint32_t*)0x200000000118 = 8;
*(uint32_t*)0x20000000011c = 0x20;
*(uint64_t*)0x200000000120 = 0;
*(uint32_t*)0x200000000128 = -1;
*(uint32_t*)0x20000000012c = 0;
*(uint32_t*)0x200000000130 = 0;
*(uint32_t*)0x200000000134 = 0;
*(uint32_t*)0x200000000138 = 0;
*(uint32_t*)0x20000000013c = 0;
*(uint32_t*)0x200000000140 = 0;
*(uint32_t*)0x200000000144 = 0;
*(uint32_t*)0x200000000148 = 0;
*(uint32_t*)0x20000000014c = 0;
*(uint64_t*)0x200000000150 = 0;
*(uint32_t*)0x200000000158 = 0;
*(uint32_t*)0x20000000015c = 0;
	syscall(__NR_ioctl, /*fd=*/r[0], /*cmd=*/0x2285, /*arg=*/0x2000000000c0ul);

}
int main(void)
{
		syscall(__NR_mmap, /*addr=*/0x1ffffffff000ul, /*len=*/0x1000ul, /*prot=*/0ul, /*flags=MAP_FIXED|MAP_ANONYMOUS|MAP_PRIVATE*/0x32ul, /*fd=*/(intptr_t)-1, /*offset=*/0ul);
	syscall(__NR_mmap, /*addr=*/0x200000000000ul, /*len=*/0x1000000ul, /*prot=PROT_WRITE|PROT_READ|PROT_EXEC*/7ul, /*flags=MAP_FIXED|MAP_ANONYMOUS|MAP_PRIVATE*/0x32ul, /*fd=*/(intptr_t)-1, /*offset=*/0ul);
	syscall(__NR_mmap, /*addr=*/0x200001000000ul, /*len=*/0x1000ul, /*prot=*/0ul, /*flags=MAP_FIXED|MAP_ANONYMOUS|MAP_PRIVATE*/0x32ul, /*fd=*/(intptr_t)-1, /*offset=*/0ul);
	const char* reason;
	(void)reason;
	if ((reason = setup_leak()))
		printf("the reproducer may not work as expected: leak checking setup failed: %s\n", reason);
			loop();
	return 0;
}
