Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // autogenerated by syzkaller (http://github.com/google/syzkaller)
- #define _GNU_SOURCE
- #include <endian.h>
- #include <sys/syscall.h>
- #include <unistd.h>
- #include <linux/futex.h>
- #include <pthread.h>
- #include <stdlib.h>
- #include <errno.h>
- #include <signal.h>
- #include <stdarg.h>
- #include <stdio.h>
- #include <sys/time.h>
- #include <sys/wait.h>
- #include <time.h>
- #include <sys/prctl.h>
- #include <dirent.h>
- #include <sys/mount.h>
- __attribute__((noreturn)) static void doexit(int status)
- {
- volatile unsigned i;
- syscall(__NR_exit_group, status);
- for (i = 0;; i++) {
- }
- }
- #include <stdint.h>
- #include <string.h>
- #include <errno.h>
- #include <stdarg.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <sys/stat.h>
- case 5:
- const int kFailStatus = 67;
- const int kRetryStatus = 69;
- static void fail(const char* msg, ...)
- {
- int e = errno;
- va_list args;
- va_start(args, msg);
- vfprintf(stderr, msg, args);
- va_end(args);
- fprintf(stderr, " (errno %d)\n", e);
- doexit((e == ENOMEM || e == EAGAIN) ? kRetryStatus : kFailStatus);
- }
- static void exitf(const char* msg, ...)
- {
- int e = errno;
- va_list args;
- va_start(args, msg);
- vfprintf(stderr, msg, args);
- va_end(args);
- fprintf(stderr, " (errno %d)\n", e);
- doexit(kRetryStatus);
- }
- static uint64_t current_time_ms()
- {
- struct timespec ts;
- if (clock_gettime(CLOCK_MONOTONIC, &ts))
- fail("clock_gettime failed");
- return (uint64_t)ts.tv_sec * 1000 + (uint64_t)ts.tv_nsec / 1000000;
- }
- static void use_temporary_dir()
- {
- char tmpdir_template[] = "./syzkaller.XXXXXX";
- char* tmpdir = mkdtemp(tmpdir_template);
- if (!tmpdir)
- fail("failed to mkdtemp");
- if (chmod(tmpdir, 0777))
- fail("failed to chmod");
- if (chdir(tmpdir))
- fail("failed to chdir");
- }
- static void remove_dir(const char* dir)
- {
- DIR* dp;
- struct dirent* ep;
- int iter = 0;
- retry:
- while (umount2(dir, MNT_DETACH) == 0) {
- }
- dp = opendir(dir);
- if (dp == NULL) {
- if (errno == EMFILE) {
- exitf("opendir(%s) failed due to NOFILE, exiting", dir);
- }
- exitf("opendir(%s) failed", dir);
- }
- while ((ep = readdir(dp))) {
- if (strcmp(ep->d_name, ".") == 0 || strcmp(ep->d_name, "..") == 0)
- continue;
- char filename[FILENAME_MAX];
- snprintf(filename, sizeof(filename), "%s/%s", dir, ep->d_name);
- struct stat st;
- if (lstat(filename, &st))
- exitf("lstat(%s) failed", filename);
- if (S_ISDIR(st.st_mode)) {
- remove_dir(filename);
- continue;
- }
- int i;
- for (i = 0;; i++) {
- if (unlink(filename) == 0)
- break;
- if (errno == EROFS) {
- break;
- }
- if (errno != EBUSY || i > 100)
- exitf("unlink(%s) failed", filename);
- if (umount2(filename, MNT_DETACH))
- exitf("umount(%s) failed", filename);
- }
- }
- closedir(dp);
- int i;
- for (i = 0;; i++) {
- if (rmdir(dir) == 0)
- break;
- if (i < 100) {
- if (errno == EROFS) {
- break;
- }
- if (errno == EBUSY) {
- if (umount2(dir, MNT_DETACH))
- exitf("umount(%s) failed", dir);
- continue;
- }
- if (errno == ENOTEMPTY) {
- if (iter < 100) {
- iter++;
- goto retry;
- }
- }
- }
- exitf("rmdir(%s) failed", dir);
- }
- }
- static void execute_one();
- extern unsigned long long procid;
- static void loop()
- {
- int iter;
- for (iter = 0;; iter++) {
- char cwdbuf[32];
- sprintf(cwdbuf, "./%d", iter);
- if (mkdir(cwdbuf, 0777))
- fail("failed to mkdir");
- int pid = fork();
- if (pid < 0)
- fail("clone failed");
- if (pid == 0) {
- prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0);
- setpgrp();
- if (chdir(cwdbuf))
- fail("failed to chdir");
- execute_one();
- doexit(0);
- }
- int status = 0;
- uint64_t start = current_time_ms();
- for (;;) {
- int res = waitpid(-1, &status, __WALL | WNOHANG);
- if (res == pid) {
- break;
- }
- usleep(1000);
- if (current_time_ms() - start < 3 * 1000)
- continue;
- kill(-pid, SIGKILL);
- kill(pid, SIGKILL);
- while (waitpid(-1, &status, __WALL) != pid) {
- }
- break;
- }
- remove_dir(cwdbuf);
- }
- }
- struct thread_t {
- int created, running, call;
- pthread_t th;
- };
- static struct thread_t threads[16];
- static void execute_call(int call);
- static int running;
- static int collide;
- static void* thr(void* arg)
- {
- struct thread_t* th = (struct thread_t*)arg;
- for (;;) {
- while (!__atomic_load_n(&th->running, __ATOMIC_ACQUIRE))
- syscall(SYS_futex, &th->running, FUTEX_WAIT, 0, 0);
- execute_call(th->call);
- __atomic_fetch_sub(&running, 1, __ATOMIC_RELAXED);
- __atomic_store_n(&th->running, 0, __ATOMIC_RELEASE);
- syscall(SYS_futex, &th->running, FUTEX_WAKE);
- }
- return 0;
- }
- static void execute(int num_calls)
- {
- int call, thread;
- running = 0;
- for (call = 0; call < num_calls; call++) {
- for (thread = 0; thread < sizeof(threads) / sizeof(threads[0]); thread++) {
- struct thread_t* th = &threads[thread];
- if (!th->created) {
- th->created = 1;
- pthread_attr_t attr;
- pthread_attr_init(&attr);
- pthread_attr_setstacksize(&attr, 128 << 10);
- pthread_create(&th->th, &attr, thr, th);
- }
- if (!__atomic_load_n(&th->running, __ATOMIC_ACQUIRE)) {
- th->call = call;
- __atomic_fetch_add(&running, 1, __ATOMIC_RELAXED);
- __atomic_store_n(&th->running, 1, __ATOMIC_RELEASE);
- syscall(SYS_futex, &th->running, FUTEX_WAKE);
- if (collide && call % 2)
- break;
- struct timespec ts;
- ts.tv_sec = 0;
- ts.tv_nsec = 20 * 1000 * 1000;
- syscall(SYS_futex, &th->running, FUTEX_WAIT, 1, &ts);
- if (running)
- usleep((call == num_calls - 1) ? 10000 : 1000);
- break;
- }
- }
- }
- }
- uint64_t r[2] = {0xffffffffffffffff, 0xffffffffffffffff};
- unsigned long long procid;
- void execute_call(int call)
- {
- long res; switch (call) {
- case 0:
- memcpy((void*)0x20000040, "./file0", 8);
- res = syscall(__NR_open, 0x20000040, 0x43fd, 0xfffffffffffffffe);
- if (res != -1)
- r[0] = res;
- break;
- case 1:
- memcpy((void*)0x20000075, "/lib/x86_64-linux-gnu/libc.so.6", 32);
- res = syscall(__NR_open, 0x20000075, 0, 0);
- if (res != -1)
- r[1] = res;
- break;
- case 2:
- *(uint64_t*)0x20000140 = 7;
- syscall(__NR_fcntl, r[0], 0x40e, 0x20000140);
- break;
- case 3:
- syscall(__NR_close, r[1]);
- break;
- case 4:
- memcpy((void*)0x2000044a, "./file0", 8);
- syscall(__NR_open, 0x2000044a, 0x242, 0);
- break;
- case 5:
- syscall(__NR_mmap, 0x20000000, 0x4000, 0x40000000002, 0x11, r[1], 0);
- break;
- case 6:
- syscall(__NR_ftruncate, r[1], 0x1073b4);
- break;
- case 7:
- syscall(__NR_fcntl, -1, 9);
- break;
- case 8:
- *(uint64_t*)0x20000000 = 0;
- syscall(__NR_write, r[0], 0x20000000, 0xd996d7aa);
- break;
- }
- }
- void execute_one()
- {
- execute(9);
- collide = 1;
- execute(9);
- }
- int main()
- {
- syscall(__NR_mmap, 0x20000000, 0x1000000, 3, 0x32, -1, 0);
- char *cwd = get_current_dir_name();
- for (procid = 0; procid < 8; procid++) {
- if (fork() == 0) {
- for (;;) {
- if (chdir(cwd))
- fail("failed to chdir");
- use_temporary_dir();
- loop();
- }
- }
- }
- sleep(1000000);
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement