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 <stdint.h>
- #include <string.h>
- #include <sys/syscall.h>
- #include <unistd.h>
- #include <pthread.h>
- #include <stdlib.h>
- #include <setjmp.h>
- #include <signal.h>
- #include <string.h>
- #include <errno.h>
- #include <stdarg.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <sys/stat.h>
- #include <errno.h>
- #include <signal.h>
- #include <stdarg.h>
- #include <stdio.h>
- #include <sys/prctl.h>
- #include <sys/time.h>
- #include <sys/wait.h>
- #include <time.h>
- #include <dirent.h>
- #include <sys/mount.h>
- #include <errno.h>
- #include <sched.h>
- #include <signal.h>
- #include <stdarg.h>
- #include <stdbool.h>
- #include <stdio.h>
- #include <sys/prctl.h>
- #include <sys/resource.h>
- #include <sys/time.h>
- #include <sys/wait.h>
- #include <grp.h>
- #include <arpa/inet.h>
- #include <errno.h>
- #include <fcntl.h>
- #include <linux/if.h>
- #include <linux/if_ether.h>
- #include <linux/if_tun.h>
- #include <linux/ip.h>
- #include <linux/tcp.h>
- #include <net/if_arp.h>
- #include <stdarg.h>
- #include <stdbool.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <sys/ioctl.h>
- #include <sys/stat.h>
- const int kFailStatus = 67;
- const int kRetryStatus = 69;
- __attribute__((noreturn)) static void doexit(int status)
- {
- volatile unsigned i;
- syscall(__NR_exit_group, status);
- for (i = 0;; i++) {
- }
- }
- __attribute__((noreturn)) static void fail(const char* msg, ...)
- {
- int e = errno;
- fflush(stdout);
- 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);
- }
- __attribute__((noreturn)) static void exitf(const char* msg, ...)
- {
- int e = errno;
- fflush(stdout);
- va_list args;
- va_start(args, msg);
- vfprintf(stderr, msg, args);
- va_end(args);
- fprintf(stderr, " (errno %d)\n", e);
- doexit(kRetryStatus);
- }
- static __thread int skip_segv;
- static __thread jmp_buf segv_env;
- static void segv_handler(int sig, siginfo_t* info, void* uctx)
- {
- 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);
- }
- doexit(sig);
- for (;;) {
- }
- }
- static void install_segv_handler()
- {
- 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 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 vsnprintf_check(char* str, size_t size, const char* format, va_list args)
- {
- int rv;
- rv = vsnprintf(str, size, format, args);
- if (rv < 0)
- fail("tun: snprintf failed");
- if ((size_t)rv >= size)
- fail("tun: string '%s...' doesn't fit into buffer", str);
- }
- static void snprintf_check(char* str, size_t size, const char* format, ...)
- {
- va_list args;
- va_start(args, format);
- vsnprintf_check(str, size, format, args);
- va_end(args);
- }
- #define COMMAND_MAX_LEN 128
- static void execute_command(const char* format, ...)
- {
- va_list args;
- char command[COMMAND_MAX_LEN];
- int rv;
- va_start(args, format);
- vsnprintf_check(command, sizeof(command), format, args);
- rv = system(command);
- if (rv != 0)
- fail("tun: command \"%s\" failed with code %d", &command[0], rv);
- va_end(args);
- }
- static int tunfd = -1;
- #define SYZ_TUN_MAX_PACKET_SIZE 1000
- #define MAX_PIDS 32
- #define ADDR_MAX_LEN 32
- #define LOCAL_MAC "aa:aa:aa:aa:aa:%02hx"
- #define REMOTE_MAC "bb:bb:bb:bb:bb:%02hx"
- #define LOCAL_IPV4 "172.20.%d.170"
- #define REMOTE_IPV4 "172.20.%d.187"
- #define LOCAL_IPV6 "fe80::%02hxaa"
- #define REMOTE_IPV6 "fe80::%02hxbb"
- static void initialize_tun(uint64_t pid)
- {
- if (pid >= MAX_PIDS)
- fail("tun: no more than %d executors", MAX_PIDS);
- int id = pid;
- tunfd = open("/dev/net/tun", O_RDWR | O_NONBLOCK);
- if (tunfd == -1)
- fail("tun: can't open /dev/net/tun");
- char iface[IFNAMSIZ];
- snprintf_check(iface, sizeof(iface), "syz%d", id);
- struct ifreq ifr;
- memset(&ifr, 0, sizeof(ifr));
- strncpy(ifr.ifr_name, iface, IFNAMSIZ);
- ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
- if (ioctl(tunfd, TUNSETIFF, (void*)&ifr) < 0)
- fail("tun: ioctl(TUNSETIFF) failed");
- char local_mac[ADDR_MAX_LEN];
- snprintf_check(local_mac, sizeof(local_mac), LOCAL_MAC, id);
- char remote_mac[ADDR_MAX_LEN];
- snprintf_check(remote_mac, sizeof(remote_mac), REMOTE_MAC, id);
- char local_ipv4[ADDR_MAX_LEN];
- snprintf_check(local_ipv4, sizeof(local_ipv4), LOCAL_IPV4, id);
- char remote_ipv4[ADDR_MAX_LEN];
- snprintf_check(remote_ipv4, sizeof(remote_ipv4), REMOTE_IPV4, id);
- char local_ipv6[ADDR_MAX_LEN];
- snprintf_check(local_ipv6, sizeof(local_ipv6), LOCAL_IPV6, id);
- char remote_ipv6[ADDR_MAX_LEN];
- snprintf_check(remote_ipv6, sizeof(remote_ipv6), REMOTE_IPV6, id);
- execute_command("sysctl -w net.ipv6.conf.%s.accept_dad=0", iface);
- execute_command("sysctl -w net.ipv6.conf.%s.router_solicitations=0", iface);
- execute_command("ip link set dev %s address %s", iface, local_mac);
- execute_command("ip addr add %s/24 dev %s", local_ipv4, iface);
- execute_command("ip -6 addr add %s/120 dev %s", local_ipv6, iface);
- execute_command("ip neigh add %s lladdr %s dev %s nud permanent", remote_ipv4, remote_mac, iface);
- execute_command("ip -6 neigh add %s lladdr %s dev %s nud permanent", remote_ipv6, remote_mac, iface);
- execute_command("ip link set dev %s up", iface);
- }
- static void setup_tun(uint64_t pid, bool enable_tun)
- {
- if (enable_tun)
- initialize_tun(pid);
- }
- static int read_tun(char* data, int size)
- {
- int rv = read(tunfd, data, size);
- if (rv < 0) {
- if (errno == EAGAIN)
- return -1;
- fail("tun: read failed with %d, errno: %d", rv, errno);
- }
- return rv;
- }
- static void flush_tun()
- {
- char data[SYZ_TUN_MAX_PACKET_SIZE];
- while (read_tun(&data[0], sizeof(data)) != -1)
- ;
- }
- static void loop();
- static void sandbox_common()
- {
- prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0);
- setpgrp();
- setsid();
- struct rlimit rlim;
- rlim.rlim_cur = rlim.rlim_max = 128 << 20;
- setrlimit(RLIMIT_AS, &rlim);
- rlim.rlim_cur = rlim.rlim_max = 8 << 20;
- setrlimit(RLIMIT_MEMLOCK, &rlim);
- rlim.rlim_cur = rlim.rlim_max = 1 << 20;
- setrlimit(RLIMIT_FSIZE, &rlim);
- rlim.rlim_cur = rlim.rlim_max = 1 << 20;
- setrlimit(RLIMIT_STACK, &rlim);
- rlim.rlim_cur = rlim.rlim_max = 0;
- setrlimit(RLIMIT_CORE, &rlim);
- unshare(CLONE_NEWNS);
- unshare(CLONE_NEWIPC);
- unshare(CLONE_IO);
- }
- static int do_sandbox_setuid(int executor_pid, bool enable_tun)
- {
- int pid = fork();
- if (pid)
- return pid;
- sandbox_common();
- setup_tun(executor_pid, enable_tun);
- const int nobody = 65534;
- if (setgroups(0, NULL))
- fail("failed to setgroups");
- if (syscall(SYS_setresgid, nobody, nobody, nobody))
- fail("failed to setresgid");
- if (syscall(SYS_setresuid, nobody, nobody, nobody))
- fail("failed to setresuid");
- prctl(PR_SET_DUMPABLE, 1, 0, 0, 0);
- loop();
- doexit(1);
- }
- static void remove_dir(const char* dir)
- {
- DIR* dp;
- struct dirent* ep;
- int iter = 0;
- retry:
- dp = opendir(dir);
- if (dp == NULL) {
- if (errno == EMFILE) {
- exitf("opendir(%s) failed due to NOFILE, exiting");
- }
- 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 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 test();
- void loop()
- {
- int iter;
- for (iter = 0;; iter++) {
- char cwdbuf[256];
- 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");
- flush_tun();
- test();
- 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 > 5 * 1000) {
- kill(-pid, SIGKILL);
- kill(pid, SIGKILL);
- while (waitpid(-1, &status, __WALL) != pid) {
- }
- break;
- }
- }
- remove_dir(cwdbuf);
- }
- }
- long r[5];
- void *thr(void *arg)
- {
- switch ((long)arg) {
- case 0:
- NONFAILING(*(uint32_t*)0x20005000 = (uint32_t)0x0);
- NONFAILING(*(uint64_t*)0x20002ff0 = (uint64_t)0x0);
- NONFAILING(*(uint64_t*)0x20002ff8 = (uint64_t)0x0);
- NONFAILING(*(uint32_t*)0x20005ffc = (uint32_t)0x0);
- r[4] = syscall(__NR_futex, 0x20005000ul, 0x8000000000000085ul, 0x0ul, 0x20002ff0ul, 0x20005ffcul, 0xfffffffffffffffeul);
- break;
- }
- return 0;
- }
- void test()
- {
- long i;
- pthread_t th[2];
- syscall(SYS_write, 1, "executing program\n", strlen("executing program\n"));
- memset(r, -1, sizeof(r));
- for (i = 0; i < 1; i++) {
- pthread_create(&th[i], 0, thr, (void*)i);
- usleep(rand()%10000);
- }
- usleep(rand()%100000);
- }
- int main()
- {
- int i; for (i = 0; i < 4; i++) {
- if (fork() == 0) {
- install_segv_handler();
- use_temporary_dir();
- int pid = do_sandbox_setuid(i, true);
- int status = 0;
- while (waitpid(pid, &status, __WALL) != pid) {}
- return 0;
- }
- }
- sleep(1000000);
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement