Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #define _GNU_SOURCE
- #include <dirent.h>
- #include <endian.h>
- #include <errno.h>
- #include <fcntl.h>
- #include <pthread.h>
- #include <setjmp.h>
- #include <signal.h>
- #include <stdarg.h>
- #include <stdbool.h>
- #include <stddef.h>
- #include <stdint.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <sys/ioctl.h>
- #include <sys/mman.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/futex.h>
- #include <linux/loop.h>
- #ifndef __NR_memfd_create
- #define __NR_memfd_create 319
- #endif
- static unsigned long long procid;
- static __thread int clone_ongoing;
- static __thread int skip_segv;
- static __thread jmp_buf segv_env;
- static void segv_handler(int sig, siginfo_t* info, void* ctx)
- {
- if (__atomic_load_n(&clone_ongoing, __ATOMIC_RELAXED) != 0) {
- exit(sig);
- }
- uintptr_t addr = (uintptr_t)info->si_addr;
- const uintptr_t prog_start = 1 << 20;
- const uintptr_t prog_end = 100 << 20;
- int skip = __atomic_load_n(&skip_segv, __ATOMIC_RELAXED) != 0;
- int valid = addr < prog_start || addr > prog_end;
- if (skip && valid) {
- _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(...) \
- ({ \
- int ok = 1; \
- __atomic_fetch_add(&skip_segv, 1, __ATOMIC_SEQ_CST); \
- if (_setjmp(segv_env) == 0) { \
- __VA_ARGS__; \
- } else \
- ok = 0; \
- __atomic_fetch_sub(&skip_segv, 1, __ATOMIC_SEQ_CST); \
- ok; \
- })
- 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 void use_temporary_dir(void)
- {
- char tmpdir_template[] = "./syzkaller.XXXXXX";
- char* tmpdir = mkdtemp(tmpdir_template);
- if (!tmpdir)
- exit(1);
- if (chmod(tmpdir, 0777))
- exit(1);
- if (chdir(tmpdir))
- exit(1);
- }
- static void thread_start(void* (*fn)(void*), void* arg)
- {
- pthread_t th;
- pthread_attr_t attr;
- pthread_attr_init(&attr);
- pthread_attr_setstacksize(&attr, 128 << 10);
- int i = 0;
- for (; i < 100; i++) {
- if (pthread_create(&th, &attr, fn, arg) == 0) {
- pthread_attr_destroy(&attr);
- return;
- }
- if (errno == EAGAIN) {
- usleep(50);
- continue;
- }
- break;
- }
- exit(1);
- }
- typedef struct {
- int state;
- } event_t;
- static void event_init(event_t* ev)
- {
- ev->state = 0;
- }
- static void event_reset(event_t* ev)
- {
- ev->state = 0;
- }
- static void event_set(event_t* ev)
- {
- if (ev->state)
- exit(1);
- __atomic_store_n(&ev->state, 1, __ATOMIC_RELEASE);
- syscall(SYS_futex, &ev->state, FUTEX_WAKE | FUTEX_PRIVATE_FLAG, 1000000);
- }
- static void event_wait(event_t* ev)
- {
- while (!__atomic_load_n(&ev->state, __ATOMIC_ACQUIRE))
- syscall(SYS_futex, &ev->state, FUTEX_WAIT | FUTEX_PRIVATE_FLAG, 0, 0);
- }
- static int event_isset(event_t* ev)
- {
- return __atomic_load_n(&ev->state, __ATOMIC_ACQUIRE);
- }
- static int event_timedwait(event_t* ev, uint64_t timeout)
- {
- uint64_t start = current_time_ms();
- uint64_t now = start;
- for (;;) {
- uint64_t remain = timeout - (now - start);
- struct timespec ts;
- ts.tv_sec = remain / 1000;
- ts.tv_nsec = (remain % 1000) * 1000 * 1000;
- syscall(SYS_futex, &ev->state, FUTEX_WAIT | FUTEX_PRIVATE_FLAG, 0, &ts);
- if (__atomic_load_n(&ev->state, __ATOMIC_ACQUIRE))
- return 1;
- now = current_time_ms();
- if (now - start > timeout)
- return 0;
- }
- }
- 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;
- }
- //% This code is derived from puff.{c,h}, found in the zlib development. The
- //% original files come with the following copyright notice:
- //% Copyright (C) 2002-2013 Mark Adler, all rights reserved
- //% version 2.3, 21 Jan 2013
- //% This software is provided 'as-is', without any express or implied
- //% warranty. In no event will the author be held liable for any damages
- //% arising from the use of this software.
- //% Permission is granted to anyone to use this software for any purpose,
- //% including commercial applications, and to alter it and redistribute it
- //% freely, subject to the following restrictions:
- //% 1. The origin of this software must not be misrepresented; you must not
- //% claim that you wrote the original software. If you use this software
- //% in a product, an acknowledgment in the product documentation would be
- //% appreciated but is not required.
- //% 2. Altered source versions must be plainly marked as such, and must not be
- //% misrepresented as being the original software.
- //% 3. This notice may not be removed or altered from any source distribution.
- //% Mark Adler [email protected]
- //% BEGIN CODE DERIVED FROM puff.{c,h}
- #define MAXBITS 15
- #define MAXLCODES 286
- #define MAXDCODES 30
- #define MAXCODES (MAXLCODES + MAXDCODES)
- #define FIXLCODES 288
- struct puff_state {
- unsigned char* out;
- unsigned long outlen;
- unsigned long outcnt;
- const unsigned char* in;
- unsigned long inlen;
- unsigned long incnt;
- int bitbuf;
- int bitcnt;
- jmp_buf env;
- };
- static int puff_bits(struct puff_state* s, int need)
- {
- long val = s->bitbuf;
- while (s->bitcnt < need) {
- if (s->incnt == s->inlen)
- longjmp(s->env, 1);
- val |= (long)(s->in[s->incnt++]) << s->bitcnt;
- s->bitcnt += 8;
- }
- s->bitbuf = (int)(val >> need);
- s->bitcnt -= need;
- return (int)(val & ((1L << need) - 1));
- }
- static int puff_stored(struct puff_state* s)
- {
- s->bitbuf = 0;
- s->bitcnt = 0;
- if (s->incnt + 4 > s->inlen)
- return 2;
- unsigned len = s->in[s->incnt++];
- len |= s->in[s->incnt++] << 8;
- if (s->in[s->incnt++] != (~len & 0xff) ||
- s->in[s->incnt++] != ((~len >> 8) & 0xff))
- return -2;
- if (s->incnt + len > s->inlen)
- return 2;
- if (s->outcnt + len > s->outlen)
- return 1;
- for (; len--; s->outcnt++, s->incnt++) {
- if (s->in[s->incnt])
- s->out[s->outcnt] = s->in[s->incnt];
- }
- return 0;
- }
- struct puff_huffman {
- short* count;
- short* symbol;
- };
- static int puff_decode(struct puff_state* s, const struct puff_huffman* h)
- {
- int first = 0;
- int index = 0;
- int bitbuf = s->bitbuf;
- int left = s->bitcnt;
- int code = first = index = 0;
- int len = 1;
- short* next = h->count + 1;
- while (1) {
- while (left--) {
- code |= bitbuf & 1;
- bitbuf >>= 1;
- int count = *next++;
- if (code - count < first) {
- s->bitbuf = bitbuf;
- s->bitcnt = (s->bitcnt - len) & 7;
- return h->symbol[index + (code - first)];
- }
- index += count;
- first += count;
- first <<= 1;
- code <<= 1;
- len++;
- }
- left = (MAXBITS + 1) - len;
- if (left == 0)
- break;
- if (s->incnt == s->inlen)
- longjmp(s->env, 1);
- bitbuf = s->in[s->incnt++];
- if (left > 8)
- left = 8;
- }
- return -10;
- }
- static int puff_construct(struct puff_huffman* h, const short* length, int n)
- {
- int len;
- for (len = 0; len <= MAXBITS; len++)
- h->count[len] = 0;
- int symbol;
- for (symbol = 0; symbol < n; symbol++)
- (h->count[length[symbol]])++;
- if (h->count[0] == n)
- return 0;
- int left = 1;
- for (len = 1; len <= MAXBITS; len++) {
- left <<= 1;
- left -= h->count[len];
- if (left < 0)
- return left;
- }
- short offs[MAXBITS + 1];
- offs[1] = 0;
- for (len = 1; len < MAXBITS; len++)
- offs[len + 1] = offs[len] + h->count[len];
- for (symbol = 0; symbol < n; symbol++)
- if (length[symbol] != 0)
- h->symbol[offs[length[symbol]]++] = symbol;
- return left;
- }
- static int puff_codes(struct puff_state* s, const struct puff_huffman* lencode,
- const struct puff_huffman* distcode)
- {
- static const short lens[29] = {3, 4, 5, 6, 7, 8, 9, 10, 11, 13,
- 15, 17, 19, 23, 27, 31, 35, 43, 51, 59,
- 67, 83, 99, 115, 131, 163, 195, 227, 258};
- static const short lext[29] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2,
- 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0};
- static const short dists[30] = {
- 1, 2, 3, 4, 5, 7, 9, 13, 17, 25,
- 33, 49, 65, 97, 129, 193, 257, 385, 513, 769,
- 1025, 1537, 2049, 3073, 4097, 6145, 8193, 12289, 16385, 24577};
- static const short dext[30] = {0, 0, 0, 0, 1, 1, 2, 2, 3, 3,
- 4, 4, 5, 5, 6, 6, 7, 7, 8, 8,
- 9, 9, 10, 10, 11, 11, 12, 12, 13, 13};
- int symbol;
- do {
- symbol = puff_decode(s, lencode);
- if (symbol < 0)
- return symbol;
- if (symbol < 256) {
- if (s->outcnt == s->outlen)
- return 1;
- if (symbol)
- s->out[s->outcnt] = symbol;
- s->outcnt++;
- } else if (symbol > 256) {
- symbol -= 257;
- if (symbol >= 29)
- return -10;
- int len = lens[symbol] + puff_bits(s, lext[symbol]);
- symbol = puff_decode(s, distcode);
- if (symbol < 0)
- return symbol;
- unsigned dist = dists[symbol] + puff_bits(s, dext[symbol]);
- if (dist > s->outcnt)
- return -11;
- if (s->outcnt + len > s->outlen)
- return 1;
- while (len--) {
- if (dist <= s->outcnt && s->out[s->outcnt - dist])
- s->out[s->outcnt] = s->out[s->outcnt - dist];
- s->outcnt++;
- }
- }
- } while (symbol != 256);
- return 0;
- }
- static int puff_fixed(struct puff_state* s)
- {
- static int virgin = 1;
- static short lencnt[MAXBITS + 1], lensym[FIXLCODES];
- static short distcnt[MAXBITS + 1], distsym[MAXDCODES];
- static struct puff_huffman lencode, distcode;
- if (virgin) {
- lencode.count = lencnt;
- lencode.symbol = lensym;
- distcode.count = distcnt;
- distcode.symbol = distsym;
- short lengths[FIXLCODES];
- int symbol;
- for (symbol = 0; symbol < 144; symbol++)
- lengths[symbol] = 8;
- for (; symbol < 256; symbol++)
- lengths[symbol] = 9;
- for (; symbol < 280; symbol++)
- lengths[symbol] = 7;
- for (; symbol < FIXLCODES; symbol++)
- lengths[symbol] = 8;
- puff_construct(&lencode, lengths, FIXLCODES);
- for (symbol = 0; symbol < MAXDCODES; symbol++)
- lengths[symbol] = 5;
- puff_construct(&distcode, lengths, MAXDCODES);
- virgin = 0;
- }
- return puff_codes(s, &lencode, &distcode);
- }
- static int puff_dynamic(struct puff_state* s)
- {
- static const short order[19] = {16, 17, 18, 0, 8, 7, 9, 6, 10, 5,
- 11, 4, 12, 3, 13, 2, 14, 1, 15};
- int nlen = puff_bits(s, 5) + 257;
- int ndist = puff_bits(s, 5) + 1;
- int ncode = puff_bits(s, 4) + 4;
- if (nlen > MAXLCODES || ndist > MAXDCODES)
- return -3;
- short lengths[MAXCODES];
- int index;
- for (index = 0; index < ncode; index++)
- lengths[order[index]] = puff_bits(s, 3);
- for (; index < 19; index++)
- lengths[order[index]] = 0;
- short lencnt[MAXBITS + 1], lensym[MAXLCODES];
- struct puff_huffman lencode = {lencnt, lensym};
- int err = puff_construct(&lencode, lengths, 19);
- if (err != 0)
- return -4;
- index = 0;
- while (index < nlen + ndist) {
- int symbol;
- int len;
- symbol = puff_decode(s, &lencode);
- if (symbol < 0)
- return symbol;
- if (symbol < 16)
- lengths[index++] = symbol;
- else {
- len = 0;
- if (symbol == 16) {
- if (index == 0)
- return -5;
- len = lengths[index - 1];
- symbol = 3 + puff_bits(s, 2);
- } else if (symbol == 17)
- symbol = 3 + puff_bits(s, 3);
- else
- symbol = 11 + puff_bits(s, 7);
- if (index + symbol > nlen + ndist)
- return -6;
- while (symbol--)
- lengths[index++] = len;
- }
- }
- if (lengths[256] == 0)
- return -9;
- err = puff_construct(&lencode, lengths, nlen);
- if (err && (err < 0 || nlen != lencode.count[0] + lencode.count[1]))
- return -7;
- short distcnt[MAXBITS + 1], distsym[MAXDCODES];
- struct puff_huffman distcode = {distcnt, distsym};
- err = puff_construct(&distcode, lengths + nlen, ndist);
- if (err && (err < 0 || ndist != distcode.count[0] + distcode.count[1]))
- return -8;
- return puff_codes(s, &lencode, &distcode);
- }
- static int puff(unsigned char* dest, unsigned long* destlen,
- const unsigned char* source, unsigned long sourcelen)
- {
- struct puff_state s = {
- .out = dest,
- .outlen = *destlen,
- .outcnt = 0,
- .in = source,
- .inlen = sourcelen,
- .incnt = 0,
- .bitbuf = 0,
- .bitcnt = 0,
- };
- int err;
- if (setjmp(s.env) != 0)
- err = 2;
- else {
- int last;
- do {
- last = puff_bits(&s, 1);
- int type = puff_bits(&s, 2);
- err = type == 0 ? puff_stored(&s)
- : (type == 1 ? puff_fixed(&s)
- : (type == 2 ? puff_dynamic(&s) : -1));
- if (err != 0)
- break;
- } while (!last);
- }
- *destlen = s.outcnt;
- return err;
- }
- //% END CODE DERIVED FROM puff.{c,h}
- #define ZLIB_HEADER_WIDTH 2
- static int puff_zlib_to_file(const unsigned char* source,
- unsigned long sourcelen, int dest_fd)
- {
- if (sourcelen < ZLIB_HEADER_WIDTH)
- return 0;
- source += ZLIB_HEADER_WIDTH;
- sourcelen -= ZLIB_HEADER_WIDTH;
- const unsigned long max_destlen = 132 << 20;
- void* ret = mmap(0, max_destlen, PROT_WRITE | PROT_READ,
- MAP_PRIVATE | MAP_ANON, -1, 0);
- if (ret == MAP_FAILED)
- return -1;
- unsigned char* dest = (unsigned char*)ret;
- unsigned long destlen = max_destlen;
- int err = puff(dest, &destlen, source, sourcelen);
- if (err) {
- munmap(dest, max_destlen);
- errno = -err;
- return -1;
- }
- if (write(dest_fd, dest, destlen) != (ssize_t)destlen) {
- munmap(dest, max_destlen);
- return -1;
- }
- return munmap(dest, max_destlen);
- }
- static int setup_loop_device(unsigned char* data, unsigned long size,
- const char* loopname, int* loopfd_p)
- {
- int err = 0, loopfd = -1;
- int memfd = syscall(__NR_memfd_create, "syzkaller", 0);
- if (memfd == -1) {
- err = errno;
- goto error;
- }
- if (puff_zlib_to_file(data, size, memfd)) {
- err = errno;
- goto error_close_memfd;
- }
- 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;
- }
- }
- close(memfd);
- *loopfd_p = loopfd;
- return 0;
- error_close_loop:
- close(loopfd);
- error_close_memfd:
- close(memfd);
- error:
- errno = err;
- return -1;
- }
- static void reset_loop_device(const char* loopname)
- {
- int loopfd = open(loopname, O_RDWR);
- if (loopfd == -1) {
- return;
- }
- if (ioctl(loopfd, LOOP_CLR_FD, 0)) {
- }
- close(loopfd);
- }
- static long syz_mount_image(volatile long fsarg, volatile long dir,
- volatile long flags, volatile long optsarg,
- volatile long change_dir,
- volatile unsigned long size, volatile long image)
- {
- unsigned char* data = (unsigned char*)image;
- int res = -1, err = 0, need_loop_device = !!size;
- char* mount_opts = (char*)optsarg;
- char* target = (char*)dir;
- char* fs = (char*)fsarg;
- char* source = NULL;
- char loopname[64];
- if (need_loop_device) {
- int loopfd;
- memset(loopname, 0, sizeof(loopname));
- snprintf(loopname, sizeof(loopname), "/dev/loop%llu", procid);
- if (setup_loop_device(data, size, loopname, &loopfd) == -1)
- return -1;
- close(loopfd);
- source = loopname;
- }
- mkdir(target, 0777);
- char opts[256];
- memset(opts, 0, sizeof(opts));
- if (strlen(mount_opts) > (sizeof(opts) - 32)) {
- }
- strncpy(opts, mount_opts, sizeof(opts) - 32);
- if (strcmp(fs, "iso9660") == 0) {
- flags |= MS_RDONLY;
- } else if (strncmp(fs, "ext", 3) == 0) {
- bool has_remount_ro = false;
- char* remount_ro_start = strstr(opts, "errors=remount-ro");
- if (remount_ro_start != NULL) {
- char after = *(remount_ro_start + strlen("errors=remount-ro"));
- char before = remount_ro_start == opts ? '\0' : *(remount_ro_start - 1);
- has_remount_ro = ((before == '\0' || before == ',') &&
- (after == '\0' || after == ','));
- }
- if (strstr(opts, "errors=panic") || !has_remount_ro)
- strcat(opts, ",errors=continue");
- } else if (strcmp(fs, "xfs") == 0) {
- strcat(opts, ",nouuid");
- }
- res = mount(source, target, fs, flags, opts);
- if (res == -1) {
- err = errno;
- goto error_clear_loop;
- }
- res = open(target, O_RDONLY | O_DIRECTORY);
- if (res == -1) {
- err = errno;
- goto error_clear_loop;
- }
- if (change_dir) {
- res = chdir(target);
- if (res == -1) {
- err = errno;
- }
- }
- error_clear_loop:
- if (need_loop_device)
- reset_loop_device(loopname);
- errno = err;
- return res;
- }
- #define FS_IOC_SETFLAGS _IOW('f', 2, long)
- static void remove_dir(const char* dir)
- {
- int iter = 0;
- DIR* dp = 0;
- retry:
- while (umount2(dir, MNT_DETACH | UMOUNT_NOFOLLOW) == 0) {
- }
- dp = opendir(dir);
- if (dp == NULL) {
- if (errno == EMFILE) {
- exit(1);
- }
- exit(1);
- }
- struct dirent* ep = 0;
- 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);
- while (umount2(filename, MNT_DETACH | UMOUNT_NOFOLLOW) == 0) {
- }
- struct stat st;
- if (lstat(filename, &st))
- exit(1);
- if (S_ISDIR(st.st_mode)) {
- remove_dir(filename);
- continue;
- }
- int i;
- for (i = 0;; i++) {
- if (unlink(filename) == 0)
- break;
- if (errno == EPERM) {
- int fd = open(filename, O_RDONLY);
- if (fd != -1) {
- long flags = 0;
- if (ioctl(fd, FS_IOC_SETFLAGS, &flags) == 0) {
- }
- close(fd);
- continue;
- }
- }
- if (errno == EROFS) {
- break;
- }
- if (errno != EBUSY || i > 100)
- exit(1);
- if (umount2(filename, MNT_DETACH | UMOUNT_NOFOLLOW))
- exit(1);
- }
- }
- closedir(dp);
- for (int i = 0;; i++) {
- if (rmdir(dir) == 0)
- break;
- if (i < 100) {
- if (errno == EPERM) {
- int fd = open(dir, O_RDONLY);
- if (fd != -1) {
- long flags = 0;
- if (ioctl(fd, FS_IOC_SETFLAGS, &flags) == 0) {
- }
- close(fd);
- continue;
- }
- }
- if (errno == EROFS) {
- break;
- }
- if (errno == EBUSY) {
- if (umount2(dir, MNT_DETACH | UMOUNT_NOFOLLOW))
- exit(1);
- continue;
- }
- if (errno == ENOTEMPTY) {
- if (iter < 100) {
- iter++;
- goto retry;
- }
- }
- }
- exit(1);
- }
- }
- 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 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);
- }
- }
- static void setup_test()
- {
- prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0);
- setpgrp();
- write_file("/proc/self/oom_score_adj", "1000");
- if (symlink("/dev/binderfs", "./binderfs")) {
- }
- }
- struct thread_t {
- int created, call;
- event_t ready, done;
- };
- static struct thread_t threads[16];
- static void execute_call(int call);
- static int running;
- static void* thr(void* arg)
- {
- struct thread_t* th = (struct thread_t*)arg;
- for (;;) {
- event_wait(&th->ready);
- event_reset(&th->ready);
- execute_call(th->call);
- __atomic_fetch_sub(&running, 1, __ATOMIC_RELAXED);
- event_set(&th->done);
- }
- return 0;
- }
- static void execute_one(void)
- {
- int i, call, thread;
- for (call = 0; call < 8; call++) {
- for (thread = 0; thread < (int)(sizeof(threads) / sizeof(threads[0]));
- thread++) {
- struct thread_t* th = &threads[thread];
- if (!th->created) {
- th->created = 1;
- event_init(&th->ready);
- event_init(&th->done);
- event_set(&th->done);
- thread_start(thr, th);
- }
- if (!event_isset(&th->done))
- continue;
- event_reset(&th->done);
- th->call = call;
- __atomic_fetch_add(&running, 1, __ATOMIC_RELAXED);
- event_set(&th->ready);
- if (call == 2 || call == 6)
- break;
- event_timedwait(&th->done, 50 + (call == 0 ? 4000 : 0));
- break;
- }
- }
- for (i = 0; i < 100 && __atomic_load_n(&running, __ATOMIC_RELAXED); i++)
- sleep_ms(1);
- }
- static void execute_one(void);
- #define WAIT_FLAGS __WALL
- static void loop(void)
- {
- int iter = 0;
- for (;; iter++) {
- char cwdbuf[32];
- sprintf(cwdbuf, "./%d", iter);
- if (mkdir(cwdbuf, 0777))
- exit(1);
- reset_loop();
- int pid = fork();
- if (pid < 0)
- exit(1);
- if (pid == 0) {
- if (chdir(cwdbuf))
- exit(1);
- 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;
- }
- remove_dir(cwdbuf);
- }
- }
- uint64_t r[2] = {0xffffffffffffffff, 0xffffffffffffffff};
- void execute_call(int call)
- {
- intptr_t res = 0;
- switch (call) {
- case 0:
- NONFAILING(memcpy((void*)0x20000040, "ext4\000", 5));
- NONFAILING(memcpy((void*)0x20000500, "./file1\000", 8));
- NONFAILING(memcpy((void*)0x20000540, "errors=remount-ro", 17));
- NONFAILING(*(uint8_t*)0x20000551 = 0x2c);
- NONFAILING(memcpy((void*)0x20000552, "sysvgroups", 10));
- NONFAILING(*(uint8_t*)0x2000055c = 0x2c);
- NONFAILING(memcpy((void*)0x2000055d, "dioread_lock", 12));
- NONFAILING(*(uint8_t*)0x20000569 = 0x2c);
- NONFAILING(memcpy((void*)0x2000056a, "grpquota", 8));
- NONFAILING(*(uint8_t*)0x20000572 = 0x2c);
- NONFAILING(memcpy((void*)0x20000573, "noauto_da_alloc", 15));
- NONFAILING(*(uint8_t*)0x20000582 = 0x2c);
- NONFAILING(memcpy((void*)0x20000583, "resgid", 6));
- NONFAILING(*(uint8_t*)0x20000589 = 0x3d);
- NONFAILING(sprintf((char*)0x2000058a, "0x%016llx", (long long)0));
- NONFAILING(*(uint8_t*)0x2000059c = 0x2c);
- NONFAILING(memcpy((void*)0x2000059d, "barrier", 7));
- NONFAILING(*(uint8_t*)0x200005a4 = 0x2c);
- NONFAILING(memcpy((void*)0x200005a5, "auto_da_alloc", 13));
- NONFAILING(*(uint8_t*)0x200005b2 = 0x2c);
- NONFAILING(memcpy((void*)0x200005b3, "usrquota", 8));
- NONFAILING(*(uint8_t*)0x200005bb = 0x2c);
- NONFAILING(*(uint8_t*)0x200005bc = 0);
- NONFAILING(memcpy(
- (void*)0x20001b00,
- "\x78\x9c\xec\xdd\xdf\x6b\x5b\xd7\x1d\x00\xf0\xef\xbd\xb6\xb2\xfc\x70"
- "\x66\x67\xdb\x43\x16\x58\x16\x96\x0c\x27\x6c\x91\xec\x78\x49\xcc\x1e"
- "\xb2\x0c\xc6\xf2\x14\xd8\x96\xbd\x67\x9e\x2d\x1b\x63\xd9\x32\x96\x9c"
- "\xc4\x26\x0c\x87\xfd\x01\x83\x31\xd6\x42\x9f\xfa\xd4\x97\x42\xff\x80"
- "\x42\xc9\x9f\x50\x0a\x81\xf6\xbd\xb4\xa5\xa5\xb4\x49\xfb\xd0\x87\xb6"
- "\x2a\x92\xae\xd2\xc4\x95\x62\x87\xc8\xbe\x60\x7f\x3e\x70\x7c\xcf\xb9"
- "\x57\xd2\xf7\x7b\x6c\x74\x75\xcf\xbd\xc7\xba\x01\xec\x5b\xa7\x22\xe2"
- "\x6a\x44\x0c\x44\xc4\xb9\x88\x18\xce\xd6\xa7\x59\xb9\xd6\x6c\x6c\xb4"
- "\x1f\xf7\xe8\xe1\xdd\xe9\x66\x49\xa2\xd1\xb8\xf1\x59\x12\x49\xb6\xae"
- "\xf3\x5a\x49\xb6\x3c\xd2\x7e\x4a\x1c\x8c\x88\xbf\x5d\x8b\xf8\x67\xf2"
- "\xc3\xb8\xb5\xb5\xf5\x85\xa9\x4a\xa5\xbc\x92\xb5\x4b\xf5\xc5\xe5\x52"
- "\x6d\x6d\xfd\xfc\xfc\xe2\xd4\x5c\x79\xae\xbc\x34\x31\x31\x7e\x69\xf2"
- "\xf2\xe4\xc5\xc9\xb1\xbe\xf4\x73\x24\x22\xae\xfc\xe9\xa3\xff\xff\xe7"
- "\xb5\x3f\x5f\x79\xeb\xb7\xb7\xdf\xbf\xf9\xc9\xd9\x7f\x35\xd3\x1a\xca"
- "\xb6\x3f\xd9\x8f\x7e\x6a\x77\xbd\xd0\xfa\x5d\x74\x0c\x46\xc4\xca\x4e"
- "\x04\xcb\xc1\x40\xb6\x2c\xe4\x9c\x07\x00\x00\xdb\xd3\x3c\xc6\xff\x49"
- "\x44\xfc\xaa\x75\xfc\x3f\x1c\x03\xad\xa3\x53\x00\x00\x00\x60\x2f\x69"
- "\xfc\x61\x28\xbe\x4e\x22\x1a\x00\x00\x00\xc0\x9e\x95\xb6\xe6\xc0\x26"
- "\x69\x31\x9b\x0b\x30\x14\x69\x5a\x2c\xb6\xe7\xf0\xfe\x2c\x0e\xa7\x95"
- "\x6a\xad\xfe\x9b\xd9\xea\xea\xd2\x4c\x7b\xae\xec\x48\x14\xd2\xd9\xf9"
- "\x4a\x79\x2c\x9b\x2b\x3c\x12\x85\xa4\xd9\x1e\xcf\xe6\xd8\x76\xda\x17"
- "\x36\xb5\x27\x22\xe2\x58\x44\xfc\x6f\xf8\x50\xab\x5d\x9c\xae\x56\x66"
- "\xf2\x3e\xf9\x01\x00\x00\x00\xfb\xc4\x91\x4d\xe3\xff\x2f\x87\xdb\xe3"
- "\x7f\x00\x00\x00\x60\x8f\x19\xc9\x3b\x01\x00\x00\x00\x60\xc7\x19\xff"
- "\x03\x00\x00\xc0\xde\x67\xfc\x0f\x00\x00\x00\x7b\xda\x5f\xae\x5f\x6f"
- "\x96\x46\xe7\xfe\xd7\x33\xb7\xd6\x56\x17\xaa\xb7\xce\xcf\x94\x6b\x0b"
- "\xc5\xc5\xd5\xe9\xe2\x74\x75\x65\xb9\x38\x57\xad\xce\xb5\xbe\xb3\x6f"
- "\x71\xab\xd7\xab\x54\xab\xcb\xbf\x8b\xa5\xd5\x3b\xa5\x7a\xb9\x56\x2f"
- "\xd5\xd6\xd6\x6f\x2e\x56\x57\x97\xea\x37\xe7\x9f\xba\x05\x36\x00\x00"
- "\x00\xb0\x8b\x8e\xfd\xf2\xfe\x7b\x49\x44\x6c\xfc\xfe\x50\xab\x34\x1d"
- "\xc8\x3b\x29\x60\x57\x24\xcf\xf3\xe0\x0f\x77\x2e\x0f\x60\xf7\x0d\xe4"
- "\x9d\x00\x90\x9b\xc1\xbc\x13\x00\x72\x53\xc8\x3b\x01\x20\x77\x5b\x9d"
- "\x07\xe8\x39\x79\xe7\xed\xfe\xe7\x02\x00\x00\xec\x8c\xd1\x9f\xf7\xbe"
- "\xfe\xef\xdc\x00\xec\x6d\x69\xde\x09\x00\x00\xbb\xce\xf5\x7f\xd8\xbf"
- "\x0a\x66\x00\xc2\xbe\xf7\xe3\x2d\xb6\xbf\xf8\xf5\xff\x46\xe3\xb9\x12"
- "\x02\x00\x00\xfa\x6e\xa8\x55\x92\xb4\x98\x5d\x0b\x1c\x8a\x34\x2d\x16"
- "\x23\x8e\xb6\x6e\x0b\x50\x48\x66\xe7\x2b\xe5\xb1\x6c\x7c\xf0\xee\x70"
- "\xe1\x47\xcd\xf6\x78\xeb\x99\xc9\xf3\xfd\xef\x30\x00\x00\x00\x00\x00"
- "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xec\x63\x8d"
- "\x46\x12\x0d\x00\x00\x00\x60\x4f\x8b\x48\x3f\x4e\x5a\xdf\xe6\x1f\x31"
- "\x3a\x7c\x66\x68\xf3\xf9\x81\x03\xc9\x57\xc3\xad\x65\x44\xdc\x7e\xe5"
- "\xc6\x4b\x77\xa6\xea\xf5\x95\xf1\xe6\xfa\xcf\x1f\xaf\xaf\xbf\x9c\xad"
- "\xbf\x90\xc7\x19\x0c\x00\x00\x00\x60\xb3\xce\x38\xbd\x33\x8e\x07\x00"
- "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
- "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
- "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
- "\x00\x00\x80\x7e\x7a\xf4\xf0\xee\x74\xa7\xec\x66\xdc\x4f\xff\x18\x11"
- "\x23\xdd\xe2\x0f\xc6\xc1\xd6\xf2\x60\x14\x22\xe2\xf0\x17\x49\x0c\x3e"
- "\xf1\xbc\x24\x22\x06\xfa\x10\x7f\xe3\x5e\x44\x1c\xef\x16\x3f\x69\xa6"
- "\x15\x23\x59\x16\xdd\xe2\x1f\xca\x31\x7e\x1a\x11\x47\xfa\x10\x1f\xf6"
- "\xb3\xfb\xcd\xfd\xcf\xd5\x6e\xef\xbf\x34\x4e\xb5\x96\xdd\xdf\x7f\x83"
- "\x59\x79\x51\xbd\xf7\x7f\xe9\xe3\xfd\xdf\x40\x8f\xfd\xcf\xd1\x6d\xc6"
- "\x38\xf1\xe0\x8d\x52\xcf\xf8\xf7\x22\x4e\x0c\x76\xdf\xff\x74\xe2\x27"
- "\x3d\xe2\x9f\xde\x66\xfc\x7f\xfc\x7d\x7d\xbd\xd7\xb6\xc6\xab\x11\xa3"
- "\x5d\x3f\x7f\x92\xa7\x62\x95\xea\x8b\xcb\xa5\xda\xda\xfa\xf9\xf9\xc5"
- "\xa9\xb9\xf2\x5c\x79\x69\x62\x62\xfc\xd2\xe4\xe5\xc9\x8b\x93\x63\xa5"
- "\xd9\xf9\x4a\x39\xfb\xd9\x35\xc6\x7f\x7f\xf1\xe6\xb7\xcf\xea\xff\xe1"
- "\x1e\xf1\x47\xb6\xe8\xff\x99\x6d\xf6\xff\x9b\x07\x77\x1e\xfe\xb4\x5d"
- "\x2d\x74\x8b\x7f\xf6\x74\xf7\xcf\xdf\xe3\x3d\xe2\xa7\xd9\x67\xdf\xaf"
- "\xb3\x7a\x73\xfb\x68\xa7\xbe\xd1\xae\x3f\xe9\xe4\xeb\xef\x9c\x7c\x56"
- "\xff\x67\x7a\xf4\x7f\xab\xbf\xff\xd9\x6d\xf6\xff\xdc\x5f\xff\xfd\xc1"
- "\x36\x1f\x0a\x00\xec\x82\xda\xda\xfa\xc2\x54\xa5\x52\x5e\x51\x51\x51"
- "\x51\x79\x5c\xc9\x7b\xcf\x04\x00\x00\xf4\xdb\xf7\x07\xfd\x79\x67\x02"
- "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xfb\xd7"
- "\x6e\x7c\x9d\xd8\xe6\x98\x1b\xf9\x74\x15\x00\x00\x00\x00\x00\x00\x00"
- "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
- "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
- "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
- "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
- "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
- "\x00\x00\xe0\x99\xbe\x0b\x00\x00\xff\xff\xf7\xa0\xd4\xed",
- 1204));
- NONFAILING(syz_mount_image(/*fs=*/0x20000040, /*dir=*/0x20000500,
- /*flags=MS_REC|MS_NOATIME|0x100*/ 0x4500,
- /*opts=*/0x20000540, /*chdir=*/0x12,
- /*size=*/0x4b4, /*img=*/0x20001b00));
- break;
- case 1:
- NONFAILING(memcpy((void*)0x200000c0, "./file1\000", 8));
- res = syscall(
- __NR_open, /*file=*/0x200000c0ul,
- /*flags=O_SYNC|O_NONBLOCK|O_NOCTTY|O_NOATIME|O_DIRECT|O_CREAT|0x2002*/
- 0x147942ul, /*mode=*/0ul);
- if (res != -1)
- r[0] = res;
- break;
- case 2:
- NONFAILING(memcpy((void*)0x20000180, "./bus\000", 6));
- syscall(__NR_open, /*file=*/0x20000180ul,
- /*flags=O_TRUNC|O_SYNC|O_NOATIME|O_LARGEFILE|O_DIRECT|O_CREAT|0x3e*/
- 0x14d27eul, /*mode=*/0ul);
- break;
- case 3:
- NONFAILING(memcpy((void*)0x20000380, "/dev/loop", 9));
- NONFAILING(*(uint8_t*)0x20000389 = 0x30);
- NONFAILING(*(uint8_t*)0x2000038a = 0);
- NONFAILING(memcpy((void*)0x20000140, "./bus\000", 6));
- syscall(__NR_mount, /*src=*/0x20000380ul, /*dst=*/0x20000140ul,
- /*type=*/0ul, /*flags=MS_BIND*/ 0x1000ul, /*data=*/0ul);
- break;
- case 4:
- NONFAILING(memcpy((void*)0x20000400, "./bus\000", 6));
- res = syscall(__NR_open, /*file=*/0x20000400ul,
- /*flags=O_SYNC|O_NOCTTY|O_NOATIME|O_RDWR|0x3c*/ 0x14113eul,
- /*mode=*/0ul);
- if (res != -1)
- r[1] = res;
- break;
- case 5:
- syscall(__NR_sendfile, /*fdout=*/r[0], /*fdin=*/r[1], /*off=*/0ul,
- /*count=*/0x8000005cul);
- break;
- case 6:
- syscall(__NR_write, /*fd=*/r[1], /*data=*/0x20000100ul,
- /*len=*/0x208e24bul);
- break;
- case 7:
- NONFAILING(*(uint16_t*)0x20000080 = 0);
- NONFAILING(*(uint16_t*)0x20000082 = 0);
- NONFAILING(*(uint64_t*)0x20000088 = 0);
- NONFAILING(*(uint64_t*)0x20000090 = 0x1ff7fdfd000);
- NONFAILING(*(uint32_t*)0x20000098 = 0);
- NONFAILING(*(uint32_t*)0x2000009c = 0x48000000);
- NONFAILING(memset((void*)0x200000a0, 0, 16));
- syscall(__NR_ioctl, /*fd=*/r[0], /*cmd=*/0x40305829, /*arg=*/0x20000080ul);
- break;
- }
- }
- int main(void)
- {
- syscall(__NR_mmap, /*addr=*/0x1ffff000ul, /*len=*/0x1000ul, /*prot=*/0ul,
- /*flags=MAP_FIXED|MAP_ANONYMOUS|MAP_PRIVATE*/ 0x32ul, /*fd=*/-1,
- /*offset=*/0ul);
- syscall(__NR_mmap, /*addr=*/0x20000000ul, /*len=*/0x1000000ul,
- /*prot=PROT_WRITE|PROT_READ|PROT_EXEC*/ 7ul,
- /*flags=MAP_FIXED|MAP_ANONYMOUS|MAP_PRIVATE*/ 0x32ul, /*fd=*/-1,
- /*offset=*/0ul);
- syscall(__NR_mmap, /*addr=*/0x21000000ul, /*len=*/0x1000ul, /*prot=*/0ul,
- /*flags=MAP_FIXED|MAP_ANONYMOUS|MAP_PRIVATE*/ 0x32ul, /*fd=*/-1,
- /*offset=*/0ul);
- install_segv_handler();
- use_temporary_dir();
- loop();
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement