ok github.com/google/syzkaller/dashboard/app (cached) ? github.com/google/syzkaller/dashboard/dashapi [no test files] ? github.com/google/syzkaller/executor [no test files] ok github.com/google/syzkaller/pkg/ast 1.316s ? github.com/google/syzkaller/pkg/bisect [no test files] ok github.com/google/syzkaller/pkg/build 0.438s ok github.com/google/syzkaller/pkg/compiler 3.906s ok github.com/google/syzkaller/pkg/config (cached) ? github.com/google/syzkaller/pkg/cover [no test files] --- FAIL: TestGenerate (1.42s) --- FAIL: TestGenerate/test/64_fork (0.06s) csource_test.go:72: seed=1568761920714397312 --- FAIL: TestGenerate/test/64_fork/0 (0.73s) csource_test.go:110: opts: {Threaded:false Collide:false Repeat:true RepeatTimes:0 Procs:0 Sandbox:none Fault:false FaultCall:0 FaultNth:0 Leak:false EnableTun:false EnableNetDev:false EnableNetReset:false EnableCgroups:false EnableBinfmtMisc:false EnableCloseFds:false UseTmpDir:true HandleSegv:false Repro:false Trace:false} program: syz_mmap(&(0x7f0000ff6000/0x4000)=nil, 0x4000) syz_mmap(&(0x7f0000ffe000/0x2000)=nil, 0x2000) syz_compare_int$4(0x4, 0x7, 0x7f, 0x71f, 0x6) syz_errno(0x4) syz_compare_int$2(0x2, 0x7, 0x80000001) syz_compare_int$4(0x4, 0x9, 0x6, 0x3ff, 0x0) syz_compare_int$3(0x3, 0x0, 0x5, 0x6) syz_errno(0xffffffff80000000) syz_compare_int$2(0x2, 0x100000001, 0x8) syz_exit(0x200) syz_compare(&(0x7f0000000000)='\x00', 0x1, &(0x7f0000000040)=@str='\x00', 0x1) syz_compare_int$2(0x2, 0x4, 0x0) syz_errno(0x40) syz_execute_func(&(0x7f0000000080)="3463eeabc755e7fdebe72521f68b06b36c8a66c3879afec0d6602164be867da564b6906889aaf93338e8179eeaa2eb98b1ef") syz_exit(0x101) syz_mmap(&(0x7f0000ff2000/0x8000)=nil, 0x8000) csource_test.go:111: failed to build program: // autogenerated by syzkaller (https://github.com/google/syzkaller) #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include static void kill_and_wait(int pid, int* status) { kill(pid, SIGKILL); while (waitpid(-1, status, 0) != pid) { } } 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 remove_dir(const char* dir) { DIR* dp; struct dirent* ep; dp = opendir(dir); if (dp == NULL) exit(1); 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)) exit(1); if (S_ISDIR(st.st_mode)) { remove_dir(filename); continue; } if (unlink(filename)) exit(1); } closedir(dp); if (rmdir(dir)) exit(1); } static long syz_mmap(volatile long a0, volatile long a1) { return (long)mmap((void*)a0, a1, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE | MAP_FIXED, -1, 0); } static long syz_errno(volatile long v) { errno = v; return v == 0 ? 0 : -1; } static long syz_exit(volatile long status) { _exit(status); return 0; } static long syz_compare(volatile long want, volatile long want_len, volatile long got, volatile long got_len) { if (want_len != got_len) { errno = EBADF; return -1; } if (memcmp((void*)want, (void*)got, want_len)) { errno = EINVAL; return -1; } return 0; } static long syz_compare_int(volatile long n, ...) { va_list args; va_start(args, n); long v0 = va_arg(args, long); long v1 = va_arg(args, long); long v2 = va_arg(args, long); long v3 = va_arg(args, long); va_end(args); if (n < 2 || n > 4) return errno = E2BIG, -1; if (n <= 2 && v2 != 0) return errno = EFAULT, -1; if (n <= 3 && v3 != 0) return errno = EFAULT, -1; if (v0 != v1) return errno = EINVAL, -1; if (n > 2 && v0 != v2) return errno = EINVAL, -1; if (n > 3 && v0 != v3) return errno = EINVAL, -1; return 0; } static void loop(); static int do_sandbox_none(void) { loop(); return 0; } static long syz_execute_func(volatile long text) { volatile long p[8] = {0}; (void)p; ((void (*)(void))(text))(); return 0; } static void execute_one(void); #define WAIT_FLAGS 0 static void loop(void) { int iter; for (iter = 0;; iter++) { char cwdbuf[32]; sprintf(cwdbuf, "./%d", iter); if (mkdir(cwdbuf, 0777)) exit(1); int pid = fork(); if (pid < 0) exit(1); if (pid == 0) { if (chdir(cwdbuf)) exit(1); 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 < 5 * 1000) continue; kill_and_wait(pid, &status); break; } remove_dir(cwdbuf); } } void execute_one(void) { syz_mmap(0x20ff6000, 0x4000); syz_mmap(0x20ffe000, 0x2000); syz_compare_int(4, 7, 0x7f, 0x71f, 6); syz_errno(4); syz_compare_int(2, 7, 0x80000001, 0, 0); syz_compare_int(4, 9, 6, 0x3ff, 0); syz_compare_int(3, 0, 5, 6, 0); syz_errno(0x80000000); syz_compare_int(2, 0x100000001, 8, 0, 0); syz_exit(0x200); memcpy((void*)0x20000000, "\000", 1); memcpy((void*)0x20000040, "\000", 1); syz_compare(0x20000000, 1, 0x20000040, 1); syz_compare_int(2, 4, 0, 0, 0); syz_errno(0x40); memcpy((void*)0x20000080, "\x34\x63\xee\xab\xc7\x55\xe7\xfd\xeb\xe7\x25\x21\xf6\x8b\x06\xb3\x6c\x8a\x66\xc3\x87\x9a\xfe\xc0\xd6\x60\x21\x64\xbe\x86\x7d\xa5\x64\xb6\x90\x68\x89\xaa\xf9\x33\x38\xe8\x17\x9e\xea\xa2\xeb\x98\xb1\xef", 50); syz_execute_func(0x20000080); syz_exit(0x101); syz_mmap(0x20ff2000, 0x8000); } int main(void) { syz_mmap(0x20000000, 0x1000000); use_temporary_dir(); do_sandbox_none(); return 0; } /usr/local/bin/ld: cannot find -lasan collect2: error: ld returned 1 exit status compiler invocation: gcc [-o /tmp/syz-executor428950660 -DGOOS_test=1 -DGOARCH_64_fork=1 -DHOSTGOOS_freebsd=1 -x c - -O2 -pthread -Wall -Werror -Wparentheses -Wunused-const-variable -Wframe-larger-than=8192 -m64 -fsanitize=address] --- FAIL: TestGenerate/test/64_fork/8 (0.93s) csource_test.go:110: opts: {Threaded:true Collide:false Repeat:true RepeatTimes:0 Procs:1 Sandbox:none Fault:false FaultCall:0 FaultNth:0 Leak:false EnableTun:false EnableNetDev:false EnableNetReset:false EnableCgroups:false EnableBinfmtMisc:false EnableCloseFds:false UseTmpDir:true HandleSegv:false Repro:false Trace:false} program: syz_mmap(&(0x7f0000ff6000/0x4000)=nil, 0x4000) syz_mmap(&(0x7f0000ffe000/0x2000)=nil, 0x2000) syz_compare_int$4(0x4, 0x7, 0x7f, 0x71f, 0x6) syz_errno(0x4) syz_compare_int$2(0x2, 0x7, 0x80000001) syz_compare_int$4(0x4, 0x9, 0x6, 0x3ff, 0x0) syz_compare_int$3(0x3, 0x0, 0x5, 0x6) syz_errno(0xffffffff80000000) syz_compare_int$2(0x2, 0x100000001, 0x8) syz_exit(0x200) syz_compare(&(0x7f0000000000)='\x00', 0x1, &(0x7f0000000040)=@str='\x00', 0x1) syz_compare_int$2(0x2, 0x4, 0x0) syz_errno(0x40) syz_execute_func(&(0x7f0000000080)="3463eeabc755e7fdebe72521f68b06b36c8a66c3879afec0d6602164be867da564b6906889aaf93338e8179eeaa2eb98b1ef") syz_exit(0x101) syz_mmap(&(0x7f0000ff2000/0x8000)=nil, 0x8000) csource_test.go:111: failed to build program: // autogenerated by syzkaller (https://github.com/google/syzkaller) #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include static void kill_and_wait(int pid, int* status) { kill(pid, SIGKILL); while (waitpid(-1, status, 0) != pid) { } } 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 remove_dir(const char* dir) { DIR* dp; struct dirent* ep; dp = opendir(dir); if (dp == NULL) exit(1); 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)) exit(1); if (S_ISDIR(st.st_mode)) { remove_dir(filename); continue; } if (unlink(filename)) exit(1); } closedir(dp); if (rmdir(dir)) 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; for (i = 0; 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 { pthread_mutex_t mu; pthread_cond_t cv; int state; } event_t; static void event_init(event_t* ev) { if (pthread_mutex_init(&ev->mu, 0)) exit(1); if (pthread_cond_init(&ev->cv, 0)) exit(1); ev->state = 0; } static void event_reset(event_t* ev) { ev->state = 0; } static void event_set(event_t* ev) { pthread_mutex_lock(&ev->mu); if (ev->state) exit(1); ev->state = 1; pthread_mutex_unlock(&ev->mu); pthread_cond_broadcast(&ev->cv); } static void event_wait(event_t* ev) { pthread_mutex_lock(&ev->mu); while (!ev->state) pthread_cond_wait(&ev->cv, &ev->mu); pthread_mutex_unlock(&ev->mu); } static int event_isset(event_t* ev) { pthread_mutex_lock(&ev->mu); int res = ev->state; pthread_mutex_unlock(&ev->mu); return res; } static int event_timedwait(event_t* ev, uint64_t timeout) { uint64_t start = current_time_ms(); uint64_t now = start; pthread_mutex_lock(&ev->mu); for (;;) { if (ev->state) break; uint64_t remain = timeout - (now - start); struct timespec ts; ts.tv_sec = remain / 1000; ts.tv_nsec = (remain % 1000) * 1000 * 1000; pthread_cond_timedwait(&ev->cv, &ev->mu, &ts); now = current_time_ms(); if (now - start > timeout) break; } int res = ev->state; pthread_mutex_unlock(&ev->mu); return res; } static long syz_mmap(volatile long a0, volatile long a1) { return (long)mmap((void*)a0, a1, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE | MAP_FIXED, -1, 0); } static long syz_errno(volatile long v) { errno = v; return v == 0 ? 0 : -1; } static long syz_exit(volatile long status) { _exit(status); return 0; } static long syz_compare(volatile long want, volatile long want_len, volatile long got, volatile long got_len) { if (want_len != got_len) { errno = EBADF; return -1; } if (memcmp((void*)want, (void*)got, want_len)) { errno = EINVAL; return -1; } return 0; } static long syz_compare_int(volatile long n, ...) { va_list args; va_start(args, n); long v0 = va_arg(args, long); long v1 = va_arg(args, long); long v2 = va_arg(args, long); long v3 = va_arg(args, long); va_end(args); if (n < 2 || n > 4) return errno = E2BIG, -1; if (n <= 2 && v2 != 0) return errno = EFAULT, -1; if (n <= 3 && v3 != 0) return errno = EFAULT, -1; if (v0 != v1) return errno = EINVAL, -1; if (n > 2 && v0 != v2) return errno = EINVAL, -1; if (n > 3 && v0 != v3) return errno = EINVAL, -1; return 0; } static void loop(); static int do_sandbox_none(void) { loop(); return 0; } static long syz_execute_func(volatile long text) { volatile long p[8] = {0}; (void)p; ((void (*)(void))(text))(); return 0; } 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 < 16; 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); event_timedwait(&th->done, 45); break; } } for (i = 0; i < 100 && __atomic_load_n(&running, __ATOMIC_RELAXED); i++) sleep_ms(1); } static void execute_one(void); #define WAIT_FLAGS 0 static void loop(void) { int iter; for (iter = 0;; iter++) { char cwdbuf[32]; sprintf(cwdbuf, "./%d", iter); if (mkdir(cwdbuf, 0777)) exit(1); int pid = fork(); if (pid < 0) exit(1); if (pid == 0) { if (chdir(cwdbuf)) exit(1); 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 < 5 * 1000) continue; kill_and_wait(pid, &status); break; } remove_dir(cwdbuf); } } void execute_call(int call) { switch (call) { case 0: syz_mmap(0x20ff6000, 0x4000); break; case 1: syz_mmap(0x20ffe000, 0x2000); break; case 2: syz_compare_int(4, 7, 0x7f, 0x71f, 6); break; case 3: syz_errno(4); break; case 4: syz_compare_int(2, 7, 0x80000001, 0, 0); break; case 5: syz_compare_int(4, 9, 6, 0x3ff, 0); break; case 6: syz_compare_int(3, 0, 5, 6, 0); break; case 7: syz_errno(0x80000000); break; case 8: syz_compare_int(2, 0x100000001, 8, 0, 0); break; case 9: syz_exit(0x200); break; case 10: memcpy((void*)0x20000000, "\000", 1); memcpy((void*)0x20000040, "\000", 1); syz_compare(0x20000000, 1, 0x20000040, 1); break; case 11: syz_compare_int(2, 4, 0, 0, 0); break; case 12: syz_errno(0x40); break; case 13: memcpy((void*)0x20000080, "\x34\x63\xee\xab\xc7\x55\xe7\xfd\xeb\xe7\x25\x21\xf6\x8b\x06\xb3\x6c\x8a\x66\xc3\x87\x9a\xfe\xc0\xd6\x60\x21\x64\xbe\x86\x7d\xa5\x64\xb6\x90\x68\x89\xaa\xf9\x33\x38\xe8\x17\x9e\xea\xa2\xeb\x98\xb1\xef", 50); syz_execute_func(0x20000080); break; case 14: syz_exit(0x101); break; case 15: syz_mmap(0x20ff2000, 0x8000); break; } } int main(void) { syz_mmap(0x20000000, 0x1000000); use_temporary_dir(); do_sandbox_none(); return 0; } /usr/local/bin/ld: cannot find -lasan collect2: error: ld returned 1 exit status compiler invocation: gcc [-o /tmp/syz-executor168101753 -DGOOS_test=1 -DGOARCH_64_fork=1 -DHOSTGOOS_freebsd=1 -x c - -O2 -pthread -Wall -Werror -Wparentheses -Wunused-const-variable -Wframe-larger-than=8192 -m64 -fsanitize=address] --- FAIL: TestGenerate/test/64_fork/4 (0.95s) csource_test.go:110: opts: {Threaded:true Collide:false Repeat:false RepeatTimes:0 Procs:0 Sandbox:none Fault:false FaultCall:0 FaultNth:0 Leak:false EnableTun:false EnableNetDev:false EnableNetReset:false EnableCgroups:false EnableBinfmtMisc:false EnableCloseFds:false UseTmpDir:true HandleSegv:false Repro:false Trace:false} program: syz_mmap(&(0x7f0000ff6000/0x4000)=nil, 0x4000) syz_mmap(&(0x7f0000ffe000/0x2000)=nil, 0x2000) syz_compare_int$4(0x4, 0x7, 0x7f, 0x71f, 0x6) syz_errno(0x4) syz_compare_int$2(0x2, 0x7, 0x80000001) syz_compare_int$4(0x4, 0x9, 0x6, 0x3ff, 0x0) syz_compare_int$3(0x3, 0x0, 0x5, 0x6) syz_errno(0xffffffff80000000) syz_compare_int$2(0x2, 0x100000001, 0x8) syz_exit(0x200) syz_compare(&(0x7f0000000000)='\x00', 0x1, &(0x7f0000000040)=@str='\x00', 0x1) syz_compare_int$2(0x2, 0x4, 0x0) syz_errno(0x40) syz_execute_func(&(0x7f0000000080)="3463eeabc755e7fdebe72521f68b06b36c8a66c3879afec0d6602164be867da564b6906889aaf93338e8179eeaa2eb98b1ef") syz_exit(0x101) syz_mmap(&(0x7f0000ff2000/0x8000)=nil, 0x8000) csource_test.go:111: failed to build program: // autogenerated by syzkaller (https://github.com/google/syzkaller) #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include 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; for (i = 0; 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 { pthread_mutex_t mu; pthread_cond_t cv; int state; } event_t; static void event_init(event_t* ev) { if (pthread_mutex_init(&ev->mu, 0)) exit(1); if (pthread_cond_init(&ev->cv, 0)) exit(1); ev->state = 0; } static void event_reset(event_t* ev) { ev->state = 0; } static void event_set(event_t* ev) { pthread_mutex_lock(&ev->mu); if (ev->state) exit(1); ev->state = 1; pthread_mutex_unlock(&ev->mu); pthread_cond_broadcast(&ev->cv); } static void event_wait(event_t* ev) { pthread_mutex_lock(&ev->mu); while (!ev->state) pthread_cond_wait(&ev->cv, &ev->mu); pthread_mutex_unlock(&ev->mu); } static int event_isset(event_t* ev) { pthread_mutex_lock(&ev->mu); int res = ev->state; pthread_mutex_unlock(&ev->mu); return res; } static int event_timedwait(event_t* ev, uint64_t timeout) { uint64_t start = current_time_ms(); uint64_t now = start; pthread_mutex_lock(&ev->mu); for (;;) { if (ev->state) break; uint64_t remain = timeout - (now - start); struct timespec ts; ts.tv_sec = remain / 1000; ts.tv_nsec = (remain % 1000) * 1000 * 1000; pthread_cond_timedwait(&ev->cv, &ev->mu, &ts); now = current_time_ms(); if (now - start > timeout) break; } int res = ev->state; pthread_mutex_unlock(&ev->mu); return res; } static long syz_mmap(volatile long a0, volatile long a1) { return (long)mmap((void*)a0, a1, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE | MAP_FIXED, -1, 0); } static long syz_errno(volatile long v) { errno = v; return v == 0 ? 0 : -1; } static long syz_exit(volatile long status) { _exit(status); return 0; } static long syz_compare(volatile long want, volatile long want_len, volatile long got, volatile long got_len) { if (want_len != got_len) { errno = EBADF; return -1; } if (memcmp((void*)want, (void*)got, want_len)) { errno = EINVAL; return -1; } return 0; } static long syz_compare_int(volatile long n, ...) { va_list args; va_start(args, n); long v0 = va_arg(args, long); long v1 = va_arg(args, long); long v2 = va_arg(args, long); long v3 = va_arg(args, long); va_end(args); if (n < 2 || n > 4) return errno = E2BIG, -1; if (n <= 2 && v2 != 0) return errno = EFAULT, -1; if (n <= 3 && v3 != 0) return errno = EFAULT, -1; if (v0 != v1) return errno = EINVAL, -1; if (n > 2 && v0 != v2) return errno = EINVAL, -1; if (n > 3 && v0 != v3) return errno = EINVAL, -1; return 0; } static void loop(); static int do_sandbox_none(void) { loop(); return 0; } static long syz_execute_func(volatile long text) { volatile long p[8] = {0}; (void)p; ((void (*)(void))(text))(); return 0; } 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 loop(void) { int i, call, thread; for (call = 0; call < 16; 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); event_timedwait(&th->done, 45); break; } } for (i = 0; i < 100 && __atomic_load_n(&running, __ATOMIC_RELAXED); i++) sleep_ms(1); } void execute_call(int call) { switch (call) { case 0: syz_mmap(0x20ff6000, 0x4000); break; case 1: syz_mmap(0x20ffe000, 0x2000); break; case 2: syz_compare_int(4, 7, 0x7f, 0x71f, 6); break; case 3: syz_errno(4); break; case 4: syz_compare_int(2, 7, 0x80000001, 0, 0); break; case 5: syz_compare_int(4, 9, 6, 0x3ff, 0); break; case 6: syz_compare_int(3, 0, 5, 6, 0); break; case 7: syz_errno(0x80000000); break; case 8: syz_compare_int(2, 0x100000001, 8, 0, 0); break; case 9: syz_exit(0x200); break; case 10: memcpy((void*)0x20000000, "\000", 1); memcpy((void*)0x20000040, "\000", 1); syz_compare(0x20000000, 1, 0x20000040, 1); break; case 11: syz_compare_int(2, 4, 0, 0, 0); break; case 12: syz_errno(0x40); break; case 13: memcpy((void*)0x20000080, "\x34\x63\xee\xab\xc7\x55\xe7\xfd\xeb\xe7\x25\x21\xf6\x8b\x06\xb3\x6c\x8a\x66\xc3\x87\x9a\xfe\xc0\xd6\x60\x21\x64\xbe\x86\x7d\xa5\x64\xb6\x90\x68\x89\xaa\xf9\x33\x38\xe8\x17\x9e\xea\xa2\xeb\x98\xb1\xef", 50); syz_execute_func(0x20000080); break; case 14: syz_exit(0x101); break; case 15: syz_mmap(0x20ff2000, 0x8000); break; } } int main(void) { syz_mmap(0x20000000, 0x1000000); use_temporary_dir(); do_sandbox_none(); return 0; } /usr/local/bin/ld: cannot find -lasan collect2: error: ld returned 1 exit status compiler invocation: gcc [-o /tmp/syz-executor287486995 -DGOOS_test=1 -DGOARCH_64_fork=1 -DHOSTGOOS_freebsd=1 -x c - -O2 -pthread -Wall -Werror -Wparentheses -Wunused-const-variable -Wframe-larger-than=8192 -m64 -fsanitize=address] --- FAIL: TestGenerate/test/64_fork/11 (1.04s) csource_test.go:110: opts: {Threaded:true Collide:false Repeat:true RepeatTimes:0 Procs:0 Sandbox:none Fault:false FaultCall:0 FaultNth:0 Leak:false EnableTun:false EnableNetDev:false EnableNetReset:false EnableCgroups:false EnableBinfmtMisc:false EnableCloseFds:false UseTmpDir:true HandleSegv:false Repro:false Trace:false} program: syz_mmap(&(0x7f0000ff6000/0x4000)=nil, 0x4000) syz_mmap(&(0x7f0000ffe000/0x2000)=nil, 0x2000) syz_compare_int$4(0x4, 0x7, 0x7f, 0x71f, 0x6) syz_errno(0x4) syz_compare_int$2(0x2, 0x7, 0x80000001) syz_compare_int$4(0x4, 0x9, 0x6, 0x3ff, 0x0) syz_compare_int$3(0x3, 0x0, 0x5, 0x6) syz_errno(0xffffffff80000000) syz_compare_int$2(0x2, 0x100000001, 0x8) syz_exit(0x200) syz_compare(&(0x7f0000000000)='\x00', 0x1, &(0x7f0000000040)=@str='\x00', 0x1) syz_compare_int$2(0x2, 0x4, 0x0) syz_errno(0x40) syz_execute_func(&(0x7f0000000080)="3463eeabc755e7fdebe72521f68b06b36c8a66c3879afec0d6602164be867da564b6906889aaf93338e8179eeaa2eb98b1ef") syz_exit(0x101) syz_mmap(&(0x7f0000ff2000/0x8000)=nil, 0x8000) csource_test.go:111: failed to build program: // autogenerated by syzkaller (https://github.com/google/syzkaller) #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include static void kill_and_wait(int pid, int* status) { kill(pid, SIGKILL); while (waitpid(-1, status, 0) != pid) { } } 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 remove_dir(const char* dir) { DIR* dp; struct dirent* ep; dp = opendir(dir); if (dp == NULL) exit(1); 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)) exit(1); if (S_ISDIR(st.st_mode)) { remove_dir(filename); continue; } if (unlink(filename)) exit(1); } closedir(dp); if (rmdir(dir)) 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; for (i = 0; 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 { pthread_mutex_t mu; pthread_cond_t cv; int state; } event_t; static void event_init(event_t* ev) { if (pthread_mutex_init(&ev->mu, 0)) exit(1); if (pthread_cond_init(&ev->cv, 0)) exit(1); ev->state = 0; } static void event_reset(event_t* ev) { ev->state = 0; } static void event_set(event_t* ev) { pthread_mutex_lock(&ev->mu); if (ev->state) exit(1); ev->state = 1; pthread_mutex_unlock(&ev->mu); pthread_cond_broadcast(&ev->cv); } static void event_wait(event_t* ev) { pthread_mutex_lock(&ev->mu); while (!ev->state) pthread_cond_wait(&ev->cv, &ev->mu); pthread_mutex_unlock(&ev->mu); } static int event_isset(event_t* ev) { pthread_mutex_lock(&ev->mu); int res = ev->state; pthread_mutex_unlock(&ev->mu); return res; } static int event_timedwait(event_t* ev, uint64_t timeout) { uint64_t start = current_time_ms(); uint64_t now = start; pthread_mutex_lock(&ev->mu); for (;;) { if (ev->state) break; uint64_t remain = timeout - (now - start); struct timespec ts; ts.tv_sec = remain / 1000; ts.tv_nsec = (remain % 1000) * 1000 * 1000; pthread_cond_timedwait(&ev->cv, &ev->mu, &ts); now = current_time_ms(); if (now - start > timeout) break; } int res = ev->state; pthread_mutex_unlock(&ev->mu); return res; } static long syz_mmap(volatile long a0, volatile long a1) { return (long)mmap((void*)a0, a1, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE | MAP_FIXED, -1, 0); } static long syz_errno(volatile long v) { errno = v; return v == 0 ? 0 : -1; } static long syz_exit(volatile long status) { _exit(status); return 0; } static long syz_compare(volatile long want, volatile long want_len, volatile long got, volatile long got_len) { if (want_len != got_len) { errno = EBADF; return -1; } if (memcmp((void*)want, (void*)got, want_len)) { errno = EINVAL; return -1; } return 0; } static long syz_compare_int(volatile long n, ...) { va_list args; va_start(args, n); long v0 = va_arg(args, long); long v1 = va_arg(args, long); long v2 = va_arg(args, long); long v3 = va_arg(args, long); va_end(args); if (n < 2 || n > 4) return errno = E2BIG, -1; if (n <= 2 && v2 != 0) return errno = EFAULT, -1; if (n <= 3 && v3 != 0) return errno = EFAULT, -1; if (v0 != v1) return errno = EINVAL, -1; if (n > 2 && v0 != v2) return errno = EINVAL, -1; if (n > 3 && v0 != v3) return errno = EINVAL, -1; return 0; } static void loop(); static int do_sandbox_none(void) { loop(); return 0; } static long syz_execute_func(volatile long text) { volatile long p[8] = {0}; (void)p; ((void (*)(void))(text))(); return 0; } 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 < 16; 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); event_timedwait(&th->done, 45); break; } } for (i = 0; i < 100 && __atomic_load_n(&running, __ATOMIC_RELAXED); i++) sleep_ms(1); } static void execute_one(void); #define WAIT_FLAGS 0 static void loop(void) { int iter; for (iter = 0;; iter++) { char cwdbuf[32]; sprintf(cwdbuf, "./%d", iter); if (mkdir(cwdbuf, 0777)) exit(1); int pid = fork(); if (pid < 0) exit(1); if (pid == 0) { if (chdir(cwdbuf)) exit(1); 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 < 5 * 1000) continue; kill_and_wait(pid, &status); break; } remove_dir(cwdbuf); } } void execute_call(int call) { switch (call) { case 0: syz_mmap(0x20ff6000, 0x4000); break; case 1: syz_mmap(0x20ffe000, 0x2000); break; case 2: syz_compare_int(4, 7, 0x7f, 0x71f, 6); break; case 3: syz_errno(4); break; case 4: syz_compare_int(2, 7, 0x80000001, 0, 0); break; case 5: syz_compare_int(4, 9, 6, 0x3ff, 0); break; case 6: syz_compare_int(3, 0, 5, 6, 0); break; case 7: syz_errno(0x80000000); break; case 8: syz_compare_int(2, 0x100000001, 8, 0, 0); break; case 9: syz_exit(0x200); break; case 10: memcpy((void*)0x20000000, "\000", 1); memcpy((void*)0x20000040, "\000", 1); syz_compare(0x20000000, 1, 0x20000040, 1); break; case 11: syz_compare_int(2, 4, 0, 0, 0); break; case 12: syz_errno(0x40); break; case 13: memcpy((void*)0x20000080, "\x34\x63\xee\xab\xc7\x55\xe7\xfd\xeb\xe7\x25\x21\xf6\x8b\x06\xb3\x6c\x8a\x66\xc3\x87\x9a\xfe\xc0\xd6\x60\x21\x64\xbe\x86\x7d\xa5\x64\xb6\x90\x68\x89\xaa\xf9\x33\x38\xe8\x17\x9e\xea\xa2\xeb\x98\xb1\xef", 50); syz_execute_func(0x20000080); break; case 14: syz_exit(0x101); break; case 15: syz_mmap(0x20ff2000, 0x8000); break; } } int main(void) { syz_mmap(0x20000000, 0x1000000); use_temporary_dir(); do_sandbox_none(); return 0; } /usr/local/bin/ld: cannot find -lasan collect2: error: ld returned 1 exit status compiler invocation: gcc [-o /tmp/syz-executor091291069 -DGOOS_test=1 -DGOARCH_64_fork=1 -DHOSTGOOS_freebsd=1 -x c - -O2 -pthread -Wall -Werror -Wparentheses -Wunused-const-variable -Wframe-larger-than=8192 -m64 -fsanitize=address] --- FAIL: TestGenerate/test/64_fork/15 (1.07s) csource_test.go:110: opts: {Threaded:true Collide:false Repeat:true RepeatTimes:0 Procs:0 Sandbox:none Fault:false FaultCall:0 FaultNth:0 Leak:false EnableTun:false EnableNetDev:false EnableNetReset:false EnableCgroups:false EnableBinfmtMisc:false EnableCloseFds:false UseTmpDir:true HandleSegv:false Repro:false Trace:false} program: syz_mmap(&(0x7f0000ff6000/0x4000)=nil, 0x4000) syz_mmap(&(0x7f0000ffe000/0x2000)=nil, 0x2000) syz_compare_int$4(0x4, 0x7, 0x7f, 0x71f, 0x6) syz_errno(0x4) syz_compare_int$2(0x2, 0x7, 0x80000001) syz_compare_int$4(0x4, 0x9, 0x6, 0x3ff, 0x0) syz_compare_int$3(0x3, 0x0, 0x5, 0x6) syz_errno(0xffffffff80000000) syz_compare_int$2(0x2, 0x100000001, 0x8) syz_exit(0x200) syz_compare(&(0x7f0000000000)='\x00', 0x1, &(0x7f0000000040)=@str='\x00', 0x1) syz_compare_int$2(0x2, 0x4, 0x0) syz_errno(0x40) syz_execute_func(&(0x7f0000000080)="3463eeabc755e7fdebe72521f68b06b36c8a66c3879afec0d6602164be867da564b6906889aaf93338e8179eeaa2eb98b1ef") syz_exit(0x101) syz_mmap(&(0x7f0000ff2000/0x8000)=nil, 0x8000) csource_test.go:111: failed to build program: // autogenerated by syzkaller (https://github.com/google/syzkaller) #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include static void kill_and_wait(int pid, int* status) { kill(pid, SIGKILL); while (waitpid(-1, status, 0) != pid) { } } 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 remove_dir(const char* dir) { DIR* dp; struct dirent* ep; dp = opendir(dir); if (dp == NULL) exit(1); 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)) exit(1); if (S_ISDIR(st.st_mode)) { remove_dir(filename); continue; } if (unlink(filename)) exit(1); } closedir(dp); if (rmdir(dir)) 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; for (i = 0; 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 { pthread_mutex_t mu; pthread_cond_t cv; int state; } event_t; static void event_init(event_t* ev) { if (pthread_mutex_init(&ev->mu, 0)) exit(1); if (pthread_cond_init(&ev->cv, 0)) exit(1); ev->state = 0; } static void event_reset(event_t* ev) { ev->state = 0; } static void event_set(event_t* ev) { pthread_mutex_lock(&ev->mu); if (ev->state) exit(1); ev->state = 1; pthread_mutex_unlock(&ev->mu); pthread_cond_broadcast(&ev->cv); } static void event_wait(event_t* ev) { pthread_mutex_lock(&ev->mu); while (!ev->state) pthread_cond_wait(&ev->cv, &ev->mu); pthread_mutex_unlock(&ev->mu); } static int event_isset(event_t* ev) { pthread_mutex_lock(&ev->mu); int res = ev->state; pthread_mutex_unlock(&ev->mu); return res; } static int event_timedwait(event_t* ev, uint64_t timeout) { uint64_t start = current_time_ms(); uint64_t now = start; pthread_mutex_lock(&ev->mu); for (;;) { if (ev->state) break; uint64_t remain = timeout - (now - start); struct timespec ts; ts.tv_sec = remain / 1000; ts.tv_nsec = (remain % 1000) * 1000 * 1000; pthread_cond_timedwait(&ev->cv, &ev->mu, &ts); now = current_time_ms(); if (now - start > timeout) break; } int res = ev->state; pthread_mutex_unlock(&ev->mu); return res; } static long syz_mmap(volatile long a0, volatile long a1) { return (long)mmap((void*)a0, a1, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE | MAP_FIXED, -1, 0); } static long syz_errno(volatile long v) { errno = v; return v == 0 ? 0 : -1; } static long syz_exit(volatile long status) { _exit(status); return 0; } static long syz_compare(volatile long want, volatile long want_len, volatile long got, volatile long got_len) { if (want_len != got_len) { errno = EBADF; return -1; } if (memcmp((void*)want, (void*)got, want_len)) { errno = EINVAL; return -1; } return 0; } static long syz_compare_int(volatile long n, ...) { va_list args; va_start(args, n); long v0 = va_arg(args, long); long v1 = va_arg(args, long); long v2 = va_arg(args, long); long v3 = va_arg(args, long); va_end(args); if (n < 2 || n > 4) return errno = E2BIG, -1; if (n <= 2 && v2 != 0) return errno = EFAULT, -1; if (n <= 3 && v3 != 0) return errno = EFAULT, -1; if (v0 != v1) return errno = EINVAL, -1; if (n > 2 && v0 != v2) return errno = EINVAL, -1; if (n > 3 && v0 != v3) return errno = EINVAL, -1; return 0; } static void loop(); static int do_sandbox_none(void) { loop(); return 0; } static long syz_execute_func(volatile long text) { volatile long p[8] = {0}; (void)p; ((void (*)(void))(text))(); return 0; } 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 < 16; 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); event_timedwait(&th->done, 45); break; } } for (i = 0; i < 100 && __atomic_load_n(&running, __ATOMIC_RELAXED); i++) sleep_ms(1); } static void execute_one(void); #define WAIT_FLAGS 0 static void loop(void) { int iter; for (iter = 0;; iter++) { char cwdbuf[32]; sprintf(cwdbuf, "./%d", iter); if (mkdir(cwdbuf, 0777)) exit(1); int pid = fork(); if (pid < 0) exit(1); if (pid == 0) { if (chdir(cwdbuf)) exit(1); 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 < 5 * 1000) continue; kill_and_wait(pid, &status); break; } remove_dir(cwdbuf); } } void execute_call(int call) { switch (call) { case 0: syz_mmap(0x20ff6000, 0x4000); break; case 1: syz_mmap(0x20ffe000, 0x2000); break; case 2: syz_compare_int(4, 7, 0x7f, 0x71f, 6); break; case 3: syz_errno(4); break; case 4: syz_compare_int(2, 7, 0x80000001, 0, 0); break; case 5: syz_compare_int(4, 9, 6, 0x3ff, 0); break; case 6: syz_compare_int(3, 0, 5, 6, 0); break; case 7: syz_errno(0x80000000); break; case 8: syz_compare_int(2, 0x100000001, 8, 0, 0); break; case 9: syz_exit(0x200); break; case 10: memcpy((void*)0x20000000, "\000", 1); memcpy((void*)0x20000040, "\000", 1); syz_compare(0x20000000, 1, 0x20000040, 1); break; case 11: syz_compare_int(2, 4, 0, 0, 0); break; case 12: syz_errno(0x40); break; case 13: memcpy((void*)0x20000080, "\x34\x63\xee\xab\xc7\x55\xe7\xfd\xeb\xe7\x25\x21\xf6\x8b\x06\xb3\x6c\x8a\x66\xc3\x87\x9a\xfe\xc0\xd6\x60\x21\x64\xbe\x86\x7d\xa5\x64\xb6\x90\x68\x89\xaa\xf9\x33\x38\xe8\x17\x9e\xea\xa2\xeb\x98\xb1\xef", 50); syz_execute_func(0x20000080); break; case 14: syz_exit(0x101); break; case 15: syz_mmap(0x20ff2000, 0x8000); break; } } int main(void) { syz_mmap(0x20000000, 0x1000000); use_temporary_dir(); do_sandbox_none(); return 0; } /usr/local/bin/ld: cannot find -lasan collect2: error: ld returned 1 exit status compiler invocation: gcc [-o /tmp/syz-executor602039382 -DGOOS_test=1 -DGOARCH_64_fork=1 -DHOSTGOOS_freebsd=1 -x c - -O2 -pthread -Wall -Werror -Wparentheses -Wunused-const-variable -Wframe-larger-than=8192 -m64 -fsanitize=address] --- FAIL: TestGenerate/test/64_fork/2 (1.11s) csource_test.go:110: opts: {Threaded:true Collide:false Repeat:true RepeatTimes:0 Procs:0 Sandbox:none Fault:false FaultCall:0 FaultNth:0 Leak:false EnableTun:false EnableNetDev:false EnableNetReset:false EnableCgroups:false EnableBinfmtMisc:false EnableCloseFds:false UseTmpDir:true HandleSegv:false Repro:false Trace:false} program: syz_mmap(&(0x7f0000ff6000/0x4000)=nil, 0x4000) syz_mmap(&(0x7f0000ffe000/0x2000)=nil, 0x2000) syz_compare_int$4(0x4, 0x7, 0x7f, 0x71f, 0x6) syz_errno(0x4) syz_compare_int$2(0x2, 0x7, 0x80000001) syz_compare_int$4(0x4, 0x9, 0x6, 0x3ff, 0x0) syz_compare_int$3(0x3, 0x0, 0x5, 0x6) syz_errno(0xffffffff80000000) syz_compare_int$2(0x2, 0x100000001, 0x8) syz_exit(0x200) syz_compare(&(0x7f0000000000)='\x00', 0x1, &(0x7f0000000040)=@str='\x00', 0x1) syz_compare_int$2(0x2, 0x4, 0x0) syz_errno(0x40) syz_execute_func(&(0x7f0000000080)="3463eeabc755e7fdebe72521f68b06b36c8a66c3879afec0d6602164be867da564b6906889aaf93338e8179eeaa2eb98b1ef") syz_exit(0x101) syz_mmap(&(0x7f0000ff2000/0x8000)=nil, 0x8000) csource_test.go:111: failed to build program: // autogenerated by syzkaller (https://github.com/google/syzkaller) #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include static void kill_and_wait(int pid, int* status) { kill(pid, SIGKILL); while (waitpid(-1, status, 0) != pid) { } } 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 remove_dir(const char* dir) { DIR* dp; struct dirent* ep; dp = opendir(dir); if (dp == NULL) exit(1); 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)) exit(1); if (S_ISDIR(st.st_mode)) { remove_dir(filename); continue; } if (unlink(filename)) exit(1); } closedir(dp); if (rmdir(dir)) 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; for (i = 0; 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 { pthread_mutex_t mu; pthread_cond_t cv; int state; } event_t; static void event_init(event_t* ev) { if (pthread_mutex_init(&ev->mu, 0)) exit(1); if (pthread_cond_init(&ev->cv, 0)) exit(1); ev->state = 0; } static void event_reset(event_t* ev) { ev->state = 0; } static void event_set(event_t* ev) { pthread_mutex_lock(&ev->mu); if (ev->state) exit(1); ev->state = 1; pthread_mutex_unlock(&ev->mu); pthread_cond_broadcast(&ev->cv); } static void event_wait(event_t* ev) { pthread_mutex_lock(&ev->mu); while (!ev->state) pthread_cond_wait(&ev->cv, &ev->mu); pthread_mutex_unlock(&ev->mu); } static int event_isset(event_t* ev) { pthread_mutex_lock(&ev->mu); int res = ev->state; pthread_mutex_unlock(&ev->mu); return res; } static int event_timedwait(event_t* ev, uint64_t timeout) { uint64_t start = current_time_ms(); uint64_t now = start; pthread_mutex_lock(&ev->mu); for (;;) { if (ev->state) break; uint64_t remain = timeout - (now - start); struct timespec ts; ts.tv_sec = remain / 1000; ts.tv_nsec = (remain % 1000) * 1000 * 1000; pthread_cond_timedwait(&ev->cv, &ev->mu, &ts); now = current_time_ms(); if (now - start > timeout) break; } int res = ev->state; pthread_mutex_unlock(&ev->mu); return res; } static long syz_mmap(volatile long a0, volatile long a1) { return (long)mmap((void*)a0, a1, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE | MAP_FIXED, -1, 0); } static long syz_errno(volatile long v) { errno = v; return v == 0 ? 0 : -1; } static long syz_exit(volatile long status) { _exit(status); return 0; } static long syz_compare(volatile long want, volatile long want_len, volatile long got, volatile long got_len) { if (want_len != got_len) { errno = EBADF; return -1; } if (memcmp((void*)want, (void*)got, want_len)) { errno = EINVAL; return -1; } return 0; } static long syz_compare_int(volatile long n, ...) { va_list args; va_start(args, n); long v0 = va_arg(args, long); long v1 = va_arg(args, long); long v2 = va_arg(args, long); long v3 = va_arg(args, long); va_end(args); if (n < 2 || n > 4) return errno = E2BIG, -1; if (n <= 2 && v2 != 0) return errno = EFAULT, -1; if (n <= 3 && v3 != 0) return errno = EFAULT, -1; if (v0 != v1) return errno = EINVAL, -1; if (n > 2 && v0 != v2) return errno = EINVAL, -1; if (n > 3 && v0 != v3) return errno = EINVAL, -1; return 0; } static void loop(); static int do_sandbox_none(void) { loop(); return 0; } static long syz_execute_func(volatile long text) { volatile long p[8] = {0}; (void)p; ((void (*)(void))(text))(); return 0; } 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 < 16; 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); event_timedwait(&th->done, 45); break; } } for (i = 0; i < 100 && __atomic_load_n(&running, __ATOMIC_RELAXED); i++) sleep_ms(1); } static void execute_one(void); #define WAIT_FLAGS 0 static void loop(void) { int iter; for (iter = 0;; iter++) { char cwdbuf[32]; sprintf(cwdbuf, "./%d", iter); if (mkdir(cwdbuf, 0777)) exit(1); int pid = fork(); if (pid < 0) exit(1); if (pid == 0) { if (chdir(cwdbuf)) exit(1); 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 < 5 * 1000) continue; kill_and_wait(pid, &status); break; } remove_dir(cwdbuf); } } void execute_call(int call) { switch (call) { case 0: syz_mmap(0x20ff6000, 0x4000); break; case 1: syz_mmap(0x20ffe000, 0x2000); break; case 2: syz_compare_int(4, 7, 0x7f, 0x71f, 6); break; case 3: syz_errno(4); break; case 4: syz_compare_int(2, 7, 0x80000001, 0, 0); break; case 5: syz_compare_int(4, 9, 6, 0x3ff, 0); break; case 6: syz_compare_int(3, 0, 5, 6, 0); break; case 7: syz_errno(0x80000000); break; case 8: syz_compare_int(2, 0x100000001, 8, 0, 0); break; case 9: syz_exit(0x200); break; case 10: memcpy((void*)0x20000000, "\000", 1); memcpy((void*)0x20000040, "\000", 1); syz_compare(0x20000000, 1, 0x20000040, 1); break; case 11: syz_compare_int(2, 4, 0, 0, 0); break; case 12: syz_errno(0x40); break; case 13: memcpy((void*)0x20000080, "\x34\x63\xee\xab\xc7\x55\xe7\xfd\xeb\xe7\x25\x21\xf6\x8b\x06\xb3\x6c\x8a\x66\xc3\x87\x9a\xfe\xc0\xd6\x60\x21\x64\xbe\x86\x7d\xa5\x64\xb6\x90\x68\x89\xaa\xf9\x33\x38\xe8\x17\x9e\xea\xa2\xeb\x98\xb1\xef", 50); syz_execute_func(0x20000080); break; case 14: syz_exit(0x101); break; case 15: syz_mmap(0x20ff2000, 0x8000); break; } } int main(void) { syz_mmap(0x20000000, 0x1000000); use_temporary_dir(); do_sandbox_none(); return 0; } /usr/local/bin/ld: cannot find -lasan collect2: error: ld returned 1 exit status compiler invocation: gcc [-o /tmp/syz-executor711632888 -DGOOS_test=1 -DGOARCH_64_fork=1 -DHOSTGOOS_freebsd=1 -x c - -O2 -pthread -Wall -Werror -Wparentheses -Wunused-const-variable -Wframe-larger-than=8192 -m64 -fsanitize=address] --- FAIL: TestGenerate/test/64_fork/13 (0.82s) csource_test.go:110: opts: {Threaded:true Collide:false Repeat:true RepeatTimes:0 Procs:0 Sandbox:none Fault:false FaultCall:0 FaultNth:0 Leak:false EnableTun:false EnableNetDev:false EnableNetReset:false EnableCgroups:false EnableBinfmtMisc:false EnableCloseFds:false UseTmpDir:true HandleSegv:false Repro:false Trace:false} program: syz_mmap(&(0x7f0000ff6000/0x4000)=nil, 0x4000) syz_mmap(&(0x7f0000ffe000/0x2000)=nil, 0x2000) syz_compare_int$4(0x4, 0x7, 0x7f, 0x71f, 0x6) syz_errno(0x4) syz_compare_int$2(0x2, 0x7, 0x80000001) syz_compare_int$4(0x4, 0x9, 0x6, 0x3ff, 0x0) syz_compare_int$3(0x3, 0x0, 0x5, 0x6) syz_errno(0xffffffff80000000) syz_compare_int$2(0x2, 0x100000001, 0x8) syz_exit(0x200) syz_compare(&(0x7f0000000000)='\x00', 0x1, &(0x7f0000000040)=@str='\x00', 0x1) syz_compare_int$2(0x2, 0x4, 0x0) syz_errno(0x40) syz_execute_func(&(0x7f0000000080)="3463eeabc755e7fdebe72521f68b06b36c8a66c3879afec0d6602164be867da564b6906889aaf93338e8179eeaa2eb98b1ef") syz_exit(0x101) syz_mmap(&(0x7f0000ff2000/0x8000)=nil, 0x8000) csource_test.go:111: failed to build program: // autogenerated by syzkaller (https://github.com/google/syzkaller) #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include static void kill_and_wait(int pid, int* status) { kill(pid, SIGKILL); while (waitpid(-1, status, 0) != pid) { } } 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 remove_dir(const char* dir) { DIR* dp; struct dirent* ep; dp = opendir(dir); if (dp == NULL) exit(1); 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)) exit(1); if (S_ISDIR(st.st_mode)) { remove_dir(filename); continue; } if (unlink(filename)) exit(1); } closedir(dp); if (rmdir(dir)) 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; for (i = 0; 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 { pthread_mutex_t mu; pthread_cond_t cv; int state; } event_t; static void event_init(event_t* ev) { if (pthread_mutex_init(&ev->mu, 0)) exit(1); if (pthread_cond_init(&ev->cv, 0)) exit(1); ev->state = 0; } static void event_reset(event_t* ev) { ev->state = 0; } static void event_set(event_t* ev) { pthread_mutex_lock(&ev->mu); if (ev->state) exit(1); ev->state = 1; pthread_mutex_unlock(&ev->mu); pthread_cond_broadcast(&ev->cv); } static void event_wait(event_t* ev) { pthread_mutex_lock(&ev->mu); while (!ev->state) pthread_cond_wait(&ev->cv, &ev->mu); pthread_mutex_unlock(&ev->mu); } static int event_isset(event_t* ev) { pthread_mutex_lock(&ev->mu); int res = ev->state; pthread_mutex_unlock(&ev->mu); return res; } static int event_timedwait(event_t* ev, uint64_t timeout) { uint64_t start = current_time_ms(); uint64_t now = start; pthread_mutex_lock(&ev->mu); for (;;) { if (ev->state) break; uint64_t remain = timeout - (now - start); struct timespec ts; ts.tv_sec = remain / 1000; ts.tv_nsec = (remain % 1000) * 1000 * 1000; pthread_cond_timedwait(&ev->cv, &ev->mu, &ts); now = current_time_ms(); if (now - start > timeout) break; } int res = ev->state; pthread_mutex_unlock(&ev->mu); return res; } static long syz_mmap(volatile long a0, volatile long a1) { return (long)mmap((void*)a0, a1, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE | MAP_FIXED, -1, 0); } static long syz_errno(volatile long v) { errno = v; return v == 0 ? 0 : -1; } static long syz_exit(volatile long status) { _exit(status); return 0; } static long syz_compare(volatile long want, volatile long want_len, volatile long got, volatile long got_len) { if (want_len != got_len) { errno = EBADF; return -1; } if (memcmp((void*)want, (void*)got, want_len)) { errno = EINVAL; return -1; } return 0; } static long syz_compare_int(volatile long n, ...) { va_list args; va_start(args, n); long v0 = va_arg(args, long); long v1 = va_arg(args, long); long v2 = va_arg(args, long); long v3 = va_arg(args, long); va_end(args); if (n < 2 || n > 4) return errno = E2BIG, -1; if (n <= 2 && v2 != 0) return errno = EFAULT, -1; if (n <= 3 && v3 != 0) return errno = EFAULT, -1; if (v0 != v1) return errno = EINVAL, -1; if (n > 2 && v0 != v2) return errno = EINVAL, -1; if (n > 3 && v0 != v3) return errno = EINVAL, -1; return 0; } static void loop(); static int do_sandbox_none(void) { loop(); return 0; } static long syz_execute_func(volatile long text) { volatile long p[8] = {0}; (void)p; ((void (*)(void))(text))(); return 0; } 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 < 16; 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); event_timedwait(&th->done, 45); break; } } for (i = 0; i < 100 && __atomic_load_n(&running, __ATOMIC_RELAXED); i++) sleep_ms(1); } static void execute_one(void); #define WAIT_FLAGS 0 static void loop(void) { int iter; for (iter = 0;; iter++) { char cwdbuf[32]; sprintf(cwdbuf, "./%d", iter); if (mkdir(cwdbuf, 0777)) exit(1); int pid = fork(); if (pid < 0) exit(1); if (pid == 0) { if (chdir(cwdbuf)) exit(1); 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 < 5 * 1000) continue; kill_and_wait(pid, &status); break; } remove_dir(cwdbuf); } } void execute_call(int call) { switch (call) { case 0: syz_mmap(0x20ff6000, 0x4000); break; case 1: syz_mmap(0x20ffe000, 0x2000); break; case 2: syz_compare_int(4, 7, 0x7f, 0x71f, 6); break; case 3: syz_errno(4); break; case 4: syz_compare_int(2, 7, 0x80000001, 0, 0); break; case 5: syz_compare_int(4, 9, 6, 0x3ff, 0); break; case 6: syz_compare_int(3, 0, 5, 6, 0); break; case 7: syz_errno(0x80000000); break; case 8: syz_compare_int(2, 0x100000001, 8, 0, 0); break; case 9: syz_exit(0x200); break; case 10: memcpy((void*)0x20000000, "\000", 1); memcpy((void*)0x20000040, "\000", 1); syz_compare(0x20000000, 1, 0x20000040, 1); break; case 11: syz_compare_int(2, 4, 0, 0, 0); break; case 12: syz_errno(0x40); break; case 13: memcpy((void*)0x20000080, "\x34\x63\xee\xab\xc7\x55\xe7\xfd\xeb\xe7\x25\x21\xf6\x8b\x06\xb3\x6c\x8a\x66\xc3\x87\x9a\xfe\xc0\xd6\x60\x21\x64\xbe\x86\x7d\xa5\x64\xb6\x90\x68\x89\xaa\xf9\x33\x38\xe8\x17\x9e\xea\xa2\xeb\x98\xb1\xef", 50); syz_execute_func(0x20000080); break; case 14: syz_exit(0x101); break; case 15: syz_mmap(0x20ff2000, 0x8000); break; } } int main(void) { syz_mmap(0x20000000, 0x1000000); use_temporary_dir(); do_sandbox_none(); return 0; } /usr/local/bin/ld: cannot find -lasan collect2: error: ld returned 1 exit status compiler invocation: gcc [-o /tmp/syz-executor660974107 -DGOOS_test=1 -DGOARCH_64_fork=1 -DHOSTGOOS_freebsd=1 -x c - -O2 -pthread -Wall -Werror -Wparentheses -Wunused-const-variable -Wframe-larger-than=8192 -m64 -fsanitize=address] --- FAIL: TestGenerate/test/64_fork/9 (1.28s) csource_test.go:110: opts: {Threaded:true Collide:false Repeat:true RepeatTimes:0 Procs:4 Sandbox:none Fault:false FaultCall:0 FaultNth:0 Leak:false EnableTun:false EnableNetDev:false EnableNetReset:false EnableCgroups:false EnableBinfmtMisc:false EnableCloseFds:false UseTmpDir:true HandleSegv:false Repro:false Trace:false} program: syz_mmap(&(0x7f0000ff6000/0x4000)=nil, 0x4000) syz_mmap(&(0x7f0000ffe000/0x2000)=nil, 0x2000) syz_compare_int$4(0x4, 0x7, 0x7f, 0x71f, 0x6) syz_errno(0x4) syz_compare_int$2(0x2, 0x7, 0x80000001) syz_compare_int$4(0x4, 0x9, 0x6, 0x3ff, 0x0) syz_compare_int$3(0x3, 0x0, 0x5, 0x6) syz_errno(0xffffffff80000000) syz_compare_int$2(0x2, 0x100000001, 0x8) syz_exit(0x200) syz_compare(&(0x7f0000000000)='\x00', 0x1, &(0x7f0000000040)=@str='\x00', 0x1) syz_compare_int$2(0x2, 0x4, 0x0) syz_errno(0x40) syz_execute_func(&(0x7f0000000080)="3463eeabc755e7fdebe72521f68b06b36c8a66c3879afec0d6602164be867da564b6906889aaf93338e8179eeaa2eb98b1ef") syz_exit(0x101) syz_mmap(&(0x7f0000ff2000/0x8000)=nil, 0x8000) csource_test.go:111: failed to build program: // autogenerated by syzkaller (https://github.com/google/syzkaller) #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include unsigned long long procid; static void kill_and_wait(int pid, int* status) { kill(pid, SIGKILL); while (waitpid(-1, status, 0) != pid) { } } 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 remove_dir(const char* dir) { DIR* dp; struct dirent* ep; dp = opendir(dir); if (dp == NULL) exit(1); 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)) exit(1); if (S_ISDIR(st.st_mode)) { remove_dir(filename); continue; } if (unlink(filename)) exit(1); } closedir(dp); if (rmdir(dir)) 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; for (i = 0; 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 { pthread_mutex_t mu; pthread_cond_t cv; int state; } event_t; static void event_init(event_t* ev) { if (pthread_mutex_init(&ev->mu, 0)) exit(1); if (pthread_cond_init(&ev->cv, 0)) exit(1); ev->state = 0; } static void event_reset(event_t* ev) { ev->state = 0; } static void event_set(event_t* ev) { pthread_mutex_lock(&ev->mu); if (ev->state) exit(1); ev->state = 1; pthread_mutex_unlock(&ev->mu); pthread_cond_broadcast(&ev->cv); } static void event_wait(event_t* ev) { pthread_mutex_lock(&ev->mu); while (!ev->state) pthread_cond_wait(&ev->cv, &ev->mu); pthread_mutex_unlock(&ev->mu); } static int event_isset(event_t* ev) { pthread_mutex_lock(&ev->mu); int res = ev->state; pthread_mutex_unlock(&ev->mu); return res; } static int event_timedwait(event_t* ev, uint64_t timeout) { uint64_t start = current_time_ms(); uint64_t now = start; pthread_mutex_lock(&ev->mu); for (;;) { if (ev->state) break; uint64_t remain = timeout - (now - start); struct timespec ts; ts.tv_sec = remain / 1000; ts.tv_nsec = (remain % 1000) * 1000 * 1000; pthread_cond_timedwait(&ev->cv, &ev->mu, &ts); now = current_time_ms(); if (now - start > timeout) break; } int res = ev->state; pthread_mutex_unlock(&ev->mu); return res; } static long syz_mmap(volatile long a0, volatile long a1) { return (long)mmap((void*)a0, a1, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE | MAP_FIXED, -1, 0); } static long syz_errno(volatile long v) { errno = v; return v == 0 ? 0 : -1; } static long syz_exit(volatile long status) { _exit(status); return 0; } static long syz_compare(volatile long want, volatile long want_len, volatile long got, volatile long got_len) { if (want_len != got_len) { errno = EBADF; return -1; } if (memcmp((void*)want, (void*)got, want_len)) { errno = EINVAL; return -1; } return 0; } static long syz_compare_int(volatile long n, ...) { va_list args; va_start(args, n); long v0 = va_arg(args, long); long v1 = va_arg(args, long); long v2 = va_arg(args, long); long v3 = va_arg(args, long); va_end(args); if (n < 2 || n > 4) return errno = E2BIG, -1; if (n <= 2 && v2 != 0) return errno = EFAULT, -1; if (n <= 3 && v3 != 0) return errno = EFAULT, -1; if (v0 != v1) return errno = EINVAL, -1; if (n > 2 && v0 != v2) return errno = EINVAL, -1; if (n > 3 && v0 != v3) return errno = EINVAL, -1; return 0; } static void loop(); static int do_sandbox_none(void) { loop(); return 0; } static long syz_execute_func(volatile long text) { volatile long p[8] = {0}; (void)p; ((void (*)(void))(text))(); return 0; } 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 < 16; 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); event_timedwait(&th->done, 45); break; } } for (i = 0; i < 100 && __atomic_load_n(&running, __ATOMIC_RELAXED); i++) sleep_ms(1); } static void execute_one(void); #define WAIT_FLAGS 0 static void loop(void) { int iter; for (iter = 0;; iter++) { char cwdbuf[32]; sprintf(cwdbuf, "./%d", iter); if (mkdir(cwdbuf, 0777)) exit(1); int pid = fork(); if (pid < 0) exit(1); if (pid == 0) { if (chdir(cwdbuf)) exit(1); 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 < 5 * 1000) continue; kill_and_wait(pid, &status); break; } remove_dir(cwdbuf); } } void execute_call(int call) { switch (call) { case 0: syz_mmap(0x20ff6000, 0x4000); break; case 1: syz_mmap(0x20ffe000, 0x2000); break; case 2: syz_compare_int(4, 7, 0x7f, 0x71f, 6); break; case 3: syz_errno(4); break; case 4: syz_compare_int(2, 7, 0x80000001, 0, 0); break; case 5: syz_compare_int(4, 9, 6, 0x3ff, 0); break; case 6: syz_compare_int(3, 0, 5, 6, 0); break; case 7: syz_errno(0x80000000); break; case 8: syz_compare_int(2, 0x100000001, 8, 0, 0); break; case 9: syz_exit(0x200); break; case 10: memcpy((void*)0x20000000, "\000", 1); memcpy((void*)0x20000040, "\000", 1); syz_compare(0x20000000, 1, 0x20000040, 1); break; case 11: syz_compare_int(2, 4, 0, 0, 0); break; case 12: syz_errno(0x40); break; case 13: memcpy((void*)0x20000080, "\x34\x63\xee\xab\xc7\x55\xe7\xfd\xeb\xe7\x25\x21\xf6\x8b\x06\xb3\x6c\x8a\x66\xc3\x87\x9a\xfe\xc0\xd6\x60\x21\x64\xbe\x86\x7d\xa5\x64\xb6\x90\x68\x89\xaa\xf9\x33\x38\xe8\x17\x9e\xea\xa2\xeb\x98\xb1\xef", 50); syz_execute_func(0x20000080); break; case 14: syz_exit(0x101); break; case 15: syz_mmap(0x20ff2000, 0x8000); break; } } int main(void) { syz_mmap(0x20000000, 0x1000000); for (procid = 0; procid < 4; procid++) { if (fork() == 0) { use_temporary_dir(); do_sandbox_none(); } } sleep(1000000); return 0; } /usr/local/bin/ld: cannot find -lasan collect2: error: ld returned 1 exit status compiler invocation: gcc [-o /tmp/syz-executor723556330 -DGOOS_test=1 -DGOARCH_64_fork=1 -DHOSTGOOS_freebsd=1 -x c - -O2 -pthread -Wall -Werror -Wparentheses -Wunused-const-variable -Wframe-larger-than=8192 -m64 -fsanitize=address] --- FAIL: TestGenerate/test/64_fork/16 (1.28s) csource_test.go:110: opts: {Threaded:true Collide:false Repeat:true RepeatTimes:0 Procs:0 Sandbox:none Fault:false FaultCall:0 FaultNth:0 Leak:false EnableTun:false EnableNetDev:false EnableNetReset:false EnableCgroups:false EnableBinfmtMisc:false EnableCloseFds:false UseTmpDir:true HandleSegv:false Repro:false Trace:false} program: syz_mmap(&(0x7f0000ff6000/0x4000)=nil, 0x4000) syz_mmap(&(0x7f0000ffe000/0x2000)=nil, 0x2000) syz_compare_int$4(0x4, 0x7, 0x7f, 0x71f, 0x6) syz_errno(0x4) syz_compare_int$2(0x2, 0x7, 0x80000001) syz_compare_int$4(0x4, 0x9, 0x6, 0x3ff, 0x0) syz_compare_int$3(0x3, 0x0, 0x5, 0x6) syz_errno(0xffffffff80000000) syz_compare_int$2(0x2, 0x100000001, 0x8) syz_exit(0x200) syz_compare(&(0x7f0000000000)='\x00', 0x1, &(0x7f0000000040)=@str='\x00', 0x1) syz_compare_int$2(0x2, 0x4, 0x0) syz_errno(0x40) syz_execute_func(&(0x7f0000000080)="3463eeabc755e7fdebe72521f68b06b36c8a66c3879afec0d6602164be867da564b6906889aaf93338e8179eeaa2eb98b1ef") syz_exit(0x101) syz_mmap(&(0x7f0000ff2000/0x8000)=nil, 0x8000) csource_test.go:111: failed to build program: // autogenerated by syzkaller (https://github.com/google/syzkaller) #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include static void kill_and_wait(int pid, int* status) { kill(pid, SIGKILL); while (waitpid(-1, status, 0) != pid) { } } 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 remove_dir(const char* dir) { DIR* dp; struct dirent* ep; dp = opendir(dir); if (dp == NULL) exit(1); 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)) exit(1); if (S_ISDIR(st.st_mode)) { remove_dir(filename); continue; } if (unlink(filename)) exit(1); } closedir(dp); if (rmdir(dir)) 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; for (i = 0; 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 { pthread_mutex_t mu; pthread_cond_t cv; int state; } event_t; static void event_init(event_t* ev) { if (pthread_mutex_init(&ev->mu, 0)) exit(1); if (pthread_cond_init(&ev->cv, 0)) exit(1); ev->state = 0; } static void event_reset(event_t* ev) { ev->state = 0; } static void event_set(event_t* ev) { pthread_mutex_lock(&ev->mu); if (ev->state) exit(1); ev->state = 1; pthread_mutex_unlock(&ev->mu); pthread_cond_broadcast(&ev->cv); } static void event_wait(event_t* ev) { pthread_mutex_lock(&ev->mu); while (!ev->state) pthread_cond_wait(&ev->cv, &ev->mu); pthread_mutex_unlock(&ev->mu); } static int event_isset(event_t* ev) { pthread_mutex_lock(&ev->mu); int res = ev->state; pthread_mutex_unlock(&ev->mu); return res; } static int event_timedwait(event_t* ev, uint64_t timeout) { uint64_t start = current_time_ms(); uint64_t now = start; pthread_mutex_lock(&ev->mu); for (;;) { if (ev->state) break; uint64_t remain = timeout - (now - start); struct timespec ts; ts.tv_sec = remain / 1000; ts.tv_nsec = (remain % 1000) * 1000 * 1000; pthread_cond_timedwait(&ev->cv, &ev->mu, &ts); now = current_time_ms(); if (now - start > timeout) break; } int res = ev->state; pthread_mutex_unlock(&ev->mu); return res; } static long syz_mmap(volatile long a0, volatile long a1) { return (long)mmap((void*)a0, a1, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE | MAP_FIXED, -1, 0); } static long syz_errno(volatile long v) { errno = v; return v == 0 ? 0 : -1; } static long syz_exit(volatile long status) { _exit(status); return 0; } static long syz_compare(volatile long want, volatile long want_len, volatile long got, volatile long got_len) { if (want_len != got_len) { errno = EBADF; return -1; } if (memcmp((void*)want, (void*)got, want_len)) { errno = EINVAL; return -1; } return 0; } static long syz_compare_int(volatile long n, ...) { va_list args; va_start(args, n); long v0 = va_arg(args, long); long v1 = va_arg(args, long); long v2 = va_arg(args, long); long v3 = va_arg(args, long); va_end(args); if (n < 2 || n > 4) return errno = E2BIG, -1; if (n <= 2 && v2 != 0) return errno = EFAULT, -1; if (n <= 3 && v3 != 0) return errno = EFAULT, -1; if (v0 != v1) return errno = EINVAL, -1; if (n > 2 && v0 != v2) return errno = EINVAL, -1; if (n > 3 && v0 != v3) return errno = EINVAL, -1; return 0; } static void loop(); static int do_sandbox_none(void) { loop(); return 0; } static long syz_execute_func(volatile long text) { volatile long p[8] = {0}; (void)p; ((void (*)(void))(text))(); return 0; } 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 < 16; 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); event_timedwait(&th->done, 45); break; } } for (i = 0; i < 100 && __atomic_load_n(&running, __ATOMIC_RELAXED); i++) sleep_ms(1); } static void execute_one(void); #define WAIT_FLAGS 0 static void loop(void) { int iter; for (iter = 0;; iter++) { char cwdbuf[32]; sprintf(cwdbuf, "./%d", iter); if (mkdir(cwdbuf, 0777)) exit(1); int pid = fork(); if (pid < 0) exit(1); if (pid == 0) { if (chdir(cwdbuf)) exit(1); 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 < 5 * 1000) continue; kill_and_wait(pid, &status); break; } remove_dir(cwdbuf); } } void execute_call(int call) { switch (call) { case 0: syz_mmap(0x20ff6000, 0x4000); break; case 1: syz_mmap(0x20ffe000, 0x2000); break; case 2: syz_compare_int(4, 7, 0x7f, 0x71f, 6); break; case 3: syz_errno(4); break; case 4: syz_compare_int(2, 7, 0x80000001, 0, 0); break; case 5: syz_compare_int(4, 9, 6, 0x3ff, 0); break; case 6: syz_compare_int(3, 0, 5, 6, 0); break; case 7: syz_errno(0x80000000); break; case 8: syz_compare_int(2, 0x100000001, 8, 0, 0); break; case 9: syz_exit(0x200); break; case 10: memcpy((void*)0x20000000, "\000", 1); memcpy((void*)0x20000040, "\000", 1); syz_compare(0x20000000, 1, 0x20000040, 1); break; case 11: syz_compare_int(2, 4, 0, 0, 0); break; case 12: syz_errno(0x40); break; case 13: memcpy((void*)0x20000080, "\x34\x63\xee\xab\xc7\x55\xe7\xfd\xeb\xe7\x25\x21\xf6\x8b\x06\xb3\x6c\x8a\x66\xc3\x87\x9a\xfe\xc0\xd6\x60\x21\x64\xbe\x86\x7d\xa5\x64\xb6\x90\x68\x89\xaa\xf9\x33\x38\xe8\x17\x9e\xea\xa2\xeb\x98\xb1\xef", 50); syz_execute_func(0x20000080); break; case 14: syz_exit(0x101); break; case 15: syz_mmap(0x20ff2000, 0x8000); break; } } int main(void) { syz_mmap(0x20000000, 0x1000000); use_temporary_dir(); do_sandbox_none(); return 0; } /usr/local/bin/ld: cannot find -lasan collect2: error: ld returned 1 exit status compiler invocation: gcc [-o /tmp/syz-executor241402103 -DGOOS_test=1 -DGOARCH_64_fork=1 -DHOSTGOOS_freebsd=1 -x c - -O2 -pthread -Wall -Werror -Wparentheses -Wunused-const-variable -Wframe-larger-than=8192 -m64 -fsanitize=address] --- FAIL: TestGenerate/test/64_fork/7 (1.34s) csource_test.go:110: opts: {Threaded:true Collide:false Repeat:true RepeatTimes:10 Procs:0 Sandbox:none Fault:false FaultCall:0 FaultNth:0 Leak:false EnableTun:false EnableNetDev:false EnableNetReset:false EnableCgroups:false EnableBinfmtMisc:false EnableCloseFds:false UseTmpDir:true HandleSegv:false Repro:false Trace:false} program: syz_mmap(&(0x7f0000ff6000/0x4000)=nil, 0x4000) syz_mmap(&(0x7f0000ffe000/0x2000)=nil, 0x2000) syz_compare_int$4(0x4, 0x7, 0x7f, 0x71f, 0x6) syz_errno(0x4) syz_compare_int$2(0x2, 0x7, 0x80000001) syz_compare_int$4(0x4, 0x9, 0x6, 0x3ff, 0x0) syz_compare_int$3(0x3, 0x0, 0x5, 0x6) syz_errno(0xffffffff80000000) syz_compare_int$2(0x2, 0x100000001, 0x8) syz_exit(0x200) syz_compare(&(0x7f0000000000)='\x00', 0x1, &(0x7f0000000040)=@str='\x00', 0x1) syz_compare_int$2(0x2, 0x4, 0x0) syz_errno(0x40) syz_execute_func(&(0x7f0000000080)="3463eeabc755e7fdebe72521f68b06b36c8a66c3879afec0d6602164be867da564b6906889aaf93338e8179eeaa2eb98b1ef") syz_exit(0x101) syz_mmap(&(0x7f0000ff2000/0x8000)=nil, 0x8000) csource_test.go:111: failed to build program: // autogenerated by syzkaller (https://github.com/google/syzkaller) #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include static void kill_and_wait(int pid, int* status) { kill(pid, SIGKILL); while (waitpid(-1, status, 0) != pid) { } } 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 remove_dir(const char* dir) { DIR* dp; struct dirent* ep; dp = opendir(dir); if (dp == NULL) exit(1); 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)) exit(1); if (S_ISDIR(st.st_mode)) { remove_dir(filename); continue; } if (unlink(filename)) exit(1); } closedir(dp); if (rmdir(dir)) 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; for (i = 0; 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 { pthread_mutex_t mu; pthread_cond_t cv; int state; } event_t; static void event_init(event_t* ev) { if (pthread_mutex_init(&ev->mu, 0)) exit(1); if (pthread_cond_init(&ev->cv, 0)) exit(1); ev->state = 0; } static void event_reset(event_t* ev) { ev->state = 0; } static void event_set(event_t* ev) { pthread_mutex_lock(&ev->mu); if (ev->state) exit(1); ev->state = 1; pthread_mutex_unlock(&ev->mu); pthread_cond_broadcast(&ev->cv); } static void event_wait(event_t* ev) { pthread_mutex_lock(&ev->mu); while (!ev->state) pthread_cond_wait(&ev->cv, &ev->mu); pthread_mutex_unlock(&ev->mu); } static int event_isset(event_t* ev) { pthread_mutex_lock(&ev->mu); int res = ev->state; pthread_mutex_unlock(&ev->mu); return res; } static int event_timedwait(event_t* ev, uint64_t timeout) { uint64_t start = current_time_ms(); uint64_t now = start; pthread_mutex_lock(&ev->mu); for (;;) { if (ev->state) break; uint64_t remain = timeout - (now - start); struct timespec ts; ts.tv_sec = remain / 1000; ts.tv_nsec = (remain % 1000) * 1000 * 1000; pthread_cond_timedwait(&ev->cv, &ev->mu, &ts); now = current_time_ms(); if (now - start > timeout) break; } int res = ev->state; pthread_mutex_unlock(&ev->mu); return res; } static long syz_mmap(volatile long a0, volatile long a1) { return (long)mmap((void*)a0, a1, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE | MAP_FIXED, -1, 0); } static long syz_errno(volatile long v) { errno = v; return v == 0 ? 0 : -1; } static long syz_exit(volatile long status) { _exit(status); return 0; } static long syz_compare(volatile long want, volatile long want_len, volatile long got, volatile long got_len) { if (want_len != got_len) { errno = EBADF; return -1; } if (memcmp((void*)want, (void*)got, want_len)) { errno = EINVAL; return -1; } return 0; } static long syz_compare_int(volatile long n, ...) { va_list args; va_start(args, n); long v0 = va_arg(args, long); long v1 = va_arg(args, long); long v2 = va_arg(args, long); long v3 = va_arg(args, long); va_end(args); if (n < 2 || n > 4) return errno = E2BIG, -1; if (n <= 2 && v2 != 0) return errno = EFAULT, -1; if (n <= 3 && v3 != 0) return errno = EFAULT, -1; if (v0 != v1) return errno = EINVAL, -1; if (n > 2 && v0 != v2) return errno = EINVAL, -1; if (n > 3 && v0 != v3) return errno = EINVAL, -1; return 0; } static void loop(); static int do_sandbox_none(void) { loop(); return 0; } static long syz_execute_func(volatile long text) { volatile long p[8] = {0}; (void)p; ((void (*)(void))(text))(); return 0; } 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 < 16; 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); event_timedwait(&th->done, 45); break; } } for (i = 0; i < 100 && __atomic_load_n(&running, __ATOMIC_RELAXED); i++) sleep_ms(1); } static void execute_one(void); #define WAIT_FLAGS 0 static void loop(void) { int iter; for (iter = 0; iter < 10; iter++) { char cwdbuf[32]; sprintf(cwdbuf, "./%d", iter); if (mkdir(cwdbuf, 0777)) exit(1); int pid = fork(); if (pid < 0) exit(1); if (pid == 0) { if (chdir(cwdbuf)) exit(1); 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 < 5 * 1000) continue; kill_and_wait(pid, &status); break; } remove_dir(cwdbuf); } } void execute_call(int call) { switch (call) { case 0: syz_mmap(0x20ff6000, 0x4000); break; case 1: syz_mmap(0x20ffe000, 0x2000); break; case 2: syz_compare_int(4, 7, 0x7f, 0x71f, 6); break; case 3: syz_errno(4); break; case 4: syz_compare_int(2, 7, 0x80000001, 0, 0); break; case 5: syz_compare_int(4, 9, 6, 0x3ff, 0); break; case 6: syz_compare_int(3, 0, 5, 6, 0); break; case 7: syz_errno(0x80000000); break; case 8: syz_compare_int(2, 0x100000001, 8, 0, 0); break; case 9: syz_exit(0x200); break; case 10: memcpy((void*)0x20000000, "\000", 1); memcpy((void*)0x20000040, "\000", 1); syz_compare(0x20000000, 1, 0x20000040, 1); break; case 11: syz_compare_int(2, 4, 0, 0, 0); break; case 12: syz_errno(0x40); break; case 13: memcpy((void*)0x20000080, "\x34\x63\xee\xab\xc7\x55\xe7\xfd\xeb\xe7\x25\x21\xf6\x8b\x06\xb3\x6c\x8a\x66\xc3\x87\x9a\xfe\xc0\xd6\x60\x21\x64\xbe\x86\x7d\xa5\x64\xb6\x90\x68\x89\xaa\xf9\x33\x38\xe8\x17\x9e\xea\xa2\xeb\x98\xb1\xef", 50); syz_execute_func(0x20000080); break; case 14: syz_exit(0x101); break; case 15: syz_mmap(0x20ff2000, 0x8000); break; } } int main(void) { syz_mmap(0x20000000, 0x1000000); use_temporary_dir(); do_sandbox_none(); return 0; } /usr/local/bin/ld: cannot find -lasan collect2: error: ld returned 1 exit status compiler invocation: gcc [-o /tmp/syz-executor438856257 -DGOOS_test=1 -DGOARCH_64_fork=1 -DHOSTGOOS_freebsd=1 -x c - -O2 -pthread -Wall -Werror -Wparentheses -Wunused-const-variable -Wframe-larger-than=8192 -m64 -fsanitize=address] --- FAIL: TestGenerate/test/64_fork/12 (1.43s) csource_test.go:110: opts: {Threaded:true Collide:false Repeat:true RepeatTimes:0 Procs:0 Sandbox:none Fault:false FaultCall:0 FaultNth:0 Leak:false EnableTun:false EnableNetDev:false EnableNetReset:false EnableCgroups:false EnableBinfmtMisc:false EnableCloseFds:false UseTmpDir:true HandleSegv:false Repro:false Trace:false} program: syz_mmap(&(0x7f0000ff6000/0x4000)=nil, 0x4000) syz_mmap(&(0x7f0000ffe000/0x2000)=nil, 0x2000) syz_compare_int$4(0x4, 0x7, 0x7f, 0x71f, 0x6) syz_errno(0x4) syz_compare_int$2(0x2, 0x7, 0x80000001) syz_compare_int$4(0x4, 0x9, 0x6, 0x3ff, 0x0) syz_compare_int$3(0x3, 0x0, 0x5, 0x6) syz_errno(0xffffffff80000000) syz_compare_int$2(0x2, 0x100000001, 0x8) syz_exit(0x200) syz_compare(&(0x7f0000000000)='\x00', 0x1, &(0x7f0000000040)=@str='\x00', 0x1) syz_compare_int$2(0x2, 0x4, 0x0) syz_errno(0x40) syz_execute_func(&(0x7f0000000080)="3463eeabc755e7fdebe72521f68b06b36c8a66c3879afec0d6602164be867da564b6906889aaf93338e8179eeaa2eb98b1ef") syz_exit(0x101) syz_mmap(&(0x7f0000ff2000/0x8000)=nil, 0x8000) csource_test.go:111: failed to build program: // autogenerated by syzkaller (https://github.com/google/syzkaller) #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include static void kill_and_wait(int pid, int* status) { kill(pid, SIGKILL); while (waitpid(-1, status, 0) != pid) { } } 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 remove_dir(const char* dir) { DIR* dp; struct dirent* ep; dp = opendir(dir); if (dp == NULL) exit(1); 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)) exit(1); if (S_ISDIR(st.st_mode)) { remove_dir(filename); continue; } if (unlink(filename)) exit(1); } closedir(dp); if (rmdir(dir)) 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; for (i = 0; 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 { pthread_mutex_t mu; pthread_cond_t cv; int state; } event_t; static void event_init(event_t* ev) { if (pthread_mutex_init(&ev->mu, 0)) exit(1); if (pthread_cond_init(&ev->cv, 0)) exit(1); ev->state = 0; } static void event_reset(event_t* ev) { ev->state = 0; } static void event_set(event_t* ev) { pthread_mutex_lock(&ev->mu); if (ev->state) exit(1); ev->state = 1; pthread_mutex_unlock(&ev->mu); pthread_cond_broadcast(&ev->cv); } static void event_wait(event_t* ev) { pthread_mutex_lock(&ev->mu); while (!ev->state) pthread_cond_wait(&ev->cv, &ev->mu); pthread_mutex_unlock(&ev->mu); } static int event_isset(event_t* ev) { pthread_mutex_lock(&ev->mu); int res = ev->state; pthread_mutex_unlock(&ev->mu); return res; } static int event_timedwait(event_t* ev, uint64_t timeout) { uint64_t start = current_time_ms(); uint64_t now = start; pthread_mutex_lock(&ev->mu); for (;;) { if (ev->state) break; uint64_t remain = timeout - (now - start); struct timespec ts; ts.tv_sec = remain / 1000; ts.tv_nsec = (remain % 1000) * 1000 * 1000; pthread_cond_timedwait(&ev->cv, &ev->mu, &ts); now = current_time_ms(); if (now - start > timeout) break; } int res = ev->state; pthread_mutex_unlock(&ev->mu); return res; } static long syz_mmap(volatile long a0, volatile long a1) { return (long)mmap((void*)a0, a1, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE | MAP_FIXED, -1, 0); } static long syz_errno(volatile long v) { errno = v; return v == 0 ? 0 : -1; } static long syz_exit(volatile long status) { _exit(status); return 0; } static long syz_compare(volatile long want, volatile long want_len, volatile long got, volatile long got_len) { if (want_len != got_len) { errno = EBADF; return -1; } if (memcmp((void*)want, (void*)got, want_len)) { errno = EINVAL; return -1; } return 0; } static long syz_compare_int(volatile long n, ...) { va_list args; va_start(args, n); long v0 = va_arg(args, long); long v1 = va_arg(args, long); long v2 = va_arg(args, long); long v3 = va_arg(args, long); va_end(args); if (n < 2 || n > 4) return errno = E2BIG, -1; if (n <= 2 && v2 != 0) return errno = EFAULT, -1; if (n <= 3 && v3 != 0) return errno = EFAULT, -1; if (v0 != v1) return errno = EINVAL, -1; if (n > 2 && v0 != v2) return errno = EINVAL, -1; if (n > 3 && v0 != v3) return errno = EINVAL, -1; return 0; } static void loop(); static int do_sandbox_none(void) { loop(); return 0; } static long syz_execute_func(volatile long text) { volatile long p[8] = {0}; (void)p; ((void (*)(void))(text))(); return 0; } 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 < 16; 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); event_timedwait(&th->done, 45); break; } } for (i = 0; i < 100 && __atomic_load_n(&running, __ATOMIC_RELAXED); i++) sleep_ms(1); } static void execute_one(void); #define WAIT_FLAGS 0 static void loop(void) { int iter; for (iter = 0;; iter++) { char cwdbuf[32]; sprintf(cwdbuf, "./%d", iter); if (mkdir(cwdbuf, 0777)) exit(1); int pid = fork(); if (pid < 0) exit(1); if (pid == 0) { if (chdir(cwdbuf)) exit(1); 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 < 5 * 1000) continue; kill_and_wait(pid, &status); break; } remove_dir(cwdbuf); } } void execute_call(int call) { switch (call) { case 0: syz_mmap(0x20ff6000, 0x4000); break; case 1: syz_mmap(0x20ffe000, 0x2000); break; case 2: syz_compare_int(4, 7, 0x7f, 0x71f, 6); break; case 3: syz_errno(4); break; case 4: syz_compare_int(2, 7, 0x80000001, 0, 0); break; case 5: syz_compare_int(4, 9, 6, 0x3ff, 0); break; case 6: syz_compare_int(3, 0, 5, 6, 0); break; case 7: syz_errno(0x80000000); break; case 8: syz_compare_int(2, 0x100000001, 8, 0, 0); break; case 9: syz_exit(0x200); break; case 10: memcpy((void*)0x20000000, "\000", 1); memcpy((void*)0x20000040, "\000", 1); syz_compare(0x20000000, 1, 0x20000040, 1); break; case 11: syz_compare_int(2, 4, 0, 0, 0); break; case 12: syz_errno(0x40); break; case 13: memcpy((void*)0x20000080, "\x34\x63\xee\xab\xc7\x55\xe7\xfd\xeb\xe7\x25\x21\xf6\x8b\x06\xb3\x6c\x8a\x66\xc3\x87\x9a\xfe\xc0\xd6\x60\x21\x64\xbe\x86\x7d\xa5\x64\xb6\x90\x68\x89\xaa\xf9\x33\x38\xe8\x17\x9e\xea\xa2\xeb\x98\xb1\xef", 50); syz_execute_func(0x20000080); break; case 14: syz_exit(0x101); break; case 15: syz_mmap(0x20ff2000, 0x8000); break; } } int main(void) { syz_mmap(0x20000000, 0x1000000); use_temporary_dir(); do_sandbox_none(); return 0; } /usr/local/bin/ld: cannot find -lasan collect2: error: ld returned 1 exit status compiler invocation: gcc [-o /tmp/syz-executor187383468 -DGOOS_test=1 -DGOARCH_64_fork=1 -DHOSTGOOS_freebsd=1 -x c - -O2 -pthread -Wall -Werror -Wparentheses -Wunused-const-variable -Wframe-larger-than=8192 -m64 -fsanitize=address] --- FAIL: TestGenerate/test/64_fork/14 (1.36s) csource_test.go:110: opts: {Threaded:true Collide:false Repeat:true RepeatTimes:0 Procs:0 Sandbox:none Fault:false FaultCall:0 FaultNth:0 Leak:false EnableTun:false EnableNetDev:false EnableNetReset:false EnableCgroups:false EnableBinfmtMisc:false EnableCloseFds:false UseTmpDir:true HandleSegv:false Repro:false Trace:false} program: syz_mmap(&(0x7f0000ff6000/0x4000)=nil, 0x4000) syz_mmap(&(0x7f0000ffe000/0x2000)=nil, 0x2000) syz_compare_int$4(0x4, 0x7, 0x7f, 0x71f, 0x6) syz_errno(0x4) syz_compare_int$2(0x2, 0x7, 0x80000001) syz_compare_int$4(0x4, 0x9, 0x6, 0x3ff, 0x0) syz_compare_int$3(0x3, 0x0, 0x5, 0x6) syz_errno(0xffffffff80000000) syz_compare_int$2(0x2, 0x100000001, 0x8) syz_exit(0x200) syz_compare(&(0x7f0000000000)='\x00', 0x1, &(0x7f0000000040)=@str='\x00', 0x1) syz_compare_int$2(0x2, 0x4, 0x0) syz_errno(0x40) syz_execute_func(&(0x7f0000000080)="3463eeabc755e7fdebe72521f68b06b36c8a66c3879afec0d6602164be867da564b6906889aaf93338e8179eeaa2eb98b1ef") syz_exit(0x101) syz_mmap(&(0x7f0000ff2000/0x8000)=nil, 0x8000) csource_test.go:111: failed to build program: // autogenerated by syzkaller (https://github.com/google/syzkaller) #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include static void kill_and_wait(int pid, int* status) { kill(pid, SIGKILL); while (waitpid(-1, status, 0) != pid) { } } 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 remove_dir(const char* dir) { DIR* dp; struct dirent* ep; dp = opendir(dir); if (dp == NULL) exit(1); 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)) exit(1); if (S_ISDIR(st.st_mode)) { remove_dir(filename); continue; } if (unlink(filename)) exit(1); } closedir(dp); if (rmdir(dir)) 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; for (i = 0; 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 { pthread_mutex_t mu; pthread_cond_t cv; int state; } event_t; static void event_init(event_t* ev) { if (pthread_mutex_init(&ev->mu, 0)) exit(1); if (pthread_cond_init(&ev->cv, 0)) exit(1); ev->state = 0; } static void event_reset(event_t* ev) { ev->state = 0; } static void event_set(event_t* ev) { pthread_mutex_lock(&ev->mu); if (ev->state) exit(1); ev->state = 1; pthread_mutex_unlock(&ev->mu); pthread_cond_broadcast(&ev->cv); } static void event_wait(event_t* ev) { pthread_mutex_lock(&ev->mu); while (!ev->state) pthread_cond_wait(&ev->cv, &ev->mu); pthread_mutex_unlock(&ev->mu); } static int event_isset(event_t* ev) { pthread_mutex_lock(&ev->mu); int res = ev->state; pthread_mutex_unlock(&ev->mu); return res; } static int event_timedwait(event_t* ev, uint64_t timeout) { uint64_t start = current_time_ms(); uint64_t now = start; pthread_mutex_lock(&ev->mu); for (;;) { if (ev->state) break; uint64_t remain = timeout - (now - start); struct timespec ts; ts.tv_sec = remain / 1000; ts.tv_nsec = (remain % 1000) * 1000 * 1000; pthread_cond_timedwait(&ev->cv, &ev->mu, &ts); now = current_time_ms(); if (now - start > timeout) break; } int res = ev->state; pthread_mutex_unlock(&ev->mu); return res; } static long syz_mmap(volatile long a0, volatile long a1) { return (long)mmap((void*)a0, a1, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE | MAP_FIXED, -1, 0); } static long syz_errno(volatile long v) { errno = v; return v == 0 ? 0 : -1; } static long syz_exit(volatile long status) { _exit(status); return 0; } static long syz_compare(volatile long want, volatile long want_len, volatile long got, volatile long got_len) { if (want_len != got_len) { errno = EBADF; return -1; } if (memcmp((void*)want, (void*)got, want_len)) { errno = EINVAL; return -1; } return 0; } static long syz_compare_int(volatile long n, ...) { va_list args; va_start(args, n); long v0 = va_arg(args, long); long v1 = va_arg(args, long); long v2 = va_arg(args, long); long v3 = va_arg(args, long); va_end(args); if (n < 2 || n > 4) return errno = E2BIG, -1; if (n <= 2 && v2 != 0) return errno = EFAULT, -1; if (n <= 3 && v3 != 0) return errno = EFAULT, -1; if (v0 != v1) return errno = EINVAL, -1; if (n > 2 && v0 != v2) return errno = EINVAL, -1; if (n > 3 && v0 != v3) return errno = EINVAL, -1; return 0; } static void loop(); static int do_sandbox_none(void) { loop(); return 0; } static long syz_execute_func(volatile long text) { volatile long p[8] = {0}; (void)p; ((void (*)(void))(text))(); return 0; } 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 < 16; 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); event_timedwait(&th->done, 45); break; } } for (i = 0; i < 100 && __atomic_load_n(&running, __ATOMIC_RELAXED); i++) sleep_ms(1); } static void execute_one(void); #define WAIT_FLAGS 0 static void loop(void) { int iter; for (iter = 0;; iter++) { char cwdbuf[32]; sprintf(cwdbuf, "./%d", iter); if (mkdir(cwdbuf, 0777)) exit(1); int pid = fork(); if (pid < 0) exit(1); if (pid == 0) { if (chdir(cwdbuf)) exit(1); 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 < 5 * 1000) continue; kill_and_wait(pid, &status); break; } remove_dir(cwdbuf); } } void execute_call(int call) { switch (call) { case 0: syz_mmap(0x20ff6000, 0x4000); break; case 1: syz_mmap(0x20ffe000, 0x2000); break; case 2: syz_compare_int(4, 7, 0x7f, 0x71f, 6); break; case 3: syz_errno(4); break; case 4: syz_compare_int(2, 7, 0x80000001, 0, 0); break; case 5: syz_compare_int(4, 9, 6, 0x3ff, 0); break; case 6: syz_compare_int(3, 0, 5, 6, 0); break; case 7: syz_errno(0x80000000); break; case 8: syz_compare_int(2, 0x100000001, 8, 0, 0); break; case 9: syz_exit(0x200); break; case 10: memcpy((void*)0x20000000, "\000", 1); memcpy((void*)0x20000040, "\000", 1); syz_compare(0x20000000, 1, 0x20000040, 1); break; case 11: syz_compare_int(2, 4, 0, 0, 0); break; case 12: syz_errno(0x40); break; case 13: memcpy((void*)0x20000080, "\x34\x63\xee\xab\xc7\x55\xe7\xfd\xeb\xe7\x25\x21\xf6\x8b\x06\xb3\x6c\x8a\x66\xc3\x87\x9a\xfe\xc0\xd6\x60\x21\x64\xbe\x86\x7d\xa5\x64\xb6\x90\x68\x89\xaa\xf9\x33\x38\xe8\x17\x9e\xea\xa2\xeb\x98\xb1\xef", 50); syz_execute_func(0x20000080); break; case 14: syz_exit(0x101); break; case 15: syz_mmap(0x20ff2000, 0x8000); break; } } int main(void) { syz_mmap(0x20000000, 0x1000000); use_temporary_dir(); do_sandbox_none(); return 0; } /usr/local/bin/ld: cannot find -lasan collect2: error: ld returned 1 exit status compiler invocation: gcc [-o /tmp/syz-executor526880446 -DGOOS_test=1 -DGOARCH_64_fork=1 -DHOSTGOOS_freebsd=1 -x c - -O2 -pthread -Wall -Werror -Wparentheses -Wunused-const-variable -Wframe-larger-than=8192 -m64 -fsanitize=address] --- FAIL: TestGenerate/test/64_fork/10 (0.87s) csource_test.go:110: opts: {Threaded:true Collide:false Repeat:true RepeatTimes:0 Procs:0 Sandbox: Fault:false FaultCall:0 FaultNth:0 Leak:false EnableTun:false EnableNetDev:false EnableNetReset:false EnableCgroups:false EnableBinfmtMisc:false EnableCloseFds:false UseTmpDir:true HandleSegv:false Repro:false Trace:false} program: syz_mmap(&(0x7f0000ff6000/0x4000)=nil, 0x4000) syz_mmap(&(0x7f0000ffe000/0x2000)=nil, 0x2000) syz_compare_int$4(0x4, 0x7, 0x7f, 0x71f, 0x6) syz_errno(0x4) syz_compare_int$2(0x2, 0x7, 0x80000001) syz_compare_int$4(0x4, 0x9, 0x6, 0x3ff, 0x0) syz_compare_int$3(0x3, 0x0, 0x5, 0x6) syz_errno(0xffffffff80000000) syz_compare_int$2(0x2, 0x100000001, 0x8) syz_exit(0x200) syz_compare(&(0x7f0000000000)='\x00', 0x1, &(0x7f0000000040)=@str='\x00', 0x1) syz_compare_int$2(0x2, 0x4, 0x0) syz_errno(0x40) syz_execute_func(&(0x7f0000000080)="3463eeabc755e7fdebe72521f68b06b36c8a66c3879afec0d6602164be867da564b6906889aaf93338e8179eeaa2eb98b1ef") syz_exit(0x101) syz_mmap(&(0x7f0000ff2000/0x8000)=nil, 0x8000) csource_test.go:111: failed to build program: // autogenerated by syzkaller (https://github.com/google/syzkaller) #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include static void kill_and_wait(int pid, int* status) { kill(pid, SIGKILL); while (waitpid(-1, status, 0) != pid) { } } 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 remove_dir(const char* dir) { DIR* dp; struct dirent* ep; dp = opendir(dir); if (dp == NULL) exit(1); 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)) exit(1); if (S_ISDIR(st.st_mode)) { remove_dir(filename); continue; } if (unlink(filename)) exit(1); } closedir(dp); if (rmdir(dir)) 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; for (i = 0; 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 { pthread_mutex_t mu; pthread_cond_t cv; int state; } event_t; static void event_init(event_t* ev) { if (pthread_mutex_init(&ev->mu, 0)) exit(1); if (pthread_cond_init(&ev->cv, 0)) exit(1); ev->state = 0; } static void event_reset(event_t* ev) { ev->state = 0; } static void event_set(event_t* ev) { pthread_mutex_lock(&ev->mu); if (ev->state) exit(1); ev->state = 1; pthread_mutex_unlock(&ev->mu); pthread_cond_broadcast(&ev->cv); } static void event_wait(event_t* ev) { pthread_mutex_lock(&ev->mu); while (!ev->state) pthread_cond_wait(&ev->cv, &ev->mu); pthread_mutex_unlock(&ev->mu); } static int event_isset(event_t* ev) { pthread_mutex_lock(&ev->mu); int res = ev->state; pthread_mutex_unlock(&ev->mu); return res; } static int event_timedwait(event_t* ev, uint64_t timeout) { uint64_t start = current_time_ms(); uint64_t now = start; pthread_mutex_lock(&ev->mu); for (;;) { if (ev->state) break; uint64_t remain = timeout - (now - start); struct timespec ts; ts.tv_sec = remain / 1000; ts.tv_nsec = (remain % 1000) * 1000 * 1000; pthread_cond_timedwait(&ev->cv, &ev->mu, &ts); now = current_time_ms(); if (now - start > timeout) break; } int res = ev->state; pthread_mutex_unlock(&ev->mu); return res; } static long syz_mmap(volatile long a0, volatile long a1) { return (long)mmap((void*)a0, a1, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE | MAP_FIXED, -1, 0); } static long syz_errno(volatile long v) { errno = v; return v == 0 ? 0 : -1; } static long syz_exit(volatile long status) { _exit(status); return 0; } static long syz_compare(volatile long want, volatile long want_len, volatile long got, volatile long got_len) { if (want_len != got_len) { errno = EBADF; return -1; } if (memcmp((void*)want, (void*)got, want_len)) { errno = EINVAL; return -1; } return 0; } static long syz_compare_int(volatile long n, ...) { va_list args; va_start(args, n); long v0 = va_arg(args, long); long v1 = va_arg(args, long); long v2 = va_arg(args, long); long v3 = va_arg(args, long); va_end(args); if (n < 2 || n > 4) return errno = E2BIG, -1; if (n <= 2 && v2 != 0) return errno = EFAULT, -1; if (n <= 3 && v3 != 0) return errno = EFAULT, -1; if (v0 != v1) return errno = EINVAL, -1; if (n > 2 && v0 != v2) return errno = EINVAL, -1; if (n > 3 && v0 != v3) return errno = EINVAL, -1; return 0; } static long syz_execute_func(volatile long text) { volatile long p[8] = {0}; (void)p; ((void (*)(void))(text))(); return 0; } 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 < 16; 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); event_timedwait(&th->done, 45); break; } } for (i = 0; i < 100 && __atomic_load_n(&running, __ATOMIC_RELAXED); i++) sleep_ms(1); } static void execute_one(void); #define WAIT_FLAGS 0 static void loop(void) { int iter; for (iter = 0;; iter++) { char cwdbuf[32]; sprintf(cwdbuf, "./%d", iter); if (mkdir(cwdbuf, 0777)) exit(1); int pid = fork(); if (pid < 0) exit(1); if (pid == 0) { if (chdir(cwdbuf)) exit(1); 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 < 5 * 1000) continue; kill_and_wait(pid, &status); break; } remove_dir(cwdbuf); } } void execute_call(int call) { switch (call) { case 0: syz_mmap(0x20ff6000, 0x4000); break; case 1: syz_mmap(0x20ffe000, 0x2000); break; case 2: syz_compare_int(4, 7, 0x7f, 0x71f, 6); break; case 3: syz_errno(4); break; case 4: syz_compare_int(2, 7, 0x80000001, 0, 0); break; case 5: syz_compare_int(4, 9, 6, 0x3ff, 0); break; case 6: syz_compare_int(3, 0, 5, 6, 0); break; case 7: syz_errno(0x80000000); break; case 8: syz_compare_int(2, 0x100000001, 8, 0, 0); break; case 9: syz_exit(0x200); break; case 10: memcpy((void*)0x20000000, "\000", 1); memcpy((void*)0x20000040, "\000", 1); syz_compare(0x20000000, 1, 0x20000040, 1); break; case 11: syz_compare_int(2, 4, 0, 0, 0); break; case 12: syz_errno(0x40); break; case 13: memcpy((void*)0x20000080, "\x34\x63\xee\xab\xc7\x55\xe7\xfd\xeb\xe7\x25\x21\xf6\x8b\x06\xb3\x6c\x8a\x66\xc3\x87\x9a\xfe\xc0\xd6\x60\x21\x64\xbe\x86\x7d\xa5\x64\xb6\x90\x68\x89\xaa\xf9\x33\x38\xe8\x17\x9e\xea\xa2\xeb\x98\xb1\xef", 50); syz_execute_func(0x20000080); break; case 14: syz_exit(0x101); break; case 15: syz_mmap(0x20ff2000, 0x8000); break; } } int main(void) { syz_mmap(0x20000000, 0x1000000); use_temporary_dir(); loop(); return 0; } /usr/local/bin/ld: cannot find -lasan collect2: error: ld returned 1 exit status compiler invocation: gcc [-o /tmp/syz-executor970743557 -DGOOS_test=1 -DGOARCH_64_fork=1 -DHOSTGOOS_freebsd=1 -x c - -O2 -pthread -Wall -Werror -Wparentheses -Wunused-const-variable -Wframe-larger-than=8192 -m64 -fsanitize=address] --- FAIL: TestGenerate/test/64_fork/5 (0.80s) csource_test.go:110: opts: {Threaded:true Collide:false Repeat:true RepeatTimes:0 Procs:0 Sandbox:none Fault:false FaultCall:0 FaultNth:0 Leak:false EnableTun:false EnableNetDev:false EnableNetReset:false EnableCgroups:false EnableBinfmtMisc:false EnableCloseFds:false UseTmpDir:true HandleSegv:false Repro:false Trace:false} program: syz_mmap(&(0x7f0000ff6000/0x4000)=nil, 0x4000) syz_mmap(&(0x7f0000ffe000/0x2000)=nil, 0x2000) syz_compare_int$4(0x4, 0x7, 0x7f, 0x71f, 0x6) syz_errno(0x4) syz_compare_int$2(0x2, 0x7, 0x80000001) syz_compare_int$4(0x4, 0x9, 0x6, 0x3ff, 0x0) syz_compare_int$3(0x3, 0x0, 0x5, 0x6) syz_errno(0xffffffff80000000) syz_compare_int$2(0x2, 0x100000001, 0x8) syz_exit(0x200) syz_compare(&(0x7f0000000000)='\x00', 0x1, &(0x7f0000000040)=@str='\x00', 0x1) syz_compare_int$2(0x2, 0x4, 0x0) syz_errno(0x40) syz_execute_func(&(0x7f0000000080)="3463eeabc755e7fdebe72521f68b06b36c8a66c3879afec0d6602164be867da564b6906889aaf93338e8179eeaa2eb98b1ef") syz_exit(0x101) syz_mmap(&(0x7f0000ff2000/0x8000)=nil, 0x8000) csource_test.go:111: failed to build program: // autogenerated by syzkaller (https://github.com/google/syzkaller) #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include static void kill_and_wait(int pid, int* status) { kill(pid, SIGKILL); while (waitpid(-1, status, 0) != pid) { } } 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 remove_dir(const char* dir) { DIR* dp; struct dirent* ep; dp = opendir(dir); if (dp == NULL) exit(1); 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)) exit(1); if (S_ISDIR(st.st_mode)) { remove_dir(filename); continue; } if (unlink(filename)) exit(1); } closedir(dp); if (rmdir(dir)) 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; for (i = 0; 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 { pthread_mutex_t mu; pthread_cond_t cv; int state; } event_t; static void event_init(event_t* ev) { if (pthread_mutex_init(&ev->mu, 0)) exit(1); if (pthread_cond_init(&ev->cv, 0)) exit(1); ev->state = 0; } static void event_reset(event_t* ev) { ev->state = 0; } static void event_set(event_t* ev) { pthread_mutex_lock(&ev->mu); if (ev->state) exit(1); ev->state = 1; pthread_mutex_unlock(&ev->mu); pthread_cond_broadcast(&ev->cv); } static void event_wait(event_t* ev) { pthread_mutex_lock(&ev->mu); while (!ev->state) pthread_cond_wait(&ev->cv, &ev->mu); pthread_mutex_unlock(&ev->mu); } static int event_isset(event_t* ev) { pthread_mutex_lock(&ev->mu); int res = ev->state; pthread_mutex_unlock(&ev->mu); return res; } static int event_timedwait(event_t* ev, uint64_t timeout) { uint64_t start = current_time_ms(); uint64_t now = start; pthread_mutex_lock(&ev->mu); for (;;) { if (ev->state) break; uint64_t remain = timeout - (now - start); struct timespec ts; ts.tv_sec = remain / 1000; ts.tv_nsec = (remain % 1000) * 1000 * 1000; pthread_cond_timedwait(&ev->cv, &ev->mu, &ts); now = current_time_ms(); if (now - start > timeout) break; } int res = ev->state; pthread_mutex_unlock(&ev->mu); return res; } static long syz_mmap(volatile long a0, volatile long a1) { return (long)mmap((void*)a0, a1, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE | MAP_FIXED, -1, 0); } static long syz_errno(volatile long v) { errno = v; return v == 0 ? 0 : -1; } static long syz_exit(volatile long status) { _exit(status); return 0; } static long syz_compare(volatile long want, volatile long want_len, volatile long got, volatile long got_len) { if (want_len != got_len) { errno = EBADF; return -1; } if (memcmp((void*)want, (void*)got, want_len)) { errno = EINVAL; return -1; } return 0; } static long syz_compare_int(volatile long n, ...) { va_list args; va_start(args, n); long v0 = va_arg(args, long); long v1 = va_arg(args, long); long v2 = va_arg(args, long); long v3 = va_arg(args, long); va_end(args); if (n < 2 || n > 4) return errno = E2BIG, -1; if (n <= 2 && v2 != 0) return errno = EFAULT, -1; if (n <= 3 && v3 != 0) return errno = EFAULT, -1; if (v0 != v1) return errno = EINVAL, -1; if (n > 2 && v0 != v2) return errno = EINVAL, -1; if (n > 3 && v0 != v3) return errno = EINVAL, -1; return 0; } static void loop(); static int do_sandbox_none(void) { loop(); return 0; } static long syz_execute_func(volatile long text) { volatile long p[8] = {0}; (void)p; ((void (*)(void))(text))(); return 0; } 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 < 16; 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); event_timedwait(&th->done, 45); break; } } for (i = 0; i < 100 && __atomic_load_n(&running, __ATOMIC_RELAXED); i++) sleep_ms(1); } static void execute_one(void); #define WAIT_FLAGS 0 static void loop(void) { int iter; for (iter = 0;; iter++) { char cwdbuf[32]; sprintf(cwdbuf, "./%d", iter); if (mkdir(cwdbuf, 0777)) exit(1); int pid = fork(); if (pid < 0) exit(1); if (pid == 0) { if (chdir(cwdbuf)) exit(1); 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 < 5 * 1000) continue; kill_and_wait(pid, &status); break; } remove_dir(cwdbuf); } } void execute_call(int call) { switch (call) { case 0: syz_mmap(0x20ff6000, 0x4000); break; case 1: syz_mmap(0x20ffe000, 0x2000); break; case 2: syz_compare_int(4, 7, 0x7f, 0x71f, 6); break; case 3: syz_errno(4); break; case 4: syz_compare_int(2, 7, 0x80000001, 0, 0); break; case 5: syz_compare_int(4, 9, 6, 0x3ff, 0); break; case 6: syz_compare_int(3, 0, 5, 6, 0); break; case 7: syz_errno(0x80000000); break; case 8: syz_compare_int(2, 0x100000001, 8, 0, 0); break; case 9: syz_exit(0x200); break; case 10: memcpy((void*)0x20000000, "\000", 1); memcpy((void*)0x20000040, "\000", 1); syz_compare(0x20000000, 1, 0x20000040, 1); break; case 11: syz_compare_int(2, 4, 0, 0, 0); break; case 12: syz_errno(0x40); break; case 13: memcpy((void*)0x20000080, "\x34\x63\xee\xab\xc7\x55\xe7\xfd\xeb\xe7\x25\x21\xf6\x8b\x06\xb3\x6c\x8a\x66\xc3\x87\x9a\xfe\xc0\xd6\x60\x21\x64\xbe\x86\x7d\xa5\x64\xb6\x90\x68\x89\xaa\xf9\x33\x38\xe8\x17\x9e\xea\xa2\xeb\x98\xb1\xef", 50); syz_execute_func(0x20000080); break; case 14: syz_exit(0x101); break; case 15: syz_mmap(0x20ff2000, 0x8000); break; } } int main(void) { syz_mmap(0x20000000, 0x1000000); use_temporary_dir(); do_sandbox_none(); return 0; } /usr/local/bin/ld: cannot find -lasan collect2: error: ld returned 1 exit status compiler invocation: gcc [-o /tmp/syz-executor941322912 -DGOOS_test=1 -DGOARCH_64_fork=1 -DHOSTGOOS_freebsd=1 -x c - -O2 -pthread -Wall -Werror -Wparentheses -Wunused-const-variable -Wframe-larger-than=8192 -m64 -fsanitize=address] --- FAIL: TestGenerate/test/64_fork/6 (1.22s) csource_test.go:110: opts: {Threaded:true Collide:false Repeat:true RepeatTimes:0 Procs:0 Sandbox:none Fault:false FaultCall:0 FaultNth:0 Leak:false EnableTun:false EnableNetDev:false EnableNetReset:false EnableCgroups:false EnableBinfmtMisc:false EnableCloseFds:false UseTmpDir:true HandleSegv:false Repro:false Trace:false} program: syz_mmap(&(0x7f0000ff6000/0x4000)=nil, 0x4000) syz_mmap(&(0x7f0000ffe000/0x2000)=nil, 0x2000) syz_compare_int$4(0x4, 0x7, 0x7f, 0x71f, 0x6) syz_errno(0x4) syz_compare_int$2(0x2, 0x7, 0x80000001) syz_compare_int$4(0x4, 0x9, 0x6, 0x3ff, 0x0) syz_compare_int$3(0x3, 0x0, 0x5, 0x6) syz_errno(0xffffffff80000000) syz_compare_int$2(0x2, 0x100000001, 0x8) syz_exit(0x200) syz_compare(&(0x7f0000000000)='\x00', 0x1, &(0x7f0000000040)=@str='\x00', 0x1) syz_compare_int$2(0x2, 0x4, 0x0) syz_errno(0x40) syz_execute_func(&(0x7f0000000080)="3463eeabc755e7fdebe72521f68b06b36c8a66c3879afec0d6602164be867da564b6906889aaf93338e8179eeaa2eb98b1ef") syz_exit(0x101) syz_mmap(&(0x7f0000ff2000/0x8000)=nil, 0x8000) csource_test.go:111: failed to build program: // autogenerated by syzkaller (https://github.com/google/syzkaller) #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include static void kill_and_wait(int pid, int* status) { kill(pid, SIGKILL); while (waitpid(-1, status, 0) != pid) { } } 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 remove_dir(const char* dir) { DIR* dp; struct dirent* ep; dp = opendir(dir); if (dp == NULL) exit(1); 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)) exit(1); if (S_ISDIR(st.st_mode)) { remove_dir(filename); continue; } if (unlink(filename)) exit(1); } closedir(dp); if (rmdir(dir)) 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; for (i = 0; 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 { pthread_mutex_t mu; pthread_cond_t cv; int state; } event_t; static void event_init(event_t* ev) { if (pthread_mutex_init(&ev->mu, 0)) exit(1); if (pthread_cond_init(&ev->cv, 0)) exit(1); ev->state = 0; } static void event_reset(event_t* ev) { ev->state = 0; } static void event_set(event_t* ev) { pthread_mutex_lock(&ev->mu); if (ev->state) exit(1); ev->state = 1; pthread_mutex_unlock(&ev->mu); pthread_cond_broadcast(&ev->cv); } static void event_wait(event_t* ev) { pthread_mutex_lock(&ev->mu); while (!ev->state) pthread_cond_wait(&ev->cv, &ev->mu); pthread_mutex_unlock(&ev->mu); } static int event_isset(event_t* ev) { pthread_mutex_lock(&ev->mu); int res = ev->state; pthread_mutex_unlock(&ev->mu); return res; } static int event_timedwait(event_t* ev, uint64_t timeout) { uint64_t start = current_time_ms(); uint64_t now = start; pthread_mutex_lock(&ev->mu); for (;;) { if (ev->state) break; uint64_t remain = timeout - (now - start); struct timespec ts; ts.tv_sec = remain / 1000; ts.tv_nsec = (remain % 1000) * 1000 * 1000; pthread_cond_timedwait(&ev->cv, &ev->mu, &ts); now = current_time_ms(); if (now - start > timeout) break; } int res = ev->state; pthread_mutex_unlock(&ev->mu); return res; } static long syz_mmap(volatile long a0, volatile long a1) { return (long)mmap((void*)a0, a1, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE | MAP_FIXED, -1, 0); } static long syz_errno(volatile long v) { errno = v; return v == 0 ? 0 : -1; } static long syz_exit(volatile long status) { _exit(status); return 0; } static long syz_compare(volatile long want, volatile long want_len, volatile long got, volatile long got_len) { if (want_len != got_len) { errno = EBADF; return -1; } if (memcmp((void*)want, (void*)got, want_len)) { errno = EINVAL; return -1; } return 0; } static long syz_compare_int(volatile long n, ...) { va_list args; va_start(args, n); long v0 = va_arg(args, long); long v1 = va_arg(args, long); long v2 = va_arg(args, long); long v3 = va_arg(args, long); va_end(args); if (n < 2 || n > 4) return errno = E2BIG, -1; if (n <= 2 && v2 != 0) return errno = EFAULT, -1; if (n <= 3 && v3 != 0) return errno = EFAULT, -1; if (v0 != v1) return errno = EINVAL, -1; if (n > 2 && v0 != v2) return errno = EINVAL, -1; if (n > 3 && v0 != v3) return errno = EINVAL, -1; return 0; } static void loop(); static int do_sandbox_none(void) { loop(); return 0; } static long syz_execute_func(volatile long text) { volatile long p[8] = {0}; (void)p; ((void (*)(void))(text))(); return 0; } 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 < 16; 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); event_timedwait(&th->done, 45); break; } } for (i = 0; i < 100 && __atomic_load_n(&running, __ATOMIC_RELAXED); i++) sleep_ms(1); } static void execute_one(void); #define WAIT_FLAGS 0 static void loop(void) { int iter; for (iter = 0;; iter++) { char cwdbuf[32]; sprintf(cwdbuf, "./%d", iter); if (mkdir(cwdbuf, 0777)) exit(1); int pid = fork(); if (pid < 0) exit(1); if (pid == 0) { if (chdir(cwdbuf)) exit(1); 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 < 5 * 1000) continue; kill_and_wait(pid, &status); break; } remove_dir(cwdbuf); } } void execute_call(int call) { switch (call) { case 0: syz_mmap(0x20ff6000, 0x4000); break; case 1: syz_mmap(0x20ffe000, 0x2000); break; case 2: syz_compare_int(4, 7, 0x7f, 0x71f, 6); break; case 3: syz_errno(4); break; case 4: syz_compare_int(2, 7, 0x80000001, 0, 0); break; case 5: syz_compare_int(4, 9, 6, 0x3ff, 0); break; case 6: syz_compare_int(3, 0, 5, 6, 0); break; case 7: syz_errno(0x80000000); break; case 8: syz_compare_int(2, 0x100000001, 8, 0, 0); break; case 9: syz_exit(0x200); break; case 10: memcpy((void*)0x20000000, "\000", 1); memcpy((void*)0x20000040, "\000", 1); syz_compare(0x20000000, 1, 0x20000040, 1); break; case 11: syz_compare_int(2, 4, 0, 0, 0); break; case 12: syz_errno(0x40); break; case 13: memcpy((void*)0x20000080, "\x34\x63\xee\xab\xc7\x55\xe7\xfd\xeb\xe7\x25\x21\xf6\x8b\x06\xb3\x6c\x8a\x66\xc3\x87\x9a\xfe\xc0\xd6\x60\x21\x64\xbe\x86\x7d\xa5\x64\xb6\x90\x68\x89\xaa\xf9\x33\x38\xe8\x17\x9e\xea\xa2\xeb\x98\xb1\xef", 50); syz_execute_func(0x20000080); break; case 14: syz_exit(0x101); break; case 15: syz_mmap(0x20ff2000, 0x8000); break; } } int main(void) { syz_mmap(0x20000000, 0x1000000); use_temporary_dir(); do_sandbox_none(); return 0; } /usr/local/bin/ld: cannot find -lasan collect2: error: ld returned 1 exit status compiler invocation: gcc [-o /tmp/syz-executor298846591 -DGOOS_test=1 -DGOARCH_64_fork=1 -DHOSTGOOS_freebsd=1 -x c - -O2 -pthread -Wall -Werror -Wparentheses -Wunused-const-variable -Wframe-larger-than=8192 -m64 -fsanitize=address] --- FAIL: TestGenerate/test/64_fork/20 (1.17s) csource_test.go:110: opts: {Threaded:true Collide:false Repeat:true RepeatTimes:0 Procs:0 Sandbox:none Fault:false FaultCall:0 FaultNth:0 Leak:false EnableTun:false EnableNetDev:false EnableNetReset:false EnableCgroups:false EnableBinfmtMisc:false EnableCloseFds:false UseTmpDir:true HandleSegv:false Repro:false Trace:false} program: syz_mmap(&(0x7f0000ff6000/0x4000)=nil, 0x4000) syz_mmap(&(0x7f0000ffe000/0x2000)=nil, 0x2000) syz_compare_int$4(0x4, 0x7, 0x7f, 0x71f, 0x6) syz_errno(0x4) syz_compare_int$2(0x2, 0x7, 0x80000001) syz_compare_int$4(0x4, 0x9, 0x6, 0x3ff, 0x0) syz_compare_int$3(0x3, 0x0, 0x5, 0x6) syz_errno(0xffffffff80000000) syz_compare_int$2(0x2, 0x100000001, 0x8) syz_exit(0x200) syz_compare(&(0x7f0000000000)='\x00', 0x1, &(0x7f0000000040)=@str='\x00', 0x1) syz_compare_int$2(0x2, 0x4, 0x0) syz_errno(0x40) syz_execute_func(&(0x7f0000000080)="3463eeabc755e7fdebe72521f68b06b36c8a66c3879afec0d6602164be867da564b6906889aaf93338e8179eeaa2eb98b1ef") syz_exit(0x101) syz_mmap(&(0x7f0000ff2000/0x8000)=nil, 0x8000) csource_test.go:111: failed to build program: // autogenerated by syzkaller (https://github.com/google/syzkaller) #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include static void kill_and_wait(int pid, int* status) { kill(pid, SIGKILL); while (waitpid(-1, status, 0) != pid) { } } 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 remove_dir(const char* dir) { DIR* dp; struct dirent* ep; dp = opendir(dir); if (dp == NULL) exit(1); 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)) exit(1); if (S_ISDIR(st.st_mode)) { remove_dir(filename); continue; } if (unlink(filename)) exit(1); } closedir(dp); if (rmdir(dir)) 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; for (i = 0; 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 { pthread_mutex_t mu; pthread_cond_t cv; int state; } event_t; static void event_init(event_t* ev) { if (pthread_mutex_init(&ev->mu, 0)) exit(1); if (pthread_cond_init(&ev->cv, 0)) exit(1); ev->state = 0; } static void event_reset(event_t* ev) { ev->state = 0; } static void event_set(event_t* ev) { pthread_mutex_lock(&ev->mu); if (ev->state) exit(1); ev->state = 1; pthread_mutex_unlock(&ev->mu); pthread_cond_broadcast(&ev->cv); } static void event_wait(event_t* ev) { pthread_mutex_lock(&ev->mu); while (!ev->state) pthread_cond_wait(&ev->cv, &ev->mu); pthread_mutex_unlock(&ev->mu); } static int event_isset(event_t* ev) { pthread_mutex_lock(&ev->mu); int res = ev->state; pthread_mutex_unlock(&ev->mu); return res; } static int event_timedwait(event_t* ev, uint64_t timeout) { uint64_t start = current_time_ms(); uint64_t now = start; pthread_mutex_lock(&ev->mu); for (;;) { if (ev->state) break; uint64_t remain = timeout - (now - start); struct timespec ts; ts.tv_sec = remain / 1000; ts.tv_nsec = (remain % 1000) * 1000 * 1000; pthread_cond_timedwait(&ev->cv, &ev->mu, &ts); now = current_time_ms(); if (now - start > timeout) break; } int res = ev->state; pthread_mutex_unlock(&ev->mu); return res; } static long syz_mmap(volatile long a0, volatile long a1) { return (long)mmap((void*)a0, a1, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE | MAP_FIXED, -1, 0); } static long syz_errno(volatile long v) { errno = v; return v == 0 ? 0 : -1; } static long syz_exit(volatile long status) { _exit(status); return 0; } static long syz_compare(volatile long want, volatile long want_len, volatile long got, volatile long got_len) { if (want_len != got_len) { errno = EBADF; return -1; } if (memcmp((void*)want, (void*)got, want_len)) { errno = EINVAL; return -1; } return 0; } static long syz_compare_int(volatile long n, ...) { va_list args; va_start(args, n); long v0 = va_arg(args, long); long v1 = va_arg(args, long); long v2 = va_arg(args, long); long v3 = va_arg(args, long); va_end(args); if (n < 2 || n > 4) return errno = E2BIG, -1; if (n <= 2 && v2 != 0) return errno = EFAULT, -1; if (n <= 3 && v3 != 0) return errno = EFAULT, -1; if (v0 != v1) return errno = EINVAL, -1; if (n > 2 && v0 != v2) return errno = EINVAL, -1; if (n > 3 && v0 != v3) return errno = EINVAL, -1; return 0; } static void loop(); static int do_sandbox_none(void) { loop(); return 0; } static long syz_execute_func(volatile long text) { volatile long p[8] = {0}; (void)p; ((void (*)(void))(text))(); return 0; } 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 < 16; 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); event_timedwait(&th->done, 45); break; } } for (i = 0; i < 100 && __atomic_load_n(&running, __ATOMIC_RELAXED); i++) sleep_ms(1); } static void execute_one(void); #define WAIT_FLAGS 0 static void loop(void) { int iter; for (iter = 0;; iter++) { char cwdbuf[32]; sprintf(cwdbuf, "./%d", iter); if (mkdir(cwdbuf, 0777)) exit(1); int pid = fork(); if (pid < 0) exit(1); if (pid == 0) { if (chdir(cwdbuf)) exit(1); 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 < 5 * 1000) continue; kill_and_wait(pid, &status); break; } remove_dir(cwdbuf); } } void execute_call(int call) { switch (call) { case 0: syz_mmap(0x20ff6000, 0x4000); break; case 1: syz_mmap(0x20ffe000, 0x2000); break; case 2: syz_compare_int(4, 7, 0x7f, 0x71f, 6); break; case 3: syz_errno(4); break; case 4: syz_compare_int(2, 7, 0x80000001, 0, 0); break; case 5: syz_compare_int(4, 9, 6, 0x3ff, 0); break; case 6: syz_compare_int(3, 0, 5, 6, 0); break; case 7: syz_errno(0x80000000); break; case 8: syz_compare_int(2, 0x100000001, 8, 0, 0); break; case 9: syz_exit(0x200); break; case 10: memcpy((void*)0x20000000, "\000", 1); memcpy((void*)0x20000040, "\000", 1); syz_compare(0x20000000, 1, 0x20000040, 1); break; case 11: syz_compare_int(2, 4, 0, 0, 0); break; case 12: syz_errno(0x40); break; case 13: memcpy((void*)0x20000080, "\x34\x63\xee\xab\xc7\x55\xe7\xfd\xeb\xe7\x25\x21\xf6\x8b\x06\xb3\x6c\x8a\x66\xc3\x87\x9a\xfe\xc0\xd6\x60\x21\x64\xbe\x86\x7d\xa5\x64\xb6\x90\x68\x89\xaa\xf9\x33\x38\xe8\x17\x9e\xea\xa2\xeb\x98\xb1\xef", 50); syz_execute_func(0x20000080); break; case 14: syz_exit(0x101); break; case 15: syz_mmap(0x20ff2000, 0x8000); break; } } int main(void) { syz_mmap(0x20000000, 0x1000000); use_temporary_dir(); do_sandbox_none(); return 0; } /usr/local/bin/ld: cannot find -lasan collect2: error: ld returned 1 exit status compiler invocation: gcc [-o /tmp/syz-executor113500370 -DGOOS_test=1 -DGOARCH_64_fork=1 -DHOSTGOOS_freebsd=1 -x c - -O2 -pthread -Wall -Werror -Wparentheses -Wunused-const-variable -Wframe-larger-than=8192 -m64 -fsanitize=address] --- FAIL: TestGenerate/test/64_fork/3 (1.24s) csource_test.go:110: opts: {Threaded:true Collide:true Repeat:true RepeatTimes:0 Procs:0 Sandbox:none Fault:false FaultCall:0 FaultNth:0 Leak:false EnableTun:false EnableNetDev:false EnableNetReset:false EnableCgroups:false EnableBinfmtMisc:false EnableCloseFds:false UseTmpDir:true HandleSegv:false Repro:false Trace:false} program: syz_mmap(&(0x7f0000ff6000/0x4000)=nil, 0x4000) syz_mmap(&(0x7f0000ffe000/0x2000)=nil, 0x2000) syz_compare_int$4(0x4, 0x7, 0x7f, 0x71f, 0x6) syz_errno(0x4) syz_compare_int$2(0x2, 0x7, 0x80000001) syz_compare_int$4(0x4, 0x9, 0x6, 0x3ff, 0x0) syz_compare_int$3(0x3, 0x0, 0x5, 0x6) syz_errno(0xffffffff80000000) syz_compare_int$2(0x2, 0x100000001, 0x8) syz_exit(0x200) syz_compare(&(0x7f0000000000)='\x00', 0x1, &(0x7f0000000040)=@str='\x00', 0x1) syz_compare_int$2(0x2, 0x4, 0x0) syz_errno(0x40) syz_execute_func(&(0x7f0000000080)="3463eeabc755e7fdebe72521f68b06b36c8a66c3879afec0d6602164be867da564b6906889aaf93338e8179eeaa2eb98b1ef") syz_exit(0x101) syz_mmap(&(0x7f0000ff2000/0x8000)=nil, 0x8000) csource_test.go:111: failed to build program: // autogenerated by syzkaller (https://github.com/google/syzkaller) #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include static void kill_and_wait(int pid, int* status) { kill(pid, SIGKILL); while (waitpid(-1, status, 0) != pid) { } } 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 remove_dir(const char* dir) { DIR* dp; struct dirent* ep; dp = opendir(dir); if (dp == NULL) exit(1); 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)) exit(1); if (S_ISDIR(st.st_mode)) { remove_dir(filename); continue; } if (unlink(filename)) exit(1); } closedir(dp); if (rmdir(dir)) 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; for (i = 0; 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 { pthread_mutex_t mu; pthread_cond_t cv; int state; } event_t; static void event_init(event_t* ev) { if (pthread_mutex_init(&ev->mu, 0)) exit(1); if (pthread_cond_init(&ev->cv, 0)) exit(1); ev->state = 0; } static void event_reset(event_t* ev) { ev->state = 0; } static void event_set(event_t* ev) { pthread_mutex_lock(&ev->mu); if (ev->state) exit(1); ev->state = 1; pthread_mutex_unlock(&ev->mu); pthread_cond_broadcast(&ev->cv); } static void event_wait(event_t* ev) { pthread_mutex_lock(&ev->mu); while (!ev->state) pthread_cond_wait(&ev->cv, &ev->mu); pthread_mutex_unlock(&ev->mu); } static int event_isset(event_t* ev) { pthread_mutex_lock(&ev->mu); int res = ev->state; pthread_mutex_unlock(&ev->mu); return res; } static int event_timedwait(event_t* ev, uint64_t timeout) { uint64_t start = current_time_ms(); uint64_t now = start; pthread_mutex_lock(&ev->mu); for (;;) { if (ev->state) break; uint64_t remain = timeout - (now - start); struct timespec ts; ts.tv_sec = remain / 1000; ts.tv_nsec = (remain % 1000) * 1000 * 1000; pthread_cond_timedwait(&ev->cv, &ev->mu, &ts); now = current_time_ms(); if (now - start > timeout) break; } int res = ev->state; pthread_mutex_unlock(&ev->mu); return res; } static long syz_mmap(volatile long a0, volatile long a1) { return (long)mmap((void*)a0, a1, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE | MAP_FIXED, -1, 0); } static long syz_errno(volatile long v) { errno = v; return v == 0 ? 0 : -1; } static long syz_exit(volatile long status) { _exit(status); return 0; } static long syz_compare(volatile long want, volatile long want_len, volatile long got, volatile long got_len) { if (want_len != got_len) { errno = EBADF; return -1; } if (memcmp((void*)want, (void*)got, want_len)) { errno = EINVAL; return -1; } return 0; } static long syz_compare_int(volatile long n, ...) { va_list args; va_start(args, n); long v0 = va_arg(args, long); long v1 = va_arg(args, long); long v2 = va_arg(args, long); long v3 = va_arg(args, long); va_end(args); if (n < 2 || n > 4) return errno = E2BIG, -1; if (n <= 2 && v2 != 0) return errno = EFAULT, -1; if (n <= 3 && v3 != 0) return errno = EFAULT, -1; if (v0 != v1) return errno = EINVAL, -1; if (n > 2 && v0 != v2) return errno = EINVAL, -1; if (n > 3 && v0 != v3) return errno = EINVAL, -1; return 0; } static void loop(); static int do_sandbox_none(void) { loop(); return 0; } static long syz_execute_func(volatile long text) { volatile long p[8] = {0}; (void)p; ((void (*)(void))(text))(); return 0; } 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; int collide = 0; again: for (call = 0; call < 16; 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 (collide && (call % 2) == 0) break; event_timedwait(&th->done, 45); break; } } for (i = 0; i < 100 && __atomic_load_n(&running, __ATOMIC_RELAXED); i++) sleep_ms(1); if (!collide) { collide = 1; goto again; } } static void execute_one(void); #define WAIT_FLAGS 0 static void loop(void) { int iter; for (iter = 0;; iter++) { char cwdbuf[32]; sprintf(cwdbuf, "./%d", iter); if (mkdir(cwdbuf, 0777)) exit(1); int pid = fork(); if (pid < 0) exit(1); if (pid == 0) { if (chdir(cwdbuf)) exit(1); 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 < 5 * 1000) continue; kill_and_wait(pid, &status); break; } remove_dir(cwdbuf); } } void execute_call(int call) { switch (call) { case 0: syz_mmap(0x20ff6000, 0x4000); break; case 1: syz_mmap(0x20ffe000, 0x2000); break; case 2: syz_compare_int(4, 7, 0x7f, 0x71f, 6); break; case 3: syz_errno(4); break; case 4: syz_compare_int(2, 7, 0x80000001, 0, 0); break; case 5: syz_compare_int(4, 9, 6, 0x3ff, 0); break; case 6: syz_compare_int(3, 0, 5, 6, 0); break; case 7: syz_errno(0x80000000); break; case 8: syz_compare_int(2, 0x100000001, 8, 0, 0); break; case 9: syz_exit(0x200); break; case 10: memcpy((void*)0x20000000, "\000", 1); memcpy((void*)0x20000040, "\000", 1); syz_compare(0x20000000, 1, 0x20000040, 1); break; case 11: syz_compare_int(2, 4, 0, 0, 0); break; case 12: syz_errno(0x40); break; case 13: memcpy((void*)0x20000080, "\x34\x63\xee\xab\xc7\x55\xe7\xfd\xeb\xe7\x25\x21\xf6\x8b\x06\xb3\x6c\x8a\x66\xc3\x87\x9a\xfe\xc0\xd6\x60\x21\x64\xbe\x86\x7d\xa5\x64\xb6\x90\x68\x89\xaa\xf9\x33\x38\xe8\x17\x9e\xea\xa2\xeb\x98\xb1\xef", 50); syz_execute_func(0x20000080); break; case 14: syz_exit(0x101); break; case 15: syz_mmap(0x20ff2000, 0x8000); break; } } int main(void) { syz_mmap(0x20000000, 0x1000000); use_temporary_dir(); do_sandbox_none(); return 0; } /usr/local/bin/ld: cannot find -lasan collect2: error: ld returned 1 exit status compiler invocation: gcc [-o /tmp/syz-executor852263715 -DGOOS_test=1 -DGOARCH_64_fork=1 -DHOSTGOOS_freebsd=1 -x c - -O2 -pthread -Wall -Werror -Wparentheses -Wunused-const-variable -Wframe-larger-than=8192 -m64 -fsanitize=address] --- FAIL: TestGenerate/test/64_fork/24 (1.25s) csource_test.go:110: opts: {Threaded:true Collide:false Repeat:true RepeatTimes:0 Procs:0 Sandbox:none Fault:false FaultCall:0 FaultNth:0 Leak:false EnableTun:false EnableNetDev:false EnableNetReset:false EnableCgroups:false EnableBinfmtMisc:false EnableCloseFds:false UseTmpDir:true HandleSegv:false Repro:false Trace:false} program: syz_mmap(&(0x7f0000ff6000/0x4000)=nil, 0x4000) syz_mmap(&(0x7f0000ffe000/0x2000)=nil, 0x2000) syz_compare_int$4(0x4, 0x7, 0x7f, 0x71f, 0x6) syz_errno(0x4) syz_compare_int$2(0x2, 0x7, 0x80000001) syz_compare_int$4(0x4, 0x9, 0x6, 0x3ff, 0x0) syz_compare_int$3(0x3, 0x0, 0x5, 0x6) syz_errno(0xffffffff80000000) syz_compare_int$2(0x2, 0x100000001, 0x8) syz_exit(0x200) syz_compare(&(0x7f0000000000)='\x00', 0x1, &(0x7f0000000040)=@str='\x00', 0x1) syz_compare_int$2(0x2, 0x4, 0x0) syz_errno(0x40) syz_execute_func(&(0x7f0000000080)="3463eeabc755e7fdebe72521f68b06b36c8a66c3879afec0d6602164be867da564b6906889aaf93338e8179eeaa2eb98b1ef") syz_exit(0x101) syz_mmap(&(0x7f0000ff2000/0x8000)=nil, 0x8000) csource_test.go:111: failed to build program: // autogenerated by syzkaller (https://github.com/google/syzkaller) #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include static void kill_and_wait(int pid, int* status) { kill(pid, SIGKILL); while (waitpid(-1, status, 0) != pid) { } } 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 remove_dir(const char* dir) { DIR* dp; struct dirent* ep; dp = opendir(dir); if (dp == NULL) exit(1); 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)) exit(1); if (S_ISDIR(st.st_mode)) { remove_dir(filename); continue; } if (unlink(filename)) exit(1); } closedir(dp); if (rmdir(dir)) 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; for (i = 0; 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 { pthread_mutex_t mu; pthread_cond_t cv; int state; } event_t; static void event_init(event_t* ev) { if (pthread_mutex_init(&ev->mu, 0)) exit(1); if (pthread_cond_init(&ev->cv, 0)) exit(1); ev->state = 0; } static void event_reset(event_t* ev) { ev->state = 0; } static void event_set(event_t* ev) { pthread_mutex_lock(&ev->mu); if (ev->state) exit(1); ev->state = 1; pthread_mutex_unlock(&ev->mu); pthread_cond_broadcast(&ev->cv); } static void event_wait(event_t* ev) { pthread_mutex_lock(&ev->mu); while (!ev->state) pthread_cond_wait(&ev->cv, &ev->mu); pthread_mutex_unlock(&ev->mu); } static int event_isset(event_t* ev) { pthread_mutex_lock(&ev->mu); int res = ev->state; pthread_mutex_unlock(&ev->mu); return res; } static int event_timedwait(event_t* ev, uint64_t timeout) { uint64_t start = current_time_ms(); uint64_t now = start; pthread_mutex_lock(&ev->mu); for (;;) { if (ev->state) break; uint64_t remain = timeout - (now - start); struct timespec ts; ts.tv_sec = remain / 1000; ts.tv_nsec = (remain % 1000) * 1000 * 1000; pthread_cond_timedwait(&ev->cv, &ev->mu, &ts); now = current_time_ms(); if (now - start > timeout) break; } int res = ev->state; pthread_mutex_unlock(&ev->mu); return res; } static long syz_mmap(volatile long a0, volatile long a1) { return (long)mmap((void*)a0, a1, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE | MAP_FIXED, -1, 0); } static long syz_errno(volatile long v) { errno = v; return v == 0 ? 0 : -1; } static long syz_exit(volatile long status) { _exit(status); return 0; } static long syz_compare(volatile long want, volatile long want_len, volatile long got, volatile long got_len) { if (want_len != got_len) { errno = EBADF; return -1; } if (memcmp((void*)want, (void*)got, want_len)) { errno = EINVAL; return -1; } return 0; } static long syz_compare_int(volatile long n, ...) { va_list args; va_start(args, n); long v0 = va_arg(args, long); long v1 = va_arg(args, long); long v2 = va_arg(args, long); long v3 = va_arg(args, long); va_end(args); if (n < 2 || n > 4) return errno = E2BIG, -1; if (n <= 2 && v2 != 0) return errno = EFAULT, -1; if (n <= 3 && v3 != 0) return errno = EFAULT, -1; if (v0 != v1) return errno = EINVAL, -1; if (n > 2 && v0 != v2) return errno = EINVAL, -1; if (n > 3 && v0 != v3) return errno = EINVAL, -1; return 0; } static void loop(); static int do_sandbox_none(void) { loop(); return 0; } static long syz_execute_func(volatile long text) { volatile long p[8] = {0}; (void)p; ((void (*)(void))(text))(); return 0; } 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 < 16; 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); event_timedwait(&th->done, 45); break; } } for (i = 0; i < 100 && __atomic_load_n(&running, __ATOMIC_RELAXED); i++) sleep_ms(1); } static void execute_one(void); #define WAIT_FLAGS 0 static void loop(void) { int iter; for (iter = 0;; iter++) { char cwdbuf[32]; sprintf(cwdbuf, "./%d", iter); if (mkdir(cwdbuf, 0777)) exit(1); int pid = fork(); if (pid < 0) exit(1); if (pid == 0) { if (chdir(cwdbuf)) exit(1); 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 < 5 * 1000) continue; kill_and_wait(pid, &status); break; } remove_dir(cwdbuf); } } void execute_call(int call) { switch (call) { case 0: syz_mmap(0x20ff6000, 0x4000); break; case 1: syz_mmap(0x20ffe000, 0x2000); break; case 2: syz_compare_int(4, 7, 0x7f, 0x71f, 6); break; case 3: syz_errno(4); break; case 4: syz_compare_int(2, 7, 0x80000001, 0, 0); break; case 5: syz_compare_int(4, 9, 6, 0x3ff, 0); break; case 6: syz_compare_int(3, 0, 5, 6, 0); break; case 7: syz_errno(0x80000000); break; case 8: syz_compare_int(2, 0x100000001, 8, 0, 0); break; case 9: syz_exit(0x200); break; case 10: memcpy((void*)0x20000000, "\000", 1); memcpy((void*)0x20000040, "\000", 1); syz_compare(0x20000000, 1, 0x20000040, 1); break; case 11: syz_compare_int(2, 4, 0, 0, 0); break; case 12: syz_errno(0x40); break; case 13: memcpy((void*)0x20000080, "\x34\x63\xee\xab\xc7\x55\xe7\xfd\xeb\xe7\x25\x21\xf6\x8b\x06\xb3\x6c\x8a\x66\xc3\x87\x9a\xfe\xc0\xd6\x60\x21\x64\xbe\x86\x7d\xa5\x64\xb6\x90\x68\x89\xaa\xf9\x33\x38\xe8\x17\x9e\xea\xa2\xeb\x98\xb1\xef", 50); syz_execute_func(0x20000080); break; case 14: syz_exit(0x101); break; case 15: syz_mmap(0x20ff2000, 0x8000); break; } } int main(void) { syz_mmap(0x20000000, 0x1000000); use_temporary_dir(); do_sandbox_none(); return 0; } /usr/local/bin/ld: cannot find -lasan collect2: error: ld returned 1 exit status compiler invocation: gcc [-o /tmp/syz-executor238897161 -DGOOS_test=1 -DGOARCH_64_fork=1 -DHOSTGOOS_freebsd=1 -x c - -O2 -pthread -Wall -Werror -Wparentheses -Wunused-const-variable -Wframe-larger-than=8192 -m64 -fsanitize=address] --- FAIL: TestGenerate/test/64_fork/22 (1.02s) csource_test.go:110: opts: {Threaded:true Collide:false Repeat:true RepeatTimes:0 Procs:0 Sandbox:none Fault:false FaultCall:0 FaultNth:0 Leak:false EnableTun:false EnableNetDev:false EnableNetReset:false EnableCgroups:false EnableBinfmtMisc:false EnableCloseFds:false UseTmpDir:false HandleSegv:false Repro:false Trace:false} program: syz_mmap(&(0x7f0000ff6000/0x4000)=nil, 0x4000) syz_mmap(&(0x7f0000ffe000/0x2000)=nil, 0x2000) syz_compare_int$4(0x4, 0x7, 0x7f, 0x71f, 0x6) syz_errno(0x4) syz_compare_int$2(0x2, 0x7, 0x80000001) syz_compare_int$4(0x4, 0x9, 0x6, 0x3ff, 0x0) syz_compare_int$3(0x3, 0x0, 0x5, 0x6) syz_errno(0xffffffff80000000) syz_compare_int$2(0x2, 0x100000001, 0x8) syz_exit(0x200) syz_compare(&(0x7f0000000000)='\x00', 0x1, &(0x7f0000000040)=@str='\x00', 0x1) syz_compare_int$2(0x2, 0x4, 0x0) syz_errno(0x40) syz_execute_func(&(0x7f0000000080)="3463eeabc755e7fdebe72521f68b06b36c8a66c3879afec0d6602164be867da564b6906889aaf93338e8179eeaa2eb98b1ef") syz_exit(0x101) syz_mmap(&(0x7f0000ff2000/0x8000)=nil, 0x8000) csource_test.go:111: failed to build program: // autogenerated by syzkaller (https://github.com/google/syzkaller) #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include #include #include static void kill_and_wait(int pid, int* status) { kill(pid, SIGKILL); while (waitpid(-1, status, 0) != pid) { } } 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 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; for (i = 0; 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 { pthread_mutex_t mu; pthread_cond_t cv; int state; } event_t; static void event_init(event_t* ev) { if (pthread_mutex_init(&ev->mu, 0)) exit(1); if (pthread_cond_init(&ev->cv, 0)) exit(1); ev->state = 0; } static void event_reset(event_t* ev) { ev->state = 0; } static void event_set(event_t* ev) { pthread_mutex_lock(&ev->mu); if (ev->state) exit(1); ev->state = 1; pthread_mutex_unlock(&ev->mu); pthread_cond_broadcast(&ev->cv); } static void event_wait(event_t* ev) { pthread_mutex_lock(&ev->mu); while (!ev->state) pthread_cond_wait(&ev->cv, &ev->mu); pthread_mutex_unlock(&ev->mu); } static int event_isset(event_t* ev) { pthread_mutex_lock(&ev->mu); int res = ev->state; pthread_mutex_unlock(&ev->mu); return res; } static int event_timedwait(event_t* ev, uint64_t timeout) { uint64_t start = current_time_ms(); uint64_t now = start; pthread_mutex_lock(&ev->mu); for (;;) { if (ev->state) break; uint64_t remain = timeout - (now - start); struct timespec ts; ts.tv_sec = remain / 1000; ts.tv_nsec = (remain % 1000) * 1000 * 1000; pthread_cond_timedwait(&ev->cv, &ev->mu, &ts); now = current_time_ms(); if (now - start > timeout) break; } int res = ev->state; pthread_mutex_unlock(&ev->mu); return res; } static long syz_mmap(volatile long a0, volatile long a1) { return (long)mmap((void*)a0, a1, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE | MAP_FIXED, -1, 0); } static long syz_errno(volatile long v) { errno = v; return v == 0 ? 0 : -1; } static long syz_exit(volatile long status) { _exit(status); return 0; } static long syz_compare(volatile long want, volatile long want_len, volatile long got, volatile long got_len) { if (want_len != got_len) { errno = EBADF; return -1; } if (memcmp((void*)want, (void*)got, want_len)) { errno = EINVAL; return -1; } return 0; } static long syz_compare_int(volatile long n, ...) { va_list args; va_start(args, n); long v0 = va_arg(args, long); long v1 = va_arg(args, long); long v2 = va_arg(args, long); long v3 = va_arg(args, long); va_end(args); if (n < 2 || n > 4) return errno = E2BIG, -1; if (n <= 2 && v2 != 0) return errno = EFAULT, -1; if (n <= 3 && v3 != 0) return errno = EFAULT, -1; if (v0 != v1) return errno = EINVAL, -1; if (n > 2 && v0 != v2) return errno = EINVAL, -1; if (n > 3 && v0 != v3) return errno = EINVAL, -1; return 0; } static void loop(); static int do_sandbox_none(void) { loop(); return 0; } static long syz_execute_func(volatile long text) { volatile long p[8] = {0}; (void)p; ((void (*)(void))(text))(); return 0; } 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 < 16; 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); event_timedwait(&th->done, 45); break; } } for (i = 0; i < 100 && __atomic_load_n(&running, __ATOMIC_RELAXED); i++) sleep_ms(1); } static void execute_one(void); #define WAIT_FLAGS 0 static void loop(void) { int iter; for (iter = 0;; iter++) { int pid = fork(); if (pid < 0) exit(1); if (pid == 0) { 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 < 5 * 1000) continue; kill_and_wait(pid, &status); break; } } } void execute_call(int call) { switch (call) { case 0: syz_mmap(0x20ff6000, 0x4000); break; case 1: syz_mmap(0x20ffe000, 0x2000); break; case 2: syz_compare_int(4, 7, 0x7f, 0x71f, 6); break; case 3: syz_errno(4); break; case 4: syz_compare_int(2, 7, 0x80000001, 0, 0); break; case 5: syz_compare_int(4, 9, 6, 0x3ff, 0); break; case 6: syz_compare_int(3, 0, 5, 6, 0); break; case 7: syz_errno(0x80000000); break; case 8: syz_compare_int(2, 0x100000001, 8, 0, 0); break; case 9: syz_exit(0x200); break; case 10: memcpy((void*)0x20000000, "\000", 1); memcpy((void*)0x20000040, "\000", 1); syz_compare(0x20000000, 1, 0x20000040, 1); break; case 11: syz_compare_int(2, 4, 0, 0, 0); break; case 12: syz_errno(0x40); break; case 13: memcpy((void*)0x20000080, "\x34\x63\xee\xab\xc7\x55\xe7\xfd\xeb\xe7\x25\x21\xf6\x8b\x06\xb3\x6c\x8a\x66\xc3\x87\x9a\xfe\xc0\xd6\x60\x21\x64\xbe\x86\x7d\xa5\x64\xb6\x90\x68\x89\xaa\xf9\x33\x38\xe8\x17\x9e\xea\xa2\xeb\x98\xb1\xef", 50); syz_execute_func(0x20000080); break; case 14: syz_exit(0x101); break; case 15: syz_mmap(0x20ff2000, 0x8000); break; } } int main(void) { syz_mmap(0x20000000, 0x1000000); do_sandbox_none(); return 0; } /usr/local/bin/ld: cannot find -lasan collect2: error: ld returned 1 exit status compiler invocation: gcc [-o /tmp/syz-executor149633608 -DGOOS_test=1 -DGOARCH_64_fork=1 -DHOSTGOOS_freebsd=1 -x c - -O2 -pthread -Wall -Werror -Wparentheses -Wunused-const-variable -Wframe-larger-than=8192 -m64 -fsanitize=address] --- FAIL: TestGenerate/test/64_fork/30 (1.16s) csource_test.go:110: opts: {Threaded:true Collide:true Repeat:true RepeatTimes:0 Procs:2 Sandbox:none Fault:false FaultCall:0 FaultNth:0 Leak:false EnableTun:false EnableNetDev:false EnableNetReset:false EnableCgroups:false EnableBinfmtMisc:false EnableCloseFds:false UseTmpDir:true HandleSegv:false Repro:true Trace:false} program: syz_mmap(&(0x7f0000ff6000/0x4000)=nil, 0x4000) syz_mmap(&(0x7f0000ffe000/0x2000)=nil, 0x2000) syz_compare_int$4(0x4, 0x7, 0x7f, 0x71f, 0x6) syz_errno(0x4) syz_compare_int$2(0x2, 0x7, 0x80000001) syz_compare_int$4(0x4, 0x9, 0x6, 0x3ff, 0x0) syz_compare_int$3(0x3, 0x0, 0x5, 0x6) syz_errno(0xffffffff80000000) syz_compare_int$2(0x2, 0x100000001, 0x8) syz_exit(0x200) syz_compare(&(0x7f0000000000)='\x00', 0x1, &(0x7f0000000040)=@str='\x00', 0x1) syz_compare_int$2(0x2, 0x4, 0x0) syz_errno(0x40) syz_execute_func(&(0x7f0000000080)="3463eeabc755e7fdebe72521f68b06b36c8a66c3879afec0d6602164be867da564b6906889aaf93338e8179eeaa2eb98b1ef") syz_exit(0x101) syz_mmap(&(0x7f0000ff2000/0x8000)=nil, 0x8000) csource_test.go:111: failed to build program: // autogenerated by syzkaller (https://github.com/google/syzkaller) #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include unsigned long long procid; static void kill_and_wait(int pid, int* status) { kill(pid, SIGKILL); while (waitpid(-1, status, 0) != pid) { } } 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 remove_dir(const char* dir) { DIR* dp; struct dirent* ep; dp = opendir(dir); if (dp == NULL) exit(1); 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)) exit(1); if (S_ISDIR(st.st_mode)) { remove_dir(filename); continue; } if (unlink(filename)) exit(1); } closedir(dp); if (rmdir(dir)) 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; for (i = 0; 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 { pthread_mutex_t mu; pthread_cond_t cv; int state; } event_t; static void event_init(event_t* ev) { if (pthread_mutex_init(&ev->mu, 0)) exit(1); if (pthread_cond_init(&ev->cv, 0)) exit(1); ev->state = 0; } static void event_reset(event_t* ev) { ev->state = 0; } static void event_set(event_t* ev) { pthread_mutex_lock(&ev->mu); if (ev->state) exit(1); ev->state = 1; pthread_mutex_unlock(&ev->mu); pthread_cond_broadcast(&ev->cv); } static void event_wait(event_t* ev) { pthread_mutex_lock(&ev->mu); while (!ev->state) pthread_cond_wait(&ev->cv, &ev->mu); pthread_mutex_unlock(&ev->mu); } static int event_isset(event_t* ev) { pthread_mutex_lock(&ev->mu); int res = ev->state; pthread_mutex_unlock(&ev->mu); return res; } static int event_timedwait(event_t* ev, uint64_t timeout) { uint64_t start = current_time_ms(); uint64_t now = start; pthread_mutex_lock(&ev->mu); for (;;) { if (ev->state) break; uint64_t remain = timeout - (now - start); struct timespec ts; ts.tv_sec = remain / 1000; ts.tv_nsec = (remain % 1000) * 1000 * 1000; pthread_cond_timedwait(&ev->cv, &ev->mu, &ts); now = current_time_ms(); if (now - start > timeout) break; } int res = ev->state; pthread_mutex_unlock(&ev->mu); return res; } static long syz_mmap(volatile long a0, volatile long a1) { return (long)mmap((void*)a0, a1, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE | MAP_FIXED, -1, 0); } static long syz_errno(volatile long v) { errno = v; return v == 0 ? 0 : -1; } static long syz_exit(volatile long status) { _exit(status); return 0; } static long syz_compare(volatile long want, volatile long want_len, volatile long got, volatile long got_len) { if (want_len != got_len) { errno = EBADF; return -1; } if (memcmp((void*)want, (void*)got, want_len)) { errno = EINVAL; return -1; } return 0; } static long syz_compare_int(volatile long n, ...) { va_list args; va_start(args, n); long v0 = va_arg(args, long); long v1 = va_arg(args, long); long v2 = va_arg(args, long); long v3 = va_arg(args, long); va_end(args); if (n < 2 || n > 4) return errno = E2BIG, -1; if (n <= 2 && v2 != 0) return errno = EFAULT, -1; if (n <= 3 && v3 != 0) return errno = EFAULT, -1; if (v0 != v1) return errno = EINVAL, -1; if (n > 2 && v0 != v2) return errno = EINVAL, -1; if (n > 3 && v0 != v3) return errno = EINVAL, -1; return 0; } static void loop(); static int do_sandbox_none(void) { loop(); return 0; } static long syz_execute_func(volatile long text) { volatile long p[8] = {0}; (void)p; ((void (*)(void))(text))(); return 0; } 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) { if (write(1, "executing program\n", sizeof("executing program\n") - 1)) { } int i, call, thread; int collide = 0; again: for (call = 0; call < 16; 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 (collide && (call % 2) == 0) break; event_timedwait(&th->done, 45); break; } } for (i = 0; i < 100 && __atomic_load_n(&running, __ATOMIC_RELAXED); i++) sleep_ms(1); if (!collide) { collide = 1; goto again; } } static void execute_one(void); #define WAIT_FLAGS 0 static void loop(void) { int iter; for (iter = 0;; iter++) { char cwdbuf[32]; sprintf(cwdbuf, "./%d", iter); if (mkdir(cwdbuf, 0777)) exit(1); int pid = fork(); if (pid < 0) exit(1); if (pid == 0) { if (chdir(cwdbuf)) exit(1); 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 < 5 * 1000) continue; kill_and_wait(pid, &status); break; } remove_dir(cwdbuf); } } void execute_call(int call) { switch (call) { case 0: syz_mmap(0x20ff6000, 0x4000); break; case 1: syz_mmap(0x20ffe000, 0x2000); break; case 2: syz_compare_int(4, 7, 0x7f, 0x71f, 6); break; case 3: syz_errno(4); break; case 4: syz_compare_int(2, 7, 0x80000001, 0, 0); break; case 5: syz_compare_int(4, 9, 6, 0x3ff, 0); break; case 6: syz_compare_int(3, 0, 5, 6, 0); break; case 7: syz_errno(0x80000000); break; case 8: syz_compare_int(2, 0x100000001, 8, 0, 0); break; case 9: syz_exit(0x200); break; case 10: memcpy((void*)0x20000000, "\000", 1); memcpy((void*)0x20000040, "\000", 1); syz_compare(0x20000000, 1, 0x20000040, 1); break; case 11: syz_compare_int(2, 4, 0, 0, 0); break; case 12: syz_errno(0x40); break; case 13: memcpy((void*)0x20000080, "\x34\x63\xee\xab\xc7\x55\xe7\xfd\xeb\xe7\x25\x21\xf6\x8b\x06\xb3\x6c\x8a\x66\xc3\x87\x9a\xfe\xc0\xd6\x60\x21\x64\xbe\x86\x7d\xa5\x64\xb6\x90\x68\x89\xaa\xf9\x33\x38\xe8\x17\x9e\xea\xa2\xeb\x98\xb1\xef", 50); syz_execute_func(0x20000080); break; case 14: syz_exit(0x101); break; case 15: syz_mmap(0x20ff2000, 0x8000); break; } } int main(void) { syz_mmap(0x20000000, 0x1000000); for (procid = 0; procid < 2; procid++) { if (fork() == 0) { use_temporary_dir(); do_sandbox_none(); } } sleep(1000000); return 0; } /usr/local/bin/ld: cannot find -lasan collect2: error: ld returned 1 exit status compiler invocation: gcc [-o /tmp/syz-executor598218196 -DGOOS_test=1 -DGOARCH_64_fork=1 -DHOSTGOOS_freebsd=1 -x c - -O2 -pthread -Wall -Werror -Wparentheses -Wunused-const-variable -Wframe-larger-than=8192 -m64 -fsanitize=address] --- FAIL: TestGenerate/test/64_fork/29 (1.43s) csource_test.go:110: opts: {Threaded:true Collide:false Repeat:true RepeatTimes:0 Procs:0 Sandbox:none Fault:false FaultCall:0 FaultNth:0 Leak:false EnableTun:false EnableNetDev:false EnableNetReset:false EnableCgroups:false EnableBinfmtMisc:false EnableCloseFds:false UseTmpDir:true HandleSegv:false Repro:false Trace:true} program: syz_mmap(&(0x7f0000ff6000/0x4000)=nil, 0x4000) syz_mmap(&(0x7f0000ffe000/0x2000)=nil, 0x2000) syz_compare_int$4(0x4, 0x7, 0x7f, 0x71f, 0x6) syz_errno(0x4) syz_compare_int$2(0x2, 0x7, 0x80000001) syz_compare_int$4(0x4, 0x9, 0x6, 0x3ff, 0x0) syz_compare_int$3(0x3, 0x0, 0x5, 0x6) syz_errno(0xffffffff80000000) syz_compare_int$2(0x2, 0x100000001, 0x8) syz_exit(0x200) syz_compare(&(0x7f0000000000)='\x00', 0x1, &(0x7f0000000040)=@str='\x00', 0x1) syz_compare_int$2(0x2, 0x4, 0x0) syz_errno(0x40) syz_execute_func(&(0x7f0000000080)="3463eeabc755e7fdebe72521f68b06b36c8a66c3879afec0d6602164be867da564b6906889aaf93338e8179eeaa2eb98b1ef") syz_exit(0x101) syz_mmap(&(0x7f0000ff2000/0x8000)=nil, 0x8000) csource_test.go:111: failed to build program: // autogenerated by syzkaller (https://github.com/google/syzkaller) #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include static void kill_and_wait(int pid, int* status) { kill(pid, SIGKILL); while (waitpid(-1, status, 0) != pid) { } } 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 remove_dir(const char* dir) { DIR* dp; struct dirent* ep; dp = opendir(dir); if (dp == NULL) exit(1); 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)) exit(1); if (S_ISDIR(st.st_mode)) { remove_dir(filename); continue; } if (unlink(filename)) exit(1); } closedir(dp); if (rmdir(dir)) 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; for (i = 0; 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 { pthread_mutex_t mu; pthread_cond_t cv; int state; } event_t; static void event_init(event_t* ev) { if (pthread_mutex_init(&ev->mu, 0)) exit(1); if (pthread_cond_init(&ev->cv, 0)) exit(1); ev->state = 0; } static void event_reset(event_t* ev) { ev->state = 0; } static void event_set(event_t* ev) { pthread_mutex_lock(&ev->mu); if (ev->state) exit(1); ev->state = 1; pthread_mutex_unlock(&ev->mu); pthread_cond_broadcast(&ev->cv); } static void event_wait(event_t* ev) { pthread_mutex_lock(&ev->mu); while (!ev->state) pthread_cond_wait(&ev->cv, &ev->mu); pthread_mutex_unlock(&ev->mu); } static int event_isset(event_t* ev) { pthread_mutex_lock(&ev->mu); int res = ev->state; pthread_mutex_unlock(&ev->mu); return res; } static int event_timedwait(event_t* ev, uint64_t timeout) { uint64_t start = current_time_ms(); uint64_t now = start; pthread_mutex_lock(&ev->mu); for (;;) { if (ev->state) break; uint64_t remain = timeout - (now - start); struct timespec ts; ts.tv_sec = remain / 1000; ts.tv_nsec = (remain % 1000) * 1000 * 1000; pthread_cond_timedwait(&ev->cv, &ev->mu, &ts); now = current_time_ms(); if (now - start > timeout) break; } int res = ev->state; pthread_mutex_unlock(&ev->mu); return res; } static long syz_mmap(volatile long a0, volatile long a1) { return (long)mmap((void*)a0, a1, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE | MAP_FIXED, -1, 0); } static long syz_errno(volatile long v) { errno = v; return v == 0 ? 0 : -1; } static long syz_exit(volatile long status) { _exit(status); return 0; } static long syz_compare(volatile long want, volatile long want_len, volatile long got, volatile long got_len) { if (want_len != got_len) { errno = EBADF; return -1; } if (memcmp((void*)want, (void*)got, want_len)) { errno = EINVAL; return -1; } return 0; } static long syz_compare_int(volatile long n, ...) { va_list args; va_start(args, n); long v0 = va_arg(args, long); long v1 = va_arg(args, long); long v2 = va_arg(args, long); long v3 = va_arg(args, long); va_end(args); if (n < 2 || n > 4) return errno = E2BIG, -1; if (n <= 2 && v2 != 0) return errno = EFAULT, -1; if (n <= 3 && v3 != 0) return errno = EFAULT, -1; if (v0 != v1) return errno = EINVAL, -1; if (n > 2 && v0 != v2) return errno = EINVAL, -1; if (n > 3 && v0 != v3) return errno = EINVAL, -1; return 0; } static void loop(); static int do_sandbox_none(void) { loop(); return 0; } static long syz_execute_func(volatile long text) { volatile long p[8] = {0}; (void)p; ((void (*)(void))(text))(); return 0; } 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) { fprintf(stderr, "### start\n"); int i, call, thread; for (call = 0; call < 16; 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); event_timedwait(&th->done, 45); break; } } for (i = 0; i < 100 && __atomic_load_n(&running, __ATOMIC_RELAXED); i++) sleep_ms(1); } static void execute_one(void); #define WAIT_FLAGS 0 static void loop(void) { int iter; for (iter = 0;; iter++) { char cwdbuf[32]; sprintf(cwdbuf, "./%d", iter); if (mkdir(cwdbuf, 0777)) exit(1); int pid = fork(); if (pid < 0) exit(1); if (pid == 0) { if (chdir(cwdbuf)) exit(1); 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 < 5 * 1000) continue; kill_and_wait(pid, &status); break; } remove_dir(cwdbuf); } } void execute_call(int call) { intptr_t res; switch (call) { case 0: res = syz_mmap(0x20ff6000, 0x4000); fprintf(stderr, "### call=0 errno=%u\n", res == -1 ? errno : 0); break; case 1: res = syz_mmap(0x20ffe000, 0x2000); fprintf(stderr, "### call=1 errno=%u\n", res == -1 ? errno : 0); break; case 2: res = syz_compare_int(4, 7, 0x7f, 0x71f, 6); fprintf(stderr, "### call=2 errno=%u\n", res == -1 ? errno : 0); break; case 3: res = syz_errno(4); fprintf(stderr, "### call=3 errno=%u\n", res == -1 ? errno : 0); break; case 4: res = syz_compare_int(2, 7, 0x80000001, 0, 0); fprintf(stderr, "### call=4 errno=%u\n", res == -1 ? errno : 0); break; case 5: res = syz_compare_int(4, 9, 6, 0x3ff, 0); fprintf(stderr, "### call=5 errno=%u\n", res == -1 ? errno : 0); break; case 6: res = syz_compare_int(3, 0, 5, 6, 0); fprintf(stderr, "### call=6 errno=%u\n", res == -1 ? errno : 0); break; case 7: res = syz_errno(0x80000000); fprintf(stderr, "### call=7 errno=%u\n", res == -1 ? errno : 0); break; case 8: res = syz_compare_int(2, 0x100000001, 8, 0, 0); fprintf(stderr, "### call=8 errno=%u\n", res == -1 ? errno : 0); break; case 9: res = syz_exit(0x200); fprintf(stderr, "### call=9 errno=%u\n", res == -1 ? errno : 0); break; case 10: memcpy((void*)0x20000000, "\000", 1); memcpy((void*)0x20000040, "\000", 1); res = syz_compare(0x20000000, 1, 0x20000040, 1); fprintf(stderr, "### call=10 errno=%u\n", res == -1 ? errno : 0); break; case 11: res = syz_compare_int(2, 4, 0, 0, 0); fprintf(stderr, "### call=11 errno=%u\n", res == -1 ? errno : 0); break; case 12: res = syz_errno(0x40); fprintf(stderr, "### call=12 errno=%u\n", res == -1 ? errno : 0); break; case 13: memcpy((void*)0x20000080, "\x34\x63\xee\xab\xc7\x55\xe7\xfd\xeb\xe7\x25\x21\xf6\x8b\x06\xb3\x6c\x8a\x66\xc3\x87\x9a\xfe\xc0\xd6\x60\x21\x64\xbe\x86\x7d\xa5\x64\xb6\x90\x68\x89\xaa\xf9\x33\x38\xe8\x17\x9e\xea\xa2\xeb\x98\xb1\xef", 50); res = syz_execute_func(0x20000080); fprintf(stderr, "### call=13 errno=%u\n", res == -1 ? errno : 0); break; case 14: res = syz_exit(0x101); fprintf(stderr, "### call=14 errno=%u\n", res == -1 ? errno : 0); break; case 15: res = syz_mmap(0x20ff2000, 0x8000); fprintf(stderr, "### call=15 errno=%u\n", res == -1 ? errno : 0); break; } } int main(void) { syz_mmap(0x20000000, 0x1000000); use_temporary_dir(); do_sandbox_none(); return 0; } /usr/local/bin/ld: cannot find -lasan collect2: error: ld returned 1 exit status compiler invocation: gcc [-o /tmp/syz-executor306700109 -DGOOS_test=1 -DGOARCH_64_fork=1 -DHOSTGOOS_freebsd=1 -x c - -O2 -pthread -Wall -Werror -Wparentheses -Wunused-const-variable -Wframe-larger-than=8192 -m64 -fsanitize=address] --- FAIL: TestGenerate/test/64_fork/23 (1.51s) csource_test.go:110: opts: {Threaded:true Collide:false Repeat:true RepeatTimes:0 Procs:0 Sandbox:none Fault:false FaultCall:0 FaultNth:0 Leak:false EnableTun:false EnableNetDev:false EnableNetReset:false EnableCgroups:false EnableBinfmtMisc:false EnableCloseFds:false UseTmpDir:true HandleSegv:false Repro:false Trace:false} program: syz_mmap(&(0x7f0000ff6000/0x4000)=nil, 0x4000) syz_mmap(&(0x7f0000ffe000/0x2000)=nil, 0x2000) syz_compare_int$4(0x4, 0x7, 0x7f, 0x71f, 0x6) syz_errno(0x4) syz_compare_int$2(0x2, 0x7, 0x80000001) syz_compare_int$4(0x4, 0x9, 0x6, 0x3ff, 0x0) syz_compare_int$3(0x3, 0x0, 0x5, 0x6) syz_errno(0xffffffff80000000) syz_compare_int$2(0x2, 0x100000001, 0x8) syz_exit(0x200) syz_compare(&(0x7f0000000000)='\x00', 0x1, &(0x7f0000000040)=@str='\x00', 0x1) syz_compare_int$2(0x2, 0x4, 0x0) syz_errno(0x40) syz_execute_func(&(0x7f0000000080)="3463eeabc755e7fdebe72521f68b06b36c8a66c3879afec0d6602164be867da564b6906889aaf93338e8179eeaa2eb98b1ef") syz_exit(0x101) syz_mmap(&(0x7f0000ff2000/0x8000)=nil, 0x8000) csource_test.go:111: failed to build program: // autogenerated by syzkaller (https://github.com/google/syzkaller) #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include static void kill_and_wait(int pid, int* status) { kill(pid, SIGKILL); while (waitpid(-1, status, 0) != pid) { } } 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 remove_dir(const char* dir) { DIR* dp; struct dirent* ep; dp = opendir(dir); if (dp == NULL) exit(1); 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)) exit(1); if (S_ISDIR(st.st_mode)) { remove_dir(filename); continue; } if (unlink(filename)) exit(1); } closedir(dp); if (rmdir(dir)) 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; for (i = 0; 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 { pthread_mutex_t mu; pthread_cond_t cv; int state; } event_t; static void event_init(event_t* ev) { if (pthread_mutex_init(&ev->mu, 0)) exit(1); if (pthread_cond_init(&ev->cv, 0)) exit(1); ev->state = 0; } static void event_reset(event_t* ev) { ev->state = 0; } static void event_set(event_t* ev) { pthread_mutex_lock(&ev->mu); if (ev->state) exit(1); ev->state = 1; pthread_mutex_unlock(&ev->mu); pthread_cond_broadcast(&ev->cv); } static void event_wait(event_t* ev) { pthread_mutex_lock(&ev->mu); while (!ev->state) pthread_cond_wait(&ev->cv, &ev->mu); pthread_mutex_unlock(&ev->mu); } static int event_isset(event_t* ev) { pthread_mutex_lock(&ev->mu); int res = ev->state; pthread_mutex_unlock(&ev->mu); return res; } static int event_timedwait(event_t* ev, uint64_t timeout) { uint64_t start = current_time_ms(); uint64_t now = start; pthread_mutex_lock(&ev->mu); for (;;) { if (ev->state) break; uint64_t remain = timeout - (now - start); struct timespec ts; ts.tv_sec = remain / 1000; ts.tv_nsec = (remain % 1000) * 1000 * 1000; pthread_cond_timedwait(&ev->cv, &ev->mu, &ts); now = current_time_ms(); if (now - start > timeout) break; } int res = ev->state; pthread_mutex_unlock(&ev->mu); return res; } static long syz_mmap(volatile long a0, volatile long a1) { return (long)mmap((void*)a0, a1, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE | MAP_FIXED, -1, 0); } static long syz_errno(volatile long v) { errno = v; return v == 0 ? 0 : -1; } static long syz_exit(volatile long status) { _exit(status); return 0; } static long syz_compare(volatile long want, volatile long want_len, volatile long got, volatile long got_len) { if (want_len != got_len) { errno = EBADF; return -1; } if (memcmp((void*)want, (void*)got, want_len)) { errno = EINVAL; return -1; } return 0; } static long syz_compare_int(volatile long n, ...) { va_list args; va_start(args, n); long v0 = va_arg(args, long); long v1 = va_arg(args, long); long v2 = va_arg(args, long); long v3 = va_arg(args, long); va_end(args); if (n < 2 || n > 4) return errno = E2BIG, -1; if (n <= 2 && v2 != 0) return errno = EFAULT, -1; if (n <= 3 && v3 != 0) return errno = EFAULT, -1; if (v0 != v1) return errno = EINVAL, -1; if (n > 2 && v0 != v2) return errno = EINVAL, -1; if (n > 3 && v0 != v3) return errno = EINVAL, -1; return 0; } static void loop(); static int do_sandbox_none(void) { loop(); return 0; } static long syz_execute_func(volatile long text) { volatile long p[8] = {0}; (void)p; ((void (*)(void))(text))(); return 0; } 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 < 16; 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); event_timedwait(&th->done, 45); break; } } for (i = 0; i < 100 && __atomic_load_n(&running, __ATOMIC_RELAXED); i++) sleep_ms(1); } static void execute_one(void); #define WAIT_FLAGS 0 static void loop(void) { int iter; for (iter = 0;; iter++) { char cwdbuf[32]; sprintf(cwdbuf, "./%d", iter); if (mkdir(cwdbuf, 0777)) exit(1); int pid = fork(); if (pid < 0) exit(1); if (pid == 0) { if (chdir(cwdbuf)) exit(1); 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 < 5 * 1000) continue; kill_and_wait(pid, &status); break; } remove_dir(cwdbuf); } } void execute_call(int call) { switch (call) { case 0: syz_mmap(0x20ff6000, 0x4000); break; case 1: syz_mmap(0x20ffe000, 0x2000); break; case 2: syz_compare_int(4, 7, 0x7f, 0x71f, 6); break; case 3: syz_errno(4); break; case 4: syz_compare_int(2, 7, 0x80000001, 0, 0); break; case 5: syz_compare_int(4, 9, 6, 0x3ff, 0); break; case 6: syz_compare_int(3, 0, 5, 6, 0); break; case 7: syz_errno(0x80000000); break; case 8: syz_compare_int(2, 0x100000001, 8, 0, 0); break; case 9: syz_exit(0x200); break; case 10: memcpy((void*)0x20000000, "\000", 1); memcpy((void*)0x20000040, "\000", 1); syz_compare(0x20000000, 1, 0x20000040, 1); break; case 11: syz_compare_int(2, 4, 0, 0, 0); break; case 12: syz_errno(0x40); break; case 13: memcpy((void*)0x20000080, "\x34\x63\xee\xab\xc7\x55\xe7\xfd\xeb\xe7\x25\x21\xf6\x8b\x06\xb3\x6c\x8a\x66\xc3\x87\x9a\xfe\xc0\xd6\x60\x21\x64\xbe\x86\x7d\xa5\x64\xb6\x90\x68\x89\xaa\xf9\x33\x38\xe8\x17\x9e\xea\xa2\xeb\x98\xb1\xef", 50); syz_execute_func(0x20000080); break; case 14: syz_exit(0x101); break; case 15: syz_mmap(0x20ff2000, 0x8000); break; } } int main(void) { syz_mmap(0x20000000, 0x1000000); use_temporary_dir(); do_sandbox_none(); return 0; } /usr/local/bin/ld: cannot find -lasan collect2: error: ld returned 1 exit status compiler invocation: gcc [-o /tmp/syz-executor295648294 -DGOOS_test=1 -DGOARCH_64_fork=1 -DHOSTGOOS_freebsd=1 -x c - -O2 -pthread -Wall -Werror -Wparentheses -Wunused-const-variable -Wframe-larger-than=8192 -m64 -fsanitize=address] --- FAIL: TestGenerate/test/64_fork/28 (1.34s) csource_test.go:110: opts: {Threaded:true Collide:false Repeat:true RepeatTimes:0 Procs:0 Sandbox:none Fault:false FaultCall:0 FaultNth:0 Leak:false EnableTun:false EnableNetDev:false EnableNetReset:false EnableCgroups:false EnableBinfmtMisc:false EnableCloseFds:false UseTmpDir:true HandleSegv:false Repro:false Trace:false} program: syz_mmap(&(0x7f0000ff6000/0x4000)=nil, 0x4000) syz_mmap(&(0x7f0000ffe000/0x2000)=nil, 0x2000) syz_compare_int$4(0x4, 0x7, 0x7f, 0x71f, 0x6) syz_errno(0x4) syz_compare_int$2(0x2, 0x7, 0x80000001) syz_compare_int$4(0x4, 0x9, 0x6, 0x3ff, 0x0) syz_compare_int$3(0x3, 0x0, 0x5, 0x6) syz_errno(0xffffffff80000000) syz_compare_int$2(0x2, 0x100000001, 0x8) syz_exit(0x200) syz_compare(&(0x7f0000000000)='\x00', 0x1, &(0x7f0000000040)=@str='\x00', 0x1) syz_compare_int$2(0x2, 0x4, 0x0) syz_errno(0x40) syz_execute_func(&(0x7f0000000080)="3463eeabc755e7fdebe72521f68b06b36c8a66c3879afec0d6602164be867da564b6906889aaf93338e8179eeaa2eb98b1ef") syz_exit(0x101) syz_mmap(&(0x7f0000ff2000/0x8000)=nil, 0x8000) csource_test.go:111: failed to build program: // autogenerated by syzkaller (https://github.com/google/syzkaller) #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include static void kill_and_wait(int pid, int* status) { kill(pid, SIGKILL); while (waitpid(-1, status, 0) != pid) { } } 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 remove_dir(const char* dir) { DIR* dp; struct dirent* ep; dp = opendir(dir); if (dp == NULL) exit(1); 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)) exit(1); if (S_ISDIR(st.st_mode)) { remove_dir(filename); continue; } if (unlink(filename)) exit(1); } closedir(dp); if (rmdir(dir)) 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; for (i = 0; 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 { pthread_mutex_t mu; pthread_cond_t cv; int state; } event_t; static void event_init(event_t* ev) { if (pthread_mutex_init(&ev->mu, 0)) exit(1); if (pthread_cond_init(&ev->cv, 0)) exit(1); ev->state = 0; } static void event_reset(event_t* ev) { ev->state = 0; } static void event_set(event_t* ev) { pthread_mutex_lock(&ev->mu); if (ev->state) exit(1); ev->state = 1; pthread_mutex_unlock(&ev->mu); pthread_cond_broadcast(&ev->cv); } static void event_wait(event_t* ev) { pthread_mutex_lock(&ev->mu); while (!ev->state) pthread_cond_wait(&ev->cv, &ev->mu); pthread_mutex_unlock(&ev->mu); } static int event_isset(event_t* ev) { pthread_mutex_lock(&ev->mu); int res = ev->state; pthread_mutex_unlock(&ev->mu); return res; } static int event_timedwait(event_t* ev, uint64_t timeout) { uint64_t start = current_time_ms(); uint64_t now = start; pthread_mutex_lock(&ev->mu); for (;;) { if (ev->state) break; uint64_t remain = timeout - (now - start); struct timespec ts; ts.tv_sec = remain / 1000; ts.tv_nsec = (remain % 1000) * 1000 * 1000; pthread_cond_timedwait(&ev->cv, &ev->mu, &ts); now = current_time_ms(); if (now - start > timeout) break; } int res = ev->state; pthread_mutex_unlock(&ev->mu); return res; } static long syz_mmap(volatile long a0, volatile long a1) { return (long)mmap((void*)a0, a1, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE | MAP_FIXED, -1, 0); } static long syz_errno(volatile long v) { errno = v; return v == 0 ? 0 : -1; } static long syz_exit(volatile long status) { _exit(status); return 0; } static long syz_compare(volatile long want, volatile long want_len, volatile long got, volatile long got_len) { if (want_len != got_len) { errno = EBADF; return -1; } if (memcmp((void*)want, (void*)got, want_len)) { errno = EINVAL; return -1; } return 0; } static long syz_compare_int(volatile long n, ...) { va_list args; va_start(args, n); long v0 = va_arg(args, long); long v1 = va_arg(args, long); long v2 = va_arg(args, long); long v3 = va_arg(args, long); va_end(args); if (n < 2 || n > 4) return errno = E2BIG, -1; if (n <= 2 && v2 != 0) return errno = EFAULT, -1; if (n <= 3 && v3 != 0) return errno = EFAULT, -1; if (v0 != v1) return errno = EINVAL, -1; if (n > 2 && v0 != v2) return errno = EINVAL, -1; if (n > 3 && v0 != v3) return errno = EINVAL, -1; return 0; } static void loop(); static int do_sandbox_none(void) { loop(); return 0; } static long syz_execute_func(volatile long text) { volatile long p[8] = {0}; (void)p; ((void (*)(void))(text))(); return 0; } 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 < 16; 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); event_timedwait(&th->done, 45); break; } } for (i = 0; i < 100 && __atomic_load_n(&running, __ATOMIC_RELAXED); i++) sleep_ms(1); } static void execute_one(void); #define WAIT_FLAGS 0 static void loop(void) { int iter; for (iter = 0;; iter++) { char cwdbuf[32]; sprintf(cwdbuf, "./%d", iter); if (mkdir(cwdbuf, 0777)) exit(1); int pid = fork(); if (pid < 0) exit(1); if (pid == 0) { if (chdir(cwdbuf)) exit(1); 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 < 5 * 1000) continue; kill_and_wait(pid, &status); break; } remove_dir(cwdbuf); } } void execute_call(int call) { switch (call) { case 0: syz_mmap(0x20ff6000, 0x4000); break; case 1: syz_mmap(0x20ffe000, 0x2000); break; case 2: syz_compare_int(4, 7, 0x7f, 0x71f, 6); break; case 3: syz_errno(4); break; case 4: syz_compare_int(2, 7, 0x80000001, 0, 0); break; case 5: syz_compare_int(4, 9, 6, 0x3ff, 0); break; case 6: syz_compare_int(3, 0, 5, 6, 0); break; case 7: syz_errno(0x80000000); break; case 8: syz_compare_int(2, 0x100000001, 8, 0, 0); break; case 9: syz_exit(0x200); break; case 10: memcpy((void*)0x20000000, "\000", 1); memcpy((void*)0x20000040, "\000", 1); syz_compare(0x20000000, 1, 0x20000040, 1); break; case 11: syz_compare_int(2, 4, 0, 0, 0); break; case 12: syz_errno(0x40); break; case 13: memcpy((void*)0x20000080, "\x34\x63\xee\xab\xc7\x55\xe7\xfd\xeb\xe7\x25\x21\xf6\x8b\x06\xb3\x6c\x8a\x66\xc3\x87\x9a\xfe\xc0\xd6\x60\x21\x64\xbe\x86\x7d\xa5\x64\xb6\x90\x68\x89\xaa\xf9\x33\x38\xe8\x17\x9e\xea\xa2\xeb\x98\xb1\xef", 50); syz_execute_func(0x20000080); break; case 14: syz_exit(0x101); break; case 15: syz_mmap(0x20ff2000, 0x8000); break; } } int main(void) { syz_mmap(0x20000000, 0x1000000); use_temporary_dir(); do_sandbox_none(); return 0; } /usr/local/bin/ld: cannot find -lasan collect2: error: ld returned 1 exit status compiler invocation: gcc [-o /tmp/syz-executor446798087 -DGOOS_test=1 -DGOARCH_64_fork=1 -DHOSTGOOS_freebsd=1 -x c - -O2 -pthread -Wall -Werror -Wparentheses -Wunused-const-variable -Wframe-larger-than=8192 -m64 -fsanitize=address] --- FAIL: TestGenerate/test/64_fork/17 (1.07s) csource_test.go:110: opts: {Threaded:true Collide:false Repeat:true RepeatTimes:0 Procs:0 Sandbox:none Fault:false FaultCall:0 FaultNth:0 Leak:false EnableTun:false EnableNetDev:false EnableNetReset:false EnableCgroups:false EnableBinfmtMisc:false EnableCloseFds:false UseTmpDir:true HandleSegv:false Repro:false Trace:false} program: syz_mmap(&(0x7f0000ff6000/0x4000)=nil, 0x4000) syz_mmap(&(0x7f0000ffe000/0x2000)=nil, 0x2000) syz_compare_int$4(0x4, 0x7, 0x7f, 0x71f, 0x6) syz_errno(0x4) syz_compare_int$2(0x2, 0x7, 0x80000001) syz_compare_int$4(0x4, 0x9, 0x6, 0x3ff, 0x0) syz_compare_int$3(0x3, 0x0, 0x5, 0x6) syz_errno(0xffffffff80000000) syz_compare_int$2(0x2, 0x100000001, 0x8) syz_exit(0x200) syz_compare(&(0x7f0000000000)='\x00', 0x1, &(0x7f0000000040)=@str='\x00', 0x1) syz_compare_int$2(0x2, 0x4, 0x0) syz_errno(0x40) syz_execute_func(&(0x7f0000000080)="3463eeabc755e7fdebe72521f68b06b36c8a66c3879afec0d6602164be867da564b6906889aaf93338e8179eeaa2eb98b1ef") syz_exit(0x101) syz_mmap(&(0x7f0000ff2000/0x8000)=nil, 0x8000) csource_test.go:111: failed to build program: // autogenerated by syzkaller (https://github.com/google/syzkaller) #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include static void kill_and_wait(int pid, int* status) { kill(pid, SIGKILL); while (waitpid(-1, status, 0) != pid) { } } 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 remove_dir(const char* dir) { DIR* dp; struct dirent* ep; dp = opendir(dir); if (dp == NULL) exit(1); 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)) exit(1); if (S_ISDIR(st.st_mode)) { remove_dir(filename); continue; } if (unlink(filename)) exit(1); } closedir(dp); if (rmdir(dir)) 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; for (i = 0; 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 { pthread_mutex_t mu; pthread_cond_t cv; int state; } event_t; static void event_init(event_t* ev) { if (pthread_mutex_init(&ev->mu, 0)) exit(1); if (pthread_cond_init(&ev->cv, 0)) exit(1); ev->state = 0; } static void event_reset(event_t* ev) { ev->state = 0; } static void event_set(event_t* ev) { pthread_mutex_lock(&ev->mu); if (ev->state) exit(1); ev->state = 1; pthread_mutex_unlock(&ev->mu); pthread_cond_broadcast(&ev->cv); } static void event_wait(event_t* ev) { pthread_mutex_lock(&ev->mu); while (!ev->state) pthread_cond_wait(&ev->cv, &ev->mu); pthread_mutex_unlock(&ev->mu); } static int event_isset(event_t* ev) { pthread_mutex_lock(&ev->mu); int res = ev->state; pthread_mutex_unlock(&ev->mu); return res; } static int event_timedwait(event_t* ev, uint64_t timeout) { uint64_t start = current_time_ms(); uint64_t now = start; pthread_mutex_lock(&ev->mu); for (;;) { if (ev->state) break; uint64_t remain = timeout - (now - start); struct timespec ts; ts.tv_sec = remain / 1000; ts.tv_nsec = (remain % 1000) * 1000 * 1000; pthread_cond_timedwait(&ev->cv, &ev->mu, &ts); now = current_time_ms(); if (now - start > timeout) break; } int res = ev->state; pthread_mutex_unlock(&ev->mu); return res; } static long syz_mmap(volatile long a0, volatile long a1) { return (long)mmap((void*)a0, a1, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE | MAP_FIXED, -1, 0); } static long syz_errno(volatile long v) { errno = v; return v == 0 ? 0 : -1; } static long syz_exit(volatile long status) { _exit(status); return 0; } static long syz_compare(volatile long want, volatile long want_len, volatile long got, volatile long got_len) { if (want_len != got_len) { errno = EBADF; return -1; } if (memcmp((void*)want, (void*)got, want_len)) { errno = EINVAL; return -1; } return 0; } static long syz_compare_int(volatile long n, ...) { va_list args; va_start(args, n); long v0 = va_arg(args, long); long v1 = va_arg(args, long); long v2 = va_arg(args, long); long v3 = va_arg(args, long); va_end(args); if (n < 2 || n > 4) return errno = E2BIG, -1; if (n <= 2 && v2 != 0) return errno = EFAULT, -1; if (n <= 3 && v3 != 0) return errno = EFAULT, -1; if (v0 != v1) return errno = EINVAL, -1; if (n > 2 && v0 != v2) return errno = EINVAL, -1; if (n > 3 && v0 != v3) return errno = EINVAL, -1; return 0; } static void loop(); static int do_sandbox_none(void) { loop(); return 0; } static long syz_execute_func(volatile long text) { volatile long p[8] = {0}; (void)p; ((void (*)(void))(text))(); return 0; } 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 < 16; 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); event_timedwait(&th->done, 45); break; } } for (i = 0; i < 100 && __atomic_load_n(&running, __ATOMIC_RELAXED); i++) sleep_ms(1); } static void execute_one(void); #define WAIT_FLAGS 0 static void loop(void) { int iter; for (iter = 0;; iter++) { char cwdbuf[32]; sprintf(cwdbuf, "./%d", iter); if (mkdir(cwdbuf, 0777)) exit(1); int pid = fork(); if (pid < 0) exit(1); if (pid == 0) { if (chdir(cwdbuf)) exit(1); 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 < 5 * 1000) continue; kill_and_wait(pid, &status); break; } remove_dir(cwdbuf); } } void execute_call(int call) { switch (call) { case 0: syz_mmap(0x20ff6000, 0x4000); break; case 1: syz_mmap(0x20ffe000, 0x2000); break; case 2: syz_compare_int(4, 7, 0x7f, 0x71f, 6); break; case 3: syz_errno(4); break; case 4: syz_compare_int(2, 7, 0x80000001, 0, 0); break; case 5: syz_compare_int(4, 9, 6, 0x3ff, 0); break; case 6: syz_compare_int(3, 0, 5, 6, 0); break; case 7: syz_errno(0x80000000); break; case 8: syz_compare_int(2, 0x100000001, 8, 0, 0); break; case 9: syz_exit(0x200); break; case 10: memcpy((void*)0x20000000, "\000", 1); memcpy((void*)0x20000040, "\000", 1); syz_compare(0x20000000, 1, 0x20000040, 1); break; case 11: syz_compare_int(2, 4, 0, 0, 0); break; case 12: syz_errno(0x40); break; case 13: memcpy((void*)0x20000080, "\x34\x63\xee\xab\xc7\x55\xe7\xfd\xeb\xe7\x25\x21\xf6\x8b\x06\xb3\x6c\x8a\x66\xc3\x87\x9a\xfe\xc0\xd6\x60\x21\x64\xbe\x86\x7d\xa5\x64\xb6\x90\x68\x89\xaa\xf9\x33\x38\xe8\x17\x9e\xea\xa2\xeb\x98\xb1\xef", 50); syz_execute_func(0x20000080); break; case 14: syz_exit(0x101); break; case 15: syz_mmap(0x20ff2000, 0x8000); break; } } int main(void) { syz_mmap(0x20000000, 0x1000000); use_temporary_dir(); do_sandbox_none(); return 0; } /usr/local/bin/ld: cannot find -lasan collect2: error: ld returned 1 exit status compiler invocation: gcc [-o /tmp/syz-executor947594426 -DGOOS_test=1 -DGOARCH_64_fork=1 -DHOSTGOOS_freebsd=1 -x c - -O2 -pthread -Wall -Werror -Wparentheses -Wunused-const-variable -Wframe-larger-than=8192 -m64 -fsanitize=address] --- FAIL: TestGenerate/test/64_fork/27 (1.34s) csource_test.go:110: opts: {Threaded:true Collide:false Repeat:true RepeatTimes:0 Procs:0 Sandbox:none Fault:false FaultCall:0 FaultNth:0 Leak:false EnableTun:false EnableNetDev:false EnableNetReset:false EnableCgroups:false EnableBinfmtMisc:false EnableCloseFds:false UseTmpDir:true HandleSegv:false Repro:true Trace:false} program: syz_mmap(&(0x7f0000ff6000/0x4000)=nil, 0x4000) syz_mmap(&(0x7f0000ffe000/0x2000)=nil, 0x2000) syz_compare_int$4(0x4, 0x7, 0x7f, 0x71f, 0x6) syz_errno(0x4) syz_compare_int$2(0x2, 0x7, 0x80000001) syz_compare_int$4(0x4, 0x9, 0x6, 0x3ff, 0x0) syz_compare_int$3(0x3, 0x0, 0x5, 0x6) syz_errno(0xffffffff80000000) syz_compare_int$2(0x2, 0x100000001, 0x8) syz_exit(0x200) syz_compare(&(0x7f0000000000)='\x00', 0x1, &(0x7f0000000040)=@str='\x00', 0x1) syz_compare_int$2(0x2, 0x4, 0x0) syz_errno(0x40) syz_execute_func(&(0x7f0000000080)="3463eeabc755e7fdebe72521f68b06b36c8a66c3879afec0d6602164be867da564b6906889aaf93338e8179eeaa2eb98b1ef") syz_exit(0x101) syz_mmap(&(0x7f0000ff2000/0x8000)=nil, 0x8000) csource_test.go:111: failed to build program: // autogenerated by syzkaller (https://github.com/google/syzkaller) #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include static void kill_and_wait(int pid, int* status) { kill(pid, SIGKILL); while (waitpid(-1, status, 0) != pid) { } } 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 remove_dir(const char* dir) { DIR* dp; struct dirent* ep; dp = opendir(dir); if (dp == NULL) exit(1); 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)) exit(1); if (S_ISDIR(st.st_mode)) { remove_dir(filename); continue; } if (unlink(filename)) exit(1); } closedir(dp); if (rmdir(dir)) 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; for (i = 0; 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 { pthread_mutex_t mu; pthread_cond_t cv; int state; } event_t; static void event_init(event_t* ev) { if (pthread_mutex_init(&ev->mu, 0)) exit(1); if (pthread_cond_init(&ev->cv, 0)) exit(1); ev->state = 0; } static void event_reset(event_t* ev) { ev->state = 0; } static void event_set(event_t* ev) { pthread_mutex_lock(&ev->mu); if (ev->state) exit(1); ev->state = 1; pthread_mutex_unlock(&ev->mu); pthread_cond_broadcast(&ev->cv); } static void event_wait(event_t* ev) { pthread_mutex_lock(&ev->mu); while (!ev->state) pthread_cond_wait(&ev->cv, &ev->mu); pthread_mutex_unlock(&ev->mu); } static int event_isset(event_t* ev) { pthread_mutex_lock(&ev->mu); int res = ev->state; pthread_mutex_unlock(&ev->mu); return res; } static int event_timedwait(event_t* ev, uint64_t timeout) { uint64_t start = current_time_ms(); uint64_t now = start; pthread_mutex_lock(&ev->mu); for (;;) { if (ev->state) break; uint64_t remain = timeout - (now - start); struct timespec ts; ts.tv_sec = remain / 1000; ts.tv_nsec = (remain % 1000) * 1000 * 1000; pthread_cond_timedwait(&ev->cv, &ev->mu, &ts); now = current_time_ms(); if (now - start > timeout) break; } int res = ev->state; pthread_mutex_unlock(&ev->mu); return res; } static long syz_mmap(volatile long a0, volatile long a1) { return (long)mmap((void*)a0, a1, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE | MAP_FIXED, -1, 0); } static long syz_errno(volatile long v) { errno = v; return v == 0 ? 0 : -1; } static long syz_exit(volatile long status) { _exit(status); return 0; } static long syz_compare(volatile long want, volatile long want_len, volatile long got, volatile long got_len) { if (want_len != got_len) { errno = EBADF; return -1; } if (memcmp((void*)want, (void*)got, want_len)) { errno = EINVAL; return -1; } return 0; } static long syz_compare_int(volatile long n, ...) { va_list args; va_start(args, n); long v0 = va_arg(args, long); long v1 = va_arg(args, long); long v2 = va_arg(args, long); long v3 = va_arg(args, long); va_end(args); if (n < 2 || n > 4) return errno = E2BIG, -1; if (n <= 2 && v2 != 0) return errno = EFAULT, -1; if (n <= 3 && v3 != 0) return errno = EFAULT, -1; if (v0 != v1) return errno = EINVAL, -1; if (n > 2 && v0 != v2) return errno = EINVAL, -1; if (n > 3 && v0 != v3) return errno = EINVAL, -1; return 0; } static void loop(); static int do_sandbox_none(void) { loop(); return 0; } static long syz_execute_func(volatile long text) { volatile long p[8] = {0}; (void)p; ((void (*)(void))(text))(); return 0; } 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) { if (write(1, "executing program\n", sizeof("executing program\n") - 1)) { } int i, call, thread; for (call = 0; call < 16; 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); event_timedwait(&th->done, 45); break; } } for (i = 0; i < 100 && __atomic_load_n(&running, __ATOMIC_RELAXED); i++) sleep_ms(1); } static void execute_one(void); #define WAIT_FLAGS 0 static void loop(void) { int iter; for (iter = 0;; iter++) { char cwdbuf[32]; sprintf(cwdbuf, "./%d", iter); if (mkdir(cwdbuf, 0777)) exit(1); int pid = fork(); if (pid < 0) exit(1); if (pid == 0) { if (chdir(cwdbuf)) exit(1); 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 < 5 * 1000) continue; kill_and_wait(pid, &status); break; } remove_dir(cwdbuf); } } void execute_call(int call) { switch (call) { case 0: syz_mmap(0x20ff6000, 0x4000); break; case 1: syz_mmap(0x20ffe000, 0x2000); break; case 2: syz_compare_int(4, 7, 0x7f, 0x71f, 6); break; case 3: syz_errno(4); break; case 4: syz_compare_int(2, 7, 0x80000001, 0, 0); break; case 5: syz_compare_int(4, 9, 6, 0x3ff, 0); break; case 6: syz_compare_int(3, 0, 5, 6, 0); break; case 7: syz_errno(0x80000000); break; case 8: syz_compare_int(2, 0x100000001, 8, 0, 0); break; case 9: syz_exit(0x200); break; case 10: memcpy((void*)0x20000000, "\000", 1); memcpy((void*)0x20000040, "\000", 1); syz_compare(0x20000000, 1, 0x20000040, 1); break; case 11: syz_compare_int(2, 4, 0, 0, 0); break; case 12: syz_errno(0x40); break; case 13: memcpy((void*)0x20000080, "\x34\x63\xee\xab\xc7\x55\xe7\xfd\xeb\xe7\x25\x21\xf6\x8b\x06\xb3\x6c\x8a\x66\xc3\x87\x9a\xfe\xc0\xd6\x60\x21\x64\xbe\x86\x7d\xa5\x64\xb6\x90\x68\x89\xaa\xf9\x33\x38\xe8\x17\x9e\xea\xa2\xeb\x98\xb1\xef", 50); syz_execute_func(0x20000080); break; case 14: syz_exit(0x101); break; case 15: syz_mmap(0x20ff2000, 0x8000); break; } } int main(void) { syz_mmap(0x20000000, 0x1000000); use_temporary_dir(); do_sandbox_none(); return 0; } /usr/local/bin/ld: cannot find -lasan collect2: error: ld returned 1 exit status compiler invocation: gcc [-o /tmp/syz-executor159691473 -DGOOS_test=1 -DGOARCH_64_fork=1 -DHOSTGOOS_freebsd=1 -x c - -O2 -pthread -Wall -Werror -Wparentheses -Wunused-const-variable -Wframe-larger-than=8192 -m64 -fsanitize=address] --- FAIL: TestGenerate/test/64_fork/21 (1.27s) csource_test.go:110: opts: {Threaded:true Collide:false Repeat:true RepeatTimes:0 Procs:0 Sandbox:none Fault:false FaultCall:0 FaultNth:0 Leak:false EnableTun:false EnableNetDev:false EnableNetReset:false EnableCgroups:false EnableBinfmtMisc:false EnableCloseFds:false UseTmpDir:true HandleSegv:false Repro:false Trace:false} program: syz_mmap(&(0x7f0000ff6000/0x4000)=nil, 0x4000) syz_mmap(&(0x7f0000ffe000/0x2000)=nil, 0x2000) syz_compare_int$4(0x4, 0x7, 0x7f, 0x71f, 0x6) syz_errno(0x4) syz_compare_int$2(0x2, 0x7, 0x80000001) syz_compare_int$4(0x4, 0x9, 0x6, 0x3ff, 0x0) syz_compare_int$3(0x3, 0x0, 0x5, 0x6) syz_errno(0xffffffff80000000) syz_compare_int$2(0x2, 0x100000001, 0x8) syz_exit(0x200) syz_compare(&(0x7f0000000000)='\x00', 0x1, &(0x7f0000000040)=@str='\x00', 0x1) syz_compare_int$2(0x2, 0x4, 0x0) syz_errno(0x40) syz_execute_func(&(0x7f0000000080)="3463eeabc755e7fdebe72521f68b06b36c8a66c3879afec0d6602164be867da564b6906889aaf93338e8179eeaa2eb98b1ef") syz_exit(0x101) syz_mmap(&(0x7f0000ff2000/0x8000)=nil, 0x8000) csource_test.go:111: failed to build program: // autogenerated by syzkaller (https://github.com/google/syzkaller) #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include static void kill_and_wait(int pid, int* status) { kill(pid, SIGKILL); while (waitpid(-1, status, 0) != pid) { } } 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 remove_dir(const char* dir) { DIR* dp; struct dirent* ep; dp = opendir(dir); if (dp == NULL) exit(1); 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)) exit(1); if (S_ISDIR(st.st_mode)) { remove_dir(filename); continue; } if (unlink(filename)) exit(1); } closedir(dp); if (rmdir(dir)) 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; for (i = 0; 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 { pthread_mutex_t mu; pthread_cond_t cv; int state; } event_t; static void event_init(event_t* ev) { if (pthread_mutex_init(&ev->mu, 0)) exit(1); if (pthread_cond_init(&ev->cv, 0)) exit(1); ev->state = 0; } static void event_reset(event_t* ev) { ev->state = 0; } static void event_set(event_t* ev) { pthread_mutex_lock(&ev->mu); if (ev->state) exit(1); ev->state = 1; pthread_mutex_unlock(&ev->mu); pthread_cond_broadcast(&ev->cv); } static void event_wait(event_t* ev) { pthread_mutex_lock(&ev->mu); while (!ev->state) pthread_cond_wait(&ev->cv, &ev->mu); pthread_mutex_unlock(&ev->mu); } static int event_isset(event_t* ev) { pthread_mutex_lock(&ev->mu); int res = ev->state; pthread_mutex_unlock(&ev->mu); return res; } static int event_timedwait(event_t* ev, uint64_t timeout) { uint64_t start = current_time_ms(); uint64_t now = start; pthread_mutex_lock(&ev->mu); for (;;) { if (ev->state) break; uint64_t remain = timeout - (now - start); struct timespec ts; ts.tv_sec = remain / 1000; ts.tv_nsec = (remain % 1000) * 1000 * 1000; pthread_cond_timedwait(&ev->cv, &ev->mu, &ts); now = current_time_ms(); if (now - start > timeout) break; } int res = ev->state; pthread_mutex_unlock(&ev->mu); return res; } static long syz_mmap(volatile long a0, volatile long a1) { return (long)mmap((void*)a0, a1, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE | MAP_FIXED, -1, 0); } static long syz_errno(volatile long v) { errno = v; return v == 0 ? 0 : -1; } static long syz_exit(volatile long status) { _exit(status); return 0; } static long syz_compare(volatile long want, volatile long want_len, volatile long got, volatile long got_len) { if (want_len != got_len) { errno = EBADF; return -1; } if (memcmp((void*)want, (void*)got, want_len)) { errno = EINVAL; return -1; } return 0; } static long syz_compare_int(volatile long n, ...) { va_list args; va_start(args, n); long v0 = va_arg(args, long); long v1 = va_arg(args, long); long v2 = va_arg(args, long); long v3 = va_arg(args, long); va_end(args); if (n < 2 || n > 4) return errno = E2BIG, -1; if (n <= 2 && v2 != 0) return errno = EFAULT, -1; if (n <= 3 && v3 != 0) return errno = EFAULT, -1; if (v0 != v1) return errno = EINVAL, -1; if (n > 2 && v0 != v2) return errno = EINVAL, -1; if (n > 3 && v0 != v3) return errno = EINVAL, -1; return 0; } static void loop(); static int do_sandbox_none(void) { loop(); return 0; } static long syz_execute_func(volatile long text) { volatile long p[8] = {0}; (void)p; ((void (*)(void))(text))(); return 0; } 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 < 16; 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); event_timedwait(&th->done, 45); break; } } for (i = 0; i < 100 && __atomic_load_n(&running, __ATOMIC_RELAXED); i++) sleep_ms(1); } static void execute_one(void); #define WAIT_FLAGS 0 static void loop(void) { int iter; for (iter = 0;; iter++) { char cwdbuf[32]; sprintf(cwdbuf, "./%d", iter); if (mkdir(cwdbuf, 0777)) exit(1); int pid = fork(); if (pid < 0) exit(1); if (pid == 0) { if (chdir(cwdbuf)) exit(1); 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 < 5 * 1000) continue; kill_and_wait(pid, &status); break; } remove_dir(cwdbuf); } } void execute_call(int call) { switch (call) { case 0: syz_mmap(0x20ff6000, 0x4000); break; case 1: syz_mmap(0x20ffe000, 0x2000); break; case 2: syz_compare_int(4, 7, 0x7f, 0x71f, 6); break; case 3: syz_errno(4); break; case 4: syz_compare_int(2, 7, 0x80000001, 0, 0); break; case 5: syz_compare_int(4, 9, 6, 0x3ff, 0); break; case 6: syz_compare_int(3, 0, 5, 6, 0); break; case 7: syz_errno(0x80000000); break; case 8: syz_compare_int(2, 0x100000001, 8, 0, 0); break; case 9: syz_exit(0x200); break; case 10: memcpy((void*)0x20000000, "\000", 1); memcpy((void*)0x20000040, "\000", 1); syz_compare(0x20000000, 1, 0x20000040, 1); break; case 11: syz_compare_int(2, 4, 0, 0, 0); break; case 12: syz_errno(0x40); break; case 13: memcpy((void*)0x20000080, "\x34\x63\xee\xab\xc7\x55\xe7\xfd\xeb\xe7\x25\x21\xf6\x8b\x06\xb3\x6c\x8a\x66\xc3\x87\x9a\xfe\xc0\xd6\x60\x21\x64\xbe\x86\x7d\xa5\x64\xb6\x90\x68\x89\xaa\xf9\x33\x38\xe8\x17\x9e\xea\xa2\xeb\x98\xb1\xef", 50); syz_execute_func(0x20000080); break; case 14: syz_exit(0x101); break; case 15: syz_mmap(0x20ff2000, 0x8000); break; } } int main(void) { syz_mmap(0x20000000, 0x1000000); use_temporary_dir(); do_sandbox_none(); return 0; } /usr/local/bin/ld: cannot find -lasan collect2: error: ld returned 1 exit status compiler invocation: gcc [-o /tmp/syz-executor232017404 -DGOOS_test=1 -DGOARCH_64_fork=1 -DHOSTGOOS_freebsd=1 -x c - -O2 -pthread -Wall -Werror -Wparentheses -Wunused-const-variable -Wframe-larger-than=8192 -m64 -fsanitize=address] --- FAIL: TestGenerate/test/64_fork/1 (0.77s) csource_test.go:110: opts: {Threaded:true Collide:false Repeat:true RepeatTimes:0 Procs:0 Sandbox:none Fault:false FaultCall:0 FaultNth:0 Leak:false EnableTun:false EnableNetDev:false EnableNetReset:false EnableCgroups:false EnableBinfmtMisc:false EnableCloseFds:false UseTmpDir:true HandleSegv:false Repro:false Trace:false} program: syz_mmap(&(0x7f0000ff6000/0x4000)=nil, 0x4000) syz_mmap(&(0x7f0000ffe000/0x2000)=nil, 0x2000) syz_compare_int$4(0x4, 0x7, 0x7f, 0x71f, 0x6) syz_errno(0x4) syz_compare_int$2(0x2, 0x7, 0x80000001) syz_compare_int$4(0x4, 0x9, 0x6, 0x3ff, 0x0) syz_compare_int$3(0x3, 0x0, 0x5, 0x6) syz_errno(0xffffffff80000000) syz_compare_int$2(0x2, 0x100000001, 0x8) syz_exit(0x200) syz_compare(&(0x7f0000000000)='\x00', 0x1, &(0x7f0000000040)=@str='\x00', 0x1) syz_compare_int$2(0x2, 0x4, 0x0) syz_errno(0x40) syz_execute_func(&(0x7f0000000080)="3463eeabc755e7fdebe72521f68b06b36c8a66c3879afec0d6602164be867da564b6906889aaf93338e8179eeaa2eb98b1ef") syz_exit(0x101) syz_mmap(&(0x7f0000ff2000/0x8000)=nil, 0x8000) csource_test.go:111: failed to build program: // autogenerated by syzkaller (https://github.com/google/syzkaller) #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include static void kill_and_wait(int pid, int* status) { kill(pid, SIGKILL); while (waitpid(-1, status, 0) != pid) { } } 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 remove_dir(const char* dir) { DIR* dp; struct dirent* ep; dp = opendir(dir); if (dp == NULL) exit(1); 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)) exit(1); if (S_ISDIR(st.st_mode)) { remove_dir(filename); continue; } if (unlink(filename)) exit(1); } closedir(dp); if (rmdir(dir)) 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; for (i = 0; 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 { pthread_mutex_t mu; pthread_cond_t cv; int state; } event_t; static void event_init(event_t* ev) { if (pthread_mutex_init(&ev->mu, 0)) exit(1); if (pthread_cond_init(&ev->cv, 0)) exit(1); ev->state = 0; } static void event_reset(event_t* ev) { ev->state = 0; } static void event_set(event_t* ev) { pthread_mutex_lock(&ev->mu); if (ev->state) exit(1); ev->state = 1; pthread_mutex_unlock(&ev->mu); pthread_cond_broadcast(&ev->cv); } static void event_wait(event_t* ev) { pthread_mutex_lock(&ev->mu); while (!ev->state) pthread_cond_wait(&ev->cv, &ev->mu); pthread_mutex_unlock(&ev->mu); } static int event_isset(event_t* ev) { pthread_mutex_lock(&ev->mu); int res = ev->state; pthread_mutex_unlock(&ev->mu); return res; } static int event_timedwait(event_t* ev, uint64_t timeout) { uint64_t start = current_time_ms(); uint64_t now = start; pthread_mutex_lock(&ev->mu); for (;;) { if (ev->state) break; uint64_t remain = timeout - (now - start); struct timespec ts; ts.tv_sec = remain / 1000; ts.tv_nsec = (remain % 1000) * 1000 * 1000; pthread_cond_timedwait(&ev->cv, &ev->mu, &ts); now = current_time_ms(); if (now - start > timeout) break; } int res = ev->state; pthread_mutex_unlock(&ev->mu); return res; } static long syz_mmap(volatile long a0, volatile long a1) { return (long)mmap((void*)a0, a1, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE | MAP_FIXED, -1, 0); } static long syz_errno(volatile long v) { errno = v; return v == 0 ? 0 : -1; } static long syz_exit(volatile long status) { _exit(status); return 0; } static long syz_compare(volatile long want, volatile long want_len, volatile long got, volatile long got_len) { if (want_len != got_len) { errno = EBADF; return -1; } if (memcmp((void*)want, (void*)got, want_len)) { errno = EINVAL; return -1; } return 0; } static long syz_compare_int(volatile long n, ...) { va_list args; va_start(args, n); long v0 = va_arg(args, long); long v1 = va_arg(args, long); long v2 = va_arg(args, long); long v3 = va_arg(args, long); va_end(args); if (n < 2 || n > 4) return errno = E2BIG, -1; if (n <= 2 && v2 != 0) return errno = EFAULT, -1; if (n <= 3 && v3 != 0) return errno = EFAULT, -1; if (v0 != v1) return errno = EINVAL, -1; if (n > 2 && v0 != v2) return errno = EINVAL, -1; if (n > 3 && v0 != v3) return errno = EINVAL, -1; return 0; } static void loop(); static int do_sandbox_none(void) { loop(); return 0; } static long syz_execute_func(volatile long text) { volatile long p[8] = {0}; (void)p; ((void (*)(void))(text))(); return 0; } 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 < 16; 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); event_timedwait(&th->done, 45); break; } } for (i = 0; i < 100 && __atomic_load_n(&running, __ATOMIC_RELAXED); i++) sleep_ms(1); } static void execute_one(void); #define WAIT_FLAGS 0 static void loop(void) { int iter; for (iter = 0;; iter++) { char cwdbuf[32]; sprintf(cwdbuf, "./%d", iter); if (mkdir(cwdbuf, 0777)) exit(1); int pid = fork(); if (pid < 0) exit(1); if (pid == 0) { if (chdir(cwdbuf)) exit(1); 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 < 5 * 1000) continue; kill_and_wait(pid, &status); break; } remove_dir(cwdbuf); } } void execute_call(int call) { switch (call) { case 0: syz_mmap(0x20ff6000, 0x4000); break; case 1: syz_mmap(0x20ffe000, 0x2000); break; case 2: syz_compare_int(4, 7, 0x7f, 0x71f, 6); break; case 3: syz_errno(4); break; case 4: syz_compare_int(2, 7, 0x80000001, 0, 0); break; case 5: syz_compare_int(4, 9, 6, 0x3ff, 0); break; case 6: syz_compare_int(3, 0, 5, 6, 0); break; case 7: syz_errno(0x80000000); break; case 8: syz_compare_int(2, 0x100000001, 8, 0, 0); break; case 9: syz_exit(0x200); break; case 10: memcpy((void*)0x20000000, "\000", 1); memcpy((void*)0x20000040, "\000", 1); syz_compare(0x20000000, 1, 0x20000040, 1); break; case 11: syz_compare_int(2, 4, 0, 0, 0); break; case 12: syz_errno(0x40); break; case 13: memcpy((void*)0x20000080, "\x34\x63\xee\xab\xc7\x55\xe7\xfd\xeb\xe7\x25\x21\xf6\x8b\x06\xb3\x6c\x8a\x66\xc3\x87\x9a\xfe\xc0\xd6\x60\x21\x64\xbe\x86\x7d\xa5\x64\xb6\x90\x68\x89\xaa\xf9\x33\x38\xe8\x17\x9e\xea\xa2\xeb\x98\xb1\xef", 50); syz_execute_func(0x20000080); break; case 14: syz_exit(0x101); break; case 15: syz_mmap(0x20ff2000, 0x8000); break; } } int main(void) { syz_mmap(0x20000000, 0x1000000); use_temporary_dir(); do_sandbox_none(); return 0; } /usr/local/bin/ld: cannot find -lasan collect2: error: ld returned 1 exit status compiler invocation: gcc [-o /tmp/syz-executor619008299 -DGOOS_test=1 -DGOARCH_64_fork=1 -DHOSTGOOS_freebsd=1 -x c - -O2 -pthread -Wall -Werror -Wparentheses -Wunused-const-variable -Wframe-larger-than=8192 -m64 -fsanitize=address] --- FAIL: TestGenerate/test/64_fork/18 (1.09s) csource_test.go:110: opts: {Threaded:true Collide:false Repeat:true RepeatTimes:0 Procs:0 Sandbox:none Fault:false FaultCall:0 FaultNth:0 Leak:false EnableTun:false EnableNetDev:false EnableNetReset:false EnableCgroups:false EnableBinfmtMisc:false EnableCloseFds:false UseTmpDir:true HandleSegv:false Repro:false Trace:false} program: syz_mmap(&(0x7f0000ff6000/0x4000)=nil, 0x4000) syz_mmap(&(0x7f0000ffe000/0x2000)=nil, 0x2000) syz_compare_int$4(0x4, 0x7, 0x7f, 0x71f, 0x6) syz_errno(0x4) syz_compare_int$2(0x2, 0x7, 0x80000001) syz_compare_int$4(0x4, 0x9, 0x6, 0x3ff, 0x0) syz_compare_int$3(0x3, 0x0, 0x5, 0x6) syz_errno(0xffffffff80000000) syz_compare_int$2(0x2, 0x100000001, 0x8) syz_exit(0x200) syz_compare(&(0x7f0000000000)='\x00', 0x1, &(0x7f0000000040)=@str='\x00', 0x1) syz_compare_int$2(0x2, 0x4, 0x0) syz_errno(0x40) syz_execute_func(&(0x7f0000000080)="3463eeabc755e7fdebe72521f68b06b36c8a66c3879afec0d6602164be867da564b6906889aaf93338e8179eeaa2eb98b1ef") syz_exit(0x101) syz_mmap(&(0x7f0000ff2000/0x8000)=nil, 0x8000) csource_test.go:111: failed to build program: // autogenerated by syzkaller (https://github.com/google/syzkaller) #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include static void kill_and_wait(int pid, int* status) { kill(pid, SIGKILL); while (waitpid(-1, status, 0) != pid) { } } 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 remove_dir(const char* dir) { DIR* dp; struct dirent* ep; dp = opendir(dir); if (dp == NULL) exit(1); 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)) exit(1); if (S_ISDIR(st.st_mode)) { remove_dir(filename); continue; } if (unlink(filename)) exit(1); } closedir(dp); if (rmdir(dir)) 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; for (i = 0; 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 { pthread_mutex_t mu; pthread_cond_t cv; int state; } event_t; static void event_init(event_t* ev) { if (pthread_mutex_init(&ev->mu, 0)) exit(1); if (pthread_cond_init(&ev->cv, 0)) exit(1); ev->state = 0; } static void event_reset(event_t* ev) { ev->state = 0; } static void event_set(event_t* ev) { pthread_mutex_lock(&ev->mu); if (ev->state) exit(1); ev->state = 1; pthread_mutex_unlock(&ev->mu); pthread_cond_broadcast(&ev->cv); } static void event_wait(event_t* ev) { pthread_mutex_lock(&ev->mu); while (!ev->state) pthread_cond_wait(&ev->cv, &ev->mu); pthread_mutex_unlock(&ev->mu); } static int event_isset(event_t* ev) { pthread_mutex_lock(&ev->mu); int res = ev->state; pthread_mutex_unlock(&ev->mu); return res; } static int event_timedwait(event_t* ev, uint64_t timeout) { uint64_t start = current_time_ms(); uint64_t now = start; pthread_mutex_lock(&ev->mu); for (;;) { if (ev->state) break; uint64_t remain = timeout - (now - start); struct timespec ts; ts.tv_sec = remain / 1000; ts.tv_nsec = (remain % 1000) * 1000 * 1000; pthread_cond_timedwait(&ev->cv, &ev->mu, &ts); now = current_time_ms(); if (now - start > timeout) break; } int res = ev->state; pthread_mutex_unlock(&ev->mu); return res; } static long syz_mmap(volatile long a0, volatile long a1) { return (long)mmap((void*)a0, a1, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE | MAP_FIXED, -1, 0); } static long syz_errno(volatile long v) { errno = v; return v == 0 ? 0 : -1; } static long syz_exit(volatile long status) { _exit(status); return 0; } static long syz_compare(volatile long want, volatile long want_len, volatile long got, volatile long got_len) { if (want_len != got_len) { errno = EBADF; return -1; } if (memcmp((void*)want, (void*)got, want_len)) { errno = EINVAL; return -1; } return 0; } static long syz_compare_int(volatile long n, ...) { va_list args; va_start(args, n); long v0 = va_arg(args, long); long v1 = va_arg(args, long); long v2 = va_arg(args, long); long v3 = va_arg(args, long); va_end(args); if (n < 2 || n > 4) return errno = E2BIG, -1; if (n <= 2 && v2 != 0) return errno = EFAULT, -1; if (n <= 3 && v3 != 0) return errno = EFAULT, -1; if (v0 != v1) return errno = EINVAL, -1; if (n > 2 && v0 != v2) return errno = EINVAL, -1; if (n > 3 && v0 != v3) return errno = EINVAL, -1; return 0; } static void loop(); static int do_sandbox_none(void) { loop(); return 0; } static long syz_execute_func(volatile long text) { volatile long p[8] = {0}; (void)p; ((void (*)(void))(text))(); return 0; } 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 < 16; 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); event_timedwait(&th->done, 45); break; } } for (i = 0; i < 100 && __atomic_load_n(&running, __ATOMIC_RELAXED); i++) sleep_ms(1); } static void execute_one(void); #define WAIT_FLAGS 0 static void loop(void) { int iter; for (iter = 0;; iter++) { char cwdbuf[32]; sprintf(cwdbuf, "./%d", iter); if (mkdir(cwdbuf, 0777)) exit(1); int pid = fork(); if (pid < 0) exit(1); if (pid == 0) { if (chdir(cwdbuf)) exit(1); 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 < 5 * 1000) continue; kill_and_wait(pid, &status); break; } remove_dir(cwdbuf); } } void execute_call(int call) { switch (call) { case 0: syz_mmap(0x20ff6000, 0x4000); break; case 1: syz_mmap(0x20ffe000, 0x2000); break; case 2: syz_compare_int(4, 7, 0x7f, 0x71f, 6); break; case 3: syz_errno(4); break; case 4: syz_compare_int(2, 7, 0x80000001, 0, 0); break; case 5: syz_compare_int(4, 9, 6, 0x3ff, 0); break; case 6: syz_compare_int(3, 0, 5, 6, 0); break; case 7: syz_errno(0x80000000); break; case 8: syz_compare_int(2, 0x100000001, 8, 0, 0); break; case 9: syz_exit(0x200); break; case 10: memcpy((void*)0x20000000, "\000", 1); memcpy((void*)0x20000040, "\000", 1); syz_compare(0x20000000, 1, 0x20000040, 1); break; case 11: syz_compare_int(2, 4, 0, 0, 0); break; case 12: syz_errno(0x40); break; case 13: memcpy((void*)0x20000080, "\x34\x63\xee\xab\xc7\x55\xe7\xfd\xeb\xe7\x25\x21\xf6\x8b\x06\xb3\x6c\x8a\x66\xc3\x87\x9a\xfe\xc0\xd6\x60\x21\x64\xbe\x86\x7d\xa5\x64\xb6\x90\x68\x89\xaa\xf9\x33\x38\xe8\x17\x9e\xea\xa2\xeb\x98\xb1\xef", 50); syz_execute_func(0x20000080); break; case 14: syz_exit(0x101); break; case 15: syz_mmap(0x20ff2000, 0x8000); break; } } int main(void) { syz_mmap(0x20000000, 0x1000000); use_temporary_dir(); do_sandbox_none(); return 0; } /usr/local/bin/ld: cannot find -lasan collect2: error: ld returned 1 exit status compiler invocation: gcc [-o /tmp/syz-executor738421390 -DGOOS_test=1 -DGOARCH_64_fork=1 -DHOSTGOOS_freebsd=1 -x c - -O2 -pthread -Wall -Werror -Wparentheses -Wunused-const-variable -Wframe-larger-than=8192 -m64 -fsanitize=address] --- FAIL: TestGenerate/test/64_fork/19 (1.10s) csource_test.go:110: opts: {Threaded:true Collide:false Repeat:true RepeatTimes:0 Procs:0 Sandbox:none Fault:false FaultCall:0 FaultNth:0 Leak:false EnableTun:false EnableNetDev:false EnableNetReset:false EnableCgroups:false EnableBinfmtMisc:false EnableCloseFds:false UseTmpDir:true HandleSegv:false Repro:false Trace:false} program: syz_mmap(&(0x7f0000ff6000/0x4000)=nil, 0x4000) syz_mmap(&(0x7f0000ffe000/0x2000)=nil, 0x2000) syz_compare_int$4(0x4, 0x7, 0x7f, 0x71f, 0x6) syz_errno(0x4) syz_compare_int$2(0x2, 0x7, 0x80000001) syz_compare_int$4(0x4, 0x9, 0x6, 0x3ff, 0x0) syz_compare_int$3(0x3, 0x0, 0x5, 0x6) syz_errno(0xffffffff80000000) syz_compare_int$2(0x2, 0x100000001, 0x8) syz_exit(0x200) syz_compare(&(0x7f0000000000)='\x00', 0x1, &(0x7f0000000040)=@str='\x00', 0x1) syz_compare_int$2(0x2, 0x4, 0x0) syz_errno(0x40) syz_execute_func(&(0x7f0000000080)="3463eeabc755e7fdebe72521f68b06b36c8a66c3879afec0d6602164be867da564b6906889aaf93338e8179eeaa2eb98b1ef") syz_exit(0x101) syz_mmap(&(0x7f0000ff2000/0x8000)=nil, 0x8000) csource_test.go:111: failed to build program: // autogenerated by syzkaller (https://github.com/google/syzkaller) #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include static void kill_and_wait(int pid, int* status) { kill(pid, SIGKILL); while (waitpid(-1, status, 0) != pid) { } } 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 remove_dir(const char* dir) { DIR* dp; struct dirent* ep; dp = opendir(dir); if (dp == NULL) exit(1); 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)) exit(1); if (S_ISDIR(st.st_mode)) { remove_dir(filename); continue; } if (unlink(filename)) exit(1); } closedir(dp); if (rmdir(dir)) 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; for (i = 0; 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 { pthread_mutex_t mu; pthread_cond_t cv; int state; } event_t; static void event_init(event_t* ev) { if (pthread_mutex_init(&ev->mu, 0)) exit(1); if (pthread_cond_init(&ev->cv, 0)) exit(1); ev->state = 0; } static void event_reset(event_t* ev) { ev->state = 0; } static void event_set(event_t* ev) { pthread_mutex_lock(&ev->mu); if (ev->state) exit(1); ev->state = 1; pthread_mutex_unlock(&ev->mu); pthread_cond_broadcast(&ev->cv); } static void event_wait(event_t* ev) { pthread_mutex_lock(&ev->mu); while (!ev->state) pthread_cond_wait(&ev->cv, &ev->mu); pthread_mutex_unlock(&ev->mu); } static int event_isset(event_t* ev) { pthread_mutex_lock(&ev->mu); int res = ev->state; pthread_mutex_unlock(&ev->mu); return res; } static int event_timedwait(event_t* ev, uint64_t timeout) { uint64_t start = current_time_ms(); uint64_t now = start; pthread_mutex_lock(&ev->mu); for (;;) { if (ev->state) break; uint64_t remain = timeout - (now - start); struct timespec ts; ts.tv_sec = remain / 1000; ts.tv_nsec = (remain % 1000) * 1000 * 1000; pthread_cond_timedwait(&ev->cv, &ev->mu, &ts); now = current_time_ms(); if (now - start > timeout) break; } int res = ev->state; pthread_mutex_unlock(&ev->mu); return res; } static long syz_mmap(volatile long a0, volatile long a1) { return (long)mmap((void*)a0, a1, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE | MAP_FIXED, -1, 0); } static long syz_errno(volatile long v) { errno = v; return v == 0 ? 0 : -1; } static long syz_exit(volatile long status) { _exit(status); return 0; } static long syz_compare(volatile long want, volatile long want_len, volatile long got, volatile long got_len) { if (want_len != got_len) { errno = EBADF; return -1; } if (memcmp((void*)want, (void*)got, want_len)) { errno = EINVAL; return -1; } return 0; } static long syz_compare_int(volatile long n, ...) { va_list args; va_start(args, n); long v0 = va_arg(args, long); long v1 = va_arg(args, long); long v2 = va_arg(args, long); long v3 = va_arg(args, long); va_end(args); if (n < 2 || n > 4) return errno = E2BIG, -1; if (n <= 2 && v2 != 0) return errno = EFAULT, -1; if (n <= 3 && v3 != 0) return errno = EFAULT, -1; if (v0 != v1) return errno = EINVAL, -1; if (n > 2 && v0 != v2) return errno = EINVAL, -1; if (n > 3 && v0 != v3) return errno = EINVAL, -1; return 0; } static void loop(); static int do_sandbox_none(void) { loop(); return 0; } static long syz_execute_func(volatile long text) { volatile long p[8] = {0}; (void)p; ((void (*)(void))(text))(); return 0; } 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 < 16; 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); event_timedwait(&th->done, 45); break; } } for (i = 0; i < 100 && __atomic_load_n(&running, __ATOMIC_RELAXED); i++) sleep_ms(1); } static void execute_one(void); #define WAIT_FLAGS 0 static void loop(void) { int iter; for (iter = 0;; iter++) { char cwdbuf[32]; sprintf(cwdbuf, "./%d", iter); if (mkdir(cwdbuf, 0777)) exit(1); int pid = fork(); if (pid < 0) exit(1); if (pid == 0) { if (chdir(cwdbuf)) exit(1); 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 < 5 * 1000) continue; kill_and_wait(pid, &status); break; } remove_dir(cwdbuf); } } void execute_call(int call) { switch (call) { case 0: syz_mmap(0x20ff6000, 0x4000); break; case 1: syz_mmap(0x20ffe000, 0x2000); break; case 2: syz_compare_int(4, 7, 0x7f, 0x71f, 6); break; case 3: syz_errno(4); break; case 4: syz_compare_int(2, 7, 0x80000001, 0, 0); break; case 5: syz_compare_int(4, 9, 6, 0x3ff, 0); break; case 6: syz_compare_int(3, 0, 5, 6, 0); break; case 7: syz_errno(0x80000000); break; case 8: syz_compare_int(2, 0x100000001, 8, 0, 0); break; case 9: syz_exit(0x200); break; case 10: memcpy((void*)0x20000000, "\000", 1); memcpy((void*)0x20000040, "\000", 1); syz_compare(0x20000000, 1, 0x20000040, 1); break; case 11: syz_compare_int(2, 4, 0, 0, 0); break; case 12: syz_errno(0x40); break; case 13: memcpy((void*)0x20000080, "\x34\x63\xee\xab\xc7\x55\xe7\xfd\xeb\xe7\x25\x21\xf6\x8b\x06\xb3\x6c\x8a\x66\xc3\x87\x9a\xfe\xc0\xd6\x60\x21\x64\xbe\x86\x7d\xa5\x64\xb6\x90\x68\x89\xaa\xf9\x33\x38\xe8\x17\x9e\xea\xa2\xeb\x98\xb1\xef", 50); syz_execute_func(0x20000080); break; case 14: syz_exit(0x101); break; case 15: syz_mmap(0x20ff2000, 0x8000); break; } } int main(void) { syz_mmap(0x20000000, 0x1000000); use_temporary_dir(); do_sandbox_none(); return 0; } /usr/local/bin/ld: cannot find -lasan collect2: error: ld returned 1 exit status compiler invocation: gcc [-o /tmp/syz-executor856727189 -DGOOS_test=1 -DGOARCH_64_fork=1 -DHOSTGOOS_freebsd=1 -x c - -O2 -pthread -Wall -Werror -Wparentheses -Wunused-const-variable -Wframe-larger-than=8192 -m64 -fsanitize=address] --- FAIL: TestGenerate/test/64_fork/25 (1.52s) csource_test.go:110: opts: {Threaded:true Collide:false Repeat:true RepeatTimes:0 Procs:0 Sandbox:none Fault:false FaultCall:0 FaultNth:0 Leak:false EnableTun:false EnableNetDev:false EnableNetReset:false EnableCgroups:false EnableBinfmtMisc:false EnableCloseFds:false UseTmpDir:true HandleSegv:true Repro:false Trace:false} program: syz_mmap(&(0x7f0000ff6000/0x4000)=nil, 0x4000) syz_mmap(&(0x7f0000ffe000/0x2000)=nil, 0x2000) syz_compare_int$4(0x4, 0x7, 0x7f, 0x71f, 0x6) syz_errno(0x4) syz_compare_int$2(0x2, 0x7, 0x80000001) syz_compare_int$4(0x4, 0x9, 0x6, 0x3ff, 0x0) syz_compare_int$3(0x3, 0x0, 0x5, 0x6) syz_errno(0xffffffff80000000) syz_compare_int$2(0x2, 0x100000001, 0x8) syz_exit(0x200) syz_compare(&(0x7f0000000000)='\x00', 0x1, &(0x7f0000000040)=@str='\x00', 0x1) syz_compare_int$2(0x2, 0x4, 0x0) syz_errno(0x40) syz_execute_func(&(0x7f0000000080)="3463eeabc755e7fdebe72521f68b06b36c8a66c3879afec0d6602164be867da564b6906889aaf93338e8179eeaa2eb98b1ef") syz_exit(0x101) syz_mmap(&(0x7f0000ff2000/0x8000)=nil, 0x8000) csource_test.go:111: failed to build program: // autogenerated by syzkaller (https://github.com/google/syzkaller) #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include 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_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 kill_and_wait(int pid, int* status) { kill(pid, SIGKILL); while (waitpid(-1, status, 0) != pid) { } } 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 remove_dir(const char* dir) { DIR* dp; struct dirent* ep; dp = opendir(dir); if (dp == NULL) exit(1); 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)) exit(1); if (S_ISDIR(st.st_mode)) { remove_dir(filename); continue; } if (unlink(filename)) exit(1); } closedir(dp); if (rmdir(dir)) 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; for (i = 0; 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 { pthread_mutex_t mu; pthread_cond_t cv; int state; } event_t; static void event_init(event_t* ev) { if (pthread_mutex_init(&ev->mu, 0)) exit(1); if (pthread_cond_init(&ev->cv, 0)) exit(1); ev->state = 0; } static void event_reset(event_t* ev) { ev->state = 0; } static void event_set(event_t* ev) { pthread_mutex_lock(&ev->mu); if (ev->state) exit(1); ev->state = 1; pthread_mutex_unlock(&ev->mu); pthread_cond_broadcast(&ev->cv); } static void event_wait(event_t* ev) { pthread_mutex_lock(&ev->mu); while (!ev->state) pthread_cond_wait(&ev->cv, &ev->mu); pthread_mutex_unlock(&ev->mu); } static int event_isset(event_t* ev) { pthread_mutex_lock(&ev->mu); int res = ev->state; pthread_mutex_unlock(&ev->mu); return res; } static int event_timedwait(event_t* ev, uint64_t timeout) { uint64_t start = current_time_ms(); uint64_t now = start; pthread_mutex_lock(&ev->mu); for (;;) { if (ev->state) break; uint64_t remain = timeout - (now - start); struct timespec ts; ts.tv_sec = remain / 1000; ts.tv_nsec = (remain % 1000) * 1000 * 1000; pthread_cond_timedwait(&ev->cv, &ev->mu, &ts); now = current_time_ms(); if (now - start > timeout) break; } int res = ev->state; pthread_mutex_unlock(&ev->mu); return res; } static long syz_mmap(volatile long a0, volatile long a1) { return (long)mmap((void*)a0, a1, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE | MAP_FIXED, -1, 0); } static long syz_errno(volatile long v) { errno = v; return v == 0 ? 0 : -1; } static long syz_exit(volatile long status) { _exit(status); return 0; } static long syz_compare(volatile long want, volatile long want_len, volatile long got, volatile long got_len) { if (want_len != got_len) { errno = EBADF; return -1; } if (memcmp((void*)want, (void*)got, want_len)) { errno = EINVAL; return -1; } return 0; } static long syz_compare_int(volatile long n, ...) { va_list args; va_start(args, n); long v0 = va_arg(args, long); long v1 = va_arg(args, long); long v2 = va_arg(args, long); long v3 = va_arg(args, long); va_end(args); if (n < 2 || n > 4) return errno = E2BIG, -1; if (n <= 2 && v2 != 0) return errno = EFAULT, -1; if (n <= 3 && v3 != 0) return errno = EFAULT, -1; if (v0 != v1) return errno = EINVAL, -1; if (n > 2 && v0 != v2) return errno = EINVAL, -1; if (n > 3 && v0 != v3) return errno = EINVAL, -1; return 0; } static void loop(); static int do_sandbox_none(void) { loop(); return 0; } static long syz_execute_func(volatile long text) { volatile long p[8] = {0}; (void)p; NONFAILING(((void (*)(void))(text))()); return 0; } 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 < 16; 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); event_timedwait(&th->done, 45); break; } } for (i = 0; i < 100 && __atomic_load_n(&running, __ATOMIC_RELAXED); i++) sleep_ms(1); } static void execute_one(void); #define WAIT_FLAGS 0 static void loop(void) { int iter; for (iter = 0;; iter++) { char cwdbuf[32]; sprintf(cwdbuf, "./%d", iter); if (mkdir(cwdbuf, 0777)) exit(1); int pid = fork(); if (pid < 0) exit(1); if (pid == 0) { if (chdir(cwdbuf)) exit(1); 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 < 5 * 1000) continue; kill_and_wait(pid, &status); break; } remove_dir(cwdbuf); } } void execute_call(int call) { switch (call) { case 0: syz_mmap(0x20ff6000, 0x4000); break; case 1: syz_mmap(0x20ffe000, 0x2000); break; case 2: syz_compare_int(4, 7, 0x7f, 0x71f, 6); break; case 3: syz_errno(4); break; case 4: syz_compare_int(2, 7, 0x80000001, 0, 0); break; case 5: syz_compare_int(4, 9, 6, 0x3ff, 0); break; case 6: syz_compare_int(3, 0, 5, 6, 0); break; case 7: syz_errno(0x80000000); break; case 8: syz_compare_int(2, 0x100000001, 8, 0, 0); break; case 9: syz_exit(0x200); break; case 10: NONFAILING(memcpy((void*)0x20000000, "\000", 1)); NONFAILING(memcpy((void*)0x20000040, "\000", 1)); syz_compare(0x20000000, 1, 0x20000040, 1); break; case 11: syz_compare_int(2, 4, 0, 0, 0); break; case 12: syz_errno(0x40); break; case 13: NONFAILING(memcpy((void*)0x20000080, "\x34\x63\xee\xab\xc7\x55\xe7\xfd\xeb\xe7\x25\x21\xf6\x8b\x06\xb3\x6c\x8a\x66\xc3\x87\x9a\xfe\xc0\xd6\x60\x21\x64\xbe\x86\x7d\xa5\x64\xb6\x90\x68\x89\xaa\xf9\x33\x38\xe8\x17\x9e\xea\xa2\xeb\x98\xb1\xef", 50)); syz_execute_func(0x20000080); break; case 14: syz_exit(0x101); break; case 15: syz_mmap(0x20ff2000, 0x8000); break; } } int main(void) { syz_mmap(0x20000000, 0x1000000); install_segv_handler(); use_temporary_dir(); do_sandbox_none(); return 0; } /usr/local/bin/ld: cannot find -lasan collect2: error: ld returned 1 exit status compiler invocation: gcc [-o /tmp/syz-executor400786672 -DGOOS_test=1 -DGOARCH_64_fork=1 -DHOSTGOOS_freebsd=1 -x c - -O2 -pthread -Wall -Werror -Wparentheses -Wunused-const-variable -Wframe-larger-than=8192 -m64 -fsanitize=address] --- FAIL: TestGenerate/test/64_fork/26 (1.64s) csource_test.go:110: opts: {Threaded:true Collide:false Repeat:true RepeatTimes:0 Procs:0 Sandbox:none Fault:false FaultCall:0 FaultNth:0 Leak:false EnableTun:false EnableNetDev:false EnableNetReset:false EnableCgroups:false EnableBinfmtMisc:false EnableCloseFds:false UseTmpDir:true HandleSegv:false Repro:false Trace:false} program: syz_mmap(&(0x7f0000ff6000/0x4000)=nil, 0x4000) syz_mmap(&(0x7f0000ffe000/0x2000)=nil, 0x2000) syz_compare_int$4(0x4, 0x7, 0x7f, 0x71f, 0x6) syz_errno(0x4) syz_compare_int$2(0x2, 0x7, 0x80000001) syz_compare_int$4(0x4, 0x9, 0x6, 0x3ff, 0x0) syz_compare_int$3(0x3, 0x0, 0x5, 0x6) syz_errno(0xffffffff80000000) syz_compare_int$2(0x2, 0x100000001, 0x8) syz_exit(0x200) syz_compare(&(0x7f0000000000)='\x00', 0x1, &(0x7f0000000040)=@str='\x00', 0x1) syz_compare_int$2(0x2, 0x4, 0x0) syz_errno(0x40) syz_execute_func(&(0x7f0000000080)="3463eeabc755e7fdebe72521f68b06b36c8a66c3879afec0d6602164be867da564b6906889aaf93338e8179eeaa2eb98b1ef") syz_exit(0x101) syz_mmap(&(0x7f0000ff2000/0x8000)=nil, 0x8000) csource_test.go:111: failed to build program: // autogenerated by syzkaller (https://github.com/google/syzkaller) #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include static void kill_and_wait(int pid, int* status) { kill(pid, SIGKILL); while (waitpid(-1, status, 0) != pid) { } } 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 remove_dir(const char* dir) { DIR* dp; struct dirent* ep; dp = opendir(dir); if (dp == NULL) exit(1); 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)) exit(1); if (S_ISDIR(st.st_mode)) { remove_dir(filename); continue; } if (unlink(filename)) exit(1); } closedir(dp); if (rmdir(dir)) 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; for (i = 0; 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 { pthread_mutex_t mu; pthread_cond_t cv; int state; } event_t; static void event_init(event_t* ev) { if (pthread_mutex_init(&ev->mu, 0)) exit(1); if (pthread_cond_init(&ev->cv, 0)) exit(1); ev->state = 0; } static void event_reset(event_t* ev) { ev->state = 0; } static void event_set(event_t* ev) { pthread_mutex_lock(&ev->mu); if (ev->state) exit(1); ev->state = 1; pthread_mutex_unlock(&ev->mu); pthread_cond_broadcast(&ev->cv); } static void event_wait(event_t* ev) { pthread_mutex_lock(&ev->mu); while (!ev->state) pthread_cond_wait(&ev->cv, &ev->mu); pthread_mutex_unlock(&ev->mu); } static int event_isset(event_t* ev) { pthread_mutex_lock(&ev->mu); int res = ev->state; pthread_mutex_unlock(&ev->mu); return res; } static int event_timedwait(event_t* ev, uint64_t timeout) { uint64_t start = current_time_ms(); uint64_t now = start; pthread_mutex_lock(&ev->mu); for (;;) { if (ev->state) break; uint64_t remain = timeout - (now - start); struct timespec ts; ts.tv_sec = remain / 1000; ts.tv_nsec = (remain % 1000) * 1000 * 1000; pthread_cond_timedwait(&ev->cv, &ev->mu, &ts); now = current_time_ms(); if (now - start > timeout) break; } int res = ev->state; pthread_mutex_unlock(&ev->mu); return res; } static long syz_mmap(volatile long a0, volatile long a1) { return (long)mmap((void*)a0, a1, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE | MAP_FIXED, -1, 0); } static long syz_errno(volatile long v) { errno = v; return v == 0 ? 0 : -1; } static long syz_exit(volatile long status) { _exit(status); return 0; } static long syz_compare(volatile long want, volatile long want_len, volatile long got, volatile long got_len) { if (want_len != got_len) { errno = EBADF; return -1; } if (memcmp((void*)want, (void*)got, want_len)) { errno = EINVAL; return -1; } return 0; } static long syz_compare_int(volatile long n, ...) { va_list args; va_start(args, n); long v0 = va_arg(args, long); long v1 = va_arg(args, long); long v2 = va_arg(args, long); long v3 = va_arg(args, long); va_end(args); if (n < 2 || n > 4) return errno = E2BIG, -1; if (n <= 2 && v2 != 0) return errno = EFAULT, -1; if (n <= 3 && v3 != 0) return errno = EFAULT, -1; if (v0 != v1) return errno = EINVAL, -1; if (n > 2 && v0 != v2) return errno = EINVAL, -1; if (n > 3 && v0 != v3) return errno = EINVAL, -1; return 0; } static void loop(); static int do_sandbox_none(void) { loop(); return 0; } static long syz_execute_func(volatile long text) { volatile long p[8] = {0}; (void)p; ((void (*)(void))(text))(); return 0; } 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 < 16; 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); event_timedwait(&th->done, 45); break; } } for (i = 0; i < 100 && __atomic_load_n(&running, __ATOMIC_RELAXED); i++) sleep_ms(1); } static void execute_one(void); #define WAIT_FLAGS 0 static void loop(void) { int iter; for (iter = 0;; iter++) { char cwdbuf[32]; sprintf(cwdbuf, "./%d", iter); if (mkdir(cwdbuf, 0777)) exit(1); int pid = fork(); if (pid < 0) exit(1); if (pid == 0) { if (chdir(cwdbuf)) exit(1); 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 < 5 * 1000) continue; kill_and_wait(pid, &status); break; } remove_dir(cwdbuf); } } void execute_call(int call) { switch (call) { case 0: syz_mmap(0x20ff6000, 0x4000); break; case 1: syz_mmap(0x20ffe000, 0x2000); break; case 2: syz_compare_int(4, 7, 0x7f, 0x71f, 6); break; case 3: syz_errno(4); break; case 4: syz_compare_int(2, 7, 0x80000001, 0, 0); break; case 5: syz_compare_int(4, 9, 6, 0x3ff, 0); break; case 6: syz_compare_int(3, 0, 5, 6, 0); break; case 7: syz_errno(0x80000000); break; case 8: syz_compare_int(2, 0x100000001, 8, 0, 0); break; case 9: syz_exit(0x200); break; case 10: memcpy((void*)0x20000000, "\000", 1); memcpy((void*)0x20000040, "\000", 1); syz_compare(0x20000000, 1, 0x20000040, 1); break; case 11: syz_compare_int(2, 4, 0, 0, 0); break; case 12: syz_errno(0x40); break; case 13: memcpy((void*)0x20000080, "\x34\x63\xee\xab\xc7\x55\xe7\xfd\xeb\xe7\x25\x21\xf6\x8b\x06\xb3\x6c\x8a\x66\xc3\x87\x9a\xfe\xc0\xd6\x60\x21\x64\xbe\x86\x7d\xa5\x64\xb6\x90\x68\x89\xaa\xf9\x33\x38\xe8\x17\x9e\xea\xa2\xeb\x98\xb1\xef", 50); syz_execute_func(0x20000080); break; case 14: syz_exit(0x101); break; case 15: syz_mmap(0x20ff2000, 0x8000); break; } } int main(void) { syz_mmap(0x20000000, 0x1000000); use_temporary_dir(); do_sandbox_none(); return 0; } /usr/local/bin/ld: cannot find -lasan collect2: error: ld returned 1 exit status compiler invocation: gcc [-o /tmp/syz-executor062132642 -DGOOS_test=1 -DGOARCH_64_fork=1 -DHOSTGOOS_freebsd=1 -x c - -O2 -pthread -Wall -Werror -Wparentheses -Wunused-const-variable -Wframe-larger-than=8192 -m64 -fsanitize=address] --- FAIL: TestGenerate/test/64 (0.18s) csource_test.go:72: seed=1568761920714396194 --- FAIL: TestGenerate/test/64/0 (0.78s) csource_test.go:110: opts: {Threaded:false Collide:false Repeat:true RepeatTimes:0 Procs:0 Sandbox:none Fault:false FaultCall:0 FaultNth:0 Leak:false EnableTun:false EnableNetDev:false EnableNetReset:false EnableCgroups:false EnableBinfmtMisc:false EnableCloseFds:false UseTmpDir:true HandleSegv:false Repro:false Trace:false} program: test$int(0x401, 0x1ff, 0x5, 0x8, 0x10001) syz_mmap(&(0x7f0000ffc000/0x3000)=nil, 0x3000) test$array1(&(0x7f0000000000)={0x7ff, "413e9c088f550bb2"}) test$length6(&(0x7f0000000040)={[0x9, 0x10001, 0x7, 0x7], 0x4}) test$union1(&(0x7f0000000080)={@f0=0xc917, 0x8}) test$align5(&(0x7f00000000c0)={{0x7, [0x8]}, {0x4, [0x7ac]}, 0x5}) foo$fmt5(&(0x7f0000000100)={0x5}) test$length27(&(0x7f0000000140)={0x6}, 0x2a) serialize1(&(0x7f0000000180)=""/106, 0x6a) test$array0(&(0x7f0000000200)={0x7, [@f1=0xffffffffffff3fcd, @f1=0xffffffff], 0x40}) syz_compare(&(0x7f0000000000)='@\x00', 0x2, &(0x7f0000000040)=@bf1={{0x7, 0x100, 0x1}, 0xffff}, 0x8) syz_compare_int$2(0x2, 0x2bb, 0x5) syz_errno(0xff) syz_execute_func(&(0x7f0000000080)="8fba4d8976c6e121fcb9559d464bd733d7f9eb3904e145878a0330b13323c09b6464f27301db8a6bb6e695a90ca7c3f5b07e") syz_exit(0x5) syz_mmap(&(0x7f0000ffb000/0x3000)=nil, 0x3000) csource_test.go:111: failed to build program: // autogenerated by syzkaller (https://github.com/google/syzkaller) #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include 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); } #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)))) static long syz_mmap(volatile long a0, volatile long a1) { return (long)mmap((void*)a0, a1, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE | MAP_FIXED, -1, 0); } static long syz_errno(volatile long v) { errno = v; return v == 0 ? 0 : -1; } static long syz_exit(volatile long status) { _exit(status); return 0; } static long syz_compare(volatile long want, volatile long want_len, volatile long got, volatile long got_len) { if (want_len != got_len) { errno = EBADF; return -1; } if (memcmp((void*)want, (void*)got, want_len)) { errno = EINVAL; return -1; } return 0; } static long syz_compare_int(volatile long n, ...) { va_list args; va_start(args, n); long v0 = va_arg(args, long); long v1 = va_arg(args, long); long v2 = va_arg(args, long); long v3 = va_arg(args, long); va_end(args); if (n < 2 || n > 4) return errno = E2BIG, -1; if (n <= 2 && v2 != 0) return errno = EFAULT, -1; if (n <= 3 && v3 != 0) return errno = EFAULT, -1; if (v0 != v1) return errno = EINVAL, -1; if (n > 2 && v0 != v2) return errno = EINVAL, -1; if (n > 3 && v0 != v3) return errno = EINVAL, -1; return 0; } static void loop(); static int do_sandbox_none(void) { loop(); return 0; } static long syz_execute_func(volatile long text) { volatile long p[8] = {0}; (void)p; ((void (*)(void))(text))(); return 0; } static void execute_one(void); static void loop(void) { execute_one(); } #ifndef SYS_foo #define SYS_foo 0 #endif #ifndef SYS_serialize1 #define SYS_serialize1 0 #endif #ifndef SYS_test #define SYS_test 0 #endif void execute_one(void) { syscall(SYS_test, 0x401, -1, 5, 8, 0x10001, 0); syz_mmap(0x20ffc000, 0x3000); *(uint8_t*)0x20000000 = -1; memcpy((void*)0x20000001, "\x41\x3e\x9c\x08\x8f\x55\x0b\xb2", 8); syscall(SYS_test, 0x20000000, 0, 0, 0, 0, 0); *(uint16_t*)0x20000040 = 9; *(uint16_t*)0x20000042 = 1; *(uint16_t*)0x20000044 = 7; *(uint16_t*)0x20000046 = 7; *(uint16_t*)0x20000048 = 4; syscall(SYS_test, 0x20000040, 0, 0, 0, 0, 0); *(uint64_t*)0x20000080 = 0xc917; *(uint8_t*)0x20000088 = 8; syscall(SYS_test, 0x20000080, 0, 0, 0, 0, 0); *(uint64_t*)0x200000c0 = 7; *(uint16_t*)0x200000c8 = 8; *(uint64_t*)0x200000ca = 4; *(uint16_t*)0x200000d2 = 0x7ac; *(uint8_t*)0x200000d4 = 5; syscall(SYS_test, 0x200000c0, 0, 0, 0, 0, 0); sprintf((char*)0x20000100, "%020llu", (long long)5); syscall(SYS_foo, 0x20000100, 0); *(uint8_t*)0x20000140 = 6; syscall(SYS_test, 0x20000140, 0x2a, 0, 0, 0, 0); syscall(SYS_serialize1, 0x20000180, 0x6a); *(uint8_t*)0x20000200 = 7; *(uint64_t*)0x20000201 = 0xffffffffffff3fcd; *(uint64_t*)0x20000209 = 0xffffffff; *(uint64_t*)0x20000211 = 0x40; syscall(SYS_test, 0x20000200, 0, 0, 0, 0, 0); memcpy((void*)0x20000000, "@\000", 2); STORE_BY_BITMASK(uint32_t, , 0x20000040, 7, 0, 10); STORE_BY_BITMASK(uint32_t, , 0x20000040, 0x100, 10, 10); STORE_BY_BITMASK(uint32_t, , 0x20000040, 1, 20, 10); *(uint8_t*)0x20000044 = -1; syz_compare(0x20000000, 2, 0x20000040, 8); syz_compare_int(2, 0x2bb, 5, 0, 0); syz_errno(0xff); memcpy((void*)0x20000080, "\x8f\xba\x4d\x89\x76\xc6\xe1\x21\xfc\xb9\x55\x9d\x46\x4b\xd7\x33\xd7\xf9\xeb\x39\x04\xe1\x45\x87\x8a\x03\x30\xb1\x33\x23\xc0\x9b\x64\x64\xf2\x73\x01\xdb\x8a\x6b\xb6\xe6\x95\xa9\x0c\xa7\xc3\xf5\xb0\x7e", 50); syz_execute_func(0x20000080); syz_exit(5); syz_mmap(0x20ffb000, 0x3000); } int main(void) { syz_mmap(0x20000000, 0x1000000); use_temporary_dir(); do_sandbox_none(); return 0; } /usr/local/bin/ld: cannot find -lasan collect2: error: ld returned 1 exit status compiler invocation: gcc [-o /tmp/syz-executor219823023 -DGOOS_test=1 -DGOARCH_64=1 -DHOSTGOOS_freebsd=1 -x c - -O2 -pthread -Wall -Werror -Wparentheses -Wunused-const-variable -Wframe-larger-than=8192 -m64 -fsanitize=address] --- FAIL: TestGenerate/test/64/30 (1.06s) csource_test.go:110: opts: {Threaded:true Collide:true Repeat:true RepeatTimes:0 Procs:2 Sandbox:none Fault:false FaultCall:0 FaultNth:0 Leak:false EnableTun:false EnableNetDev:false EnableNetReset:false EnableCgroups:false EnableBinfmtMisc:false EnableCloseFds:false UseTmpDir:true HandleSegv:false Repro:true Trace:false} program: test$int(0x401, 0x1ff, 0x5, 0x8, 0x10001) syz_mmap(&(0x7f0000ffc000/0x3000)=nil, 0x3000) test$array1(&(0x7f0000000000)={0x7ff, "413e9c088f550bb2"}) test$length6(&(0x7f0000000040)={[0x9, 0x10001, 0x7, 0x7], 0x4}) test$union1(&(0x7f0000000080)={@f0=0xc917, 0x8}) test$align5(&(0x7f00000000c0)={{0x7, [0x8]}, {0x4, [0x7ac]}, 0x5}) foo$fmt5(&(0x7f0000000100)={0x5}) test$length27(&(0x7f0000000140)={0x6}, 0x2a) serialize1(&(0x7f0000000180)=""/106, 0x6a) test$array0(&(0x7f0000000200)={0x7, [@f1=0xffffffffffff3fcd, @f1=0xffffffff], 0x40}) syz_compare(&(0x7f0000000000)='@\x00', 0x2, &(0x7f0000000040)=@bf1={{0x7, 0x100, 0x1}, 0xffff}, 0x8) syz_compare_int$2(0x2, 0x2bb, 0x5) syz_errno(0xff) syz_execute_func(&(0x7f0000000080)="8fba4d8976c6e121fcb9559d464bd733d7f9eb3904e145878a0330b13323c09b6464f27301db8a6bb6e695a90ca7c3f5b07e") syz_exit(0x5) syz_mmap(&(0x7f0000ffb000/0x3000)=nil, 0x3000) csource_test.go:111: failed to build program: // autogenerated by syzkaller (https://github.com/google/syzkaller) #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include unsigned long long procid; 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; for (i = 0; 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 { pthread_mutex_t mu; pthread_cond_t cv; int state; } event_t; static void event_init(event_t* ev) { if (pthread_mutex_init(&ev->mu, 0)) exit(1); if (pthread_cond_init(&ev->cv, 0)) exit(1); ev->state = 0; } static void event_reset(event_t* ev) { ev->state = 0; } static void event_set(event_t* ev) { pthread_mutex_lock(&ev->mu); if (ev->state) exit(1); ev->state = 1; pthread_mutex_unlock(&ev->mu); pthread_cond_broadcast(&ev->cv); } static void event_wait(event_t* ev) { pthread_mutex_lock(&ev->mu); while (!ev->state) pthread_cond_wait(&ev->cv, &ev->mu); pthread_mutex_unlock(&ev->mu); } static int event_isset(event_t* ev) { pthread_mutex_lock(&ev->mu); int res = ev->state; pthread_mutex_unlock(&ev->mu); return res; } static int event_timedwait(event_t* ev, uint64_t timeout) { uint64_t start = current_time_ms(); uint64_t now = start; pthread_mutex_lock(&ev->mu); for (;;) { if (ev->state) break; uint64_t remain = timeout - (now - start); struct timespec ts; ts.tv_sec = remain / 1000; ts.tv_nsec = (remain % 1000) * 1000 * 1000; pthread_cond_timedwait(&ev->cv, &ev->mu, &ts); now = current_time_ms(); if (now - start > timeout) break; } int res = ev->state; pthread_mutex_unlock(&ev->mu); return res; } #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)))) static long syz_mmap(volatile long a0, volatile long a1) { return (long)mmap((void*)a0, a1, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE | MAP_FIXED, -1, 0); } static long syz_errno(volatile long v) { errno = v; return v == 0 ? 0 : -1; } static long syz_exit(volatile long status) { _exit(status); return 0; } static long syz_compare(volatile long want, volatile long want_len, volatile long got, volatile long got_len) { if (want_len != got_len) { errno = EBADF; return -1; } if (memcmp((void*)want, (void*)got, want_len)) { errno = EINVAL; return -1; } return 0; } static long syz_compare_int(volatile long n, ...) { va_list args; va_start(args, n); long v0 = va_arg(args, long); long v1 = va_arg(args, long); long v2 = va_arg(args, long); long v3 = va_arg(args, long); va_end(args); if (n < 2 || n > 4) return errno = E2BIG, -1; if (n <= 2 && v2 != 0) return errno = EFAULT, -1; if (n <= 3 && v3 != 0) return errno = EFAULT, -1; if (v0 != v1) return errno = EINVAL, -1; if (n > 2 && v0 != v2) return errno = EINVAL, -1; if (n > 3 && v0 != v3) return errno = EINVAL, -1; return 0; } static void loop(); static int do_sandbox_none(void) { loop(); return 0; } static long syz_execute_func(volatile long text) { volatile long p[8] = {0}; (void)p; ((void (*)(void))(text))(); return 0; } 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) { if (write(1, "executing program\n", sizeof("executing program\n") - 1)) { } int i, call, thread; int collide = 0; again: for (call = 0; call < 16; 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 (collide && (call % 2) == 0) break; event_timedwait(&th->done, 45); break; } } for (i = 0; i < 100 && __atomic_load_n(&running, __ATOMIC_RELAXED); i++) sleep_ms(1); if (!collide) { collide = 1; goto again; } } static void execute_one(void); static void loop(void) { execute_one(); } #ifndef SYS_foo #define SYS_foo 0 #endif #ifndef SYS_serialize1 #define SYS_serialize1 0 #endif #ifndef SYS_test #define SYS_test 0 #endif void execute_call(int call) { switch (call) { case 0: syscall(SYS_test, 0x401, -1, 5, 8, 0x10001, 0); break; case 1: syz_mmap(0x20ffc000, 0x3000); break; case 2: *(uint8_t*)0x20000000 = -1; memcpy((void*)0x20000001, "\x41\x3e\x9c\x08\x8f\x55\x0b\xb2", 8); syscall(SYS_test, 0x20000000, 0, 0, 0, 0, 0); break; case 3: *(uint16_t*)0x20000040 = 9; *(uint16_t*)0x20000042 = 1; *(uint16_t*)0x20000044 = 7; *(uint16_t*)0x20000046 = 7; *(uint16_t*)0x20000048 = 4; syscall(SYS_test, 0x20000040, 0, 0, 0, 0, 0); break; case 4: *(uint64_t*)0x20000080 = 0xc917; *(uint8_t*)0x20000088 = 8; syscall(SYS_test, 0x20000080, 0, 0, 0, 0, 0); break; case 5: *(uint64_t*)0x200000c0 = 7; *(uint16_t*)0x200000c8 = 8; *(uint64_t*)0x200000ca = 4; *(uint16_t*)0x200000d2 = 0x7ac; *(uint8_t*)0x200000d4 = 5; syscall(SYS_test, 0x200000c0, 0, 0, 0, 0, 0); break; case 6: sprintf((char*)0x20000100, "%020llu", (long long)5); syscall(SYS_foo, 0x20000100, 0); break; case 7: *(uint8_t*)0x20000140 = 6; syscall(SYS_test, 0x20000140, 0x2a, 0, 0, 0, 0); break; case 8: syscall(SYS_serialize1, 0x20000180, 0x6a); break; case 9: *(uint8_t*)0x20000200 = 7; *(uint64_t*)0x20000201 = 0xffffffffffff3fcd; *(uint64_t*)0x20000209 = 0xffffffff; *(uint64_t*)0x20000211 = 0x40; syscall(SYS_test, 0x20000200, 0, 0, 0, 0, 0); break; case 10: memcpy((void*)0x20000000, "@\000", 2); STORE_BY_BITMASK(uint32_t, , 0x20000040, 7, 0, 10); STORE_BY_BITMASK(uint32_t, , 0x20000040, 0x100, 10, 10); STORE_BY_BITMASK(uint32_t, , 0x20000040, 1, 20, 10); *(uint8_t*)0x20000044 = -1; syz_compare(0x20000000, 2, 0x20000040, 8); break; case 11: syz_compare_int(2, 0x2bb, 5, 0, 0); break; case 12: syz_errno(0xff); break; case 13: memcpy((void*)0x20000080, "\x8f\xba\x4d\x89\x76\xc6\xe1\x21\xfc\xb9\x55\x9d\x46\x4b\xd7\x33\xd7\xf9\xeb\x39\x04\xe1\x45\x87\x8a\x03\x30\xb1\x33\x23\xc0\x9b\x64\x64\xf2\x73\x01\xdb\x8a\x6b\xb6\xe6\x95\xa9\x0c\xa7\xc3\xf5\xb0\x7e", 50); syz_execute_func(0x20000080); break; case 14: syz_exit(5); break; case 15: syz_mmap(0x20ffb000, 0x3000); break; } } int main(void) { syz_mmap(0x20000000, 0x1000000); for (procid = 0; procid < 2; procid++) { if (fork() == 0) { use_temporary_dir(); do_sandbox_none(); } } sleep(1000000); return 0; } /usr/local/bin/ld: cannot find -lasan collect2: error: ld returned 1 exit status compiler invocation: gcc [-o /tmp/syz-executor140080211 -DGOOS_test=1 -DGOARCH_64=1 -DHOSTGOOS_freebsd=1 -x c - -O2 -pthread -Wall -Werror -Wparentheses -Wunused-const-variable -Wframe-larger-than=8192 -m64 -fsanitize=address] --- FAIL: TestGenerate/test/64/28 (0.88s) csource_test.go:110: opts: {Threaded:true Collide:false Repeat:true RepeatTimes:0 Procs:0 Sandbox:none Fault:false FaultCall:0 FaultNth:0 Leak:false EnableTun:false EnableNetDev:false EnableNetReset:false EnableCgroups:false EnableBinfmtMisc:false EnableCloseFds:false UseTmpDir:true HandleSegv:false Repro:false Trace:false} program: test$int(0x401, 0x1ff, 0x5, 0x8, 0x10001) syz_mmap(&(0x7f0000ffc000/0x3000)=nil, 0x3000) test$array1(&(0x7f0000000000)={0x7ff, "413e9c088f550bb2"}) test$length6(&(0x7f0000000040)={[0x9, 0x10001, 0x7, 0x7], 0x4}) test$union1(&(0x7f0000000080)={@f0=0xc917, 0x8}) test$align5(&(0x7f00000000c0)={{0x7, [0x8]}, {0x4, [0x7ac]}, 0x5}) foo$fmt5(&(0x7f0000000100)={0x5}) test$length27(&(0x7f0000000140)={0x6}, 0x2a) serialize1(&(0x7f0000000180)=""/106, 0x6a) test$array0(&(0x7f0000000200)={0x7, [@f1=0xffffffffffff3fcd, @f1=0xffffffff], 0x40}) syz_compare(&(0x7f0000000000)='@\x00', 0x2, &(0x7f0000000040)=@bf1={{0x7, 0x100, 0x1}, 0xffff}, 0x8) syz_compare_int$2(0x2, 0x2bb, 0x5) syz_errno(0xff) syz_execute_func(&(0x7f0000000080)="8fba4d8976c6e121fcb9559d464bd733d7f9eb3904e145878a0330b13323c09b6464f27301db8a6bb6e695a90ca7c3f5b07e") syz_exit(0x5) syz_mmap(&(0x7f0000ffb000/0x3000)=nil, 0x3000) csource_test.go:111: failed to build program: // autogenerated by syzkaller (https://github.com/google/syzkaller) #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include 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; for (i = 0; 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 { pthread_mutex_t mu; pthread_cond_t cv; int state; } event_t; static void event_init(event_t* ev) { if (pthread_mutex_init(&ev->mu, 0)) exit(1); if (pthread_cond_init(&ev->cv, 0)) exit(1); ev->state = 0; } static void event_reset(event_t* ev) { ev->state = 0; } static void event_set(event_t* ev) { pthread_mutex_lock(&ev->mu); if (ev->state) exit(1); ev->state = 1; pthread_mutex_unlock(&ev->mu); pthread_cond_broadcast(&ev->cv); } static void event_wait(event_t* ev) { pthread_mutex_lock(&ev->mu); while (!ev->state) pthread_cond_wait(&ev->cv, &ev->mu); pthread_mutex_unlock(&ev->mu); } static int event_isset(event_t* ev) { pthread_mutex_lock(&ev->mu); int res = ev->state; pthread_mutex_unlock(&ev->mu); return res; } static int event_timedwait(event_t* ev, uint64_t timeout) { uint64_t start = current_time_ms(); uint64_t now = start; pthread_mutex_lock(&ev->mu); for (;;) { if (ev->state) break; uint64_t remain = timeout - (now - start); struct timespec ts; ts.tv_sec = remain / 1000; ts.tv_nsec = (remain % 1000) * 1000 * 1000; pthread_cond_timedwait(&ev->cv, &ev->mu, &ts); now = current_time_ms(); if (now - start > timeout) break; } int res = ev->state; pthread_mutex_unlock(&ev->mu); return res; } #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)))) static long syz_mmap(volatile long a0, volatile long a1) { return (long)mmap((void*)a0, a1, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE | MAP_FIXED, -1, 0); } static long syz_errno(volatile long v) { errno = v; return v == 0 ? 0 : -1; } static long syz_exit(volatile long status) { _exit(status); return 0; } static long syz_compare(volatile long want, volatile long want_len, volatile long got, volatile long got_len) { if (want_len != got_len) { errno = EBADF; return -1; } if (memcmp((void*)want, (void*)got, want_len)) { errno = EINVAL; return -1; } return 0; } static long syz_compare_int(volatile long n, ...) { va_list args; va_start(args, n); long v0 = va_arg(args, long); long v1 = va_arg(args, long); long v2 = va_arg(args, long); long v3 = va_arg(args, long); va_end(args); if (n < 2 || n > 4) return errno = E2BIG, -1; if (n <= 2 && v2 != 0) return errno = EFAULT, -1; if (n <= 3 && v3 != 0) return errno = EFAULT, -1; if (v0 != v1) return errno = EINVAL, -1; if (n > 2 && v0 != v2) return errno = EINVAL, -1; if (n > 3 && v0 != v3) return errno = EINVAL, -1; return 0; } static void loop(); static int do_sandbox_none(void) { loop(); return 0; } static long syz_execute_func(volatile long text) { volatile long p[8] = {0}; (void)p; ((void (*)(void))(text))(); return 0; } 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 < 16; 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); event_timedwait(&th->done, 45); break; } } for (i = 0; i < 100 && __atomic_load_n(&running, __ATOMIC_RELAXED); i++) sleep_ms(1); } static void execute_one(void); static void loop(void) { execute_one(); } #ifndef SYS_foo #define SYS_foo 0 #endif #ifndef SYS_serialize1 #define SYS_serialize1 0 #endif #ifndef SYS_test #define SYS_test 0 #endif void execute_call(int call) { switch (call) { case 0: syscall(SYS_test, 0x401, -1, 5, 8, 0x10001, 0); break; case 1: syz_mmap(0x20ffc000, 0x3000); break; case 2: *(uint8_t*)0x20000000 = -1; memcpy((void*)0x20000001, "\x41\x3e\x9c\x08\x8f\x55\x0b\xb2", 8); syscall(SYS_test, 0x20000000, 0, 0, 0, 0, 0); break; case 3: *(uint16_t*)0x20000040 = 9; *(uint16_t*)0x20000042 = 1; *(uint16_t*)0x20000044 = 7; *(uint16_t*)0x20000046 = 7; *(uint16_t*)0x20000048 = 4; syscall(SYS_test, 0x20000040, 0, 0, 0, 0, 0); break; case 4: *(uint64_t*)0x20000080 = 0xc917; *(uint8_t*)0x20000088 = 8; syscall(SYS_test, 0x20000080, 0, 0, 0, 0, 0); break; case 5: *(uint64_t*)0x200000c0 = 7; *(uint16_t*)0x200000c8 = 8; *(uint64_t*)0x200000ca = 4; *(uint16_t*)0x200000d2 = 0x7ac; *(uint8_t*)0x200000d4 = 5; syscall(SYS_test, 0x200000c0, 0, 0, 0, 0, 0); break; case 6: sprintf((char*)0x20000100, "%020llu", (long long)5); syscall(SYS_foo, 0x20000100, 0); break; case 7: *(uint8_t*)0x20000140 = 6; syscall(SYS_test, 0x20000140, 0x2a, 0, 0, 0, 0); break; case 8: syscall(SYS_serialize1, 0x20000180, 0x6a); break; case 9: *(uint8_t*)0x20000200 = 7; *(uint64_t*)0x20000201 = 0xffffffffffff3fcd; *(uint64_t*)0x20000209 = 0xffffffff; *(uint64_t*)0x20000211 = 0x40; syscall(SYS_test, 0x20000200, 0, 0, 0, 0, 0); break; case 10: memcpy((void*)0x20000000, "@\000", 2); STORE_BY_BITMASK(uint32_t, , 0x20000040, 7, 0, 10); STORE_BY_BITMASK(uint32_t, , 0x20000040, 0x100, 10, 10); STORE_BY_BITMASK(uint32_t, , 0x20000040, 1, 20, 10); *(uint8_t*)0x20000044 = -1; syz_compare(0x20000000, 2, 0x20000040, 8); break; case 11: syz_compare_int(2, 0x2bb, 5, 0, 0); break; case 12: syz_errno(0xff); break; case 13: memcpy((void*)0x20000080, "\x8f\xba\x4d\x89\x76\xc6\xe1\x21\xfc\xb9\x55\x9d\x46\x4b\xd7\x33\xd7\xf9\xeb\x39\x04\xe1\x45\x87\x8a\x03\x30\xb1\x33\x23\xc0\x9b\x64\x64\xf2\x73\x01\xdb\x8a\x6b\xb6\xe6\x95\xa9\x0c\xa7\xc3\xf5\xb0\x7e", 50); syz_execute_func(0x20000080); break; case 14: syz_exit(5); break; case 15: syz_mmap(0x20ffb000, 0x3000); break; } } int main(void) { syz_mmap(0x20000000, 0x1000000); use_temporary_dir(); do_sandbox_none(); return 0; } /usr/local/bin/ld: cannot find -lasan collect2: error: ld returned 1 exit status compiler invocation: gcc [-o /tmp/syz-executor842553750 -DGOOS_test=1 -DGOARCH_64=1 -DHOSTGOOS_freebsd=1 -x c - -O2 -pthread -Wall -Werror -Wparentheses -Wunused-const-variable -Wframe-larger-than=8192 -m64 -fsanitize=address] --- FAIL: TestGenerate/test/64/29 (1.17s) csource_test.go:110: opts: {Threaded:true Collide:false Repeat:true RepeatTimes:0 Procs:0 Sandbox:none Fault:false FaultCall:0 FaultNth:0 Leak:false EnableTun:false EnableNetDev:false EnableNetReset:false EnableCgroups:false EnableBinfmtMisc:false EnableCloseFds:false UseTmpDir:true HandleSegv:false Repro:false Trace:true} program: test$int(0x401, 0x1ff, 0x5, 0x8, 0x10001) syz_mmap(&(0x7f0000ffc000/0x3000)=nil, 0x3000) test$array1(&(0x7f0000000000)={0x7ff, "413e9c088f550bb2"}) test$length6(&(0x7f0000000040)={[0x9, 0x10001, 0x7, 0x7], 0x4}) test$union1(&(0x7f0000000080)={@f0=0xc917, 0x8}) test$align5(&(0x7f00000000c0)={{0x7, [0x8]}, {0x4, [0x7ac]}, 0x5}) foo$fmt5(&(0x7f0000000100)={0x5}) test$length27(&(0x7f0000000140)={0x6}, 0x2a) serialize1(&(0x7f0000000180)=""/106, 0x6a) test$array0(&(0x7f0000000200)={0x7, [@f1=0xffffffffffff3fcd, @f1=0xffffffff], 0x40}) syz_compare(&(0x7f0000000000)='@\x00', 0x2, &(0x7f0000000040)=@bf1={{0x7, 0x100, 0x1}, 0xffff}, 0x8) syz_compare_int$2(0x2, 0x2bb, 0x5) syz_errno(0xff) syz_execute_func(&(0x7f0000000080)="8fba4d8976c6e121fcb9559d464bd733d7f9eb3904e145878a0330b13323c09b6464f27301db8a6bb6e695a90ca7c3f5b07e") syz_exit(0x5) syz_mmap(&(0x7f0000ffb000/0x3000)=nil, 0x3000) csource_test.go:111: failed to build program: // autogenerated by syzkaller (https://github.com/google/syzkaller) #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include 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; for (i = 0; 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 { pthread_mutex_t mu; pthread_cond_t cv; int state; } event_t; static void event_init(event_t* ev) { if (pthread_mutex_init(&ev->mu, 0)) exit(1); if (pthread_cond_init(&ev->cv, 0)) exit(1); ev->state = 0; } static void event_reset(event_t* ev) { ev->state = 0; } static void event_set(event_t* ev) { pthread_mutex_lock(&ev->mu); if (ev->state) exit(1); ev->state = 1; pthread_mutex_unlock(&ev->mu); pthread_cond_broadcast(&ev->cv); } static void event_wait(event_t* ev) { pthread_mutex_lock(&ev->mu); while (!ev->state) pthread_cond_wait(&ev->cv, &ev->mu); pthread_mutex_unlock(&ev->mu); } static int event_isset(event_t* ev) { pthread_mutex_lock(&ev->mu); int res = ev->state; pthread_mutex_unlock(&ev->mu); return res; } static int event_timedwait(event_t* ev, uint64_t timeout) { uint64_t start = current_time_ms(); uint64_t now = start; pthread_mutex_lock(&ev->mu); for (;;) { if (ev->state) break; uint64_t remain = timeout - (now - start); struct timespec ts; ts.tv_sec = remain / 1000; ts.tv_nsec = (remain % 1000) * 1000 * 1000; pthread_cond_timedwait(&ev->cv, &ev->mu, &ts); now = current_time_ms(); if (now - start > timeout) break; } int res = ev->state; pthread_mutex_unlock(&ev->mu); return res; } #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)))) static long syz_mmap(volatile long a0, volatile long a1) { return (long)mmap((void*)a0, a1, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE | MAP_FIXED, -1, 0); } static long syz_errno(volatile long v) { errno = v; return v == 0 ? 0 : -1; } static long syz_exit(volatile long status) { _exit(status); return 0; } static long syz_compare(volatile long want, volatile long want_len, volatile long got, volatile long got_len) { if (want_len != got_len) { errno = EBADF; return -1; } if (memcmp((void*)want, (void*)got, want_len)) { errno = EINVAL; return -1; } return 0; } static long syz_compare_int(volatile long n, ...) { va_list args; va_start(args, n); long v0 = va_arg(args, long); long v1 = va_arg(args, long); long v2 = va_arg(args, long); long v3 = va_arg(args, long); va_end(args); if (n < 2 || n > 4) return errno = E2BIG, -1; if (n <= 2 && v2 != 0) return errno = EFAULT, -1; if (n <= 3 && v3 != 0) return errno = EFAULT, -1; if (v0 != v1) return errno = EINVAL, -1; if (n > 2 && v0 != v2) return errno = EINVAL, -1; if (n > 3 && v0 != v3) return errno = EINVAL, -1; return 0; } static void loop(); static int do_sandbox_none(void) { loop(); return 0; } static long syz_execute_func(volatile long text) { volatile long p[8] = {0}; (void)p; ((void (*)(void))(text))(); return 0; } 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) { fprintf(stderr, "### start\n"); int i, call, thread; for (call = 0; call < 16; 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); event_timedwait(&th->done, 45); break; } } for (i = 0; i < 100 && __atomic_load_n(&running, __ATOMIC_RELAXED); i++) sleep_ms(1); } static void execute_one(void); static void loop(void) { execute_one(); } #ifndef SYS_foo #define SYS_foo 0 #endif #ifndef SYS_serialize1 #define SYS_serialize1 0 #endif #ifndef SYS_test #define SYS_test 0 #endif void execute_call(int call) { intptr_t res; switch (call) { case 0: res = syscall(SYS_test, 0x401, -1, 5, 8, 0x10001, 0); fprintf(stderr, "### call=0 errno=%u\n", res == -1 ? errno : 0); break; case 1: res = syz_mmap(0x20ffc000, 0x3000); fprintf(stderr, "### call=1 errno=%u\n", res == -1 ? errno : 0); break; case 2: *(uint8_t*)0x20000000 = -1; memcpy((void*)0x20000001, "\x41\x3e\x9c\x08\x8f\x55\x0b\xb2", 8); res = syscall(SYS_test, 0x20000000, 0, 0, 0, 0, 0); fprintf(stderr, "### call=2 errno=%u\n", res == -1 ? errno : 0); break; case 3: *(uint16_t*)0x20000040 = 9; *(uint16_t*)0x20000042 = 1; *(uint16_t*)0x20000044 = 7; *(uint16_t*)0x20000046 = 7; *(uint16_t*)0x20000048 = 4; res = syscall(SYS_test, 0x20000040, 0, 0, 0, 0, 0); fprintf(stderr, "### call=3 errno=%u\n", res == -1 ? errno : 0); break; case 4: *(uint64_t*)0x20000080 = 0xc917; *(uint8_t*)0x20000088 = 8; res = syscall(SYS_test, 0x20000080, 0, 0, 0, 0, 0); fprintf(stderr, "### call=4 errno=%u\n", res == -1 ? errno : 0); break; case 5: *(uint64_t*)0x200000c0 = 7; *(uint16_t*)0x200000c8 = 8; *(uint64_t*)0x200000ca = 4; *(uint16_t*)0x200000d2 = 0x7ac; *(uint8_t*)0x200000d4 = 5; res = syscall(SYS_test, 0x200000c0, 0, 0, 0, 0, 0); fprintf(stderr, "### call=5 errno=%u\n", res == -1 ? errno : 0); break; case 6: sprintf((char*)0x20000100, "%020llu", (long long)5); res = syscall(SYS_foo, 0x20000100, 0); fprintf(stderr, "### call=6 errno=%u\n", res == -1 ? errno : 0); break; case 7: *(uint8_t*)0x20000140 = 6; res = syscall(SYS_test, 0x20000140, 0x2a, 0, 0, 0, 0); fprintf(stderr, "### call=7 errno=%u\n", res == -1 ? errno : 0); break; case 8: res = syscall(SYS_serialize1, 0x20000180, 0x6a); fprintf(stderr, "### call=8 errno=%u\n", res == -1 ? errno : 0); break; case 9: *(uint8_t*)0x20000200 = 7; *(uint64_t*)0x20000201 = 0xffffffffffff3fcd; *(uint64_t*)0x20000209 = 0xffffffff; *(uint64_t*)0x20000211 = 0x40; res = syscall(SYS_test, 0x20000200, 0, 0, 0, 0, 0); fprintf(stderr, "### call=9 errno=%u\n", res == -1 ? errno : 0); break; case 10: memcpy((void*)0x20000000, "@\000", 2); STORE_BY_BITMASK(uint32_t, , 0x20000040, 7, 0, 10); STORE_BY_BITMASK(uint32_t, , 0x20000040, 0x100, 10, 10); STORE_BY_BITMASK(uint32_t, , 0x20000040, 1, 20, 10); *(uint8_t*)0x20000044 = -1; res = syz_compare(0x20000000, 2, 0x20000040, 8); fprintf(stderr, "### call=10 errno=%u\n", res == -1 ? errno : 0); break; case 11: res = syz_compare_int(2, 0x2bb, 5, 0, 0); fprintf(stderr, "### call=11 errno=%u\n", res == -1 ? errno : 0); break; case 12: res = syz_errno(0xff); fprintf(stderr, "### call=12 errno=%u\n", res == -1 ? errno : 0); break; case 13: memcpy((void*)0x20000080, "\x8f\xba\x4d\x89\x76\xc6\xe1\x21\xfc\xb9\x55\x9d\x46\x4b\xd7\x33\xd7\xf9\xeb\x39\x04\xe1\x45\x87\x8a\x03\x30\xb1\x33\x23\xc0\x9b\x64\x64\xf2\x73\x01\xdb\x8a\x6b\xb6\xe6\x95\xa9\x0c\xa7\xc3\xf5\xb0\x7e", 50); res = syz_execute_func(0x20000080); fprintf(stderr, "### call=13 errno=%u\n", res == -1 ? errno : 0); break; case 14: res = syz_exit(5); fprintf(stderr, "### call=14 errno=%u\n", res == -1 ? errno : 0); break; case 15: res = syz_mmap(0x20ffb000, 0x3000); fprintf(stderr, "### call=15 errno=%u\n", res == -1 ? errno : 0); break; } } int main(void) { syz_mmap(0x20000000, 0x1000000); use_temporary_dir(); do_sandbox_none(); return 0; } /usr/local/bin/ld: cannot find -lasan collect2: error: ld returned 1 exit status compiler invocation: gcc [-o /tmp/syz-executor967725508 -DGOOS_test=1 -DGOARCH_64=1 -DHOSTGOOS_freebsd=1 -x c - -O2 -pthread -Wall -Werror -Wparentheses -Wunused-const-variable -Wframe-larger-than=8192 -m64 -fsanitize=address] --- FAIL: TestGenerate/test/64/26 (0.85s) csource_test.go:110: opts: {Threaded:true Collide:false Repeat:true RepeatTimes:0 Procs:0 Sandbox:none Fault:false FaultCall:0 FaultNth:0 Leak:false EnableTun:false EnableNetDev:false EnableNetReset:false EnableCgroups:false EnableBinfmtMisc:false EnableCloseFds:false UseTmpDir:true HandleSegv:false Repro:false Trace:false} program: test$int(0x401, 0x1ff, 0x5, 0x8, 0x10001) syz_mmap(&(0x7f0000ffc000/0x3000)=nil, 0x3000) test$array1(&(0x7f0000000000)={0x7ff, "413e9c088f550bb2"}) test$length6(&(0x7f0000000040)={[0x9, 0x10001, 0x7, 0x7], 0x4}) test$union1(&(0x7f0000000080)={@f0=0xc917, 0x8}) test$align5(&(0x7f00000000c0)={{0x7, [0x8]}, {0x4, [0x7ac]}, 0x5}) foo$fmt5(&(0x7f0000000100)={0x5}) test$length27(&(0x7f0000000140)={0x6}, 0x2a) serialize1(&(0x7f0000000180)=""/106, 0x6a) test$array0(&(0x7f0000000200)={0x7, [@f1=0xffffffffffff3fcd, @f1=0xffffffff], 0x40}) syz_compare(&(0x7f0000000000)='@\x00', 0x2, &(0x7f0000000040)=@bf1={{0x7, 0x100, 0x1}, 0xffff}, 0x8) syz_compare_int$2(0x2, 0x2bb, 0x5) syz_errno(0xff) syz_execute_func(&(0x7f0000000080)="8fba4d8976c6e121fcb9559d464bd733d7f9eb3904e145878a0330b13323c09b6464f27301db8a6bb6e695a90ca7c3f5b07e") syz_exit(0x5) syz_mmap(&(0x7f0000ffb000/0x3000)=nil, 0x3000) csource_test.go:111: failed to build program: // autogenerated by syzkaller (https://github.com/google/syzkaller) #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include 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; for (i = 0; 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 { pthread_mutex_t mu; pthread_cond_t cv; int state; } event_t; static void event_init(event_t* ev) { if (pthread_mutex_init(&ev->mu, 0)) exit(1); if (pthread_cond_init(&ev->cv, 0)) exit(1); ev->state = 0; } static void event_reset(event_t* ev) { ev->state = 0; } static void event_set(event_t* ev) { pthread_mutex_lock(&ev->mu); if (ev->state) exit(1); ev->state = 1; pthread_mutex_unlock(&ev->mu); pthread_cond_broadcast(&ev->cv); } static void event_wait(event_t* ev) { pthread_mutex_lock(&ev->mu); while (!ev->state) pthread_cond_wait(&ev->cv, &ev->mu); pthread_mutex_unlock(&ev->mu); } static int event_isset(event_t* ev) { pthread_mutex_lock(&ev->mu); int res = ev->state; pthread_mutex_unlock(&ev->mu); return res; } static int event_timedwait(event_t* ev, uint64_t timeout) { uint64_t start = current_time_ms(); uint64_t now = start; pthread_mutex_lock(&ev->mu); for (;;) { if (ev->state) break; uint64_t remain = timeout - (now - start); struct timespec ts; ts.tv_sec = remain / 1000; ts.tv_nsec = (remain % 1000) * 1000 * 1000; pthread_cond_timedwait(&ev->cv, &ev->mu, &ts); now = current_time_ms(); if (now - start > timeout) break; } int res = ev->state; pthread_mutex_unlock(&ev->mu); return res; } #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)))) static long syz_mmap(volatile long a0, volatile long a1) { return (long)mmap((void*)a0, a1, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE | MAP_FIXED, -1, 0); } static long syz_errno(volatile long v) { errno = v; return v == 0 ? 0 : -1; } static long syz_exit(volatile long status) { _exit(status); return 0; } static long syz_compare(volatile long want, volatile long want_len, volatile long got, volatile long got_len) { if (want_len != got_len) { errno = EBADF; return -1; } if (memcmp((void*)want, (void*)got, want_len)) { errno = EINVAL; return -1; } return 0; } static long syz_compare_int(volatile long n, ...) { va_list args; va_start(args, n); long v0 = va_arg(args, long); long v1 = va_arg(args, long); long v2 = va_arg(args, long); long v3 = va_arg(args, long); va_end(args); if (n < 2 || n > 4) return errno = E2BIG, -1; if (n <= 2 && v2 != 0) return errno = EFAULT, -1; if (n <= 3 && v3 != 0) return errno = EFAULT, -1; if (v0 != v1) return errno = EINVAL, -1; if (n > 2 && v0 != v2) return errno = EINVAL, -1; if (n > 3 && v0 != v3) return errno = EINVAL, -1; return 0; } static void loop(); static int do_sandbox_none(void) { loop(); return 0; } static long syz_execute_func(volatile long text) { volatile long p[8] = {0}; (void)p; ((void (*)(void))(text))(); return 0; } 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 < 16; 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); event_timedwait(&th->done, 45); break; } } for (i = 0; i < 100 && __atomic_load_n(&running, __ATOMIC_RELAXED); i++) sleep_ms(1); } static void execute_one(void); static void loop(void) { execute_one(); } #ifndef SYS_foo #define SYS_foo 0 #endif #ifndef SYS_serialize1 #define SYS_serialize1 0 #endif #ifndef SYS_test #define SYS_test 0 #endif void execute_call(int call) { switch (call) { case 0: syscall(SYS_test, 0x401, -1, 5, 8, 0x10001, 0); break; case 1: syz_mmap(0x20ffc000, 0x3000); break; case 2: *(uint8_t*)0x20000000 = -1; memcpy((void*)0x20000001, "\x41\x3e\x9c\x08\x8f\x55\x0b\xb2", 8); syscall(SYS_test, 0x20000000, 0, 0, 0, 0, 0); break; case 3: *(uint16_t*)0x20000040 = 9; *(uint16_t*)0x20000042 = 1; *(uint16_t*)0x20000044 = 7; *(uint16_t*)0x20000046 = 7; *(uint16_t*)0x20000048 = 4; syscall(SYS_test, 0x20000040, 0, 0, 0, 0, 0); break; case 4: *(uint64_t*)0x20000080 = 0xc917; *(uint8_t*)0x20000088 = 8; syscall(SYS_test, 0x20000080, 0, 0, 0, 0, 0); break; case 5: *(uint64_t*)0x200000c0 = 7; *(uint16_t*)0x200000c8 = 8; *(uint64_t*)0x200000ca = 4; *(uint16_t*)0x200000d2 = 0x7ac; *(uint8_t*)0x200000d4 = 5; syscall(SYS_test, 0x200000c0, 0, 0, 0, 0, 0); break; case 6: sprintf((char*)0x20000100, "%020llu", (long long)5); syscall(SYS_foo, 0x20000100, 0); break; case 7: *(uint8_t*)0x20000140 = 6; syscall(SYS_test, 0x20000140, 0x2a, 0, 0, 0, 0); break; case 8: syscall(SYS_serialize1, 0x20000180, 0x6a); break; case 9: *(uint8_t*)0x20000200 = 7; *(uint64_t*)0x20000201 = 0xffffffffffff3fcd; *(uint64_t*)0x20000209 = 0xffffffff; *(uint64_t*)0x20000211 = 0x40; syscall(SYS_test, 0x20000200, 0, 0, 0, 0, 0); break; case 10: memcpy((void*)0x20000000, "@\000", 2); STORE_BY_BITMASK(uint32_t, , 0x20000040, 7, 0, 10); STORE_BY_BITMASK(uint32_t, , 0x20000040, 0x100, 10, 10); STORE_BY_BITMASK(uint32_t, , 0x20000040, 1, 20, 10); *(uint8_t*)0x20000044 = -1; syz_compare(0x20000000, 2, 0x20000040, 8); break; case 11: syz_compare_int(2, 0x2bb, 5, 0, 0); break; case 12: syz_errno(0xff); break; case 13: memcpy((void*)0x20000080, "\x8f\xba\x4d\x89\x76\xc6\xe1\x21\xfc\xb9\x55\x9d\x46\x4b\xd7\x33\xd7\xf9\xeb\x39\x04\xe1\x45\x87\x8a\x03\x30\xb1\x33\x23\xc0\x9b\x64\x64\xf2\x73\x01\xdb\x8a\x6b\xb6\xe6\x95\xa9\x0c\xa7\xc3\xf5\xb0\x7e", 50); syz_execute_func(0x20000080); break; case 14: syz_exit(5); break; case 15: syz_mmap(0x20ffb000, 0x3000); break; } } int main(void) { syz_mmap(0x20000000, 0x1000000); use_temporary_dir(); do_sandbox_none(); return 0; } /usr/local/bin/ld: cannot find -lasan collect2: error: ld returned 1 exit status compiler invocation: gcc [-o /tmp/syz-executor353626424 -DGOOS_test=1 -DGOARCH_64=1 -DHOSTGOOS_freebsd=1 -x c - -O2 -pthread -Wall -Werror -Wparentheses -Wunused-const-variable -Wframe-larger-than=8192 -m64 -fsanitize=address] --- FAIL: TestGenerate/test/64/23 (0.52s) csource_test.go:110: opts: {Threaded:true Collide:false Repeat:true RepeatTimes:0 Procs:0 Sandbox:none Fault:false FaultCall:0 FaultNth:0 Leak:false EnableTun:false EnableNetDev:false EnableNetReset:false EnableCgroups:false EnableBinfmtMisc:false EnableCloseFds:false UseTmpDir:true HandleSegv:false Repro:false Trace:false} program: test$int(0x401, 0x1ff, 0x5, 0x8, 0x10001) syz_mmap(&(0x7f0000ffc000/0x3000)=nil, 0x3000) test$array1(&(0x7f0000000000)={0x7ff, "413e9c088f550bb2"}) test$length6(&(0x7f0000000040)={[0x9, 0x10001, 0x7, 0x7], 0x4}) test$union1(&(0x7f0000000080)={@f0=0xc917, 0x8}) test$align5(&(0x7f00000000c0)={{0x7, [0x8]}, {0x4, [0x7ac]}, 0x5}) foo$fmt5(&(0x7f0000000100)={0x5}) test$length27(&(0x7f0000000140)={0x6}, 0x2a) serialize1(&(0x7f0000000180)=""/106, 0x6a) test$array0(&(0x7f0000000200)={0x7, [@f1=0xffffffffffff3fcd, @f1=0xffffffff], 0x40}) syz_compare(&(0x7f0000000000)='@\x00', 0x2, &(0x7f0000000040)=@bf1={{0x7, 0x100, 0x1}, 0xffff}, 0x8) syz_compare_int$2(0x2, 0x2bb, 0x5) syz_errno(0xff) syz_execute_func(&(0x7f0000000080)="8fba4d8976c6e121fcb9559d464bd733d7f9eb3904e145878a0330b13323c09b6464f27301db8a6bb6e695a90ca7c3f5b07e") syz_exit(0x5) syz_mmap(&(0x7f0000ffb000/0x3000)=nil, 0x3000) csource_test.go:111: failed to build program: // autogenerated by syzkaller (https://github.com/google/syzkaller) #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include 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; for (i = 0; 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 { pthread_mutex_t mu; pthread_cond_t cv; int state; } event_t; static void event_init(event_t* ev) { if (pthread_mutex_init(&ev->mu, 0)) exit(1); if (pthread_cond_init(&ev->cv, 0)) exit(1); ev->state = 0; } static void event_reset(event_t* ev) { ev->state = 0; } static void event_set(event_t* ev) { pthread_mutex_lock(&ev->mu); if (ev->state) exit(1); ev->state = 1; pthread_mutex_unlock(&ev->mu); pthread_cond_broadcast(&ev->cv); } static void event_wait(event_t* ev) { pthread_mutex_lock(&ev->mu); while (!ev->state) pthread_cond_wait(&ev->cv, &ev->mu); pthread_mutex_unlock(&ev->mu); } static int event_isset(event_t* ev) { pthread_mutex_lock(&ev->mu); int res = ev->state; pthread_mutex_unlock(&ev->mu); return res; } static int event_timedwait(event_t* ev, uint64_t timeout) { uint64_t start = current_time_ms(); uint64_t now = start; pthread_mutex_lock(&ev->mu); for (;;) { if (ev->state) break; uint64_t remain = timeout - (now - start); struct timespec ts; ts.tv_sec = remain / 1000; ts.tv_nsec = (remain % 1000) * 1000 * 1000; pthread_cond_timedwait(&ev->cv, &ev->mu, &ts); now = current_time_ms(); if (now - start > timeout) break; } int res = ev->state; pthread_mutex_unlock(&ev->mu); return res; } #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)))) static long syz_mmap(volatile long a0, volatile long a1) { return (long)mmap((void*)a0, a1, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE | MAP_FIXED, -1, 0); } static long syz_errno(volatile long v) { errno = v; return v == 0 ? 0 : -1; } static long syz_exit(volatile long status) { _exit(status); return 0; } static long syz_compare(volatile long want, volatile long want_len, volatile long got, volatile long got_len) { if (want_len != got_len) { errno = EBADF; return -1; } if (memcmp((void*)want, (void*)got, want_len)) { errno = EINVAL; return -1; } return 0; } static long syz_compare_int(volatile long n, ...) { va_list args; va_start(args, n); long v0 = va_arg(args, long); long v1 = va_arg(args, long); long v2 = va_arg(args, long); long v3 = va_arg(args, long); va_end(args); if (n < 2 || n > 4) return errno = E2BIG, -1; if (n <= 2 && v2 != 0) return errno = EFAULT, -1; if (n <= 3 && v3 != 0) return errno = EFAULT, -1; if (v0 != v1) return errno = EINVAL, -1; if (n > 2 && v0 != v2) return errno = EINVAL, -1; if (n > 3 && v0 != v3) return errno = EINVAL, -1; return 0; } static void loop(); static int do_sandbox_none(void) { loop(); return 0; } static long syz_execute_func(volatile long text) { volatile long p[8] = {0}; (void)p; ((void (*)(void))(text))(); return 0; } 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 < 16; 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); event_timedwait(&th->done, 45); break; } } for (i = 0; i < 100 && __atomic_load_n(&running, __ATOMIC_RELAXED); i++) sleep_ms(1); } static void execute_one(void); static void loop(void) { execute_one(); } #ifndef SYS_foo #define SYS_foo 0 #endif #ifndef SYS_serialize1 #define SYS_serialize1 0 #endif #ifndef SYS_test #define SYS_test 0 #endif void execute_call(int call) { switch (call) { case 0: syscall(SYS_test, 0x401, -1, 5, 8, 0x10001, 0); break; case 1: syz_mmap(0x20ffc000, 0x3000); break; case 2: *(uint8_t*)0x20000000 = -1; memcpy((void*)0x20000001, "\x41\x3e\x9c\x08\x8f\x55\x0b\xb2", 8); syscall(SYS_test, 0x20000000, 0, 0, 0, 0, 0); break; case 3: *(uint16_t*)0x20000040 = 9; *(uint16_t*)0x20000042 = 1; *(uint16_t*)0x20000044 = 7; *(uint16_t*)0x20000046 = 7; *(uint16_t*)0x20000048 = 4; syscall(SYS_test, 0x20000040, 0, 0, 0, 0, 0); break; case 4: *(uint64_t*)0x20000080 = 0xc917; *(uint8_t*)0x20000088 = 8; syscall(SYS_test, 0x20000080, 0, 0, 0, 0, 0); break; case 5: *(uint64_t*)0x200000c0 = 7; *(uint16_t*)0x200000c8 = 8; *(uint64_t*)0x200000ca = 4; *(uint16_t*)0x200000d2 = 0x7ac; *(uint8_t*)0x200000d4 = 5; syscall(SYS_test, 0x200000c0, 0, 0, 0, 0, 0); break; case 6: sprintf((char*)0x20000100, "%020llu", (long long)5); syscall(SYS_foo, 0x20000100, 0); break; case 7: *(uint8_t*)0x20000140 = 6; syscall(SYS_test, 0x20000140, 0x2a, 0, 0, 0, 0); break; case 8: syscall(SYS_serialize1, 0x20000180, 0x6a); break; case 9: *(uint8_t*)0x20000200 = 7; *(uint64_t*)0x20000201 = 0xffffffffffff3fcd; *(uint64_t*)0x20000209 = 0xffffffff; *(uint64_t*)0x20000211 = 0x40; syscall(SYS_test, 0x20000200, 0, 0, 0, 0, 0); break; case 10: memcpy((void*)0x20000000, "@\000", 2); STORE_BY_BITMASK(uint32_t, , 0x20000040, 7, 0, 10); STORE_BY_BITMASK(uint32_t, , 0x20000040, 0x100, 10, 10); STORE_BY_BITMASK(uint32_t, , 0x20000040, 1, 20, 10); *(uint8_t*)0x20000044 = -1; syz_compare(0x20000000, 2, 0x20000040, 8); break; case 11: syz_compare_int(2, 0x2bb, 5, 0, 0); break; case 12: syz_errno(0xff); break; case 13: memcpy((void*)0x20000080, "\x8f\xba\x4d\x89\x76\xc6\xe1\x21\xfc\xb9\x55\x9d\x46\x4b\xd7\x33\xd7\xf9\xeb\x39\x04\xe1\x45\x87\x8a\x03\x30\xb1\x33\x23\xc0\x9b\x64\x64\xf2\x73\x01\xdb\x8a\x6b\xb6\xe6\x95\xa9\x0c\xa7\xc3\xf5\xb0\x7e", 50); syz_execute_func(0x20000080); break; case 14: syz_exit(5); break; case 15: syz_mmap(0x20ffb000, 0x3000); break; } } int main(void) { syz_mmap(0x20000000, 0x1000000); use_temporary_dir(); do_sandbox_none(); return 0; } /usr/local/bin/ld: cannot find -lasan collect2: error: ld returned 1 exit status compiler invocation: gcc [-o /tmp/syz-executor792875137 -DGOOS_test=1 -DGOARCH_64=1 -DHOSTGOOS_freebsd=1 -x c - -O2 -pthread -Wall -Werror -Wparentheses -Wunused-const-variable -Wframe-larger-than=8192 -m64 -fsanitize=address] --- FAIL: TestGenerate/test/64/24 (0.75s) csource_test.go:110: opts: {Threaded:true Collide:false Repeat:true RepeatTimes:0 Procs:0 Sandbox:none Fault:false FaultCall:0 FaultNth:0 Leak:false EnableTun:false EnableNetDev:false EnableNetReset:false EnableCgroups:false EnableBinfmtMisc:false EnableCloseFds:false UseTmpDir:true HandleSegv:false Repro:false Trace:false} program: test$int(0x401, 0x1ff, 0x5, 0x8, 0x10001) syz_mmap(&(0x7f0000ffc000/0x3000)=nil, 0x3000) test$array1(&(0x7f0000000000)={0x7ff, "413e9c088f550bb2"}) test$length6(&(0x7f0000000040)={[0x9, 0x10001, 0x7, 0x7], 0x4}) test$union1(&(0x7f0000000080)={@f0=0xc917, 0x8}) test$align5(&(0x7f00000000c0)={{0x7, [0x8]}, {0x4, [0x7ac]}, 0x5}) foo$fmt5(&(0x7f0000000100)={0x5}) test$length27(&(0x7f0000000140)={0x6}, 0x2a) serialize1(&(0x7f0000000180)=""/106, 0x6a) test$array0(&(0x7f0000000200)={0x7, [@f1=0xffffffffffff3fcd, @f1=0xffffffff], 0x40}) syz_compare(&(0x7f0000000000)='@\x00', 0x2, &(0x7f0000000040)=@bf1={{0x7, 0x100, 0x1}, 0xffff}, 0x8) syz_compare_int$2(0x2, 0x2bb, 0x5) syz_errno(0xff) syz_execute_func(&(0x7f0000000080)="8fba4d8976c6e121fcb9559d464bd733d7f9eb3904e145878a0330b13323c09b6464f27301db8a6bb6e695a90ca7c3f5b07e") syz_exit(0x5) syz_mmap(&(0x7f0000ffb000/0x3000)=nil, 0x3000) csource_test.go:111: failed to build program: // autogenerated by syzkaller (https://github.com/google/syzkaller) #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include 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; for (i = 0; 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 { pthread_mutex_t mu; pthread_cond_t cv; int state; } event_t; static void event_init(event_t* ev) { if (pthread_mutex_init(&ev->mu, 0)) exit(1); if (pthread_cond_init(&ev->cv, 0)) exit(1); ev->state = 0; } static void event_reset(event_t* ev) { ev->state = 0; } static void event_set(event_t* ev) { pthread_mutex_lock(&ev->mu); if (ev->state) exit(1); ev->state = 1; pthread_mutex_unlock(&ev->mu); pthread_cond_broadcast(&ev->cv); } static void event_wait(event_t* ev) { pthread_mutex_lock(&ev->mu); while (!ev->state) pthread_cond_wait(&ev->cv, &ev->mu); pthread_mutex_unlock(&ev->mu); } static int event_isset(event_t* ev) { pthread_mutex_lock(&ev->mu); int res = ev->state; pthread_mutex_unlock(&ev->mu); return res; } static int event_timedwait(event_t* ev, uint64_t timeout) { uint64_t start = current_time_ms(); uint64_t now = start; pthread_mutex_lock(&ev->mu); for (;;) { if (ev->state) break; uint64_t remain = timeout - (now - start); struct timespec ts; ts.tv_sec = remain / 1000; ts.tv_nsec = (remain % 1000) * 1000 * 1000; pthread_cond_timedwait(&ev->cv, &ev->mu, &ts); now = current_time_ms(); if (now - start > timeout) break; } int res = ev->state; pthread_mutex_unlock(&ev->mu); return res; } #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)))) static long syz_mmap(volatile long a0, volatile long a1) { return (long)mmap((void*)a0, a1, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE | MAP_FIXED, -1, 0); } static long syz_errno(volatile long v) { errno = v; return v == 0 ? 0 : -1; } static long syz_exit(volatile long status) { _exit(status); return 0; } static long syz_compare(volatile long want, volatile long want_len, volatile long got, volatile long got_len) { if (want_len != got_len) { errno = EBADF; return -1; } if (memcmp((void*)want, (void*)got, want_len)) { errno = EINVAL; return -1; } return 0; } static long syz_compare_int(volatile long n, ...) { va_list args; va_start(args, n); long v0 = va_arg(args, long); long v1 = va_arg(args, long); long v2 = va_arg(args, long); long v3 = va_arg(args, long); va_end(args); if (n < 2 || n > 4) return errno = E2BIG, -1; if (n <= 2 && v2 != 0) return errno = EFAULT, -1; if (n <= 3 && v3 != 0) return errno = EFAULT, -1; if (v0 != v1) return errno = EINVAL, -1; if (n > 2 && v0 != v2) return errno = EINVAL, -1; if (n > 3 && v0 != v3) return errno = EINVAL, -1; return 0; } static void loop(); static int do_sandbox_none(void) { loop(); return 0; } static long syz_execute_func(volatile long text) { volatile long p[8] = {0}; (void)p; ((void (*)(void))(text))(); return 0; } 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 < 16; 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); event_timedwait(&th->done, 45); break; } } for (i = 0; i < 100 && __atomic_load_n(&running, __ATOMIC_RELAXED); i++) sleep_ms(1); } static void execute_one(void); static void loop(void) { execute_one(); } #ifndef SYS_foo #define SYS_foo 0 #endif #ifndef SYS_serialize1 #define SYS_serialize1 0 #endif #ifndef SYS_test #define SYS_test 0 #endif void execute_call(int call) { switch (call) { case 0: syscall(SYS_test, 0x401, -1, 5, 8, 0x10001, 0); break; case 1: syz_mmap(0x20ffc000, 0x3000); break; case 2: *(uint8_t*)0x20000000 = -1; memcpy((void*)0x20000001, "\x41\x3e\x9c\x08\x8f\x55\x0b\xb2", 8); syscall(SYS_test, 0x20000000, 0, 0, 0, 0, 0); break; case 3: *(uint16_t*)0x20000040 = 9; *(uint16_t*)0x20000042 = 1; *(uint16_t*)0x20000044 = 7; *(uint16_t*)0x20000046 = 7; *(uint16_t*)0x20000048 = 4; syscall(SYS_test, 0x20000040, 0, 0, 0, 0, 0); break; case 4: *(uint64_t*)0x20000080 = 0xc917; *(uint8_t*)0x20000088 = 8; syscall(SYS_test, 0x20000080, 0, 0, 0, 0, 0); break; case 5: *(uint64_t*)0x200000c0 = 7; *(uint16_t*)0x200000c8 = 8; *(uint64_t*)0x200000ca = 4; *(uint16_t*)0x200000d2 = 0x7ac; *(uint8_t*)0x200000d4 = 5; syscall(SYS_test, 0x200000c0, 0, 0, 0, 0, 0); break; case 6: sprintf((char*)0x20000100, "%020llu", (long long)5); syscall(SYS_foo, 0x20000100, 0); break; case 7: *(uint8_t*)0x20000140 = 6; syscall(SYS_test, 0x20000140, 0x2a, 0, 0, 0, 0); break; case 8: syscall(SYS_serialize1, 0x20000180, 0x6a); break; case 9: *(uint8_t*)0x20000200 = 7; *(uint64_t*)0x20000201 = 0xffffffffffff3fcd; *(uint64_t*)0x20000209 = 0xffffffff; *(uint64_t*)0x20000211 = 0x40; syscall(SYS_test, 0x20000200, 0, 0, 0, 0, 0); break; case 10: memcpy((void*)0x20000000, "@\000", 2); STORE_BY_BITMASK(uint32_t, , 0x20000040, 7, 0, 10); STORE_BY_BITMASK(uint32_t, , 0x20000040, 0x100, 10, 10); STORE_BY_BITMASK(uint32_t, , 0x20000040, 1, 20, 10); *(uint8_t*)0x20000044 = -1; syz_compare(0x20000000, 2, 0x20000040, 8); break; case 11: syz_compare_int(2, 0x2bb, 5, 0, 0); break; case 12: syz_errno(0xff); break; case 13: memcpy((void*)0x20000080, "\x8f\xba\x4d\x89\x76\xc6\xe1\x21\xfc\xb9\x55\x9d\x46\x4b\xd7\x33\xd7\xf9\xeb\x39\x04\xe1\x45\x87\x8a\x03\x30\xb1\x33\x23\xc0\x9b\x64\x64\xf2\x73\x01\xdb\x8a\x6b\xb6\xe6\x95\xa9\x0c\xa7\xc3\xf5\xb0\x7e", 50); syz_execute_func(0x20000080); break; case 14: syz_exit(5); break; case 15: syz_mmap(0x20ffb000, 0x3000); break; } } int main(void) { syz_mmap(0x20000000, 0x1000000); use_temporary_dir(); do_sandbox_none(); return 0; } /usr/local/bin/ld: cannot find -lasan collect2: error: ld returned 1 exit status compiler invocation: gcc [-o /tmp/syz-executor703231274 -DGOOS_test=1 -DGOARCH_64=1 -DHOSTGOOS_freebsd=1 -x c - -O2 -pthread -Wall -Werror -Wparentheses -Wunused-const-variable -Wframe-larger-than=8192 -m64 -fsanitize=address] --- FAIL: TestGenerate/test/64/25 (0.83s) csource_test.go:110: opts: {Threaded:true Collide:false Repeat:true RepeatTimes:0 Procs:0 Sandbox:none Fault:false FaultCall:0 FaultNth:0 Leak:false EnableTun:false EnableNetDev:false EnableNetReset:false EnableCgroups:false EnableBinfmtMisc:false EnableCloseFds:false UseTmpDir:true HandleSegv:true Repro:false Trace:false} program: test$int(0x401, 0x1ff, 0x5, 0x8, 0x10001) syz_mmap(&(0x7f0000ffc000/0x3000)=nil, 0x3000) test$array1(&(0x7f0000000000)={0x7ff, "413e9c088f550bb2"}) test$length6(&(0x7f0000000040)={[0x9, 0x10001, 0x7, 0x7], 0x4}) test$union1(&(0x7f0000000080)={@f0=0xc917, 0x8}) test$align5(&(0x7f00000000c0)={{0x7, [0x8]}, {0x4, [0x7ac]}, 0x5}) foo$fmt5(&(0x7f0000000100)={0x5}) test$length27(&(0x7f0000000140)={0x6}, 0x2a) serialize1(&(0x7f0000000180)=""/106, 0x6a) test$array0(&(0x7f0000000200)={0x7, [@f1=0xffffffffffff3fcd, @f1=0xffffffff], 0x40}) syz_compare(&(0x7f0000000000)='@\x00', 0x2, &(0x7f0000000040)=@bf1={{0x7, 0x100, 0x1}, 0xffff}, 0x8) syz_compare_int$2(0x2, 0x2bb, 0x5) syz_errno(0xff) syz_execute_func(&(0x7f0000000080)="8fba4d8976c6e121fcb9559d464bd733d7f9eb3904e145878a0330b13323c09b6464f27301db8a6bb6e695a90ca7c3f5b07e") syz_exit(0x5) syz_mmap(&(0x7f0000ffb000/0x3000)=nil, 0x3000) csource_test.go:111: failed to build program: // autogenerated by syzkaller (https://github.com/google/syzkaller) #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include #include #include 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_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; } 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; for (i = 0; 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 { pthread_mutex_t mu; pthread_cond_t cv; int state; } event_t; static void event_init(event_t* ev) { if (pthread_mutex_init(&ev->mu, 0)) exit(1); if (pthread_cond_init(&ev->cv, 0)) exit(1); ev->state = 0; } static void event_reset(event_t* ev) { ev->state = 0; } static void event_set(event_t* ev) { pthread_mutex_lock(&ev->mu); if (ev->state) exit(1); ev->state = 1; pthread_mutex_unlock(&ev->mu); pthread_cond_broadcast(&ev->cv); } static void event_wait(event_t* ev) { pthread_mutex_lock(&ev->mu); while (!ev->state) pthread_cond_wait(&ev->cv, &ev->mu); pthread_mutex_unlock(&ev->mu); } static int event_isset(event_t* ev) { pthread_mutex_lock(&ev->mu); int res = ev->state; pthread_mutex_unlock(&ev->mu); return res; } static int event_timedwait(event_t* ev, uint64_t timeout) { uint64_t start = current_time_ms(); uint64_t now = start; pthread_mutex_lock(&ev->mu); for (;;) { if (ev->state) break; uint64_t remain = timeout - (now - start); struct timespec ts; ts.tv_sec = remain / 1000; ts.tv_nsec = (remain % 1000) * 1000 * 1000; pthread_cond_timedwait(&ev->cv, &ev->mu, &ts); now = current_time_ms(); if (now - start > timeout) break; } int res = ev->state; pthread_mutex_unlock(&ev->mu); return res; } #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)))) static long syz_mmap(volatile long a0, volatile long a1) { return (long)mmap((void*)a0, a1, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE | MAP_FIXED, -1, 0); } static long syz_errno(volatile long v) { errno = v; return v == 0 ? 0 : -1; } static long syz_exit(volatile long status) { _exit(status); return 0; } static long syz_compare(volatile long want, volatile long want_len, volatile long got, volatile long got_len) { if (want_len != got_len) { errno = EBADF; return -1; } if (memcmp((void*)want, (void*)got, want_len)) { errno = EINVAL; return -1; } return 0; } static long syz_compare_int(volatile long n, ...) { va_list args; va_start(args, n); long v0 = va_arg(args, long); long v1 = va_arg(args, long); long v2 = va_arg(args, long); long v3 = va_arg(args, long); va_end(args); if (n < 2 || n > 4) return errno = E2BIG, -1; if (n <= 2 && v2 != 0) return errno = EFAULT, -1; if (n <= 3 && v3 != 0) return errno = EFAULT, -1; if (v0 != v1) return errno = EINVAL, -1; if (n > 2 && v0 != v2) return errno = EINVAL, -1; if (n > 3 && v0 != v3) return errno = EINVAL, -1; return 0; } static void loop(); static int do_sandbox_none(void) { loop(); return 0; } static long syz_execute_func(volatile long text) { volatile long p[8] = {0}; (void)p; NONFAILING(((void (*)(void))(text))()); return 0; } 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 < 16; 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); event_timedwait(&th->done, 45); break; } } for (i = 0; i < 100 && __atomic_load_n(&running, __ATOMIC_RELAXED); i++) sleep_ms(1); } static void execute_one(void); static void loop(void) { execute_one(); } #ifndef SYS_foo #define SYS_foo 0 #endif #ifndef SYS_serialize1 #define SYS_serialize1 0 #endif #ifndef SYS_test #define SYS_test 0 #endif void execute_call(int call) { switch (call) { case 0: syscall(SYS_test, 0x401, -1, 5, 8, 0x10001, 0); break; case 1: syz_mmap(0x20ffc000, 0x3000); break; case 2: NONFAILING(*(uint8_t*)0x20000000 = -1); NONFAILING(memcpy((void*)0x20000001, "\x41\x3e\x9c\x08\x8f\x55\x0b\xb2", 8)); syscall(SYS_test, 0x20000000, 0, 0, 0, 0, 0); break; case 3: NONFAILING(*(uint16_t*)0x20000040 = 9); NONFAILING(*(uint16_t*)0x20000042 = 1); NONFAILING(*(uint16_t*)0x20000044 = 7); NONFAILING(*(uint16_t*)0x20000046 = 7); NONFAILING(*(uint16_t*)0x20000048 = 4); syscall(SYS_test, 0x20000040, 0, 0, 0, 0, 0); break; case 4: NONFAILING(*(uint64_t*)0x20000080 = 0xc917); NONFAILING(*(uint8_t*)0x20000088 = 8); syscall(SYS_test, 0x20000080, 0, 0, 0, 0, 0); break; case 5: NONFAILING(*(uint64_t*)0x200000c0 = 7); NONFAILING(*(uint16_t*)0x200000c8 = 8); NONFAILING(*(uint64_t*)0x200000ca = 4); NONFAILING(*(uint16_t*)0x200000d2 = 0x7ac); NONFAILING(*(uint8_t*)0x200000d4 = 5); syscall(SYS_test, 0x200000c0, 0, 0, 0, 0, 0); break; case 6: NONFAILING(sprintf((char*)0x20000100, "%020llu", (long long)5)); syscall(SYS_foo, 0x20000100, 0); break; case 7: NONFAILING(*(uint8_t*)0x20000140 = 6); syscall(SYS_test, 0x20000140, 0x2a, 0, 0, 0, 0); break; case 8: syscall(SYS_serialize1, 0x20000180, 0x6a); break; case 9: NONFAILING(*(uint8_t*)0x20000200 = 7); NONFAILING(*(uint64_t*)0x20000201 = 0xffffffffffff3fcd); NONFAILING(*(uint64_t*)0x20000209 = 0xffffffff); NONFAILING(*(uint64_t*)0x20000211 = 0x40); syscall(SYS_test, 0x20000200, 0, 0, 0, 0, 0); break; case 10: NONFAILING(memcpy((void*)0x20000000, "@\000", 2)); NONFAILING(STORE_BY_BITMASK(uint32_t, , 0x20000040, 7, 0, 10)); NONFAILING(STORE_BY_BITMASK(uint32_t, , 0x20000040, 0x100, 10, 10)); NONFAILING(STORE_BY_BITMASK(uint32_t, , 0x20000040, 1, 20, 10)); NONFAILING(*(uint8_t*)0x20000044 = -1); syz_compare(0x20000000, 2, 0x20000040, 8); break; case 11: syz_compare_int(2, 0x2bb, 5, 0, 0); break; case 12: syz_errno(0xff); break; case 13: NONFAILING(memcpy((void*)0x20000080, "\x8f\xba\x4d\x89\x76\xc6\xe1\x21\xfc\xb9\x55\x9d\x46\x4b\xd7\x33\xd7\xf9\xeb\x39\x04\xe1\x45\x87\x8a\x03\x30\xb1\x33\x23\xc0\x9b\x64\x64\xf2\x73\x01\xdb\x8a\x6b\xb6\xe6\x95\xa9\x0c\xa7\xc3\xf5\xb0\x7e", 50)); syz_execute_func(0x20000080); break; case 14: syz_exit(5); break; case 15: syz_mmap(0x20ffb000, 0x3000); break; } } int main(void) { syz_mmap(0x20000000, 0x1000000); install_segv_handler(); use_temporary_dir(); do_sandbox_none(); return 0; } /usr/local/bin/ld: cannot find -lasan collect2: error: ld returned 1 exit status compiler invocation: gcc [-o /tmp/syz-executor064363319 -DGOOS_test=1 -DGOARCH_64=1 -DHOSTGOOS_freebsd=1 -x c - -O2 -pthread -Wall -Werror -Wparentheses -Wunused-const-variable -Wframe-larger-than=8192 -m64 -fsanitize=address] --- FAIL: TestGenerate/test/64/27 (1.18s) csource_test.go:110: opts: {Threaded:true Collide:false Repeat:true RepeatTimes:0 Procs:0 Sandbox:none Fault:false FaultCall:0 FaultNth:0 Leak:false EnableTun:false EnableNetDev:false EnableNetReset:false EnableCgroups:false EnableBinfmtMisc:false EnableCloseFds:false UseTmpDir:true HandleSegv:false Repro:true Trace:false} program: test$int(0x401, 0x1ff, 0x5, 0x8, 0x10001) syz_mmap(&(0x7f0000ffc000/0x3000)=nil, 0x3000) test$array1(&(0x7f0000000000)={0x7ff, "413e9c088f550bb2"}) test$length6(&(0x7f0000000040)={[0x9, 0x10001, 0x7, 0x7], 0x4}) test$union1(&(0x7f0000000080)={@f0=0xc917, 0x8}) test$align5(&(0x7f00000000c0)={{0x7, [0x8]}, {0x4, [0x7ac]}, 0x5}) foo$fmt5(&(0x7f0000000100)={0x5}) test$length27(&(0x7f0000000140)={0x6}, 0x2a) serialize1(&(0x7f0000000180)=""/106, 0x6a) test$array0(&(0x7f0000000200)={0x7, [@f1=0xffffffffffff3fcd, @f1=0xffffffff], 0x40}) syz_compare(&(0x7f0000000000)='@\x00', 0x2, &(0x7f0000000040)=@bf1={{0x7, 0x100, 0x1}, 0xffff}, 0x8) syz_compare_int$2(0x2, 0x2bb, 0x5) syz_errno(0xff) syz_execute_func(&(0x7f0000000080)="8fba4d8976c6e121fcb9559d464bd733d7f9eb3904e145878a0330b13323c09b6464f27301db8a6bb6e695a90ca7c3f5b07e") syz_exit(0x5) syz_mmap(&(0x7f0000ffb000/0x3000)=nil, 0x3000) csource_test.go:111: failed to build program: // autogenerated by syzkaller (https://github.com/google/syzkaller) #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include 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; for (i = 0; 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 { pthread_mutex_t mu; pthread_cond_t cv; int state; } event_t; static void event_init(event_t* ev) { if (pthread_mutex_init(&ev->mu, 0)) exit(1); if (pthread_cond_init(&ev->cv, 0)) exit(1); ev->state = 0; } static void event_reset(event_t* ev) { ev->state = 0; } static void event_set(event_t* ev) { pthread_mutex_lock(&ev->mu); if (ev->state) exit(1); ev->state = 1; pthread_mutex_unlock(&ev->mu); pthread_cond_broadcast(&ev->cv); } static void event_wait(event_t* ev) { pthread_mutex_lock(&ev->mu); while (!ev->state) pthread_cond_wait(&ev->cv, &ev->mu); pthread_mutex_unlock(&ev->mu); } static int event_isset(event_t* ev) { pthread_mutex_lock(&ev->mu); int res = ev->state; pthread_mutex_unlock(&ev->mu); return res; } static int event_timedwait(event_t* ev, uint64_t timeout) { uint64_t start = current_time_ms(); uint64_t now = start; pthread_mutex_lock(&ev->mu); for (;;) { if (ev->state) break; uint64_t remain = timeout - (now - start); struct timespec ts; ts.tv_sec = remain / 1000; ts.tv_nsec = (remain % 1000) * 1000 * 1000; pthread_cond_timedwait(&ev->cv, &ev->mu, &ts); now = current_time_ms(); if (now - start > timeout) break; } int res = ev->state; pthread_mutex_unlock(&ev->mu); return res; } #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)))) static long syz_mmap(volatile long a0, volatile long a1) { return (long)mmap((void*)a0, a1, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE | MAP_FIXED, -1, 0); } static long syz_errno(volatile long v) { errno = v; return v == 0 ? 0 : -1; } static long syz_exit(volatile long status) { _exit(status); return 0; } static long syz_compare(volatile long want, volatile long want_len, volatile long got, volatile long got_len) { if (want_len != got_len) { errno = EBADF; return -1; } if (memcmp((void*)want, (void*)got, want_len)) { errno = EINVAL; return -1; } return 0; } static long syz_compare_int(volatile long n, ...) { va_list args; va_start(args, n); long v0 = va_arg(args, long); long v1 = va_arg(args, long); long v2 = va_arg(args, long); long v3 = va_arg(args, long); va_end(args); if (n < 2 || n > 4) return errno = E2BIG, -1; if (n <= 2 && v2 != 0) return errno = EFAULT, -1; if (n <= 3 && v3 != 0) return errno = EFAULT, -1; if (v0 != v1) return errno = EINVAL, -1; if (n > 2 && v0 != v2) return errno = EINVAL, -1; if (n > 3 && v0 != v3) return errno = EINVAL, -1; return 0; } static void loop(); static int do_sandbox_none(void) { loop(); return 0; } static long syz_execute_func(volatile long text) { volatile long p[8] = {0}; (void)p; ((void (*)(void))(text))(); return 0; } 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) { if (write(1, "executing program\n", sizeof("executing program\n") - 1)) { } int i, call, thread; for (call = 0; call < 16; 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); event_timedwait(&th->done, 45); break; } } for (i = 0; i < 100 && __atomic_load_n(&running, __ATOMIC_RELAXED); i++) sleep_ms(1); } static void execute_one(void); static void loop(void) { execute_one(); } #ifndef SYS_foo #define SYS_foo 0 #endif #ifndef SYS_serialize1 #define SYS_serialize1 0 #endif #ifndef SYS_test #define SYS_test 0 #endif void execute_call(int call) { switch (call) { case 0: syscall(SYS_test, 0x401, -1, 5, 8, 0x10001, 0); break; case 1: syz_mmap(0x20ffc000, 0x3000); break; case 2: *(uint8_t*)0x20000000 = -1; memcpy((void*)0x20000001, "\x41\x3e\x9c\x08\x8f\x55\x0b\xb2", 8); syscall(SYS_test, 0x20000000, 0, 0, 0, 0, 0); break; case 3: *(uint16_t*)0x20000040 = 9; *(uint16_t*)0x20000042 = 1; *(uint16_t*)0x20000044 = 7; *(uint16_t*)0x20000046 = 7; *(uint16_t*)0x20000048 = 4; syscall(SYS_test, 0x20000040, 0, 0, 0, 0, 0); break; case 4: *(uint64_t*)0x20000080 = 0xc917; *(uint8_t*)0x20000088 = 8; syscall(SYS_test, 0x20000080, 0, 0, 0, 0, 0); break; case 5: *(uint64_t*)0x200000c0 = 7; *(uint16_t*)0x200000c8 = 8; *(uint64_t*)0x200000ca = 4; *(uint16_t*)0x200000d2 = 0x7ac; *(uint8_t*)0x200000d4 = 5; syscall(SYS_test, 0x200000c0, 0, 0, 0, 0, 0); break; case 6: sprintf((char*)0x20000100, "%020llu", (long long)5); syscall(SYS_foo, 0x20000100, 0); break; case 7: *(uint8_t*)0x20000140 = 6; syscall(SYS_test, 0x20000140, 0x2a, 0, 0, 0, 0); break; case 8: syscall(SYS_serialize1, 0x20000180, 0x6a); break; case 9: *(uint8_t*)0x20000200 = 7; *(uint64_t*)0x20000201 = 0xffffffffffff3fcd; *(uint64_t*)0x20000209 = 0xffffffff; *(uint64_t*)0x20000211 = 0x40; syscall(SYS_test, 0x20000200, 0, 0, 0, 0, 0); break; case 10: memcpy((void*)0x20000000, "@\000", 2); STORE_BY_BITMASK(uint32_t, , 0x20000040, 7, 0, 10); STORE_BY_BITMASK(uint32_t, , 0x20000040, 0x100, 10, 10); STORE_BY_BITMASK(uint32_t, , 0x20000040, 1, 20, 10); *(uint8_t*)0x20000044 = -1; syz_compare(0x20000000, 2, 0x20000040, 8); break; case 11: syz_compare_int(2, 0x2bb, 5, 0, 0); break; case 12: syz_errno(0xff); break; case 13: memcpy((void*)0x20000080, "\x8f\xba\x4d\x89\x76\xc6\xe1\x21\xfc\xb9\x55\x9d\x46\x4b\xd7\x33\xd7\xf9\xeb\x39\x04\xe1\x45\x87\x8a\x03\x30\xb1\x33\x23\xc0\x9b\x64\x64\xf2\x73\x01\xdb\x8a\x6b\xb6\xe6\x95\xa9\x0c\xa7\xc3\xf5\xb0\x7e", 50); syz_execute_func(0x20000080); break; case 14: syz_exit(5); break; case 15: syz_mmap(0x20ffb000, 0x3000); break; } } int main(void) { syz_mmap(0x20000000, 0x1000000); use_temporary_dir(); do_sandbox_none(); return 0; } /usr/local/bin/ld: cannot find -lasan collect2: error: ld returned 1 exit status compiler invocation: gcc [-o /tmp/syz-executor612592125 -DGOOS_test=1 -DGOARCH_64=1 -DHOSTGOOS_freebsd=1 -x c - -O2 -pthread -Wall -Werror -Wparentheses -Wunused-const-variable -Wframe-larger-than=8192 -m64 -fsanitize=address] --- FAIL: TestGenerate/test/64/22 (0.60s) csource_test.go:110: opts: {Threaded:true Collide:false Repeat:true RepeatTimes:0 Procs:0 Sandbox:none Fault:false FaultCall:0 FaultNth:0 Leak:false EnableTun:false EnableNetDev:false EnableNetReset:false EnableCgroups:false EnableBinfmtMisc:false EnableCloseFds:false UseTmpDir:false HandleSegv:false Repro:false Trace:false} program: test$int(0x401, 0x1ff, 0x5, 0x8, 0x10001) syz_mmap(&(0x7f0000ffc000/0x3000)=nil, 0x3000) test$array1(&(0x7f0000000000)={0x7ff, "413e9c088f550bb2"}) test$length6(&(0x7f0000000040)={[0x9, 0x10001, 0x7, 0x7], 0x4}) test$union1(&(0x7f0000000080)={@f0=0xc917, 0x8}) test$align5(&(0x7f00000000c0)={{0x7, [0x8]}, {0x4, [0x7ac]}, 0x5}) foo$fmt5(&(0x7f0000000100)={0x5}) test$length27(&(0x7f0000000140)={0x6}, 0x2a) serialize1(&(0x7f0000000180)=""/106, 0x6a) test$array0(&(0x7f0000000200)={0x7, [@f1=0xffffffffffff3fcd, @f1=0xffffffff], 0x40}) syz_compare(&(0x7f0000000000)='@\x00', 0x2, &(0x7f0000000040)=@bf1={{0x7, 0x100, 0x1}, 0xffff}, 0x8) syz_compare_int$2(0x2, 0x2bb, 0x5) syz_errno(0xff) syz_execute_func(&(0x7f0000000080)="8fba4d8976c6e121fcb9559d464bd733d7f9eb3904e145878a0330b13323c09b6464f27301db8a6bb6e695a90ca7c3f5b07e") syz_exit(0x5) syz_mmap(&(0x7f0000ffb000/0x3000)=nil, 0x3000) csource_test.go:111: failed to build program: // autogenerated by syzkaller (https://github.com/google/syzkaller) #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include 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 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; for (i = 0; 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 { pthread_mutex_t mu; pthread_cond_t cv; int state; } event_t; static void event_init(event_t* ev) { if (pthread_mutex_init(&ev->mu, 0)) exit(1); if (pthread_cond_init(&ev->cv, 0)) exit(1); ev->state = 0; } static void event_reset(event_t* ev) { ev->state = 0; } static void event_set(event_t* ev) { pthread_mutex_lock(&ev->mu); if (ev->state) exit(1); ev->state = 1; pthread_mutex_unlock(&ev->mu); pthread_cond_broadcast(&ev->cv); } static void event_wait(event_t* ev) { pthread_mutex_lock(&ev->mu); while (!ev->state) pthread_cond_wait(&ev->cv, &ev->mu); pthread_mutex_unlock(&ev->mu); } static int event_isset(event_t* ev) { pthread_mutex_lock(&ev->mu); int res = ev->state; pthread_mutex_unlock(&ev->mu); return res; } static int event_timedwait(event_t* ev, uint64_t timeout) { uint64_t start = current_time_ms(); uint64_t now = start; pthread_mutex_lock(&ev->mu); for (;;) { if (ev->state) break; uint64_t remain = timeout - (now - start); struct timespec ts; ts.tv_sec = remain / 1000; ts.tv_nsec = (remain % 1000) * 1000 * 1000; pthread_cond_timedwait(&ev->cv, &ev->mu, &ts); now = current_time_ms(); if (now - start > timeout) break; } int res = ev->state; pthread_mutex_unlock(&ev->mu); return res; } #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)))) static long syz_mmap(volatile long a0, volatile long a1) { return (long)mmap((void*)a0, a1, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE | MAP_FIXED, -1, 0); } static long syz_errno(volatile long v) { errno = v; return v == 0 ? 0 : -1; } static long syz_exit(volatile long status) { _exit(status); return 0; } static long syz_compare(volatile long want, volatile long want_len, volatile long got, volatile long got_len) { if (want_len != got_len) { errno = EBADF; return -1; } if (memcmp((void*)want, (void*)got, want_len)) { errno = EINVAL; return -1; } return 0; } static long syz_compare_int(volatile long n, ...) { va_list args; va_start(args, n); long v0 = va_arg(args, long); long v1 = va_arg(args, long); long v2 = va_arg(args, long); long v3 = va_arg(args, long); va_end(args); if (n < 2 || n > 4) return errno = E2BIG, -1; if (n <= 2 && v2 != 0) return errno = EFAULT, -1; if (n <= 3 && v3 != 0) return errno = EFAULT, -1; if (v0 != v1) return errno = EINVAL, -1; if (n > 2 && v0 != v2) return errno = EINVAL, -1; if (n > 3 && v0 != v3) return errno = EINVAL, -1; return 0; } static void loop(); static int do_sandbox_none(void) { loop(); return 0; } static long syz_execute_func(volatile long text) { volatile long p[8] = {0}; (void)p; ((void (*)(void))(text))(); return 0; } 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 < 16; 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); event_timedwait(&th->done, 45); break; } } for (i = 0; i < 100 && __atomic_load_n(&running, __ATOMIC_RELAXED); i++) sleep_ms(1); } static void execute_one(void); static void loop(void) { execute_one(); } #ifndef SYS_foo #define SYS_foo 0 #endif #ifndef SYS_serialize1 #define SYS_serialize1 0 #endif #ifndef SYS_test #define SYS_test 0 #endif void execute_call(int call) { switch (call) { case 0: syscall(SYS_test, 0x401, -1, 5, 8, 0x10001, 0); break; case 1: syz_mmap(0x20ffc000, 0x3000); break; case 2: *(uint8_t*)0x20000000 = -1; memcpy((void*)0x20000001, "\x41\x3e\x9c\x08\x8f\x55\x0b\xb2", 8); syscall(SYS_test, 0x20000000, 0, 0, 0, 0, 0); break; case 3: *(uint16_t*)0x20000040 = 9; *(uint16_t*)0x20000042 = 1; *(uint16_t*)0x20000044 = 7; *(uint16_t*)0x20000046 = 7; *(uint16_t*)0x20000048 = 4; syscall(SYS_test, 0x20000040, 0, 0, 0, 0, 0); break; case 4: *(uint64_t*)0x20000080 = 0xc917; *(uint8_t*)0x20000088 = 8; syscall(SYS_test, 0x20000080, 0, 0, 0, 0, 0); break; case 5: *(uint64_t*)0x200000c0 = 7; *(uint16_t*)0x200000c8 = 8; *(uint64_t*)0x200000ca = 4; *(uint16_t*)0x200000d2 = 0x7ac; *(uint8_t*)0x200000d4 = 5; syscall(SYS_test, 0x200000c0, 0, 0, 0, 0, 0); break; case 6: sprintf((char*)0x20000100, "%020llu", (long long)5); syscall(SYS_foo, 0x20000100, 0); break; case 7: *(uint8_t*)0x20000140 = 6; syscall(SYS_test, 0x20000140, 0x2a, 0, 0, 0, 0); break; case 8: syscall(SYS_serialize1, 0x20000180, 0x6a); break; case 9: *(uint8_t*)0x20000200 = 7; *(uint64_t*)0x20000201 = 0xffffffffffff3fcd; *(uint64_t*)0x20000209 = 0xffffffff; *(uint64_t*)0x20000211 = 0x40; syscall(SYS_test, 0x20000200, 0, 0, 0, 0, 0); break; case 10: memcpy((void*)0x20000000, "@\000", 2); STORE_BY_BITMASK(uint32_t, , 0x20000040, 7, 0, 10); STORE_BY_BITMASK(uint32_t, , 0x20000040, 0x100, 10, 10); STORE_BY_BITMASK(uint32_t, , 0x20000040, 1, 20, 10); *(uint8_t*)0x20000044 = -1; syz_compare(0x20000000, 2, 0x20000040, 8); break; case 11: syz_compare_int(2, 0x2bb, 5, 0, 0); break; case 12: syz_errno(0xff); break; case 13: memcpy((void*)0x20000080, "\x8f\xba\x4d\x89\x76\xc6\xe1\x21\xfc\xb9\x55\x9d\x46\x4b\xd7\x33\xd7\xf9\xeb\x39\x04\xe1\x45\x87\x8a\x03\x30\xb1\x33\x23\xc0\x9b\x64\x64\xf2\x73\x01\xdb\x8a\x6b\xb6\xe6\x95\xa9\x0c\xa7\xc3\xf5\xb0\x7e", 50); syz_execute_func(0x20000080); break; case 14: syz_exit(5); break; case 15: syz_mmap(0x20ffb000, 0x3000); break; } } int main(void) { syz_mmap(0x20000000, 0x1000000); do_sandbox_none(); return 0; } /usr/local/bin/ld: cannot find -lasan collect2: error: ld returned 1 exit status compiler invocation: gcc [-o /tmp/syz-executor324638188 -DGOOS_test=1 -DGOARCH_64=1 -DHOSTGOOS_freebsd=1 -x c - -O2 -pthread -Wall -Werror -Wparentheses -Wunused-const-variable -Wframe-larger-than=8192 -m64 -fsanitize=address] --- FAIL: TestGenerate/test/64/21 (0.72s) csource_test.go:110: opts: {Threaded:true Collide:false Repeat:true RepeatTimes:0 Procs:0 Sandbox:none Fault:false FaultCall:0 FaultNth:0 Leak:false EnableTun:false EnableNetDev:false EnableNetReset:false EnableCgroups:false EnableBinfmtMisc:false EnableCloseFds:false UseTmpDir:true HandleSegv:false Repro:false Trace:false} program: test$int(0x401, 0x1ff, 0x5, 0x8, 0x10001) syz_mmap(&(0x7f0000ffc000/0x3000)=nil, 0x3000) test$array1(&(0x7f0000000000)={0x7ff, "413e9c088f550bb2"}) test$length6(&(0x7f0000000040)={[0x9, 0x10001, 0x7, 0x7], 0x4}) test$union1(&(0x7f0000000080)={@f0=0xc917, 0x8}) test$align5(&(0x7f00000000c0)={{0x7, [0x8]}, {0x4, [0x7ac]}, 0x5}) foo$fmt5(&(0x7f0000000100)={0x5}) test$length27(&(0x7f0000000140)={0x6}, 0x2a) serialize1(&(0x7f0000000180)=""/106, 0x6a) test$array0(&(0x7f0000000200)={0x7, [@f1=0xffffffffffff3fcd, @f1=0xffffffff], 0x40}) syz_compare(&(0x7f0000000000)='@\x00', 0x2, &(0x7f0000000040)=@bf1={{0x7, 0x100, 0x1}, 0xffff}, 0x8) syz_compare_int$2(0x2, 0x2bb, 0x5) syz_errno(0xff) syz_execute_func(&(0x7f0000000080)="8fba4d8976c6e121fcb9559d464bd733d7f9eb3904e145878a0330b13323c09b6464f27301db8a6bb6e695a90ca7c3f5b07e") syz_exit(0x5) syz_mmap(&(0x7f0000ffb000/0x3000)=nil, 0x3000) csource_test.go:111: failed to build program: // autogenerated by syzkaller (https://github.com/google/syzkaller) #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include 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; for (i = 0; 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 { pthread_mutex_t mu; pthread_cond_t cv; int state; } event_t; static void event_init(event_t* ev) { if (pthread_mutex_init(&ev->mu, 0)) exit(1); if (pthread_cond_init(&ev->cv, 0)) exit(1); ev->state = 0; } static void event_reset(event_t* ev) { ev->state = 0; } static void event_set(event_t* ev) { pthread_mutex_lock(&ev->mu); if (ev->state) exit(1); ev->state = 1; pthread_mutex_unlock(&ev->mu); pthread_cond_broadcast(&ev->cv); } static void event_wait(event_t* ev) { pthread_mutex_lock(&ev->mu); while (!ev->state) pthread_cond_wait(&ev->cv, &ev->mu); pthread_mutex_unlock(&ev->mu); } static int event_isset(event_t* ev) { pthread_mutex_lock(&ev->mu); int res = ev->state; pthread_mutex_unlock(&ev->mu); return res; } static int event_timedwait(event_t* ev, uint64_t timeout) { uint64_t start = current_time_ms(); uint64_t now = start; pthread_mutex_lock(&ev->mu); for (;;) { if (ev->state) break; uint64_t remain = timeout - (now - start); struct timespec ts; ts.tv_sec = remain / 1000; ts.tv_nsec = (remain % 1000) * 1000 * 1000; pthread_cond_timedwait(&ev->cv, &ev->mu, &ts); now = current_time_ms(); if (now - start > timeout) break; } int res = ev->state; pthread_mutex_unlock(&ev->mu); return res; } #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)))) static long syz_mmap(volatile long a0, volatile long a1) { return (long)mmap((void*)a0, a1, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE | MAP_FIXED, -1, 0); } static long syz_errno(volatile long v) { errno = v; return v == 0 ? 0 : -1; } static long syz_exit(volatile long status) { _exit(status); return 0; } static long syz_compare(volatile long want, volatile long want_len, volatile long got, volatile long got_len) { if (want_len != got_len) { errno = EBADF; return -1; } if (memcmp((void*)want, (void*)got, want_len)) { errno = EINVAL; return -1; } return 0; } static long syz_compare_int(volatile long n, ...) { va_list args; va_start(args, n); long v0 = va_arg(args, long); long v1 = va_arg(args, long); long v2 = va_arg(args, long); long v3 = va_arg(args, long); va_end(args); if (n < 2 || n > 4) return errno = E2BIG, -1; if (n <= 2 && v2 != 0) return errno = EFAULT, -1; if (n <= 3 && v3 != 0) return errno = EFAULT, -1; if (v0 != v1) return errno = EINVAL, -1; if (n > 2 && v0 != v2) return errno = EINVAL, -1; if (n > 3 && v0 != v3) return errno = EINVAL, -1; return 0; } static void loop(); static int do_sandbox_none(void) { loop(); return 0; } static long syz_execute_func(volatile long text) { volatile long p[8] = {0}; (void)p; ((void (*)(void))(text))(); return 0; } 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 < 16; 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); event_timedwait(&th->done, 45); break; } } for (i = 0; i < 100 && __atomic_load_n(&running, __ATOMIC_RELAXED); i++) sleep_ms(1); } static void execute_one(void); static void loop(void) { execute_one(); } #ifndef SYS_foo #define SYS_foo 0 #endif #ifndef SYS_serialize1 #define SYS_serialize1 0 #endif #ifndef SYS_test #define SYS_test 0 #endif void execute_call(int call) { switch (call) { case 0: syscall(SYS_test, 0x401, -1, 5, 8, 0x10001, 0); break; case 1: syz_mmap(0x20ffc000, 0x3000); break; case 2: *(uint8_t*)0x20000000 = -1; memcpy((void*)0x20000001, "\x41\x3e\x9c\x08\x8f\x55\x0b\xb2", 8); syscall(SYS_test, 0x20000000, 0, 0, 0, 0, 0); break; case 3: *(uint16_t*)0x20000040 = 9; *(uint16_t*)0x20000042 = 1; *(uint16_t*)0x20000044 = 7; *(uint16_t*)0x20000046 = 7; *(uint16_t*)0x20000048 = 4; syscall(SYS_test, 0x20000040, 0, 0, 0, 0, 0); break; case 4: *(uint64_t*)0x20000080 = 0xc917; *(uint8_t*)0x20000088 = 8; syscall(SYS_test, 0x20000080, 0, 0, 0, 0, 0); break; case 5: *(uint64_t*)0x200000c0 = 7; *(uint16_t*)0x200000c8 = 8; *(uint64_t*)0x200000ca = 4; *(uint16_t*)0x200000d2 = 0x7ac; *(uint8_t*)0x200000d4 = 5; syscall(SYS_test, 0x200000c0, 0, 0, 0, 0, 0); break; case 6: sprintf((char*)0x20000100, "%020llu", (long long)5); syscall(SYS_foo, 0x20000100, 0); break; case 7: *(uint8_t*)0x20000140 = 6; syscall(SYS_test, 0x20000140, 0x2a, 0, 0, 0, 0); break; case 8: syscall(SYS_serialize1, 0x20000180, 0x6a); break; case 9: *(uint8_t*)0x20000200 = 7; *(uint64_t*)0x20000201 = 0xffffffffffff3fcd; *(uint64_t*)0x20000209 = 0xffffffff; *(uint64_t*)0x20000211 = 0x40; syscall(SYS_test, 0x20000200, 0, 0, 0, 0, 0); break; case 10: memcpy((void*)0x20000000, "@\000", 2); STORE_BY_BITMASK(uint32_t, , 0x20000040, 7, 0, 10); STORE_BY_BITMASK(uint32_t, , 0x20000040, 0x100, 10, 10); STORE_BY_BITMASK(uint32_t, , 0x20000040, 1, 20, 10); *(uint8_t*)0x20000044 = -1; syz_compare(0x20000000, 2, 0x20000040, 8); break; case 11: syz_compare_int(2, 0x2bb, 5, 0, 0); break; case 12: syz_errno(0xff); break; case 13: memcpy((void*)0x20000080, "\x8f\xba\x4d\x89\x76\xc6\xe1\x21\xfc\xb9\x55\x9d\x46\x4b\xd7\x33\xd7\xf9\xeb\x39\x04\xe1\x45\x87\x8a\x03\x30\xb1\x33\x23\xc0\x9b\x64\x64\xf2\x73\x01\xdb\x8a\x6b\xb6\xe6\x95\xa9\x0c\xa7\xc3\xf5\xb0\x7e", 50); syz_execute_func(0x20000080); break; case 14: syz_exit(5); break; case 15: syz_mmap(0x20ffb000, 0x3000); break; } } int main(void) { syz_mmap(0x20000000, 0x1000000); use_temporary_dir(); do_sandbox_none(); return 0; } /usr/local/bin/ld: cannot find -lasan collect2: error: ld returned 1 exit status compiler invocation: gcc [-o /tmp/syz-executor586940507 -DGOOS_test=1 -DGOARCH_64=1 -DHOSTGOOS_freebsd=1 -x c - -O2 -pthread -Wall -Werror -Wparentheses -Wunused-const-variable -Wframe-larger-than=8192 -m64 -fsanitize=address] --- FAIL: TestGenerate/test/64/20 (0.71s) csource_test.go:110: opts: {Threaded:true Collide:false Repeat:true RepeatTimes:0 Procs:0 Sandbox:none Fault:false FaultCall:0 FaultNth:0 Leak:false EnableTun:false EnableNetDev:false EnableNetReset:false EnableCgroups:false EnableBinfmtMisc:false EnableCloseFds:false UseTmpDir:true HandleSegv:false Repro:false Trace:false} program: test$int(0x401, 0x1ff, 0x5, 0x8, 0x10001) syz_mmap(&(0x7f0000ffc000/0x3000)=nil, 0x3000) test$array1(&(0x7f0000000000)={0x7ff, "413e9c088f550bb2"}) test$length6(&(0x7f0000000040)={[0x9, 0x10001, 0x7, 0x7], 0x4}) test$union1(&(0x7f0000000080)={@f0=0xc917, 0x8}) test$align5(&(0x7f00000000c0)={{0x7, [0x8]}, {0x4, [0x7ac]}, 0x5}) foo$fmt5(&(0x7f0000000100)={0x5}) test$length27(&(0x7f0000000140)={0x6}, 0x2a) serialize1(&(0x7f0000000180)=""/106, 0x6a) test$array0(&(0x7f0000000200)={0x7, [@f1=0xffffffffffff3fcd, @f1=0xffffffff], 0x40}) syz_compare(&(0x7f0000000000)='@\x00', 0x2, &(0x7f0000000040)=@bf1={{0x7, 0x100, 0x1}, 0xffff}, 0x8) syz_compare_int$2(0x2, 0x2bb, 0x5) syz_errno(0xff) syz_execute_func(&(0x7f0000000080)="8fba4d8976c6e121fcb9559d464bd733d7f9eb3904e145878a0330b13323c09b6464f27301db8a6bb6e695a90ca7c3f5b07e") syz_exit(0x5) syz_mmap(&(0x7f0000ffb000/0x3000)=nil, 0x3000) csource_test.go:111: failed to build program: // autogenerated by syzkaller (https://github.com/google/syzkaller) #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include 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; for (i = 0; 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 { pthread_mutex_t mu; pthread_cond_t cv; int state; } event_t; static void event_init(event_t* ev) { if (pthread_mutex_init(&ev->mu, 0)) exit(1); if (pthread_cond_init(&ev->cv, 0)) exit(1); ev->state = 0; } static void event_reset(event_t* ev) { ev->state = 0; } static void event_set(event_t* ev) { pthread_mutex_lock(&ev->mu); if (ev->state) exit(1); ev->state = 1; pthread_mutex_unlock(&ev->mu); pthread_cond_broadcast(&ev->cv); } static void event_wait(event_t* ev) { pthread_mutex_lock(&ev->mu); while (!ev->state) pthread_cond_wait(&ev->cv, &ev->mu); pthread_mutex_unlock(&ev->mu); } static int event_isset(event_t* ev) { pthread_mutex_lock(&ev->mu); int res = ev->state; pthread_mutex_unlock(&ev->mu); return res; } static int event_timedwait(event_t* ev, uint64_t timeout) { uint64_t start = current_time_ms(); uint64_t now = start; pthread_mutex_lock(&ev->mu); for (;;) { if (ev->state) break; uint64_t remain = timeout - (now - start); struct timespec ts; ts.tv_sec = remain / 1000; ts.tv_nsec = (remain % 1000) * 1000 * 1000; pthread_cond_timedwait(&ev->cv, &ev->mu, &ts); now = current_time_ms(); if (now - start > timeout) break; } int res = ev->state; pthread_mutex_unlock(&ev->mu); return res; } #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)))) static long syz_mmap(volatile long a0, volatile long a1) { return (long)mmap((void*)a0, a1, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE | MAP_FIXED, -1, 0); } static long syz_errno(volatile long v) { errno = v; return v == 0 ? 0 : -1; } static long syz_exit(volatile long status) { _exit(status); return 0; } static long syz_compare(volatile long want, volatile long want_len, volatile long got, volatile long got_len) { if (want_len != got_len) { errno = EBADF; return -1; } if (memcmp((void*)want, (void*)got, want_len)) { errno = EINVAL; return -1; } return 0; } static long syz_compare_int(volatile long n, ...) { va_list args; va_start(args, n); long v0 = va_arg(args, long); long v1 = va_arg(args, long); long v2 = va_arg(args, long); long v3 = va_arg(args, long); va_end(args); if (n < 2 || n > 4) return errno = E2BIG, -1; if (n <= 2 && v2 != 0) return errno = EFAULT, -1; if (n <= 3 && v3 != 0) return errno = EFAULT, -1; if (v0 != v1) return errno = EINVAL, -1; if (n > 2 && v0 != v2) return errno = EINVAL, -1; if (n > 3 && v0 != v3) return errno = EINVAL, -1; return 0; } static void loop(); static int do_sandbox_none(void) { loop(); return 0; } static long syz_execute_func(volatile long text) { volatile long p[8] = {0}; (void)p; ((void (*)(void))(text))(); return 0; } 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 < 16; 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); event_timedwait(&th->done, 45); break; } } for (i = 0; i < 100 && __atomic_load_n(&running, __ATOMIC_RELAXED); i++) sleep_ms(1); } static void execute_one(void); static void loop(void) { execute_one(); } #ifndef SYS_foo #define SYS_foo 0 #endif #ifndef SYS_serialize1 #define SYS_serialize1 0 #endif #ifndef SYS_test #define SYS_test 0 #endif void execute_call(int call) { switch (call) { case 0: syscall(SYS_test, 0x401, -1, 5, 8, 0x10001, 0); break; case 1: syz_mmap(0x20ffc000, 0x3000); break; case 2: *(uint8_t*)0x20000000 = -1; memcpy((void*)0x20000001, "\x41\x3e\x9c\x08\x8f\x55\x0b\xb2", 8); syscall(SYS_test, 0x20000000, 0, 0, 0, 0, 0); break; case 3: *(uint16_t*)0x20000040 = 9; *(uint16_t*)0x20000042 = 1; *(uint16_t*)0x20000044 = 7; *(uint16_t*)0x20000046 = 7; *(uint16_t*)0x20000048 = 4; syscall(SYS_test, 0x20000040, 0, 0, 0, 0, 0); break; case 4: *(uint64_t*)0x20000080 = 0xc917; *(uint8_t*)0x20000088 = 8; syscall(SYS_test, 0x20000080, 0, 0, 0, 0, 0); break; case 5: *(uint64_t*)0x200000c0 = 7; *(uint16_t*)0x200000c8 = 8; *(uint64_t*)0x200000ca = 4; *(uint16_t*)0x200000d2 = 0x7ac; *(uint8_t*)0x200000d4 = 5; syscall(SYS_test, 0x200000c0, 0, 0, 0, 0, 0); break; case 6: sprintf((char*)0x20000100, "%020llu", (long long)5); syscall(SYS_foo, 0x20000100, 0); break; case 7: *(uint8_t*)0x20000140 = 6; syscall(SYS_test, 0x20000140, 0x2a, 0, 0, 0, 0); break; case 8: syscall(SYS_serialize1, 0x20000180, 0x6a); break; case 9: *(uint8_t*)0x20000200 = 7; *(uint64_t*)0x20000201 = 0xffffffffffff3fcd; *(uint64_t*)0x20000209 = 0xffffffff; *(uint64_t*)0x20000211 = 0x40; syscall(SYS_test, 0x20000200, 0, 0, 0, 0, 0); break; case 10: memcpy((void*)0x20000000, "@\000", 2); STORE_BY_BITMASK(uint32_t, , 0x20000040, 7, 0, 10); STORE_BY_BITMASK(uint32_t, , 0x20000040, 0x100, 10, 10); STORE_BY_BITMASK(uint32_t, , 0x20000040, 1, 20, 10); *(uint8_t*)0x20000044 = -1; syz_compare(0x20000000, 2, 0x20000040, 8); break; case 11: syz_compare_int(2, 0x2bb, 5, 0, 0); break; case 12: syz_errno(0xff); break; case 13: memcpy((void*)0x20000080, "\x8f\xba\x4d\x89\x76\xc6\xe1\x21\xfc\xb9\x55\x9d\x46\x4b\xd7\x33\xd7\xf9\xeb\x39\x04\xe1\x45\x87\x8a\x03\x30\xb1\x33\x23\xc0\x9b\x64\x64\xf2\x73\x01\xdb\x8a\x6b\xb6\xe6\x95\xa9\x0c\xa7\xc3\xf5\xb0\x7e", 50); syz_execute_func(0x20000080); break; case 14: syz_exit(5); break; case 15: syz_mmap(0x20ffb000, 0x3000); break; } } int main(void) { syz_mmap(0x20000000, 0x1000000); use_temporary_dir(); do_sandbox_none(); return 0; } /usr/local/bin/ld: cannot find -lasan collect2: error: ld returned 1 exit status compiler invocation: gcc [-o /tmp/syz-executor159031806 -DGOOS_test=1 -DGOARCH_64=1 -DHOSTGOOS_freebsd=1 -x c - -O2 -pthread -Wall -Werror -Wparentheses -Wunused-const-variable -Wframe-larger-than=8192 -m64 -fsanitize=address] --- FAIL: TestGenerate/test/64/19 (0.82s) csource_test.go:110: opts: {Threaded:true Collide:false Repeat:true RepeatTimes:0 Procs:0 Sandbox:none Fault:false FaultCall:0 FaultNth:0 Leak:false EnableTun:false EnableNetDev:false EnableNetReset:false EnableCgroups:false EnableBinfmtMisc:false EnableCloseFds:false UseTmpDir:true HandleSegv:false Repro:false Trace:false} program: test$int(0x401, 0x1ff, 0x5, 0x8, 0x10001) syz_mmap(&(0x7f0000ffc000/0x3000)=nil, 0x3000) test$array1(&(0x7f0000000000)={0x7ff, "413e9c088f550bb2"}) test$length6(&(0x7f0000000040)={[0x9, 0x10001, 0x7, 0x7], 0x4}) test$union1(&(0x7f0000000080)={@f0=0xc917, 0x8}) test$align5(&(0x7f00000000c0)={{0x7, [0x8]}, {0x4, [0x7ac]}, 0x5}) foo$fmt5(&(0x7f0000000100)={0x5}) test$length27(&(0x7f0000000140)={0x6}, 0x2a) serialize1(&(0x7f0000000180)=""/106, 0x6a) test$array0(&(0x7f0000000200)={0x7, [@f1=0xffffffffffff3fcd, @f1=0xffffffff], 0x40}) syz_compare(&(0x7f0000000000)='@\x00', 0x2, &(0x7f0000000040)=@bf1={{0x7, 0x100, 0x1}, 0xffff}, 0x8) syz_compare_int$2(0x2, 0x2bb, 0x5) syz_errno(0xff) syz_execute_func(&(0x7f0000000080)="8fba4d8976c6e121fcb9559d464bd733d7f9eb3904e145878a0330b13323c09b6464f27301db8a6bb6e695a90ca7c3f5b07e") syz_exit(0x5) syz_mmap(&(0x7f0000ffb000/0x3000)=nil, 0x3000) csource_test.go:111: failed to build program: // autogenerated by syzkaller (https://github.com/google/syzkaller) #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include 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; for (i = 0; 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 { pthread_mutex_t mu; pthread_cond_t cv; int state; } event_t; static void event_init(event_t* ev) { if (pthread_mutex_init(&ev->mu, 0)) exit(1); if (pthread_cond_init(&ev->cv, 0)) exit(1); ev->state = 0; } static void event_reset(event_t* ev) { ev->state = 0; } static void event_set(event_t* ev) { pthread_mutex_lock(&ev->mu); if (ev->state) exit(1); ev->state = 1; pthread_mutex_unlock(&ev->mu); pthread_cond_broadcast(&ev->cv); } static void event_wait(event_t* ev) { pthread_mutex_lock(&ev->mu); while (!ev->state) pthread_cond_wait(&ev->cv, &ev->mu); pthread_mutex_unlock(&ev->mu); } static int event_isset(event_t* ev) { pthread_mutex_lock(&ev->mu); int res = ev->state; pthread_mutex_unlock(&ev->mu); return res; } static int event_timedwait(event_t* ev, uint64_t timeout) { uint64_t start = current_time_ms(); uint64_t now = start; pthread_mutex_lock(&ev->mu); for (;;) { if (ev->state) break; uint64_t remain = timeout - (now - start); struct timespec ts; ts.tv_sec = remain / 1000; ts.tv_nsec = (remain % 1000) * 1000 * 1000; pthread_cond_timedwait(&ev->cv, &ev->mu, &ts); now = current_time_ms(); if (now - start > timeout) break; } int res = ev->state; pthread_mutex_unlock(&ev->mu); return res; } #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)))) static long syz_mmap(volatile long a0, volatile long a1) { return (long)mmap((void*)a0, a1, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE | MAP_FIXED, -1, 0); } static long syz_errno(volatile long v) { errno = v; return v == 0 ? 0 : -1; } static long syz_exit(volatile long status) { _exit(status); return 0; } static long syz_compare(volatile long want, volatile long want_len, volatile long got, volatile long got_len) { if (want_len != got_len) { errno = EBADF; return -1; } if (memcmp((void*)want, (void*)got, want_len)) { errno = EINVAL; return -1; } return 0; } static long syz_compare_int(volatile long n, ...) { va_list args; va_start(args, n); long v0 = va_arg(args, long); long v1 = va_arg(args, long); long v2 = va_arg(args, long); long v3 = va_arg(args, long); va_end(args); if (n < 2 || n > 4) return errno = E2BIG, -1; if (n <= 2 && v2 != 0) return errno = EFAULT, -1; if (n <= 3 && v3 != 0) return errno = EFAULT, -1; if (v0 != v1) return errno = EINVAL, -1; if (n > 2 && v0 != v2) return errno = EINVAL, -1; if (n > 3 && v0 != v3) return errno = EINVAL, -1; return 0; } static void loop(); static int do_sandbox_none(void) { loop(); return 0; } static long syz_execute_func(volatile long text) { volatile long p[8] = {0}; (void)p; ((void (*)(void))(text))(); return 0; } 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 < 16; 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); event_timedwait(&th->done, 45); break; } } for (i = 0; i < 100 && __atomic_load_n(&running, __ATOMIC_RELAXED); i++) sleep_ms(1); } static void execute_one(void); static void loop(void) { execute_one(); } #ifndef SYS_foo #define SYS_foo 0 #endif #ifndef SYS_serialize1 #define SYS_serialize1 0 #endif #ifndef SYS_test #define SYS_test 0 #endif void execute_call(int call) { switch (call) { case 0: syscall(SYS_test, 0x401, -1, 5, 8, 0x10001, 0); break; case 1: syz_mmap(0x20ffc000, 0x3000); break; case 2: *(uint8_t*)0x20000000 = -1; memcpy((void*)0x20000001, "\x41\x3e\x9c\x08\x8f\x55\x0b\xb2", 8); syscall(SYS_test, 0x20000000, 0, 0, 0, 0, 0); break; case 3: *(uint16_t*)0x20000040 = 9; *(uint16_t*)0x20000042 = 1; *(uint16_t*)0x20000044 = 7; *(uint16_t*)0x20000046 = 7; *(uint16_t*)0x20000048 = 4; syscall(SYS_test, 0x20000040, 0, 0, 0, 0, 0); break; case 4: *(uint64_t*)0x20000080 = 0xc917; *(uint8_t*)0x20000088 = 8; syscall(SYS_test, 0x20000080, 0, 0, 0, 0, 0); break; case 5: *(uint64_t*)0x200000c0 = 7; *(uint16_t*)0x200000c8 = 8; *(uint64_t*)0x200000ca = 4; *(uint16_t*)0x200000d2 = 0x7ac; *(uint8_t*)0x200000d4 = 5; syscall(SYS_test, 0x200000c0, 0, 0, 0, 0, 0); break; case 6: sprintf((char*)0x20000100, "%020llu", (long long)5); syscall(SYS_foo, 0x20000100, 0); break; case 7: *(uint8_t*)0x20000140 = 6; syscall(SYS_test, 0x20000140, 0x2a, 0, 0, 0, 0); break; case 8: syscall(SYS_serialize1, 0x20000180, 0x6a); break; case 9: *(uint8_t*)0x20000200 = 7; *(uint64_t*)0x20000201 = 0xffffffffffff3fcd; *(uint64_t*)0x20000209 = 0xffffffff; *(uint64_t*)0x20000211 = 0x40; syscall(SYS_test, 0x20000200, 0, 0, 0, 0, 0); break; case 10: memcpy((void*)0x20000000, "@\000", 2); STORE_BY_BITMASK(uint32_t, , 0x20000040, 7, 0, 10); STORE_BY_BITMASK(uint32_t, , 0x20000040, 0x100, 10, 10); STORE_BY_BITMASK(uint32_t, , 0x20000040, 1, 20, 10); *(uint8_t*)0x20000044 = -1; syz_compare(0x20000000, 2, 0x20000040, 8); break; case 11: syz_compare_int(2, 0x2bb, 5, 0, 0); break; case 12: syz_errno(0xff); break; case 13: memcpy((void*)0x20000080, "\x8f\xba\x4d\x89\x76\xc6\xe1\x21\xfc\xb9\x55\x9d\x46\x4b\xd7\x33\xd7\xf9\xeb\x39\x04\xe1\x45\x87\x8a\x03\x30\xb1\x33\x23\xc0\x9b\x64\x64\xf2\x73\x01\xdb\x8a\x6b\xb6\xe6\x95\xa9\x0c\xa7\xc3\xf5\xb0\x7e", 50); syz_execute_func(0x20000080); break; case 14: syz_exit(5); break; case 15: syz_mmap(0x20ffb000, 0x3000); break; } } int main(void) { syz_mmap(0x20000000, 0x1000000); use_temporary_dir(); do_sandbox_none(); return 0; } /usr/local/bin/ld: cannot find -lasan collect2: error: ld returned 1 exit status compiler invocation: gcc [-o /tmp/syz-executor919966533 -DGOOS_test=1 -DGOARCH_64=1 -DHOSTGOOS_freebsd=1 -x c - -O2 -pthread -Wall -Werror -Wparentheses -Wunused-const-variable -Wframe-larger-than=8192 -m64 -fsanitize=address] --- FAIL: TestGenerate/test/64/17 (0.88s) csource_test.go:110: opts: {Threaded:true Collide:false Repeat:true RepeatTimes:0 Procs:0 Sandbox:none Fault:false FaultCall:0 FaultNth:0 Leak:false EnableTun:false EnableNetDev:false EnableNetReset:false EnableCgroups:false EnableBinfmtMisc:false EnableCloseFds:false UseTmpDir:true HandleSegv:false Repro:false Trace:false} program: test$int(0x401, 0x1ff, 0x5, 0x8, 0x10001) syz_mmap(&(0x7f0000ffc000/0x3000)=nil, 0x3000) test$array1(&(0x7f0000000000)={0x7ff, "413e9c088f550bb2"}) test$length6(&(0x7f0000000040)={[0x9, 0x10001, 0x7, 0x7], 0x4}) test$union1(&(0x7f0000000080)={@f0=0xc917, 0x8}) test$align5(&(0x7f00000000c0)={{0x7, [0x8]}, {0x4, [0x7ac]}, 0x5}) foo$fmt5(&(0x7f0000000100)={0x5}) test$length27(&(0x7f0000000140)={0x6}, 0x2a) serialize1(&(0x7f0000000180)=""/106, 0x6a) test$array0(&(0x7f0000000200)={0x7, [@f1=0xffffffffffff3fcd, @f1=0xffffffff], 0x40}) syz_compare(&(0x7f0000000000)='@\x00', 0x2, &(0x7f0000000040)=@bf1={{0x7, 0x100, 0x1}, 0xffff}, 0x8) syz_compare_int$2(0x2, 0x2bb, 0x5) syz_errno(0xff) syz_execute_func(&(0x7f0000000080)="8fba4d8976c6e121fcb9559d464bd733d7f9eb3904e145878a0330b13323c09b6464f27301db8a6bb6e695a90ca7c3f5b07e") syz_exit(0x5) syz_mmap(&(0x7f0000ffb000/0x3000)=nil, 0x3000) csource_test.go:111: failed to build program: // autogenerated by syzkaller (https://github.com/google/syzkaller) #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include 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; for (i = 0; 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 { pthread_mutex_t mu; pthread_cond_t cv; int state; } event_t; static void event_init(event_t* ev) { if (pthread_mutex_init(&ev->mu, 0)) exit(1); if (pthread_cond_init(&ev->cv, 0)) exit(1); ev->state = 0; } static void event_reset(event_t* ev) { ev->state = 0; } static void event_set(event_t* ev) { pthread_mutex_lock(&ev->mu); if (ev->state) exit(1); ev->state = 1; pthread_mutex_unlock(&ev->mu); pthread_cond_broadcast(&ev->cv); } static void event_wait(event_t* ev) { pthread_mutex_lock(&ev->mu); while (!ev->state) pthread_cond_wait(&ev->cv, &ev->mu); pthread_mutex_unlock(&ev->mu); } static int event_isset(event_t* ev) { pthread_mutex_lock(&ev->mu); int res = ev->state; pthread_mutex_unlock(&ev->mu); return res; } static int event_timedwait(event_t* ev, uint64_t timeout) { uint64_t start = current_time_ms(); uint64_t now = start; pthread_mutex_lock(&ev->mu); for (;;) { if (ev->state) break; uint64_t remain = timeout - (now - start); struct timespec ts; ts.tv_sec = remain / 1000; ts.tv_nsec = (remain % 1000) * 1000 * 1000; pthread_cond_timedwait(&ev->cv, &ev->mu, &ts); now = current_time_ms(); if (now - start > timeout) break; } int res = ev->state; pthread_mutex_unlock(&ev->mu); return res; } #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)))) static long syz_mmap(volatile long a0, volatile long a1) { return (long)mmap((void*)a0, a1, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE | MAP_FIXED, -1, 0); } static long syz_errno(volatile long v) { errno = v; return v == 0 ? 0 : -1; } static long syz_exit(volatile long status) { _exit(status); return 0; } static long syz_compare(volatile long want, volatile long want_len, volatile long got, volatile long got_len) { if (want_len != got_len) { errno = EBADF; return -1; } if (memcmp((void*)want, (void*)got, want_len)) { errno = EINVAL; return -1; } return 0; } static long syz_compare_int(volatile long n, ...) { va_list args; va_start(args, n); long v0 = va_arg(args, long); long v1 = va_arg(args, long); long v2 = va_arg(args, long); long v3 = va_arg(args, long); va_end(args); if (n < 2 || n > 4) return errno = E2BIG, -1; if (n <= 2 && v2 != 0) return errno = EFAULT, -1; if (n <= 3 && v3 != 0) return errno = EFAULT, -1; if (v0 != v1) return errno = EINVAL, -1; if (n > 2 && v0 != v2) return errno = EINVAL, -1; if (n > 3 && v0 != v3) return errno = EINVAL, -1; return 0; } static void loop(); static int do_sandbox_none(void) { loop(); return 0; } static long syz_execute_func(volatile long text) { volatile long p[8] = {0}; (void)p; ((void (*)(void))(text))(); return 0; } 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 < 16; 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); event_timedwait(&th->done, 45); break; } } for (i = 0; i < 100 && __atomic_load_n(&running, __ATOMIC_RELAXED); i++) sleep_ms(1); } static void execute_one(void); static void loop(void) { execute_one(); } #ifndef SYS_foo #define SYS_foo 0 #endif #ifndef SYS_serialize1 #define SYS_serialize1 0 #endif #ifndef SYS_test #define SYS_test 0 #endif void execute_call(int call) { switch (call) { case 0: syscall(SYS_test, 0x401, -1, 5, 8, 0x10001, 0); break; case 1: syz_mmap(0x20ffc000, 0x3000); break; case 2: *(uint8_t*)0x20000000 = -1; memcpy((void*)0x20000001, "\x41\x3e\x9c\x08\x8f\x55\x0b\xb2", 8); syscall(SYS_test, 0x20000000, 0, 0, 0, 0, 0); break; case 3: *(uint16_t*)0x20000040 = 9; *(uint16_t*)0x20000042 = 1; *(uint16_t*)0x20000044 = 7; *(uint16_t*)0x20000046 = 7; *(uint16_t*)0x20000048 = 4; syscall(SYS_test, 0x20000040, 0, 0, 0, 0, 0); break; case 4: *(uint64_t*)0x20000080 = 0xc917; *(uint8_t*)0x20000088 = 8; syscall(SYS_test, 0x20000080, 0, 0, 0, 0, 0); break; case 5: *(uint64_t*)0x200000c0 = 7; *(uint16_t*)0x200000c8 = 8; *(uint64_t*)0x200000ca = 4; *(uint16_t*)0x200000d2 = 0x7ac; *(uint8_t*)0x200000d4 = 5; syscall(SYS_test, 0x200000c0, 0, 0, 0, 0, 0); break; case 6: sprintf((char*)0x20000100, "%020llu", (long long)5); syscall(SYS_foo, 0x20000100, 0); break; case 7: *(uint8_t*)0x20000140 = 6; syscall(SYS_test, 0x20000140, 0x2a, 0, 0, 0, 0); break; case 8: syscall(SYS_serialize1, 0x20000180, 0x6a); break; case 9: *(uint8_t*)0x20000200 = 7; *(uint64_t*)0x20000201 = 0xffffffffffff3fcd; *(uint64_t*)0x20000209 = 0xffffffff; *(uint64_t*)0x20000211 = 0x40; syscall(SYS_test, 0x20000200, 0, 0, 0, 0, 0); break; case 10: memcpy((void*)0x20000000, "@\000", 2); STORE_BY_BITMASK(uint32_t, , 0x20000040, 7, 0, 10); STORE_BY_BITMASK(uint32_t, , 0x20000040, 0x100, 10, 10); STORE_BY_BITMASK(uint32_t, , 0x20000040, 1, 20, 10); *(uint8_t*)0x20000044 = -1; syz_compare(0x20000000, 2, 0x20000040, 8); break; case 11: syz_compare_int(2, 0x2bb, 5, 0, 0); break; case 12: syz_errno(0xff); break; case 13: memcpy((void*)0x20000080, "\x8f\xba\x4d\x89\x76\xc6\xe1\x21\xfc\xb9\x55\x9d\x46\x4b\xd7\x33\xd7\xf9\xeb\x39\x04\xe1\x45\x87\x8a\x03\x30\xb1\x33\x23\xc0\x9b\x64\x64\xf2\x73\x01\xdb\x8a\x6b\xb6\xe6\x95\xa9\x0c\xa7\xc3\xf5\xb0\x7e", 50); syz_execute_func(0x20000080); break; case 14: syz_exit(5); break; case 15: syz_mmap(0x20ffb000, 0x3000); break; } } int main(void) { syz_mmap(0x20000000, 0x1000000); use_temporary_dir(); do_sandbox_none(); return 0; } /usr/local/bin/ld: cannot find -lasan collect2: error: ld returned 1 exit status compiler invocation: gcc [-o /tmp/syz-executor516400608 -DGOOS_test=1 -DGOARCH_64=1 -DHOSTGOOS_freebsd=1 -x c - -O2 -pthread -Wall -Werror -Wparentheses -Wunused-const-variable -Wframe-larger-than=8192 -m64 -fsanitize=address] --- FAIL: TestGenerate/test/64/14 (0.98s) csource_test.go:110: opts: {Threaded:true Collide:false Repeat:true RepeatTimes:0 Procs:0 Sandbox:none Fault:false FaultCall:0 FaultNth:0 Leak:false EnableTun:false EnableNetDev:false EnableNetReset:false EnableCgroups:false EnableBinfmtMisc:false EnableCloseFds:false UseTmpDir:true HandleSegv:false Repro:false Trace:false} program: test$int(0x401, 0x1ff, 0x5, 0x8, 0x10001) syz_mmap(&(0x7f0000ffc000/0x3000)=nil, 0x3000) test$array1(&(0x7f0000000000)={0x7ff, "413e9c088f550bb2"}) test$length6(&(0x7f0000000040)={[0x9, 0x10001, 0x7, 0x7], 0x4}) test$union1(&(0x7f0000000080)={@f0=0xc917, 0x8}) test$align5(&(0x7f00000000c0)={{0x7, [0x8]}, {0x4, [0x7ac]}, 0x5}) foo$fmt5(&(0x7f0000000100)={0x5}) test$length27(&(0x7f0000000140)={0x6}, 0x2a) serialize1(&(0x7f0000000180)=""/106, 0x6a) test$array0(&(0x7f0000000200)={0x7, [@f1=0xffffffffffff3fcd, @f1=0xffffffff], 0x40}) syz_compare(&(0x7f0000000000)='@\x00', 0x2, &(0x7f0000000040)=@bf1={{0x7, 0x100, 0x1}, 0xffff}, 0x8) syz_compare_int$2(0x2, 0x2bb, 0x5) syz_errno(0xff) syz_execute_func(&(0x7f0000000080)="8fba4d8976c6e121fcb9559d464bd733d7f9eb3904e145878a0330b13323c09b6464f27301db8a6bb6e695a90ca7c3f5b07e") syz_exit(0x5) syz_mmap(&(0x7f0000ffb000/0x3000)=nil, 0x3000) csource_test.go:111: failed to build program: // autogenerated by syzkaller (https://github.com/google/syzkaller) #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include 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; for (i = 0; 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 { pthread_mutex_t mu; pthread_cond_t cv; int state; } event_t; static void event_init(event_t* ev) { if (pthread_mutex_init(&ev->mu, 0)) exit(1); if (pthread_cond_init(&ev->cv, 0)) exit(1); ev->state = 0; } static void event_reset(event_t* ev) { ev->state = 0; } static void event_set(event_t* ev) { pthread_mutex_lock(&ev->mu); if (ev->state) exit(1); ev->state = 1; pthread_mutex_unlock(&ev->mu); pthread_cond_broadcast(&ev->cv); } static void event_wait(event_t* ev) { pthread_mutex_lock(&ev->mu); while (!ev->state) pthread_cond_wait(&ev->cv, &ev->mu); pthread_mutex_unlock(&ev->mu); } static int event_isset(event_t* ev) { pthread_mutex_lock(&ev->mu); int res = ev->state; pthread_mutex_unlock(&ev->mu); return res; } static int event_timedwait(event_t* ev, uint64_t timeout) { uint64_t start = current_time_ms(); uint64_t now = start; pthread_mutex_lock(&ev->mu); for (;;) { if (ev->state) break; uint64_t remain = timeout - (now - start); struct timespec ts; ts.tv_sec = remain / 1000; ts.tv_nsec = (remain % 1000) * 1000 * 1000; pthread_cond_timedwait(&ev->cv, &ev->mu, &ts); now = current_time_ms(); if (now - start > timeout) break; } int res = ev->state; pthread_mutex_unlock(&ev->mu); return res; } #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)))) static long syz_mmap(volatile long a0, volatile long a1) { return (long)mmap((void*)a0, a1, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE | MAP_FIXED, -1, 0); } static long syz_errno(volatile long v) { errno = v; return v == 0 ? 0 : -1; } static long syz_exit(volatile long status) { _exit(status); return 0; } static long syz_compare(volatile long want, volatile long want_len, volatile long got, volatile long got_len) { if (want_len != got_len) { errno = EBADF; return -1; } if (memcmp((void*)want, (void*)got, want_len)) { errno = EINVAL; return -1; } return 0; } static long syz_compare_int(volatile long n, ...) { va_list args; va_start(args, n); long v0 = va_arg(args, long); long v1 = va_arg(args, long); long v2 = va_arg(args, long); long v3 = va_arg(args, long); va_end(args); if (n < 2 || n > 4) return errno = E2BIG, -1; if (n <= 2 && v2 != 0) return errno = EFAULT, -1; if (n <= 3 && v3 != 0) return errno = EFAULT, -1; if (v0 != v1) return errno = EINVAL, -1; if (n > 2 && v0 != v2) return errno = EINVAL, -1; if (n > 3 && v0 != v3) return errno = EINVAL, -1; return 0; } static void loop(); static int do_sandbox_none(void) { loop(); return 0; } static long syz_execute_func(volatile long text) { volatile long p[8] = {0}; (void)p; ((void (*)(void))(text))(); return 0; } 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 < 16; 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); event_timedwait(&th->done, 45); break; } } for (i = 0; i < 100 && __atomic_load_n(&running, __ATOMIC_RELAXED); i++) sleep_ms(1); } static void execute_one(void); static void loop(void) { execute_one(); } #ifndef SYS_foo #define SYS_foo 0 #endif #ifndef SYS_serialize1 #define SYS_serialize1 0 #endif #ifndef SYS_test #define SYS_test 0 #endif void execute_call(int call) { switch (call) { case 0: syscall(SYS_test, 0x401, -1, 5, 8, 0x10001, 0); break; case 1: syz_mmap(0x20ffc000, 0x3000); break; case 2: *(uint8_t*)0x20000000 = -1; memcpy((void*)0x20000001, "\x41\x3e\x9c\x08\x8f\x55\x0b\xb2", 8); syscall(SYS_test, 0x20000000, 0, 0, 0, 0, 0); break; case 3: *(uint16_t*)0x20000040 = 9; *(uint16_t*)0x20000042 = 1; *(uint16_t*)0x20000044 = 7; *(uint16_t*)0x20000046 = 7; *(uint16_t*)0x20000048 = 4; syscall(SYS_test, 0x20000040, 0, 0, 0, 0, 0); break; case 4: *(uint64_t*)0x20000080 = 0xc917; *(uint8_t*)0x20000088 = 8; syscall(SYS_test, 0x20000080, 0, 0, 0, 0, 0); break; case 5: *(uint64_t*)0x200000c0 = 7; *(uint16_t*)0x200000c8 = 8; *(uint64_t*)0x200000ca = 4; *(uint16_t*)0x200000d2 = 0x7ac; *(uint8_t*)0x200000d4 = 5; syscall(SYS_test, 0x200000c0, 0, 0, 0, 0, 0); break; case 6: sprintf((char*)0x20000100, "%020llu", (long long)5); syscall(SYS_foo, 0x20000100, 0); break; case 7: *(uint8_t*)0x20000140 = 6; syscall(SYS_test, 0x20000140, 0x2a, 0, 0, 0, 0); break; case 8: syscall(SYS_serialize1, 0x20000180, 0x6a); break; case 9: *(uint8_t*)0x20000200 = 7; *(uint64_t*)0x20000201 = 0xffffffffffff3fcd; *(uint64_t*)0x20000209 = 0xffffffff; *(uint64_t*)0x20000211 = 0x40; syscall(SYS_test, 0x20000200, 0, 0, 0, 0, 0); break; case 10: memcpy((void*)0x20000000, "@\000", 2); STORE_BY_BITMASK(uint32_t, , 0x20000040, 7, 0, 10); STORE_BY_BITMASK(uint32_t, , 0x20000040, 0x100, 10, 10); STORE_BY_BITMASK(uint32_t, , 0x20000040, 1, 20, 10); *(uint8_t*)0x20000044 = -1; syz_compare(0x20000000, 2, 0x20000040, 8); break; case 11: syz_compare_int(2, 0x2bb, 5, 0, 0); break; case 12: syz_errno(0xff); break; case 13: memcpy((void*)0x20000080, "\x8f\xba\x4d\x89\x76\xc6\xe1\x21\xfc\xb9\x55\x9d\x46\x4b\xd7\x33\xd7\xf9\xeb\x39\x04\xe1\x45\x87\x8a\x03\x30\xb1\x33\x23\xc0\x9b\x64\x64\xf2\x73\x01\xdb\x8a\x6b\xb6\xe6\x95\xa9\x0c\xa7\xc3\xf5\xb0\x7e", 50); syz_execute_func(0x20000080); break; case 14: syz_exit(5); break; case 15: syz_mmap(0x20ffb000, 0x3000); break; } } int main(void) { syz_mmap(0x20000000, 0x1000000); use_temporary_dir(); do_sandbox_none(); return 0; } /usr/local/bin/ld: cannot find -lasan collect2: error: ld returned 1 exit status compiler invocation: gcc [-o /tmp/syz-executor175552959 -DGOOS_test=1 -DGOARCH_64=1 -DHOSTGOOS_freebsd=1 -x c - -O2 -pthread -Wall -Werror -Wparentheses -Wunused-const-variable -Wframe-larger-than=8192 -m64 -fsanitize=address] --- FAIL: TestGenerate/test/64/18 (1.18s) csource_test.go:110: opts: {Threaded:true Collide:false Repeat:true RepeatTimes:0 Procs:0 Sandbox:none Fault:false FaultCall:0 FaultNth:0 Leak:false EnableTun:false EnableNetDev:false EnableNetReset:false EnableCgroups:false EnableBinfmtMisc:false EnableCloseFds:false UseTmpDir:true HandleSegv:false Repro:false Trace:false} program: test$int(0x401, 0x1ff, 0x5, 0x8, 0x10001) syz_mmap(&(0x7f0000ffc000/0x3000)=nil, 0x3000) test$array1(&(0x7f0000000000)={0x7ff, "413e9c088f550bb2"}) test$length6(&(0x7f0000000040)={[0x9, 0x10001, 0x7, 0x7], 0x4}) test$union1(&(0x7f0000000080)={@f0=0xc917, 0x8}) test$align5(&(0x7f00000000c0)={{0x7, [0x8]}, {0x4, [0x7ac]}, 0x5}) foo$fmt5(&(0x7f0000000100)={0x5}) test$length27(&(0x7f0000000140)={0x6}, 0x2a) serialize1(&(0x7f0000000180)=""/106, 0x6a) test$array0(&(0x7f0000000200)={0x7, [@f1=0xffffffffffff3fcd, @f1=0xffffffff], 0x40}) syz_compare(&(0x7f0000000000)='@\x00', 0x2, &(0x7f0000000040)=@bf1={{0x7, 0x100, 0x1}, 0xffff}, 0x8) syz_compare_int$2(0x2, 0x2bb, 0x5) syz_errno(0xff) syz_execute_func(&(0x7f0000000080)="8fba4d8976c6e121fcb9559d464bd733d7f9eb3904e145878a0330b13323c09b6464f27301db8a6bb6e695a90ca7c3f5b07e") syz_exit(0x5) syz_mmap(&(0x7f0000ffb000/0x3000)=nil, 0x3000) csource_test.go:111: failed to build program: // autogenerated by syzkaller (https://github.com/google/syzkaller) #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include 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; for (i = 0; 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 { pthread_mutex_t mu; pthread_cond_t cv; int state; } event_t; static void event_init(event_t* ev) { if (pthread_mutex_init(&ev->mu, 0)) exit(1); if (pthread_cond_init(&ev->cv, 0)) exit(1); ev->state = 0; } static void event_reset(event_t* ev) { ev->state = 0; } static void event_set(event_t* ev) { pthread_mutex_lock(&ev->mu); if (ev->state) exit(1); ev->state = 1; pthread_mutex_unlock(&ev->mu); pthread_cond_broadcast(&ev->cv); } static void event_wait(event_t* ev) { pthread_mutex_lock(&ev->mu); while (!ev->state) pthread_cond_wait(&ev->cv, &ev->mu); pthread_mutex_unlock(&ev->mu); } static int event_isset(event_t* ev) { pthread_mutex_lock(&ev->mu); int res = ev->state; pthread_mutex_unlock(&ev->mu); return res; } static int event_timedwait(event_t* ev, uint64_t timeout) { uint64_t start = current_time_ms(); uint64_t now = start; pthread_mutex_lock(&ev->mu); for (;;) { if (ev->state) break; uint64_t remain = timeout - (now - start); struct timespec ts; ts.tv_sec = remain / 1000; ts.tv_nsec = (remain % 1000) * 1000 * 1000; pthread_cond_timedwait(&ev->cv, &ev->mu, &ts); now = current_time_ms(); if (now - start > timeout) break; } int res = ev->state; pthread_mutex_unlock(&ev->mu); return res; } #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)))) static long syz_mmap(volatile long a0, volatile long a1) { return (long)mmap((void*)a0, a1, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE | MAP_FIXED, -1, 0); } static long syz_errno(volatile long v) { errno = v; return v == 0 ? 0 : -1; } static long syz_exit(volatile long status) { _exit(status); return 0; } static long syz_compare(volatile long want, volatile long want_len, volatile long got, volatile long got_len) { if (want_len != got_len) { errno = EBADF; return -1; } if (memcmp((void*)want, (void*)got, want_len)) { errno = EINVAL; return -1; } return 0; } static long syz_compare_int(volatile long n, ...) { va_list args; va_start(args, n); long v0 = va_arg(args, long); long v1 = va_arg(args, long); long v2 = va_arg(args, long); long v3 = va_arg(args, long); va_end(args); if (n < 2 || n > 4) return errno = E2BIG, -1; if (n <= 2 && v2 != 0) return errno = EFAULT, -1; if (n <= 3 && v3 != 0) return errno = EFAULT, -1; if (v0 != v1) return errno = EINVAL, -1; if (n > 2 && v0 != v2) return errno = EINVAL, -1; if (n > 3 && v0 != v3) return errno = EINVAL, -1; return 0; } static void loop(); static int do_sandbox_none(void) { loop(); return 0; } static long syz_execute_func(volatile long text) { volatile long p[8] = {0}; (void)p; ((void (*)(void))(text))(); return 0; } 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 < 16; 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); event_timedwait(&th->done, 45); break; } } for (i = 0; i < 100 && __atomic_load_n(&running, __ATOMIC_RELAXED); i++) sleep_ms(1); } static void execute_one(void); static void loop(void) { execute_one(); } #ifndef SYS_foo #define SYS_foo 0 #endif #ifndef SYS_serialize1 #define SYS_serialize1 0 #endif #ifndef SYS_test #define SYS_test 0 #endif void execute_call(int call) { switch (call) { case 0: syscall(SYS_test, 0x401, -1, 5, 8, 0x10001, 0); break; case 1: syz_mmap(0x20ffc000, 0x3000); break; case 2: *(uint8_t*)0x20000000 = -1; memcpy((void*)0x20000001, "\x41\x3e\x9c\x08\x8f\x55\x0b\xb2", 8); syscall(SYS_test, 0x20000000, 0, 0, 0, 0, 0); break; case 3: *(uint16_t*)0x20000040 = 9; *(uint16_t*)0x20000042 = 1; *(uint16_t*)0x20000044 = 7; *(uint16_t*)0x20000046 = 7; *(uint16_t*)0x20000048 = 4; syscall(SYS_test, 0x20000040, 0, 0, 0, 0, 0); break; case 4: *(uint64_t*)0x20000080 = 0xc917; *(uint8_t*)0x20000088 = 8; syscall(SYS_test, 0x20000080, 0, 0, 0, 0, 0); break; case 5: *(uint64_t*)0x200000c0 = 7; *(uint16_t*)0x200000c8 = 8; *(uint64_t*)0x200000ca = 4; *(uint16_t*)0x200000d2 = 0x7ac; *(uint8_t*)0x200000d4 = 5; syscall(SYS_test, 0x200000c0, 0, 0, 0, 0, 0); break; case 6: sprintf((char*)0x20000100, "%020llu", (long long)5); syscall(SYS_foo, 0x20000100, 0); break; case 7: *(uint8_t*)0x20000140 = 6; syscall(SYS_test, 0x20000140, 0x2a, 0, 0, 0, 0); break; case 8: syscall(SYS_serialize1, 0x20000180, 0x6a); break; case 9: *(uint8_t*)0x20000200 = 7; *(uint64_t*)0x20000201 = 0xffffffffffff3fcd; *(uint64_t*)0x20000209 = 0xffffffff; *(uint64_t*)0x20000211 = 0x40; syscall(SYS_test, 0x20000200, 0, 0, 0, 0, 0); break; case 10: memcpy((void*)0x20000000, "@\000", 2); STORE_BY_BITMASK(uint32_t, , 0x20000040, 7, 0, 10); STORE_BY_BITMASK(uint32_t, , 0x20000040, 0x100, 10, 10); STORE_BY_BITMASK(uint32_t, , 0x20000040, 1, 20, 10); *(uint8_t*)0x20000044 = -1; syz_compare(0x20000000, 2, 0x20000040, 8); break; case 11: syz_compare_int(2, 0x2bb, 5, 0, 0); break; case 12: syz_errno(0xff); break; case 13: memcpy((void*)0x20000080, "\x8f\xba\x4d\x89\x76\xc6\xe1\x21\xfc\xb9\x55\x9d\x46\x4b\xd7\x33\xd7\xf9\xeb\x39\x04\xe1\x45\x87\x8a\x03\x30\xb1\x33\x23\xc0\x9b\x64\x64\xf2\x73\x01\xdb\x8a\x6b\xb6\xe6\x95\xa9\x0c\xa7\xc3\xf5\xb0\x7e", 50); syz_execute_func(0x20000080); break; case 14: syz_exit(5); break; case 15: syz_mmap(0x20ffb000, 0x3000); break; } } int main(void) { syz_mmap(0x20000000, 0x1000000); use_temporary_dir(); do_sandbox_none(); return 0; } /usr/local/bin/ld: cannot find -lasan collect2: error: ld returned 1 exit status compiler invocation: gcc [-o /tmp/syz-executor951068178 -DGOOS_test=1 -DGOARCH_64=1 -DHOSTGOOS_freebsd=1 -x c - -O2 -pthread -Wall -Werror -Wparentheses -Wunused-const-variable -Wframe-larger-than=8192 -m64 -fsanitize=address] --- FAIL: TestGenerate/test/64/11 (1.09s) csource_test.go:110: opts: {Threaded:true Collide:false Repeat:true RepeatTimes:0 Procs:0 Sandbox:none Fault:false FaultCall:0 FaultNth:0 Leak:false EnableTun:false EnableNetDev:false EnableNetReset:false EnableCgroups:false EnableBinfmtMisc:false EnableCloseFds:false UseTmpDir:true HandleSegv:false Repro:false Trace:false} program: test$int(0x401, 0x1ff, 0x5, 0x8, 0x10001) syz_mmap(&(0x7f0000ffc000/0x3000)=nil, 0x3000) test$array1(&(0x7f0000000000)={0x7ff, "413e9c088f550bb2"}) test$length6(&(0x7f0000000040)={[0x9, 0x10001, 0x7, 0x7], 0x4}) test$union1(&(0x7f0000000080)={@f0=0xc917, 0x8}) test$align5(&(0x7f00000000c0)={{0x7, [0x8]}, {0x4, [0x7ac]}, 0x5}) foo$fmt5(&(0x7f0000000100)={0x5}) test$length27(&(0x7f0000000140)={0x6}, 0x2a) serialize1(&(0x7f0000000180)=""/106, 0x6a) test$array0(&(0x7f0000000200)={0x7, [@f1=0xffffffffffff3fcd, @f1=0xffffffff], 0x40}) syz_compare(&(0x7f0000000000)='@\x00', 0x2, &(0x7f0000000040)=@bf1={{0x7, 0x100, 0x1}, 0xffff}, 0x8) syz_compare_int$2(0x2, 0x2bb, 0x5) syz_errno(0xff) syz_execute_func(&(0x7f0000000080)="8fba4d8976c6e121fcb9559d464bd733d7f9eb3904e145878a0330b13323c09b6464f27301db8a6bb6e695a90ca7c3f5b07e") syz_exit(0x5) syz_mmap(&(0x7f0000ffb000/0x3000)=nil, 0x3000) csource_test.go:111: failed to build program: // autogenerated by syzkaller (https://github.com/google/syzkaller) #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include 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; for (i = 0; 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 { pthread_mutex_t mu; pthread_cond_t cv; int state; } event_t; static void event_init(event_t* ev) { if (pthread_mutex_init(&ev->mu, 0)) exit(1); if (pthread_cond_init(&ev->cv, 0)) exit(1); ev->state = 0; } static void event_reset(event_t* ev) { ev->state = 0; } static void event_set(event_t* ev) { pthread_mutex_lock(&ev->mu); if (ev->state) exit(1); ev->state = 1; pthread_mutex_unlock(&ev->mu); pthread_cond_broadcast(&ev->cv); } static void event_wait(event_t* ev) { pthread_mutex_lock(&ev->mu); while (!ev->state) pthread_cond_wait(&ev->cv, &ev->mu); pthread_mutex_unlock(&ev->mu); } static int event_isset(event_t* ev) { pthread_mutex_lock(&ev->mu); int res = ev->state; pthread_mutex_unlock(&ev->mu); return res; } static int event_timedwait(event_t* ev, uint64_t timeout) { uint64_t start = current_time_ms(); uint64_t now = start; pthread_mutex_lock(&ev->mu); for (;;) { if (ev->state) break; uint64_t remain = timeout - (now - start); struct timespec ts; ts.tv_sec = remain / 1000; ts.tv_nsec = (remain % 1000) * 1000 * 1000; pthread_cond_timedwait(&ev->cv, &ev->mu, &ts); now = current_time_ms(); if (now - start > timeout) break; } int res = ev->state; pthread_mutex_unlock(&ev->mu); return res; } #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)))) static long syz_mmap(volatile long a0, volatile long a1) { return (long)mmap((void*)a0, a1, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE | MAP_FIXED, -1, 0); } static long syz_errno(volatile long v) { errno = v; return v == 0 ? 0 : -1; } static long syz_exit(volatile long status) { _exit(status); return 0; } static long syz_compare(volatile long want, volatile long want_len, volatile long got, volatile long got_len) { if (want_len != got_len) { errno = EBADF; return -1; } if (memcmp((void*)want, (void*)got, want_len)) { errno = EINVAL; return -1; } return 0; } static long syz_compare_int(volatile long n, ...) { va_list args; va_start(args, n); long v0 = va_arg(args, long); long v1 = va_arg(args, long); long v2 = va_arg(args, long); long v3 = va_arg(args, long); va_end(args); if (n < 2 || n > 4) return errno = E2BIG, -1; if (n <= 2 && v2 != 0) return errno = EFAULT, -1; if (n <= 3 && v3 != 0) return errno = EFAULT, -1; if (v0 != v1) return errno = EINVAL, -1; if (n > 2 && v0 != v2) return errno = EINVAL, -1; if (n > 3 && v0 != v3) return errno = EINVAL, -1; return 0; } static void loop(); static int do_sandbox_none(void) { loop(); return 0; } static long syz_execute_func(volatile long text) { volatile long p[8] = {0}; (void)p; ((void (*)(void))(text))(); return 0; } 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 < 16; 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); event_timedwait(&th->done, 45); break; } } for (i = 0; i < 100 && __atomic_load_n(&running, __ATOMIC_RELAXED); i++) sleep_ms(1); } static void execute_one(void); static void loop(void) { execute_one(); } #ifndef SYS_foo #define SYS_foo 0 #endif #ifndef SYS_serialize1 #define SYS_serialize1 0 #endif #ifndef SYS_test #define SYS_test 0 #endif void execute_call(int call) { switch (call) { case 0: syscall(SYS_test, 0x401, -1, 5, 8, 0x10001, 0); break; case 1: syz_mmap(0x20ffc000, 0x3000); break; case 2: *(uint8_t*)0x20000000 = -1; memcpy((void*)0x20000001, "\x41\x3e\x9c\x08\x8f\x55\x0b\xb2", 8); syscall(SYS_test, 0x20000000, 0, 0, 0, 0, 0); break; case 3: *(uint16_t*)0x20000040 = 9; *(uint16_t*)0x20000042 = 1; *(uint16_t*)0x20000044 = 7; *(uint16_t*)0x20000046 = 7; *(uint16_t*)0x20000048 = 4; syscall(SYS_test, 0x20000040, 0, 0, 0, 0, 0); break; case 4: *(uint64_t*)0x20000080 = 0xc917; *(uint8_t*)0x20000088 = 8; syscall(SYS_test, 0x20000080, 0, 0, 0, 0, 0); break; case 5: *(uint64_t*)0x200000c0 = 7; *(uint16_t*)0x200000c8 = 8; *(uint64_t*)0x200000ca = 4; *(uint16_t*)0x200000d2 = 0x7ac; *(uint8_t*)0x200000d4 = 5; syscall(SYS_test, 0x200000c0, 0, 0, 0, 0, 0); break; case 6: sprintf((char*)0x20000100, "%020llu", (long long)5); syscall(SYS_foo, 0x20000100, 0); break; case 7: *(uint8_t*)0x20000140 = 6; syscall(SYS_test, 0x20000140, 0x2a, 0, 0, 0, 0); break; case 8: syscall(SYS_serialize1, 0x20000180, 0x6a); break; case 9: *(uint8_t*)0x20000200 = 7; *(uint64_t*)0x20000201 = 0xffffffffffff3fcd; *(uint64_t*)0x20000209 = 0xffffffff; *(uint64_t*)0x20000211 = 0x40; syscall(SYS_test, 0x20000200, 0, 0, 0, 0, 0); break; case 10: memcpy((void*)0x20000000, "@\000", 2); STORE_BY_BITMASK(uint32_t, , 0x20000040, 7, 0, 10); STORE_BY_BITMASK(uint32_t, , 0x20000040, 0x100, 10, 10); STORE_BY_BITMASK(uint32_t, , 0x20000040, 1, 20, 10); *(uint8_t*)0x20000044 = -1; syz_compare(0x20000000, 2, 0x20000040, 8); break; case 11: syz_compare_int(2, 0x2bb, 5, 0, 0); break; case 12: syz_errno(0xff); break; case 13: memcpy((void*)0x20000080, "\x8f\xba\x4d\x89\x76\xc6\xe1\x21\xfc\xb9\x55\x9d\x46\x4b\xd7\x33\xd7\xf9\xeb\x39\x04\xe1\x45\x87\x8a\x03\x30\xb1\x33\x23\xc0\x9b\x64\x64\xf2\x73\x01\xdb\x8a\x6b\xb6\xe6\x95\xa9\x0c\xa7\xc3\xf5\xb0\x7e", 50); syz_execute_func(0x20000080); break; case 14: syz_exit(5); break; case 15: syz_mmap(0x20ffb000, 0x3000); break; } } int main(void) { syz_mmap(0x20000000, 0x1000000); use_temporary_dir(); do_sandbox_none(); return 0; } /usr/local/bin/ld: cannot find -lasan collect2: error: ld returned 1 exit status compiler invocation: gcc [-o /tmp/syz-executor280758857 -DGOOS_test=1 -DGOARCH_64=1 -DHOSTGOOS_freebsd=1 -x c - -O2 -pthread -Wall -Werror -Wparentheses -Wunused-const-variable -Wframe-larger-than=8192 -m64 -fsanitize=address] --- FAIL: TestGenerate/test/64/8 (1.04s) csource_test.go:110: opts: {Threaded:true Collide:false Repeat:true RepeatTimes:0 Procs:1 Sandbox:none Fault:false FaultCall:0 FaultNth:0 Leak:false EnableTun:false EnableNetDev:false EnableNetReset:false EnableCgroups:false EnableBinfmtMisc:false EnableCloseFds:false UseTmpDir:true HandleSegv:false Repro:false Trace:false} program: test$int(0x401, 0x1ff, 0x5, 0x8, 0x10001) syz_mmap(&(0x7f0000ffc000/0x3000)=nil, 0x3000) test$array1(&(0x7f0000000000)={0x7ff, "413e9c088f550bb2"}) test$length6(&(0x7f0000000040)={[0x9, 0x10001, 0x7, 0x7], 0x4}) test$union1(&(0x7f0000000080)={@f0=0xc917, 0x8}) test$align5(&(0x7f00000000c0)={{0x7, [0x8]}, {0x4, [0x7ac]}, 0x5}) foo$fmt5(&(0x7f0000000100)={0x5}) test$length27(&(0x7f0000000140)={0x6}, 0x2a) serialize1(&(0x7f0000000180)=""/106, 0x6a) test$array0(&(0x7f0000000200)={0x7, [@f1=0xffffffffffff3fcd, @f1=0xffffffff], 0x40}) syz_compare(&(0x7f0000000000)='@\x00', 0x2, &(0x7f0000000040)=@bf1={{0x7, 0x100, 0x1}, 0xffff}, 0x8) syz_compare_int$2(0x2, 0x2bb, 0x5) syz_errno(0xff) syz_execute_func(&(0x7f0000000080)="8fba4d8976c6e121fcb9559d464bd733d7f9eb3904e145878a0330b13323c09b6464f27301db8a6bb6e695a90ca7c3f5b07e") syz_exit(0x5) syz_mmap(&(0x7f0000ffb000/0x3000)=nil, 0x3000) csource_test.go:111: failed to build program: // autogenerated by syzkaller (https://github.com/google/syzkaller) #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include 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; for (i = 0; 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 { pthread_mutex_t mu; pthread_cond_t cv; int state; } event_t; static void event_init(event_t* ev) { if (pthread_mutex_init(&ev->mu, 0)) exit(1); if (pthread_cond_init(&ev->cv, 0)) exit(1); ev->state = 0; } static void event_reset(event_t* ev) { ev->state = 0; } static void event_set(event_t* ev) { pthread_mutex_lock(&ev->mu); if (ev->state) exit(1); ev->state = 1; pthread_mutex_unlock(&ev->mu); pthread_cond_broadcast(&ev->cv); } static void event_wait(event_t* ev) { pthread_mutex_lock(&ev->mu); while (!ev->state) pthread_cond_wait(&ev->cv, &ev->mu); pthread_mutex_unlock(&ev->mu); } static int event_isset(event_t* ev) { pthread_mutex_lock(&ev->mu); int res = ev->state; pthread_mutex_unlock(&ev->mu); return res; } static int event_timedwait(event_t* ev, uint64_t timeout) { uint64_t start = current_time_ms(); uint64_t now = start; pthread_mutex_lock(&ev->mu); for (;;) { if (ev->state) break; uint64_t remain = timeout - (now - start); struct timespec ts; ts.tv_sec = remain / 1000; ts.tv_nsec = (remain % 1000) * 1000 * 1000; pthread_cond_timedwait(&ev->cv, &ev->mu, &ts); now = current_time_ms(); if (now - start > timeout) break; } int res = ev->state; pthread_mutex_unlock(&ev->mu); return res; } #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)))) static long syz_mmap(volatile long a0, volatile long a1) { return (long)mmap((void*)a0, a1, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE | MAP_FIXED, -1, 0); } static long syz_errno(volatile long v) { errno = v; return v == 0 ? 0 : -1; } static long syz_exit(volatile long status) { _exit(status); return 0; } static long syz_compare(volatile long want, volatile long want_len, volatile long got, volatile long got_len) { if (want_len != got_len) { errno = EBADF; return -1; } if (memcmp((void*)want, (void*)got, want_len)) { errno = EINVAL; return -1; } return 0; } static long syz_compare_int(volatile long n, ...) { va_list args; va_start(args, n); long v0 = va_arg(args, long); long v1 = va_arg(args, long); long v2 = va_arg(args, long); long v3 = va_arg(args, long); va_end(args); if (n < 2 || n > 4) return errno = E2BIG, -1; if (n <= 2 && v2 != 0) return errno = EFAULT, -1; if (n <= 3 && v3 != 0) return errno = EFAULT, -1; if (v0 != v1) return errno = EINVAL, -1; if (n > 2 && v0 != v2) return errno = EINVAL, -1; if (n > 3 && v0 != v3) return errno = EINVAL, -1; return 0; } static void loop(); static int do_sandbox_none(void) { loop(); return 0; } static long syz_execute_func(volatile long text) { volatile long p[8] = {0}; (void)p; ((void (*)(void))(text))(); return 0; } 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 < 16; 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); event_timedwait(&th->done, 45); break; } } for (i = 0; i < 100 && __atomic_load_n(&running, __ATOMIC_RELAXED); i++) sleep_ms(1); } static void execute_one(void); static void loop(void) { execute_one(); } #ifndef SYS_foo #define SYS_foo 0 #endif #ifndef SYS_serialize1 #define SYS_serialize1 0 #endif #ifndef SYS_test #define SYS_test 0 #endif void execute_call(int call) { switch (call) { case 0: syscall(SYS_test, 0x401, -1, 5, 8, 0x10001, 0); break; case 1: syz_mmap(0x20ffc000, 0x3000); break; case 2: *(uint8_t*)0x20000000 = -1; memcpy((void*)0x20000001, "\x41\x3e\x9c\x08\x8f\x55\x0b\xb2", 8); syscall(SYS_test, 0x20000000, 0, 0, 0, 0, 0); break; case 3: *(uint16_t*)0x20000040 = 9; *(uint16_t*)0x20000042 = 1; *(uint16_t*)0x20000044 = 7; *(uint16_t*)0x20000046 = 7; *(uint16_t*)0x20000048 = 4; syscall(SYS_test, 0x20000040, 0, 0, 0, 0, 0); break; case 4: *(uint64_t*)0x20000080 = 0xc917; *(uint8_t*)0x20000088 = 8; syscall(SYS_test, 0x20000080, 0, 0, 0, 0, 0); break; case 5: *(uint64_t*)0x200000c0 = 7; *(uint16_t*)0x200000c8 = 8; *(uint64_t*)0x200000ca = 4; *(uint16_t*)0x200000d2 = 0x7ac; *(uint8_t*)0x200000d4 = 5; syscall(SYS_test, 0x200000c0, 0, 0, 0, 0, 0); break; case 6: sprintf((char*)0x20000100, "%020llu", (long long)5); syscall(SYS_foo, 0x20000100, 0); break; case 7: *(uint8_t*)0x20000140 = 6; syscall(SYS_test, 0x20000140, 0x2a, 0, 0, 0, 0); break; case 8: syscall(SYS_serialize1, 0x20000180, 0x6a); break; case 9: *(uint8_t*)0x20000200 = 7; *(uint64_t*)0x20000201 = 0xffffffffffff3fcd; *(uint64_t*)0x20000209 = 0xffffffff; *(uint64_t*)0x20000211 = 0x40; syscall(SYS_test, 0x20000200, 0, 0, 0, 0, 0); break; case 10: memcpy((void*)0x20000000, "@\000", 2); STORE_BY_BITMASK(uint32_t, , 0x20000040, 7, 0, 10); STORE_BY_BITMASK(uint32_t, , 0x20000040, 0x100, 10, 10); STORE_BY_BITMASK(uint32_t, , 0x20000040, 1, 20, 10); *(uint8_t*)0x20000044 = -1; syz_compare(0x20000000, 2, 0x20000040, 8); break; case 11: syz_compare_int(2, 0x2bb, 5, 0, 0); break; case 12: syz_errno(0xff); break; case 13: memcpy((void*)0x20000080, "\x8f\xba\x4d\x89\x76\xc6\xe1\x21\xfc\xb9\x55\x9d\x46\x4b\xd7\x33\xd7\xf9\xeb\x39\x04\xe1\x45\x87\x8a\x03\x30\xb1\x33\x23\xc0\x9b\x64\x64\xf2\x73\x01\xdb\x8a\x6b\xb6\xe6\x95\xa9\x0c\xa7\xc3\xf5\xb0\x7e", 50); syz_execute_func(0x20000080); break; case 14: syz_exit(5); break; case 15: syz_mmap(0x20ffb000, 0x3000); break; } } int main(void) { syz_mmap(0x20000000, 0x1000000); use_temporary_dir(); do_sandbox_none(); return 0; } /usr/local/bin/ld: cannot find -lasan collect2: error: ld returned 1 exit status compiler invocation: gcc [-o /tmp/syz-executor756296547 -DGOOS_test=1 -DGOARCH_64=1 -DHOSTGOOS_freebsd=1 -x c - -O2 -pthread -Wall -Werror -Wparentheses -Wunused-const-variable -Wframe-larger-than=8192 -m64 -fsanitize=address] --- FAIL: TestGenerate/test/64/16 (1.27s) csource_test.go:110: opts: {Threaded:true Collide:false Repeat:true RepeatTimes:0 Procs:0 Sandbox:none Fault:false FaultCall:0 FaultNth:0 Leak:false EnableTun:false EnableNetDev:false EnableNetReset:false EnableCgroups:false EnableBinfmtMisc:false EnableCloseFds:false UseTmpDir:true HandleSegv:false Repro:false Trace:false} program: test$int(0x401, 0x1ff, 0x5, 0x8, 0x10001) syz_mmap(&(0x7f0000ffc000/0x3000)=nil, 0x3000) test$array1(&(0x7f0000000000)={0x7ff, "413e9c088f550bb2"}) test$length6(&(0x7f0000000040)={[0x9, 0x10001, 0x7, 0x7], 0x4}) test$union1(&(0x7f0000000080)={@f0=0xc917, 0x8}) test$align5(&(0x7f00000000c0)={{0x7, [0x8]}, {0x4, [0x7ac]}, 0x5}) foo$fmt5(&(0x7f0000000100)={0x5}) test$length27(&(0x7f0000000140)={0x6}, 0x2a) serialize1(&(0x7f0000000180)=""/106, 0x6a) test$array0(&(0x7f0000000200)={0x7, [@f1=0xffffffffffff3fcd, @f1=0xffffffff], 0x40}) syz_compare(&(0x7f0000000000)='@\x00', 0x2, &(0x7f0000000040)=@bf1={{0x7, 0x100, 0x1}, 0xffff}, 0x8) syz_compare_int$2(0x2, 0x2bb, 0x5) syz_errno(0xff) syz_execute_func(&(0x7f0000000080)="8fba4d8976c6e121fcb9559d464bd733d7f9eb3904e145878a0330b13323c09b6464f27301db8a6bb6e695a90ca7c3f5b07e") syz_exit(0x5) syz_mmap(&(0x7f0000ffb000/0x3000)=nil, 0x3000) csource_test.go:111: failed to build program: // autogenerated by syzkaller (https://github.com/google/syzkaller) #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include 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; for (i = 0; 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 { pthread_mutex_t mu; pthread_cond_t cv; int state; } event_t; static void event_init(event_t* ev) { if (pthread_mutex_init(&ev->mu, 0)) exit(1); if (pthread_cond_init(&ev->cv, 0)) exit(1); ev->state = 0; } static void event_reset(event_t* ev) { ev->state = 0; } static void event_set(event_t* ev) { pthread_mutex_lock(&ev->mu); if (ev->state) exit(1); ev->state = 1; pthread_mutex_unlock(&ev->mu); pthread_cond_broadcast(&ev->cv); } static void event_wait(event_t* ev) { pthread_mutex_lock(&ev->mu); while (!ev->state) pthread_cond_wait(&ev->cv, &ev->mu); pthread_mutex_unlock(&ev->mu); } static int event_isset(event_t* ev) { pthread_mutex_lock(&ev->mu); int res = ev->state; pthread_mutex_unlock(&ev->mu); return res; } static int event_timedwait(event_t* ev, uint64_t timeout) { uint64_t start = current_time_ms(); uint64_t now = start; pthread_mutex_lock(&ev->mu); for (;;) { if (ev->state) break; uint64_t remain = timeout - (now - start); struct timespec ts; ts.tv_sec = remain / 1000; ts.tv_nsec = (remain % 1000) * 1000 * 1000; pthread_cond_timedwait(&ev->cv, &ev->mu, &ts); now = current_time_ms(); if (now - start > timeout) break; } int res = ev->state; pthread_mutex_unlock(&ev->mu); return res; } #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)))) static long syz_mmap(volatile long a0, volatile long a1) { return (long)mmap((void*)a0, a1, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE | MAP_FIXED, -1, 0); } static long syz_errno(volatile long v) { errno = v; return v == 0 ? 0 : -1; } static long syz_exit(volatile long status) { _exit(status); return 0; } static long syz_compare(volatile long want, volatile long want_len, volatile long got, volatile long got_len) { if (want_len != got_len) { errno = EBADF; return -1; } if (memcmp((void*)want, (void*)got, want_len)) { errno = EINVAL; return -1; } return 0; } static long syz_compare_int(volatile long n, ...) { va_list args; va_start(args, n); long v0 = va_arg(args, long); long v1 = va_arg(args, long); long v2 = va_arg(args, long); long v3 = va_arg(args, long); va_end(args); if (n < 2 || n > 4) return errno = E2BIG, -1; if (n <= 2 && v2 != 0) return errno = EFAULT, -1; if (n <= 3 && v3 != 0) return errno = EFAULT, -1; if (v0 != v1) return errno = EINVAL, -1; if (n > 2 && v0 != v2) return errno = EINVAL, -1; if (n > 3 && v0 != v3) return errno = EINVAL, -1; return 0; } static void loop(); static int do_sandbox_none(void) { loop(); return 0; } static long syz_execute_func(volatile long text) { volatile long p[8] = {0}; (void)p; ((void (*)(void))(text))(); return 0; } 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 < 16; 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); event_timedwait(&th->done, 45); break; } } for (i = 0; i < 100 && __atomic_load_n(&running, __ATOMIC_RELAXED); i++) sleep_ms(1); } static void execute_one(void); static void loop(void) { execute_one(); } #ifndef SYS_foo #define SYS_foo 0 #endif #ifndef SYS_serialize1 #define SYS_serialize1 0 #endif #ifndef SYS_test #define SYS_test 0 #endif void execute_call(int call) { switch (call) { case 0: syscall(SYS_test, 0x401, -1, 5, 8, 0x10001, 0); break; case 1: syz_mmap(0x20ffc000, 0x3000); break; case 2: *(uint8_t*)0x20000000 = -1; memcpy((void*)0x20000001, "\x41\x3e\x9c\x08\x8f\x55\x0b\xb2", 8); syscall(SYS_test, 0x20000000, 0, 0, 0, 0, 0); break; case 3: *(uint16_t*)0x20000040 = 9; *(uint16_t*)0x20000042 = 1; *(uint16_t*)0x20000044 = 7; *(uint16_t*)0x20000046 = 7; *(uint16_t*)0x20000048 = 4; syscall(SYS_test, 0x20000040, 0, 0, 0, 0, 0); break; case 4: *(uint64_t*)0x20000080 = 0xc917; *(uint8_t*)0x20000088 = 8; syscall(SYS_test, 0x20000080, 0, 0, 0, 0, 0); break; case 5: *(uint64_t*)0x200000c0 = 7; *(uint16_t*)0x200000c8 = 8; *(uint64_t*)0x200000ca = 4; *(uint16_t*)0x200000d2 = 0x7ac; *(uint8_t*)0x200000d4 = 5; syscall(SYS_test, 0x200000c0, 0, 0, 0, 0, 0); break; case 6: sprintf((char*)0x20000100, "%020llu", (long long)5); syscall(SYS_foo, 0x20000100, 0); break; case 7: *(uint8_t*)0x20000140 = 6; syscall(SYS_test, 0x20000140, 0x2a, 0, 0, 0, 0); break; case 8: syscall(SYS_serialize1, 0x20000180, 0x6a); break; case 9: *(uint8_t*)0x20000200 = 7; *(uint64_t*)0x20000201 = 0xffffffffffff3fcd; *(uint64_t*)0x20000209 = 0xffffffff; *(uint64_t*)0x20000211 = 0x40; syscall(SYS_test, 0x20000200, 0, 0, 0, 0, 0); break; case 10: memcpy((void*)0x20000000, "@\000", 2); STORE_BY_BITMASK(uint32_t, , 0x20000040, 7, 0, 10); STORE_BY_BITMASK(uint32_t, , 0x20000040, 0x100, 10, 10); STORE_BY_BITMASK(uint32_t, , 0x20000040, 1, 20, 10); *(uint8_t*)0x20000044 = -1; syz_compare(0x20000000, 2, 0x20000040, 8); break; case 11: syz_compare_int(2, 0x2bb, 5, 0, 0); break; case 12: syz_errno(0xff); break; case 13: memcpy((void*)0x20000080, "\x8f\xba\x4d\x89\x76\xc6\xe1\x21\xfc\xb9\x55\x9d\x46\x4b\xd7\x33\xd7\xf9\xeb\x39\x04\xe1\x45\x87\x8a\x03\x30\xb1\x33\x23\xc0\x9b\x64\x64\xf2\x73\x01\xdb\x8a\x6b\xb6\xe6\x95\xa9\x0c\xa7\xc3\xf5\xb0\x7e", 50); syz_execute_func(0x20000080); break; case 14: syz_exit(5); break; case 15: syz_mmap(0x20ffb000, 0x3000); break; } } int main(void) { syz_mmap(0x20000000, 0x1000000); use_temporary_dir(); do_sandbox_none(); return 0; } /usr/local/bin/ld: cannot find -lasan collect2: error: ld returned 1 exit status compiler invocation: gcc [-o /tmp/syz-executor888342292 -DGOOS_test=1 -DGOARCH_64=1 -DHOSTGOOS_freebsd=1 -x c - -O2 -pthread -Wall -Werror -Wparentheses -Wunused-const-variable -Wframe-larger-than=8192 -m64 -fsanitize=address] --- FAIL: TestGenerate/test/64/10 (1.20s) csource_test.go:110: opts: {Threaded:true Collide:false Repeat:true RepeatTimes:0 Procs:0 Sandbox: Fault:false FaultCall:0 FaultNth:0 Leak:false EnableTun:false EnableNetDev:false EnableNetReset:false EnableCgroups:false EnableBinfmtMisc:false EnableCloseFds:false UseTmpDir:true HandleSegv:false Repro:false Trace:false} program: test$int(0x401, 0x1ff, 0x5, 0x8, 0x10001) syz_mmap(&(0x7f0000ffc000/0x3000)=nil, 0x3000) test$array1(&(0x7f0000000000)={0x7ff, "413e9c088f550bb2"}) test$length6(&(0x7f0000000040)={[0x9, 0x10001, 0x7, 0x7], 0x4}) test$union1(&(0x7f0000000080)={@f0=0xc917, 0x8}) test$align5(&(0x7f00000000c0)={{0x7, [0x8]}, {0x4, [0x7ac]}, 0x5}) foo$fmt5(&(0x7f0000000100)={0x5}) test$length27(&(0x7f0000000140)={0x6}, 0x2a) serialize1(&(0x7f0000000180)=""/106, 0x6a) test$array0(&(0x7f0000000200)={0x7, [@f1=0xffffffffffff3fcd, @f1=0xffffffff], 0x40}) syz_compare(&(0x7f0000000000)='@\x00', 0x2, &(0x7f0000000040)=@bf1={{0x7, 0x100, 0x1}, 0xffff}, 0x8) syz_compare_int$2(0x2, 0x2bb, 0x5) syz_errno(0xff) syz_execute_func(&(0x7f0000000080)="8fba4d8976c6e121fcb9559d464bd733d7f9eb3904e145878a0330b13323c09b6464f27301db8a6bb6e695a90ca7c3f5b07e") syz_exit(0x5) syz_mmap(&(0x7f0000ffb000/0x3000)=nil, 0x3000) csource_test.go:111: failed to build program: // autogenerated by syzkaller (https://github.com/google/syzkaller) #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include 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; for (i = 0; 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 { pthread_mutex_t mu; pthread_cond_t cv; int state; } event_t; static void event_init(event_t* ev) { if (pthread_mutex_init(&ev->mu, 0)) exit(1); if (pthread_cond_init(&ev->cv, 0)) exit(1); ev->state = 0; } static void event_reset(event_t* ev) { ev->state = 0; } static void event_set(event_t* ev) { pthread_mutex_lock(&ev->mu); if (ev->state) exit(1); ev->state = 1; pthread_mutex_unlock(&ev->mu); pthread_cond_broadcast(&ev->cv); } static void event_wait(event_t* ev) { pthread_mutex_lock(&ev->mu); while (!ev->state) pthread_cond_wait(&ev->cv, &ev->mu); pthread_mutex_unlock(&ev->mu); } static int event_isset(event_t* ev) { pthread_mutex_lock(&ev->mu); int res = ev->state; pthread_mutex_unlock(&ev->mu); return res; } static int event_timedwait(event_t* ev, uint64_t timeout) { uint64_t start = current_time_ms(); uint64_t now = start; pthread_mutex_lock(&ev->mu); for (;;) { if (ev->state) break; uint64_t remain = timeout - (now - start); struct timespec ts; ts.tv_sec = remain / 1000; ts.tv_nsec = (remain % 1000) * 1000 * 1000; pthread_cond_timedwait(&ev->cv, &ev->mu, &ts); now = current_time_ms(); if (now - start > timeout) break; } int res = ev->state; pthread_mutex_unlock(&ev->mu); return res; } #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)))) static long syz_mmap(volatile long a0, volatile long a1) { return (long)mmap((void*)a0, a1, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE | MAP_FIXED, -1, 0); } static long syz_errno(volatile long v) { errno = v; return v == 0 ? 0 : -1; } static long syz_exit(volatile long status) { _exit(status); return 0; } static long syz_compare(volatile long want, volatile long want_len, volatile long got, volatile long got_len) { if (want_len != got_len) { errno = EBADF; return -1; } if (memcmp((void*)want, (void*)got, want_len)) { errno = EINVAL; return -1; } return 0; } static long syz_compare_int(volatile long n, ...) { va_list args; va_start(args, n); long v0 = va_arg(args, long); long v1 = va_arg(args, long); long v2 = va_arg(args, long); long v3 = va_arg(args, long); va_end(args); if (n < 2 || n > 4) return errno = E2BIG, -1; if (n <= 2 && v2 != 0) return errno = EFAULT, -1; if (n <= 3 && v3 != 0) return errno = EFAULT, -1; if (v0 != v1) return errno = EINVAL, -1; if (n > 2 && v0 != v2) return errno = EINVAL, -1; if (n > 3 && v0 != v3) return errno = EINVAL, -1; return 0; } static long syz_execute_func(volatile long text) { volatile long p[8] = {0}; (void)p; ((void (*)(void))(text))(); return 0; } 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 < 16; 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); event_timedwait(&th->done, 45); break; } } for (i = 0; i < 100 && __atomic_load_n(&running, __ATOMIC_RELAXED); i++) sleep_ms(1); } static void execute_one(void); static void loop(void) { execute_one(); } #ifndef SYS_foo #define SYS_foo 0 #endif #ifndef SYS_serialize1 #define SYS_serialize1 0 #endif #ifndef SYS_test #define SYS_test 0 #endif void execute_call(int call) { switch (call) { case 0: syscall(SYS_test, 0x401, -1, 5, 8, 0x10001, 0); break; case 1: syz_mmap(0x20ffc000, 0x3000); break; case 2: *(uint8_t*)0x20000000 = -1; memcpy((void*)0x20000001, "\x41\x3e\x9c\x08\x8f\x55\x0b\xb2", 8); syscall(SYS_test, 0x20000000, 0, 0, 0, 0, 0); break; case 3: *(uint16_t*)0x20000040 = 9; *(uint16_t*)0x20000042 = 1; *(uint16_t*)0x20000044 = 7; *(uint16_t*)0x20000046 = 7; *(uint16_t*)0x20000048 = 4; syscall(SYS_test, 0x20000040, 0, 0, 0, 0, 0); break; case 4: *(uint64_t*)0x20000080 = 0xc917; *(uint8_t*)0x20000088 = 8; syscall(SYS_test, 0x20000080, 0, 0, 0, 0, 0); break; case 5: *(uint64_t*)0x200000c0 = 7; *(uint16_t*)0x200000c8 = 8; *(uint64_t*)0x200000ca = 4; *(uint16_t*)0x200000d2 = 0x7ac; *(uint8_t*)0x200000d4 = 5; syscall(SYS_test, 0x200000c0, 0, 0, 0, 0, 0); break; case 6: sprintf((char*)0x20000100, "%020llu", (long long)5); syscall(SYS_foo, 0x20000100, 0); break; case 7: *(uint8_t*)0x20000140 = 6; syscall(SYS_test, 0x20000140, 0x2a, 0, 0, 0, 0); break; case 8: syscall(SYS_serialize1, 0x20000180, 0x6a); break; case 9: *(uint8_t*)0x20000200 = 7; *(uint64_t*)0x20000201 = 0xffffffffffff3fcd; *(uint64_t*)0x20000209 = 0xffffffff; *(uint64_t*)0x20000211 = 0x40; syscall(SYS_test, 0x20000200, 0, 0, 0, 0, 0); break; case 10: memcpy((void*)0x20000000, "@\000", 2); STORE_BY_BITMASK(uint32_t, , 0x20000040, 7, 0, 10); STORE_BY_BITMASK(uint32_t, , 0x20000040, 0x100, 10, 10); STORE_BY_BITMASK(uint32_t, , 0x20000040, 1, 20, 10); *(uint8_t*)0x20000044 = -1; syz_compare(0x20000000, 2, 0x20000040, 8); break; case 11: syz_compare_int(2, 0x2bb, 5, 0, 0); break; case 12: syz_errno(0xff); break; case 13: memcpy((void*)0x20000080, "\x8f\xba\x4d\x89\x76\xc6\xe1\x21\xfc\xb9\x55\x9d\x46\x4b\xd7\x33\xd7\xf9\xeb\x39\x04\xe1\x45\x87\x8a\x03\x30\xb1\x33\x23\xc0\x9b\x64\x64\xf2\x73\x01\xdb\x8a\x6b\xb6\xe6\x95\xa9\x0c\xa7\xc3\xf5\xb0\x7e", 50); syz_execute_func(0x20000080); break; case 14: syz_exit(5); break; case 15: syz_mmap(0x20ffb000, 0x3000); break; } } int main(void) { syz_mmap(0x20000000, 0x1000000); use_temporary_dir(); loop(); return 0; } /usr/local/bin/ld: cannot find -lasan collect2: error: ld returned 1 exit status compiler invocation: gcc [-o /tmp/syz-executor691433357 -DGOOS_test=1 -DGOARCH_64=1 -DHOSTGOOS_freebsd=1 -x c - -O2 -pthread -Wall -Werror -Wparentheses -Wunused-const-variable -Wframe-larger-than=8192 -m64 -fsanitize=address] --- FAIL: TestGenerate/test/64/9 (1.19s) csource_test.go:110: opts: {Threaded:true Collide:false Repeat:true RepeatTimes:0 Procs:4 Sandbox:none Fault:false FaultCall:0 FaultNth:0 Leak:false EnableTun:false EnableNetDev:false EnableNetReset:false EnableCgroups:false EnableBinfmtMisc:false EnableCloseFds:false UseTmpDir:true HandleSegv:false Repro:false Trace:false} program: test$int(0x401, 0x1ff, 0x5, 0x8, 0x10001) syz_mmap(&(0x7f0000ffc000/0x3000)=nil, 0x3000) test$array1(&(0x7f0000000000)={0x7ff, "413e9c088f550bb2"}) test$length6(&(0x7f0000000040)={[0x9, 0x10001, 0x7, 0x7], 0x4}) test$union1(&(0x7f0000000080)={@f0=0xc917, 0x8}) test$align5(&(0x7f00000000c0)={{0x7, [0x8]}, {0x4, [0x7ac]}, 0x5}) foo$fmt5(&(0x7f0000000100)={0x5}) test$length27(&(0x7f0000000140)={0x6}, 0x2a) serialize1(&(0x7f0000000180)=""/106, 0x6a) test$array0(&(0x7f0000000200)={0x7, [@f1=0xffffffffffff3fcd, @f1=0xffffffff], 0x40}) syz_compare(&(0x7f0000000000)='@\x00', 0x2, &(0x7f0000000040)=@bf1={{0x7, 0x100, 0x1}, 0xffff}, 0x8) syz_compare_int$2(0x2, 0x2bb, 0x5) syz_errno(0xff) syz_execute_func(&(0x7f0000000080)="8fba4d8976c6e121fcb9559d464bd733d7f9eb3904e145878a0330b13323c09b6464f27301db8a6bb6e695a90ca7c3f5b07e") syz_exit(0x5) syz_mmap(&(0x7f0000ffb000/0x3000)=nil, 0x3000) csource_test.go:111: failed to build program: // autogenerated by syzkaller (https://github.com/google/syzkaller) #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include unsigned long long procid; 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; for (i = 0; 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 { pthread_mutex_t mu; pthread_cond_t cv; int state; } event_t; static void event_init(event_t* ev) { if (pthread_mutex_init(&ev->mu, 0)) exit(1); if (pthread_cond_init(&ev->cv, 0)) exit(1); ev->state = 0; } static void event_reset(event_t* ev) { ev->state = 0; } static void event_set(event_t* ev) { pthread_mutex_lock(&ev->mu); if (ev->state) exit(1); ev->state = 1; pthread_mutex_unlock(&ev->mu); pthread_cond_broadcast(&ev->cv); } static void event_wait(event_t* ev) { pthread_mutex_lock(&ev->mu); while (!ev->state) pthread_cond_wait(&ev->cv, &ev->mu); pthread_mutex_unlock(&ev->mu); } static int event_isset(event_t* ev) { pthread_mutex_lock(&ev->mu); int res = ev->state; pthread_mutex_unlock(&ev->mu); return res; } static int event_timedwait(event_t* ev, uint64_t timeout) { uint64_t start = current_time_ms(); uint64_t now = start; pthread_mutex_lock(&ev->mu); for (;;) { if (ev->state) break; uint64_t remain = timeout - (now - start); struct timespec ts; ts.tv_sec = remain / 1000; ts.tv_nsec = (remain % 1000) * 1000 * 1000; pthread_cond_timedwait(&ev->cv, &ev->mu, &ts); now = current_time_ms(); if (now - start > timeout) break; } int res = ev->state; pthread_mutex_unlock(&ev->mu); return res; } #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)))) static long syz_mmap(volatile long a0, volatile long a1) { return (long)mmap((void*)a0, a1, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE | MAP_FIXED, -1, 0); } static long syz_errno(volatile long v) { errno = v; return v == 0 ? 0 : -1; } static long syz_exit(volatile long status) { _exit(status); return 0; } static long syz_compare(volatile long want, volatile long want_len, volatile long got, volatile long got_len) { if (want_len != got_len) { errno = EBADF; return -1; } if (memcmp((void*)want, (void*)got, want_len)) { errno = EINVAL; return -1; } return 0; } static long syz_compare_int(volatile long n, ...) { va_list args; va_start(args, n); long v0 = va_arg(args, long); long v1 = va_arg(args, long); long v2 = va_arg(args, long); long v3 = va_arg(args, long); va_end(args); if (n < 2 || n > 4) return errno = E2BIG, -1; if (n <= 2 && v2 != 0) return errno = EFAULT, -1; if (n <= 3 && v3 != 0) return errno = EFAULT, -1; if (v0 != v1) return errno = EINVAL, -1; if (n > 2 && v0 != v2) return errno = EINVAL, -1; if (n > 3 && v0 != v3) return errno = EINVAL, -1; return 0; } static void loop(); static int do_sandbox_none(void) { loop(); return 0; } static long syz_execute_func(volatile long text) { volatile long p[8] = {0}; (void)p; ((void (*)(void))(text))(); return 0; } 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 < 16; 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); event_timedwait(&th->done, 45); break; } } for (i = 0; i < 100 && __atomic_load_n(&running, __ATOMIC_RELAXED); i++) sleep_ms(1); } static void execute_one(void); static void loop(void) { execute_one(); } #ifndef SYS_foo #define SYS_foo 0 #endif #ifndef SYS_serialize1 #define SYS_serialize1 0 #endif #ifndef SYS_test #define SYS_test 0 #endif void execute_call(int call) { switch (call) { case 0: syscall(SYS_test, 0x401, -1, 5, 8, 0x10001, 0); break; case 1: syz_mmap(0x20ffc000, 0x3000); break; case 2: *(uint8_t*)0x20000000 = -1; memcpy((void*)0x20000001, "\x41\x3e\x9c\x08\x8f\x55\x0b\xb2", 8); syscall(SYS_test, 0x20000000, 0, 0, 0, 0, 0); break; case 3: *(uint16_t*)0x20000040 = 9; *(uint16_t*)0x20000042 = 1; *(uint16_t*)0x20000044 = 7; *(uint16_t*)0x20000046 = 7; *(uint16_t*)0x20000048 = 4; syscall(SYS_test, 0x20000040, 0, 0, 0, 0, 0); break; case 4: *(uint64_t*)0x20000080 = 0xc917; *(uint8_t*)0x20000088 = 8; syscall(SYS_test, 0x20000080, 0, 0, 0, 0, 0); break; case 5: *(uint64_t*)0x200000c0 = 7; *(uint16_t*)0x200000c8 = 8; *(uint64_t*)0x200000ca = 4; *(uint16_t*)0x200000d2 = 0x7ac; *(uint8_t*)0x200000d4 = 5; syscall(SYS_test, 0x200000c0, 0, 0, 0, 0, 0); break; case 6: sprintf((char*)0x20000100, "%020llu", (long long)5); syscall(SYS_foo, 0x20000100, 0); break; case 7: *(uint8_t*)0x20000140 = 6; syscall(SYS_test, 0x20000140, 0x2a, 0, 0, 0, 0); break; case 8: syscall(SYS_serialize1, 0x20000180, 0x6a); break; case 9: *(uint8_t*)0x20000200 = 7; *(uint64_t*)0x20000201 = 0xffffffffffff3fcd; *(uint64_t*)0x20000209 = 0xffffffff; *(uint64_t*)0x20000211 = 0x40; syscall(SYS_test, 0x20000200, 0, 0, 0, 0, 0); break; case 10: memcpy((void*)0x20000000, "@\000", 2); STORE_BY_BITMASK(uint32_t, , 0x20000040, 7, 0, 10); STORE_BY_BITMASK(uint32_t, , 0x20000040, 0x100, 10, 10); STORE_BY_BITMASK(uint32_t, , 0x20000040, 1, 20, 10); *(uint8_t*)0x20000044 = -1; syz_compare(0x20000000, 2, 0x20000040, 8); break; case 11: syz_compare_int(2, 0x2bb, 5, 0, 0); break; case 12: syz_errno(0xff); break; case 13: memcpy((void*)0x20000080, "\x8f\xba\x4d\x89\x76\xc6\xe1\x21\xfc\xb9\x55\x9d\x46\x4b\xd7\x33\xd7\xf9\xeb\x39\x04\xe1\x45\x87\x8a\x03\x30\xb1\x33\x23\xc0\x9b\x64\x64\xf2\x73\x01\xdb\x8a\x6b\xb6\xe6\x95\xa9\x0c\xa7\xc3\xf5\xb0\x7e", 50); syz_execute_func(0x20000080); break; case 14: syz_exit(5); break; case 15: syz_mmap(0x20ffb000, 0x3000); break; } } int main(void) { syz_mmap(0x20000000, 0x1000000); for (procid = 0; procid < 4; procid++) { if (fork() == 0) { use_temporary_dir(); do_sandbox_none(); } } sleep(1000000); return 0; } /usr/local/bin/ld: cannot find -lasan collect2: error: ld returned 1 exit status compiler invocation: gcc [-o /tmp/syz-executor343039846 -DGOOS_test=1 -DGOARCH_64=1 -DHOSTGOOS_freebsd=1 -x c - -O2 -pthread -Wall -Werror -Wparentheses -Wunused-const-variable -Wframe-larger-than=8192 -m64 -fsanitize=address] --- FAIL: TestGenerate/test/64/7 (1.04s) csource_test.go:110: opts: {Threaded:true Collide:false Repeat:true RepeatTimes:10 Procs:0 Sandbox:none Fault:false FaultCall:0 FaultNth:0 Leak:false EnableTun:false EnableNetDev:false EnableNetReset:false EnableCgroups:false EnableBinfmtMisc:false EnableCloseFds:false UseTmpDir:true HandleSegv:false Repro:false Trace:false} program: test$int(0x401, 0x1ff, 0x5, 0x8, 0x10001) syz_mmap(&(0x7f0000ffc000/0x3000)=nil, 0x3000) test$array1(&(0x7f0000000000)={0x7ff, "413e9c088f550bb2"}) test$length6(&(0x7f0000000040)={[0x9, 0x10001, 0x7, 0x7], 0x4}) test$union1(&(0x7f0000000080)={@f0=0xc917, 0x8}) test$align5(&(0x7f00000000c0)={{0x7, [0x8]}, {0x4, [0x7ac]}, 0x5}) foo$fmt5(&(0x7f0000000100)={0x5}) test$length27(&(0x7f0000000140)={0x6}, 0x2a) serialize1(&(0x7f0000000180)=""/106, 0x6a) test$array0(&(0x7f0000000200)={0x7, [@f1=0xffffffffffff3fcd, @f1=0xffffffff], 0x40}) syz_compare(&(0x7f0000000000)='@\x00', 0x2, &(0x7f0000000040)=@bf1={{0x7, 0x100, 0x1}, 0xffff}, 0x8) syz_compare_int$2(0x2, 0x2bb, 0x5) syz_errno(0xff) syz_execute_func(&(0x7f0000000080)="8fba4d8976c6e121fcb9559d464bd733d7f9eb3904e145878a0330b13323c09b6464f27301db8a6bb6e695a90ca7c3f5b07e") syz_exit(0x5) syz_mmap(&(0x7f0000ffb000/0x3000)=nil, 0x3000) csource_test.go:111: failed to build program: // autogenerated by syzkaller (https://github.com/google/syzkaller) #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include 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; for (i = 0; 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 { pthread_mutex_t mu; pthread_cond_t cv; int state; } event_t; static void event_init(event_t* ev) { if (pthread_mutex_init(&ev->mu, 0)) exit(1); if (pthread_cond_init(&ev->cv, 0)) exit(1); ev->state = 0; } static void event_reset(event_t* ev) { ev->state = 0; } static void event_set(event_t* ev) { pthread_mutex_lock(&ev->mu); if (ev->state) exit(1); ev->state = 1; pthread_mutex_unlock(&ev->mu); pthread_cond_broadcast(&ev->cv); } static void event_wait(event_t* ev) { pthread_mutex_lock(&ev->mu); while (!ev->state) pthread_cond_wait(&ev->cv, &ev->mu); pthread_mutex_unlock(&ev->mu); } static int event_isset(event_t* ev) { pthread_mutex_lock(&ev->mu); int res = ev->state; pthread_mutex_unlock(&ev->mu); return res; } static int event_timedwait(event_t* ev, uint64_t timeout) { uint64_t start = current_time_ms(); uint64_t now = start; pthread_mutex_lock(&ev->mu); for (;;) { if (ev->state) break; uint64_t remain = timeout - (now - start); struct timespec ts; ts.tv_sec = remain / 1000; ts.tv_nsec = (remain % 1000) * 1000 * 1000; pthread_cond_timedwait(&ev->cv, &ev->mu, &ts); now = current_time_ms(); if (now - start > timeout) break; } int res = ev->state; pthread_mutex_unlock(&ev->mu); return res; } #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)))) static long syz_mmap(volatile long a0, volatile long a1) { return (long)mmap((void*)a0, a1, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE | MAP_FIXED, -1, 0); } static long syz_errno(volatile long v) { errno = v; return v == 0 ? 0 : -1; } static long syz_exit(volatile long status) { _exit(status); return 0; } static long syz_compare(volatile long want, volatile long want_len, volatile long got, volatile long got_len) { if (want_len != got_len) { errno = EBADF; return -1; } if (memcmp((void*)want, (void*)got, want_len)) { errno = EINVAL; return -1; } return 0; } static long syz_compare_int(volatile long n, ...) { va_list args; va_start(args, n); long v0 = va_arg(args, long); long v1 = va_arg(args, long); long v2 = va_arg(args, long); long v3 = va_arg(args, long); va_end(args); if (n < 2 || n > 4) return errno = E2BIG, -1; if (n <= 2 && v2 != 0) return errno = EFAULT, -1; if (n <= 3 && v3 != 0) return errno = EFAULT, -1; if (v0 != v1) return errno = EINVAL, -1; if (n > 2 && v0 != v2) return errno = EINVAL, -1; if (n > 3 && v0 != v3) return errno = EINVAL, -1; return 0; } static void loop(); static int do_sandbox_none(void) { loop(); return 0; } static long syz_execute_func(volatile long text) { volatile long p[8] = {0}; (void)p; ((void (*)(void))(text))(); return 0; } 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 < 16; 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); event_timedwait(&th->done, 45); break; } } for (i = 0; i < 100 && __atomic_load_n(&running, __ATOMIC_RELAXED); i++) sleep_ms(1); } static void execute_one(void); static void loop(void) { execute_one(); } #ifndef SYS_foo #define SYS_foo 0 #endif #ifndef SYS_serialize1 #define SYS_serialize1 0 #endif #ifndef SYS_test #define SYS_test 0 #endif void execute_call(int call) { switch (call) { case 0: syscall(SYS_test, 0x401, -1, 5, 8, 0x10001, 0); break; case 1: syz_mmap(0x20ffc000, 0x3000); break; case 2: *(uint8_t*)0x20000000 = -1; memcpy((void*)0x20000001, "\x41\x3e\x9c\x08\x8f\x55\x0b\xb2", 8); syscall(SYS_test, 0x20000000, 0, 0, 0, 0, 0); break; case 3: *(uint16_t*)0x20000040 = 9; *(uint16_t*)0x20000042 = 1; *(uint16_t*)0x20000044 = 7; *(uint16_t*)0x20000046 = 7; *(uint16_t*)0x20000048 = 4; syscall(SYS_test, 0x20000040, 0, 0, 0, 0, 0); break; case 4: *(uint64_t*)0x20000080 = 0xc917; *(uint8_t*)0x20000088 = 8; syscall(SYS_test, 0x20000080, 0, 0, 0, 0, 0); break; case 5: *(uint64_t*)0x200000c0 = 7; *(uint16_t*)0x200000c8 = 8; *(uint64_t*)0x200000ca = 4; *(uint16_t*)0x200000d2 = 0x7ac; *(uint8_t*)0x200000d4 = 5; syscall(SYS_test, 0x200000c0, 0, 0, 0, 0, 0); break; case 6: sprintf((char*)0x20000100, "%020llu", (long long)5); syscall(SYS_foo, 0x20000100, 0); break; case 7: *(uint8_t*)0x20000140 = 6; syscall(SYS_test, 0x20000140, 0x2a, 0, 0, 0, 0); break; case 8: syscall(SYS_serialize1, 0x20000180, 0x6a); break; case 9: *(uint8_t*)0x20000200 = 7; *(uint64_t*)0x20000201 = 0xffffffffffff3fcd; *(uint64_t*)0x20000209 = 0xffffffff; *(uint64_t*)0x20000211 = 0x40; syscall(SYS_test, 0x20000200, 0, 0, 0, 0, 0); break; case 10: memcpy((void*)0x20000000, "@\000", 2); STORE_BY_BITMASK(uint32_t, , 0x20000040, 7, 0, 10); STORE_BY_BITMASK(uint32_t, , 0x20000040, 0x100, 10, 10); STORE_BY_BITMASK(uint32_t, , 0x20000040, 1, 20, 10); *(uint8_t*)0x20000044 = -1; syz_compare(0x20000000, 2, 0x20000040, 8); break; case 11: syz_compare_int(2, 0x2bb, 5, 0, 0); break; case 12: syz_errno(0xff); break; case 13: memcpy((void*)0x20000080, "\x8f\xba\x4d\x89\x76\xc6\xe1\x21\xfc\xb9\x55\x9d\x46\x4b\xd7\x33\xd7\xf9\xeb\x39\x04\xe1\x45\x87\x8a\x03\x30\xb1\x33\x23\xc0\x9b\x64\x64\xf2\x73\x01\xdb\x8a\x6b\xb6\xe6\x95\xa9\x0c\xa7\xc3\xf5\xb0\x7e", 50); syz_execute_func(0x20000080); break; case 14: syz_exit(5); break; case 15: syz_mmap(0x20ffb000, 0x3000); break; } } int main(void) { syz_mmap(0x20000000, 0x1000000); use_temporary_dir(); do_sandbox_none(); return 0; } /usr/local/bin/ld: cannot find -lasan collect2: error: ld returned 1 exit status compiler invocation: gcc [-o /tmp/syz-executor506362183 -DGOOS_test=1 -DGOARCH_64=1 -DHOSTGOOS_freebsd=1 -x c - -O2 -pthread -Wall -Werror -Wparentheses -Wunused-const-variable -Wframe-larger-than=8192 -m64 -fsanitize=address] --- FAIL: TestGenerate/test/64/15 (1.44s) csource_test.go:110: opts: {Threaded:true Collide:false Repeat:true RepeatTimes:0 Procs:0 Sandbox:none Fault:false FaultCall:0 FaultNth:0 Leak:false EnableTun:false EnableNetDev:false EnableNetReset:false EnableCgroups:false EnableBinfmtMisc:false EnableCloseFds:false UseTmpDir:true HandleSegv:false Repro:false Trace:false} program: test$int(0x401, 0x1ff, 0x5, 0x8, 0x10001) syz_mmap(&(0x7f0000ffc000/0x3000)=nil, 0x3000) test$array1(&(0x7f0000000000)={0x7ff, "413e9c088f550bb2"}) test$length6(&(0x7f0000000040)={[0x9, 0x10001, 0x7, 0x7], 0x4}) test$union1(&(0x7f0000000080)={@f0=0xc917, 0x8}) test$align5(&(0x7f00000000c0)={{0x7, [0x8]}, {0x4, [0x7ac]}, 0x5}) foo$fmt5(&(0x7f0000000100)={0x5}) test$length27(&(0x7f0000000140)={0x6}, 0x2a) serialize1(&(0x7f0000000180)=""/106, 0x6a) test$array0(&(0x7f0000000200)={0x7, [@f1=0xffffffffffff3fcd, @f1=0xffffffff], 0x40}) syz_compare(&(0x7f0000000000)='@\x00', 0x2, &(0x7f0000000040)=@bf1={{0x7, 0x100, 0x1}, 0xffff}, 0x8) syz_compare_int$2(0x2, 0x2bb, 0x5) syz_errno(0xff) syz_execute_func(&(0x7f0000000080)="8fba4d8976c6e121fcb9559d464bd733d7f9eb3904e145878a0330b13323c09b6464f27301db8a6bb6e695a90ca7c3f5b07e") syz_exit(0x5) syz_mmap(&(0x7f0000ffb000/0x3000)=nil, 0x3000) csource_test.go:111: failed to build program: // autogenerated by syzkaller (https://github.com/google/syzkaller) #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include 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; for (i = 0; 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 { pthread_mutex_t mu; pthread_cond_t cv; int state; } event_t; static void event_init(event_t* ev) { if (pthread_mutex_init(&ev->mu, 0)) exit(1); if (pthread_cond_init(&ev->cv, 0)) exit(1); ev->state = 0; } static void event_reset(event_t* ev) { ev->state = 0; } static void event_set(event_t* ev) { pthread_mutex_lock(&ev->mu); if (ev->state) exit(1); ev->state = 1; pthread_mutex_unlock(&ev->mu); pthread_cond_broadcast(&ev->cv); } static void event_wait(event_t* ev) { pthread_mutex_lock(&ev->mu); while (!ev->state) pthread_cond_wait(&ev->cv, &ev->mu); pthread_mutex_unlock(&ev->mu); } static int event_isset(event_t* ev) { pthread_mutex_lock(&ev->mu); int res = ev->state; pthread_mutex_unlock(&ev->mu); return res; } static int event_timedwait(event_t* ev, uint64_t timeout) { uint64_t start = current_time_ms(); uint64_t now = start; pthread_mutex_lock(&ev->mu); for (;;) { if (ev->state) break; uint64_t remain = timeout - (now - start); struct timespec ts; ts.tv_sec = remain / 1000; ts.tv_nsec = (remain % 1000) * 1000 * 1000; pthread_cond_timedwait(&ev->cv, &ev->mu, &ts); now = current_time_ms(); if (now - start > timeout) break; } int res = ev->state; pthread_mutex_unlock(&ev->mu); return res; } #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)))) static long syz_mmap(volatile long a0, volatile long a1) { return (long)mmap((void*)a0, a1, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE | MAP_FIXED, -1, 0); } static long syz_errno(volatile long v) { errno = v; return v == 0 ? 0 : -1; } static long syz_exit(volatile long status) { _exit(status); return 0; } static long syz_compare(volatile long want, volatile long want_len, volatile long got, volatile long got_len) { if (want_len != got_len) { errno = EBADF; return -1; } if (memcmp((void*)want, (void*)got, want_len)) { errno = EINVAL; return -1; } return 0; } static long syz_compare_int(volatile long n, ...) { va_list args; va_start(args, n); long v0 = va_arg(args, long); long v1 = va_arg(args, long); long v2 = va_arg(args, long); long v3 = va_arg(args, long); va_end(args); if (n < 2 || n > 4) return errno = E2BIG, -1; if (n <= 2 && v2 != 0) return errno = EFAULT, -1; if (n <= 3 && v3 != 0) return errno = EFAULT, -1; if (v0 != v1) return errno = EINVAL, -1; if (n > 2 && v0 != v2) return errno = EINVAL, -1; if (n > 3 && v0 != v3) return errno = EINVAL, -1; return 0; } static void loop(); static int do_sandbox_none(void) { loop(); return 0; } static long syz_execute_func(volatile long text) { volatile long p[8] = {0}; (void)p; ((void (*)(void))(text))(); return 0; } 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 < 16; 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); event_timedwait(&th->done, 45); break; } } for (i = 0; i < 100 && __atomic_load_n(&running, __ATOMIC_RELAXED); i++) sleep_ms(1); } static void execute_one(void); static void loop(void) { execute_one(); } #ifndef SYS_foo #define SYS_foo 0 #endif #ifndef SYS_serialize1 #define SYS_serialize1 0 #endif #ifndef SYS_test #define SYS_test 0 #endif void execute_call(int call) { switch (call) { case 0: syscall(SYS_test, 0x401, -1, 5, 8, 0x10001, 0); break; case 1: syz_mmap(0x20ffc000, 0x3000); break; case 2: *(uint8_t*)0x20000000 = -1; memcpy((void*)0x20000001, "\x41\x3e\x9c\x08\x8f\x55\x0b\xb2", 8); syscall(SYS_test, 0x20000000, 0, 0, 0, 0, 0); break; case 3: *(uint16_t*)0x20000040 = 9; *(uint16_t*)0x20000042 = 1; *(uint16_t*)0x20000044 = 7; *(uint16_t*)0x20000046 = 7; *(uint16_t*)0x20000048 = 4; syscall(SYS_test, 0x20000040, 0, 0, 0, 0, 0); break; case 4: *(uint64_t*)0x20000080 = 0xc917; *(uint8_t*)0x20000088 = 8; syscall(SYS_test, 0x20000080, 0, 0, 0, 0, 0); break; case 5: *(uint64_t*)0x200000c0 = 7; *(uint16_t*)0x200000c8 = 8; *(uint64_t*)0x200000ca = 4; *(uint16_t*)0x200000d2 = 0x7ac; *(uint8_t*)0x200000d4 = 5; syscall(SYS_test, 0x200000c0, 0, 0, 0, 0, 0); break; case 6: sprintf((char*)0x20000100, "%020llu", (long long)5); syscall(SYS_foo, 0x20000100, 0); break; case 7: *(uint8_t*)0x20000140 = 6; syscall(SYS_test, 0x20000140, 0x2a, 0, 0, 0, 0); break; case 8: syscall(SYS_serialize1, 0x20000180, 0x6a); break; case 9: *(uint8_t*)0x20000200 = 7; *(uint64_t*)0x20000201 = 0xffffffffffff3fcd; *(uint64_t*)0x20000209 = 0xffffffff; *(uint64_t*)0x20000211 = 0x40; syscall(SYS_test, 0x20000200, 0, 0, 0, 0, 0); break; case 10: memcpy((void*)0x20000000, "@\000", 2); STORE_BY_BITMASK(uint32_t, , 0x20000040, 7, 0, 10); STORE_BY_BITMASK(uint32_t, , 0x20000040, 0x100, 10, 10); STORE_BY_BITMASK(uint32_t, , 0x20000040, 1, 20, 10); *(uint8_t*)0x20000044 = -1; syz_compare(0x20000000, 2, 0x20000040, 8); break; case 11: syz_compare_int(2, 0x2bb, 5, 0, 0); break; case 12: syz_errno(0xff); break; case 13: memcpy((void*)0x20000080, "\x8f\xba\x4d\x89\x76\xc6\xe1\x21\xfc\xb9\x55\x9d\x46\x4b\xd7\x33\xd7\xf9\xeb\x39\x04\xe1\x45\x87\x8a\x03\x30\xb1\x33\x23\xc0\x9b\x64\x64\xf2\x73\x01\xdb\x8a\x6b\xb6\xe6\x95\xa9\x0c\xa7\xc3\xf5\xb0\x7e", 50); syz_execute_func(0x20000080); break; case 14: syz_exit(5); break; case 15: syz_mmap(0x20ffb000, 0x3000); break; } } int main(void) { syz_mmap(0x20000000, 0x1000000); use_temporary_dir(); do_sandbox_none(); return 0; } /usr/local/bin/ld: cannot find -lasan collect2: error: ld returned 1 exit status compiler invocation: gcc [-o /tmp/syz-executor916024712 -DGOOS_test=1 -DGOARCH_64=1 -DHOSTGOOS_freebsd=1 -x c - -O2 -pthread -Wall -Werror -Wparentheses -Wunused-const-variable -Wframe-larger-than=8192 -m64 -fsanitize=address] --- FAIL: TestGenerate/test/64/13 (1.36s) csource_test.go:110: opts: {Threaded:true Collide:false Repeat:true RepeatTimes:0 Procs:0 Sandbox:none Fault:false FaultCall:0 FaultNth:0 Leak:false EnableTun:false EnableNetDev:false EnableNetReset:false EnableCgroups:false EnableBinfmtMisc:false EnableCloseFds:false UseTmpDir:true HandleSegv:false Repro:false Trace:false} program: test$int(0x401, 0x1ff, 0x5, 0x8, 0x10001) syz_mmap(&(0x7f0000ffc000/0x3000)=nil, 0x3000) test$array1(&(0x7f0000000000)={0x7ff, "413e9c088f550bb2"}) test$length6(&(0x7f0000000040)={[0x9, 0x10001, 0x7, 0x7], 0x4}) test$union1(&(0x7f0000000080)={@f0=0xc917, 0x8}) test$align5(&(0x7f00000000c0)={{0x7, [0x8]}, {0x4, [0x7ac]}, 0x5}) foo$fmt5(&(0x7f0000000100)={0x5}) test$length27(&(0x7f0000000140)={0x6}, 0x2a) serialize1(&(0x7f0000000180)=""/106, 0x6a) test$array0(&(0x7f0000000200)={0x7, [@f1=0xffffffffffff3fcd, @f1=0xffffffff], 0x40}) syz_compare(&(0x7f0000000000)='@\x00', 0x2, &(0x7f0000000040)=@bf1={{0x7, 0x100, 0x1}, 0xffff}, 0x8) syz_compare_int$2(0x2, 0x2bb, 0x5) syz_errno(0xff) syz_execute_func(&(0x7f0000000080)="8fba4d8976c6e121fcb9559d464bd733d7f9eb3904e145878a0330b13323c09b6464f27301db8a6bb6e695a90ca7c3f5b07e") syz_exit(0x5) syz_mmap(&(0x7f0000ffb000/0x3000)=nil, 0x3000) csource_test.go:111: failed to build program: // autogenerated by syzkaller (https://github.com/google/syzkaller) #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include 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; for (i = 0; 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 { pthread_mutex_t mu; pthread_cond_t cv; int state; } event_t; static void event_init(event_t* ev) { if (pthread_mutex_init(&ev->mu, 0)) exit(1); if (pthread_cond_init(&ev->cv, 0)) exit(1); ev->state = 0; } static void event_reset(event_t* ev) { ev->state = 0; } static void event_set(event_t* ev) { pthread_mutex_lock(&ev->mu); if (ev->state) exit(1); ev->state = 1; pthread_mutex_unlock(&ev->mu); pthread_cond_broadcast(&ev->cv); } static void event_wait(event_t* ev) { pthread_mutex_lock(&ev->mu); while (!ev->state) pthread_cond_wait(&ev->cv, &ev->mu); pthread_mutex_unlock(&ev->mu); } static int event_isset(event_t* ev) { pthread_mutex_lock(&ev->mu); int res = ev->state; pthread_mutex_unlock(&ev->mu); return res; } static int event_timedwait(event_t* ev, uint64_t timeout) { uint64_t start = current_time_ms(); uint64_t now = start; pthread_mutex_lock(&ev->mu); for (;;) { if (ev->state) break; uint64_t remain = timeout - (now - start); struct timespec ts; ts.tv_sec = remain / 1000; ts.tv_nsec = (remain % 1000) * 1000 * 1000; pthread_cond_timedwait(&ev->cv, &ev->mu, &ts); now = current_time_ms(); if (now - start > timeout) break; } int res = ev->state; pthread_mutex_unlock(&ev->mu); return res; } #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)))) static long syz_mmap(volatile long a0, volatile long a1) { return (long)mmap((void*)a0, a1, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE | MAP_FIXED, -1, 0); } static long syz_errno(volatile long v) { errno = v; return v == 0 ? 0 : -1; } static long syz_exit(volatile long status) { _exit(status); return 0; } static long syz_compare(volatile long want, volatile long want_len, volatile long got, volatile long got_len) { if (want_len != got_len) { errno = EBADF; return -1; } if (memcmp((void*)want, (void*)got, want_len)) { errno = EINVAL; return -1; } return 0; } static long syz_compare_int(volatile long n, ...) { va_list args; va_start(args, n); long v0 = va_arg(args, long); long v1 = va_arg(args, long); long v2 = va_arg(args, long); long v3 = va_arg(args, long); va_end(args); if (n < 2 || n > 4) return errno = E2BIG, -1; if (n <= 2 && v2 != 0) return errno = EFAULT, -1; if (n <= 3 && v3 != 0) return errno = EFAULT, -1; if (v0 != v1) return errno = EINVAL, -1; if (n > 2 && v0 != v2) return errno = EINVAL, -1; if (n > 3 && v0 != v3) return errno = EINVAL, -1; return 0; } static void loop(); static int do_sandbox_none(void) { loop(); return 0; } static long syz_execute_func(volatile long text) { volatile long p[8] = {0}; (void)p; ((void (*)(void))(text))(); return 0; } 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 < 16; 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); event_timedwait(&th->done, 45); break; } } for (i = 0; i < 100 && __atomic_load_n(&running, __ATOMIC_RELAXED); i++) sleep_ms(1); } static void execute_one(void); static void loop(void) { execute_one(); } #ifndef SYS_foo #define SYS_foo 0 #endif #ifndef SYS_serialize1 #define SYS_serialize1 0 #endif #ifndef SYS_test #define SYS_test 0 #endif void execute_call(int call) { switch (call) { case 0: syscall(SYS_test, 0x401, -1, 5, 8, 0x10001, 0); break; case 1: syz_mmap(0x20ffc000, 0x3000); break; case 2: *(uint8_t*)0x20000000 = -1; memcpy((void*)0x20000001, "\x41\x3e\x9c\x08\x8f\x55\x0b\xb2", 8); syscall(SYS_test, 0x20000000, 0, 0, 0, 0, 0); break; case 3: *(uint16_t*)0x20000040 = 9; *(uint16_t*)0x20000042 = 1; *(uint16_t*)0x20000044 = 7; *(uint16_t*)0x20000046 = 7; *(uint16_t*)0x20000048 = 4; syscall(SYS_test, 0x20000040, 0, 0, 0, 0, 0); break; case 4: *(uint64_t*)0x20000080 = 0xc917; *(uint8_t*)0x20000088 = 8; syscall(SYS_test, 0x20000080, 0, 0, 0, 0, 0); break; case 5: *(uint64_t*)0x200000c0 = 7; *(uint16_t*)0x200000c8 = 8; *(uint64_t*)0x200000ca = 4; *(uint16_t*)0x200000d2 = 0x7ac; *(uint8_t*)0x200000d4 = 5; syscall(SYS_test, 0x200000c0, 0, 0, 0, 0, 0); break; case 6: sprintf((char*)0x20000100, "%020llu", (long long)5); syscall(SYS_foo, 0x20000100, 0); break; case 7: *(uint8_t*)0x20000140 = 6; syscall(SYS_test, 0x20000140, 0x2a, 0, 0, 0, 0); break; case 8: syscall(SYS_serialize1, 0x20000180, 0x6a); break; case 9: *(uint8_t*)0x20000200 = 7; *(uint64_t*)0x20000201 = 0xffffffffffff3fcd; *(uint64_t*)0x20000209 = 0xffffffff; *(uint64_t*)0x20000211 = 0x40; syscall(SYS_test, 0x20000200, 0, 0, 0, 0, 0); break; case 10: memcpy((void*)0x20000000, "@\000", 2); STORE_BY_BITMASK(uint32_t, , 0x20000040, 7, 0, 10); STORE_BY_BITMASK(uint32_t, , 0x20000040, 0x100, 10, 10); STORE_BY_BITMASK(uint32_t, , 0x20000040, 1, 20, 10); *(uint8_t*)0x20000044 = -1; syz_compare(0x20000000, 2, 0x20000040, 8); break; case 11: syz_compare_int(2, 0x2bb, 5, 0, 0); break; case 12: syz_errno(0xff); break; case 13: memcpy((void*)0x20000080, "\x8f\xba\x4d\x89\x76\xc6\xe1\x21\xfc\xb9\x55\x9d\x46\x4b\xd7\x33\xd7\xf9\xeb\x39\x04\xe1\x45\x87\x8a\x03\x30\xb1\x33\x23\xc0\x9b\x64\x64\xf2\x73\x01\xdb\x8a\x6b\xb6\xe6\x95\xa9\x0c\xa7\xc3\xf5\xb0\x7e", 50); syz_execute_func(0x20000080); break; case 14: syz_exit(5); break; case 15: syz_mmap(0x20ffb000, 0x3000); break; } } int main(void) { syz_mmap(0x20000000, 0x1000000); use_temporary_dir(); do_sandbox_none(); return 0; } /usr/local/bin/ld: cannot find -lasan collect2: error: ld returned 1 exit status compiler invocation: gcc [-o /tmp/syz-executor554460666 -DGOOS_test=1 -DGOARCH_64=1 -DHOSTGOOS_freebsd=1 -x c - -O2 -pthread -Wall -Werror -Wparentheses -Wunused-const-variable -Wframe-larger-than=8192 -m64 -fsanitize=address] --- FAIL: TestGenerate/test/64/4 (0.94s) csource_test.go:110: opts: {Threaded:true Collide:false Repeat:false RepeatTimes:0 Procs:0 Sandbox:none Fault:false FaultCall:0 FaultNth:0 Leak:false EnableTun:false EnableNetDev:false EnableNetReset:false EnableCgroups:false EnableBinfmtMisc:false EnableCloseFds:false UseTmpDir:true HandleSegv:false Repro:false Trace:false} program: test$int(0x401, 0x1ff, 0x5, 0x8, 0x10001) syz_mmap(&(0x7f0000ffc000/0x3000)=nil, 0x3000) test$array1(&(0x7f0000000000)={0x7ff, "413e9c088f550bb2"}) test$length6(&(0x7f0000000040)={[0x9, 0x10001, 0x7, 0x7], 0x4}) test$union1(&(0x7f0000000080)={@f0=0xc917, 0x8}) test$align5(&(0x7f00000000c0)={{0x7, [0x8]}, {0x4, [0x7ac]}, 0x5}) foo$fmt5(&(0x7f0000000100)={0x5}) test$length27(&(0x7f0000000140)={0x6}, 0x2a) serialize1(&(0x7f0000000180)=""/106, 0x6a) test$array0(&(0x7f0000000200)={0x7, [@f1=0xffffffffffff3fcd, @f1=0xffffffff], 0x40}) syz_compare(&(0x7f0000000000)='@\x00', 0x2, &(0x7f0000000040)=@bf1={{0x7, 0x100, 0x1}, 0xffff}, 0x8) syz_compare_int$2(0x2, 0x2bb, 0x5) syz_errno(0xff) syz_execute_func(&(0x7f0000000080)="8fba4d8976c6e121fcb9559d464bd733d7f9eb3904e145878a0330b13323c09b6464f27301db8a6bb6e695a90ca7c3f5b07e") syz_exit(0x5) syz_mmap(&(0x7f0000ffb000/0x3000)=nil, 0x3000) csource_test.go:111: failed to build program: // autogenerated by syzkaller (https://github.com/google/syzkaller) #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include 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; for (i = 0; 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 { pthread_mutex_t mu; pthread_cond_t cv; int state; } event_t; static void event_init(event_t* ev) { if (pthread_mutex_init(&ev->mu, 0)) exit(1); if (pthread_cond_init(&ev->cv, 0)) exit(1); ev->state = 0; } static void event_reset(event_t* ev) { ev->state = 0; } static void event_set(event_t* ev) { pthread_mutex_lock(&ev->mu); if (ev->state) exit(1); ev->state = 1; pthread_mutex_unlock(&ev->mu); pthread_cond_broadcast(&ev->cv); } static void event_wait(event_t* ev) { pthread_mutex_lock(&ev->mu); while (!ev->state) pthread_cond_wait(&ev->cv, &ev->mu); pthread_mutex_unlock(&ev->mu); } static int event_isset(event_t* ev) { pthread_mutex_lock(&ev->mu); int res = ev->state; pthread_mutex_unlock(&ev->mu); return res; } static int event_timedwait(event_t* ev, uint64_t timeout) { uint64_t start = current_time_ms(); uint64_t now = start; pthread_mutex_lock(&ev->mu); for (;;) { if (ev->state) break; uint64_t remain = timeout - (now - start); struct timespec ts; ts.tv_sec = remain / 1000; ts.tv_nsec = (remain % 1000) * 1000 * 1000; pthread_cond_timedwait(&ev->cv, &ev->mu, &ts); now = current_time_ms(); if (now - start > timeout) break; } int res = ev->state; pthread_mutex_unlock(&ev->mu); return res; } #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)))) static long syz_mmap(volatile long a0, volatile long a1) { return (long)mmap((void*)a0, a1, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE | MAP_FIXED, -1, 0); } static long syz_errno(volatile long v) { errno = v; return v == 0 ? 0 : -1; } static long syz_exit(volatile long status) { _exit(status); return 0; } static long syz_compare(volatile long want, volatile long want_len, volatile long got, volatile long got_len) { if (want_len != got_len) { errno = EBADF; return -1; } if (memcmp((void*)want, (void*)got, want_len)) { errno = EINVAL; return -1; } return 0; } static long syz_compare_int(volatile long n, ...) { va_list args; va_start(args, n); long v0 = va_arg(args, long); long v1 = va_arg(args, long); long v2 = va_arg(args, long); long v3 = va_arg(args, long); va_end(args); if (n < 2 || n > 4) return errno = E2BIG, -1; if (n <= 2 && v2 != 0) return errno = EFAULT, -1; if (n <= 3 && v3 != 0) return errno = EFAULT, -1; if (v0 != v1) return errno = EINVAL, -1; if (n > 2 && v0 != v2) return errno = EINVAL, -1; if (n > 3 && v0 != v3) return errno = EINVAL, -1; return 0; } static void loop(); static int do_sandbox_none(void) { loop(); return 0; } static long syz_execute_func(volatile long text) { volatile long p[8] = {0}; (void)p; ((void (*)(void))(text))(); return 0; } 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 loop(void) { int i, call, thread; for (call = 0; call < 16; 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); event_timedwait(&th->done, 45); break; } } for (i = 0; i < 100 && __atomic_load_n(&running, __ATOMIC_RELAXED); i++) sleep_ms(1); } #ifndef SYS_foo #define SYS_foo 0 #endif #ifndef SYS_serialize1 #define SYS_serialize1 0 #endif #ifndef SYS_test #define SYS_test 0 #endif void execute_call(int call) { switch (call) { case 0: syscall(SYS_test, 0x401, -1, 5, 8, 0x10001, 0); break; case 1: syz_mmap(0x20ffc000, 0x3000); break; case 2: *(uint8_t*)0x20000000 = -1; memcpy((void*)0x20000001, "\x41\x3e\x9c\x08\x8f\x55\x0b\xb2", 8); syscall(SYS_test, 0x20000000, 0, 0, 0, 0, 0); break; case 3: *(uint16_t*)0x20000040 = 9; *(uint16_t*)0x20000042 = 1; *(uint16_t*)0x20000044 = 7; *(uint16_t*)0x20000046 = 7; *(uint16_t*)0x20000048 = 4; syscall(SYS_test, 0x20000040, 0, 0, 0, 0, 0); break; case 4: *(uint64_t*)0x20000080 = 0xc917; *(uint8_t*)0x20000088 = 8; syscall(SYS_test, 0x20000080, 0, 0, 0, 0, 0); break; case 5: *(uint64_t*)0x200000c0 = 7; *(uint16_t*)0x200000c8 = 8; *(uint64_t*)0x200000ca = 4; *(uint16_t*)0x200000d2 = 0x7ac; *(uint8_t*)0x200000d4 = 5; syscall(SYS_test, 0x200000c0, 0, 0, 0, 0, 0); break; case 6: sprintf((char*)0x20000100, "%020llu", (long long)5); syscall(SYS_foo, 0x20000100, 0); break; case 7: *(uint8_t*)0x20000140 = 6; syscall(SYS_test, 0x20000140, 0x2a, 0, 0, 0, 0); break; case 8: syscall(SYS_serialize1, 0x20000180, 0x6a); break; case 9: *(uint8_t*)0x20000200 = 7; *(uint64_t*)0x20000201 = 0xffffffffffff3fcd; *(uint64_t*)0x20000209 = 0xffffffff; *(uint64_t*)0x20000211 = 0x40; syscall(SYS_test, 0x20000200, 0, 0, 0, 0, 0); break; case 10: memcpy((void*)0x20000000, "@\000", 2); STORE_BY_BITMASK(uint32_t, , 0x20000040, 7, 0, 10); STORE_BY_BITMASK(uint32_t, , 0x20000040, 0x100, 10, 10); STORE_BY_BITMASK(uint32_t, , 0x20000040, 1, 20, 10); *(uint8_t*)0x20000044 = -1; syz_compare(0x20000000, 2, 0x20000040, 8); break; case 11: syz_compare_int(2, 0x2bb, 5, 0, 0); break; case 12: syz_errno(0xff); break; case 13: memcpy((void*)0x20000080, "\x8f\xba\x4d\x89\x76\xc6\xe1\x21\xfc\xb9\x55\x9d\x46\x4b\xd7\x33\xd7\xf9\xeb\x39\x04\xe1\x45\x87\x8a\x03\x30\xb1\x33\x23\xc0\x9b\x64\x64\xf2\x73\x01\xdb\x8a\x6b\xb6\xe6\x95\xa9\x0c\xa7\xc3\xf5\xb0\x7e", 50); syz_execute_func(0x20000080); break; case 14: syz_exit(5); break; case 15: syz_mmap(0x20ffb000, 0x3000); break; } } int main(void) { syz_mmap(0x20000000, 0x1000000); use_temporary_dir(); do_sandbox_none(); return 0; } /usr/local/bin/ld: cannot find -lasan collect2: error: ld returned 1 exit status compiler invocation: gcc [-o /tmp/syz-executor491478801 -DGOOS_test=1 -DGOARCH_64=1 -DHOSTGOOS_freebsd=1 -x c - -O2 -pthread -Wall -Werror -Wparentheses -Wunused-const-variable -Wframe-larger-than=8192 -m64 -fsanitize=address] --- FAIL: TestGenerate/test/64/6 (1.25s) csource_test.go:110: opts: {Threaded:true Collide:false Repeat:true RepeatTimes:0 Procs:0 Sandbox:none Fault:false FaultCall:0 FaultNth:0 Leak:false EnableTun:false EnableNetDev:false EnableNetReset:false EnableCgroups:false EnableBinfmtMisc:false EnableCloseFds:false UseTmpDir:true HandleSegv:false Repro:false Trace:false} program: test$int(0x401, 0x1ff, 0x5, 0x8, 0x10001) syz_mmap(&(0x7f0000ffc000/0x3000)=nil, 0x3000) test$array1(&(0x7f0000000000)={0x7ff, "413e9c088f550bb2"}) test$length6(&(0x7f0000000040)={[0x9, 0x10001, 0x7, 0x7], 0x4}) test$union1(&(0x7f0000000080)={@f0=0xc917, 0x8}) test$align5(&(0x7f00000000c0)={{0x7, [0x8]}, {0x4, [0x7ac]}, 0x5}) foo$fmt5(&(0x7f0000000100)={0x5}) test$length27(&(0x7f0000000140)={0x6}, 0x2a) serialize1(&(0x7f0000000180)=""/106, 0x6a) test$array0(&(0x7f0000000200)={0x7, [@f1=0xffffffffffff3fcd, @f1=0xffffffff], 0x40}) syz_compare(&(0x7f0000000000)='@\x00', 0x2, &(0x7f0000000040)=@bf1={{0x7, 0x100, 0x1}, 0xffff}, 0x8) syz_compare_int$2(0x2, 0x2bb, 0x5) syz_errno(0xff) syz_execute_func(&(0x7f0000000080)="8fba4d8976c6e121fcb9559d464bd733d7f9eb3904e145878a0330b13323c09b6464f27301db8a6bb6e695a90ca7c3f5b07e") syz_exit(0x5) syz_mmap(&(0x7f0000ffb000/0x3000)=nil, 0x3000) csource_test.go:111: failed to build program: // autogenerated by syzkaller (https://github.com/google/syzkaller) #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include 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; for (i = 0; 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 { pthread_mutex_t mu; pthread_cond_t cv; int state; } event_t; static void event_init(event_t* ev) { if (pthread_mutex_init(&ev->mu, 0)) exit(1); if (pthread_cond_init(&ev->cv, 0)) exit(1); ev->state = 0; } static void event_reset(event_t* ev) { ev->state = 0; } static void event_set(event_t* ev) { pthread_mutex_lock(&ev->mu); if (ev->state) exit(1); ev->state = 1; pthread_mutex_unlock(&ev->mu); pthread_cond_broadcast(&ev->cv); } static void event_wait(event_t* ev) { pthread_mutex_lock(&ev->mu); while (!ev->state) pthread_cond_wait(&ev->cv, &ev->mu); pthread_mutex_unlock(&ev->mu); } static int event_isset(event_t* ev) { pthread_mutex_lock(&ev->mu); int res = ev->state; pthread_mutex_unlock(&ev->mu); return res; } static int event_timedwait(event_t* ev, uint64_t timeout) { uint64_t start = current_time_ms(); uint64_t now = start; pthread_mutex_lock(&ev->mu); for (;;) { if (ev->state) break; uint64_t remain = timeout - (now - start); struct timespec ts; ts.tv_sec = remain / 1000; ts.tv_nsec = (remain % 1000) * 1000 * 1000; pthread_cond_timedwait(&ev->cv, &ev->mu, &ts); now = current_time_ms(); if (now - start > timeout) break; } int res = ev->state; pthread_mutex_unlock(&ev->mu); return res; } #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)))) static long syz_mmap(volatile long a0, volatile long a1) { return (long)mmap((void*)a0, a1, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE | MAP_FIXED, -1, 0); } static long syz_errno(volatile long v) { errno = v; return v == 0 ? 0 : -1; } static long syz_exit(volatile long status) { _exit(status); return 0; } static long syz_compare(volatile long want, volatile long want_len, volatile long got, volatile long got_len) { if (want_len != got_len) { errno = EBADF; return -1; } if (memcmp((void*)want, (void*)got, want_len)) { errno = EINVAL; return -1; } return 0; } static long syz_compare_int(volatile long n, ...) { va_list args; va_start(args, n); long v0 = va_arg(args, long); long v1 = va_arg(args, long); long v2 = va_arg(args, long); long v3 = va_arg(args, long); va_end(args); if (n < 2 || n > 4) return errno = E2BIG, -1; if (n <= 2 && v2 != 0) return errno = EFAULT, -1; if (n <= 3 && v3 != 0) return errno = EFAULT, -1; if (v0 != v1) return errno = EINVAL, -1; if (n > 2 && v0 != v2) return errno = EINVAL, -1; if (n > 3 && v0 != v3) return errno = EINVAL, -1; return 0; } static void loop(); static int do_sandbox_none(void) { loop(); return 0; } static long syz_execute_func(volatile long text) { volatile long p[8] = {0}; (void)p; ((void (*)(void))(text))(); return 0; } 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 < 16; 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); event_timedwait(&th->done, 45); break; } } for (i = 0; i < 100 && __atomic_load_n(&running, __ATOMIC_RELAXED); i++) sleep_ms(1); } static void execute_one(void); static void loop(void) { execute_one(); } #ifndef SYS_foo #define SYS_foo 0 #endif #ifndef SYS_serialize1 #define SYS_serialize1 0 #endif #ifndef SYS_test #define SYS_test 0 #endif void execute_call(int call) { switch (call) { case 0: syscall(SYS_test, 0x401, -1, 5, 8, 0x10001, 0); break; case 1: syz_mmap(0x20ffc000, 0x3000); break; case 2: *(uint8_t*)0x20000000 = -1; memcpy((void*)0x20000001, "\x41\x3e\x9c\x08\x8f\x55\x0b\xb2", 8); syscall(SYS_test, 0x20000000, 0, 0, 0, 0, 0); break; case 3: *(uint16_t*)0x20000040 = 9; *(uint16_t*)0x20000042 = 1; *(uint16_t*)0x20000044 = 7; *(uint16_t*)0x20000046 = 7; *(uint16_t*)0x20000048 = 4; syscall(SYS_test, 0x20000040, 0, 0, 0, 0, 0); break; case 4: *(uint64_t*)0x20000080 = 0xc917; *(uint8_t*)0x20000088 = 8; syscall(SYS_test, 0x20000080, 0, 0, 0, 0, 0); break; case 5: *(uint64_t*)0x200000c0 = 7; *(uint16_t*)0x200000c8 = 8; *(uint64_t*)0x200000ca = 4; *(uint16_t*)0x200000d2 = 0x7ac; *(uint8_t*)0x200000d4 = 5; syscall(SYS_test, 0x200000c0, 0, 0, 0, 0, 0); break; case 6: sprintf((char*)0x20000100, "%020llu", (long long)5); syscall(SYS_foo, 0x20000100, 0); break; case 7: *(uint8_t*)0x20000140 = 6; syscall(SYS_test, 0x20000140, 0x2a, 0, 0, 0, 0); break; case 8: syscall(SYS_serialize1, 0x20000180, 0x6a); break; case 9: *(uint8_t*)0x20000200 = 7; *(uint64_t*)0x20000201 = 0xffffffffffff3fcd; *(uint64_t*)0x20000209 = 0xffffffff; *(uint64_t*)0x20000211 = 0x40; syscall(SYS_test, 0x20000200, 0, 0, 0, 0, 0); break; case 10: memcpy((void*)0x20000000, "@\000", 2); STORE_BY_BITMASK(uint32_t, , 0x20000040, 7, 0, 10); STORE_BY_BITMASK(uint32_t, , 0x20000040, 0x100, 10, 10); STORE_BY_BITMASK(uint32_t, , 0x20000040, 1, 20, 10); *(uint8_t*)0x20000044 = -1; syz_compare(0x20000000, 2, 0x20000040, 8); break; case 11: syz_compare_int(2, 0x2bb, 5, 0, 0); break; case 12: syz_errno(0xff); break; case 13: memcpy((void*)0x20000080, "\x8f\xba\x4d\x89\x76\xc6\xe1\x21\xfc\xb9\x55\x9d\x46\x4b\xd7\x33\xd7\xf9\xeb\x39\x04\xe1\x45\x87\x8a\x03\x30\xb1\x33\x23\xc0\x9b\x64\x64\xf2\x73\x01\xdb\x8a\x6b\xb6\xe6\x95\xa9\x0c\xa7\xc3\xf5\xb0\x7e", 50); syz_execute_func(0x20000080); break; case 14: syz_exit(5); break; case 15: syz_mmap(0x20ffb000, 0x3000); break; } } int main(void) { syz_mmap(0x20000000, 0x1000000); use_temporary_dir(); do_sandbox_none(); return 0; } /usr/local/bin/ld: cannot find -lasan collect2: error: ld returned 1 exit status compiler invocation: gcc [-o /tmp/syz-executor418912206 -DGOOS_test=1 -DGOARCH_64=1 -DHOSTGOOS_freebsd=1 -x c - -O2 -pthread -Wall -Werror -Wparentheses -Wunused-const-variable -Wframe-larger-than=8192 -m64 -fsanitize=address] --- FAIL: TestGenerate/test/64/5 (1.19s) csource_test.go:110: opts: {Threaded:true Collide:false Repeat:true RepeatTimes:0 Procs:0 Sandbox:none Fault:false FaultCall:0 FaultNth:0 Leak:false EnableTun:false EnableNetDev:false EnableNetReset:false EnableCgroups:false EnableBinfmtMisc:false EnableCloseFds:false UseTmpDir:true HandleSegv:false Repro:false Trace:false} program: test$int(0x401, 0x1ff, 0x5, 0x8, 0x10001) syz_mmap(&(0x7f0000ffc000/0x3000)=nil, 0x3000) test$array1(&(0x7f0000000000)={0x7ff, "413e9c088f550bb2"}) test$length6(&(0x7f0000000040)={[0x9, 0x10001, 0x7, 0x7], 0x4}) test$union1(&(0x7f0000000080)={@f0=0xc917, 0x8}) test$align5(&(0x7f00000000c0)={{0x7, [0x8]}, {0x4, [0x7ac]}, 0x5}) foo$fmt5(&(0x7f0000000100)={0x5}) test$length27(&(0x7f0000000140)={0x6}, 0x2a) serialize1(&(0x7f0000000180)=""/106, 0x6a) test$array0(&(0x7f0000000200)={0x7, [@f1=0xffffffffffff3fcd, @f1=0xffffffff], 0x40}) syz_compare(&(0x7f0000000000)='@\x00', 0x2, &(0x7f0000000040)=@bf1={{0x7, 0x100, 0x1}, 0xffff}, 0x8) syz_compare_int$2(0x2, 0x2bb, 0x5) syz_errno(0xff) syz_execute_func(&(0x7f0000000080)="8fba4d8976c6e121fcb9559d464bd733d7f9eb3904e145878a0330b13323c09b6464f27301db8a6bb6e695a90ca7c3f5b07e") syz_exit(0x5) syz_mmap(&(0x7f0000ffb000/0x3000)=nil, 0x3000) csource_test.go:111: failed to build program: // autogenerated by syzkaller (https://github.com/google/syzkaller) #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include 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; for (i = 0; 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 { pthread_mutex_t mu; pthread_cond_t cv; int state; } event_t; static void event_init(event_t* ev) { if (pthread_mutex_init(&ev->mu, 0)) exit(1); if (pthread_cond_init(&ev->cv, 0)) exit(1); ev->state = 0; } static void event_reset(event_t* ev) { ev->state = 0; } static void event_set(event_t* ev) { pthread_mutex_lock(&ev->mu); if (ev->state) exit(1); ev->state = 1; pthread_mutex_unlock(&ev->mu); pthread_cond_broadcast(&ev->cv); } static void event_wait(event_t* ev) { pthread_mutex_lock(&ev->mu); while (!ev->state) pthread_cond_wait(&ev->cv, &ev->mu); pthread_mutex_unlock(&ev->mu); } static int event_isset(event_t* ev) { pthread_mutex_lock(&ev->mu); int res = ev->state; pthread_mutex_unlock(&ev->mu); return res; } static int event_timedwait(event_t* ev, uint64_t timeout) { uint64_t start = current_time_ms(); uint64_t now = start; pthread_mutex_lock(&ev->mu); for (;;) { if (ev->state) break; uint64_t remain = timeout - (now - start); struct timespec ts; ts.tv_sec = remain / 1000; ts.tv_nsec = (remain % 1000) * 1000 * 1000; pthread_cond_timedwait(&ev->cv, &ev->mu, &ts); now = current_time_ms(); if (now - start > timeout) break; } int res = ev->state; pthread_mutex_unlock(&ev->mu); return res; } #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)))) static long syz_mmap(volatile long a0, volatile long a1) { return (long)mmap((void*)a0, a1, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE | MAP_FIXED, -1, 0); } static long syz_errno(volatile long v) { errno = v; return v == 0 ? 0 : -1; } static long syz_exit(volatile long status) { _exit(status); return 0; } static long syz_compare(volatile long want, volatile long want_len, volatile long got, volatile long got_len) { if (want_len != got_len) { errno = EBADF; return -1; } if (memcmp((void*)want, (void*)got, want_len)) { errno = EINVAL; return -1; } return 0; } static long syz_compare_int(volatile long n, ...) { va_list args; va_start(args, n); long v0 = va_arg(args, long); long v1 = va_arg(args, long); long v2 = va_arg(args, long); long v3 = va_arg(args, long); va_end(args); if (n < 2 || n > 4) return errno = E2BIG, -1; if (n <= 2 && v2 != 0) return errno = EFAULT, -1; if (n <= 3 && v3 != 0) return errno = EFAULT, -1; if (v0 != v1) return errno = EINVAL, -1; if (n > 2 && v0 != v2) return errno = EINVAL, -1; if (n > 3 && v0 != v3) return errno = EINVAL, -1; return 0; } static void loop(); static int do_sandbox_none(void) { loop(); return 0; } static long syz_execute_func(volatile long text) { volatile long p[8] = {0}; (void)p; ((void (*)(void))(text))(); return 0; } 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 < 16; 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); event_timedwait(&th->done, 45); break; } } for (i = 0; i < 100 && __atomic_load_n(&running, __ATOMIC_RELAXED); i++) sleep_ms(1); } static void execute_one(void); static void loop(void) { execute_one(); } #ifndef SYS_foo #define SYS_foo 0 #endif #ifndef SYS_serialize1 #define SYS_serialize1 0 #endif #ifndef SYS_test #define SYS_test 0 #endif void execute_call(int call) { switch (call) { case 0: syscall(SYS_test, 0x401, -1, 5, 8, 0x10001, 0); break; case 1: syz_mmap(0x20ffc000, 0x3000); break; case 2: *(uint8_t*)0x20000000 = -1; memcpy((void*)0x20000001, "\x41\x3e\x9c\x08\x8f\x55\x0b\xb2", 8); syscall(SYS_test, 0x20000000, 0, 0, 0, 0, 0); break; case 3: *(uint16_t*)0x20000040 = 9; *(uint16_t*)0x20000042 = 1; *(uint16_t*)0x20000044 = 7; *(uint16_t*)0x20000046 = 7; *(uint16_t*)0x20000048 = 4; syscall(SYS_test, 0x20000040, 0, 0, 0, 0, 0); break; case 4: *(uint64_t*)0x20000080 = 0xc917; *(uint8_t*)0x20000088 = 8; syscall(SYS_test, 0x20000080, 0, 0, 0, 0, 0); break; case 5: *(uint64_t*)0x200000c0 = 7; *(uint16_t*)0x200000c8 = 8; *(uint64_t*)0x200000ca = 4; *(uint16_t*)0x200000d2 = 0x7ac; *(uint8_t*)0x200000d4 = 5; syscall(SYS_test, 0x200000c0, 0, 0, 0, 0, 0); break; case 6: sprintf((char*)0x20000100, "%020llu", (long long)5); syscall(SYS_foo, 0x20000100, 0); break; case 7: *(uint8_t*)0x20000140 = 6; syscall(SYS_test, 0x20000140, 0x2a, 0, 0, 0, 0); break; case 8: syscall(SYS_serialize1, 0x20000180, 0x6a); break; case 9: *(uint8_t*)0x20000200 = 7; *(uint64_t*)0x20000201 = 0xffffffffffff3fcd; *(uint64_t*)0x20000209 = 0xffffffff; *(uint64_t*)0x20000211 = 0x40; syscall(SYS_test, 0x20000200, 0, 0, 0, 0, 0); break; case 10: memcpy((void*)0x20000000, "@\000", 2); STORE_BY_BITMASK(uint32_t, , 0x20000040, 7, 0, 10); STORE_BY_BITMASK(uint32_t, , 0x20000040, 0x100, 10, 10); STORE_BY_BITMASK(uint32_t, , 0x20000040, 1, 20, 10); *(uint8_t*)0x20000044 = -1; syz_compare(0x20000000, 2, 0x20000040, 8); break; case 11: syz_compare_int(2, 0x2bb, 5, 0, 0); break; case 12: syz_errno(0xff); break; case 13: memcpy((void*)0x20000080, "\x8f\xba\x4d\x89\x76\xc6\xe1\x21\xfc\xb9\x55\x9d\x46\x4b\xd7\x33\xd7\xf9\xeb\x39\x04\xe1\x45\x87\x8a\x03\x30\xb1\x33\x23\xc0\x9b\x64\x64\xf2\x73\x01\xdb\x8a\x6b\xb6\xe6\x95\xa9\x0c\xa7\xc3\xf5\xb0\x7e", 50); syz_execute_func(0x20000080); break; case 14: syz_exit(5); break; case 15: syz_mmap(0x20ffb000, 0x3000); break; } } int main(void) { syz_mmap(0x20000000, 0x1000000); use_temporary_dir(); do_sandbox_none(); return 0; } /usr/local/bin/ld: cannot find -lasan collect2: error: ld returned 1 exit status compiler invocation: gcc [-o /tmp/syz-executor372934972 -DGOOS_test=1 -DGOARCH_64=1 -DHOSTGOOS_freebsd=1 -x c - -O2 -pthread -Wall -Werror -Wparentheses -Wunused-const-variable -Wframe-larger-than=8192 -m64 -fsanitize=address] --- FAIL: TestGenerate/test/64/12 (1.65s) csource_test.go:110: opts: {Threaded:true Collide:false Repeat:true RepeatTimes:0 Procs:0 Sandbox:none Fault:false FaultCall:0 FaultNth:0 Leak:false EnableTun:false EnableNetDev:false EnableNetReset:false EnableCgroups:false EnableBinfmtMisc:false EnableCloseFds:false UseTmpDir:true HandleSegv:false Repro:false Trace:false} program: test$int(0x401, 0x1ff, 0x5, 0x8, 0x10001) syz_mmap(&(0x7f0000ffc000/0x3000)=nil, 0x3000) test$array1(&(0x7f0000000000)={0x7ff, "413e9c088f550bb2"}) test$length6(&(0x7f0000000040)={[0x9, 0x10001, 0x7, 0x7], 0x4}) test$union1(&(0x7f0000000080)={@f0=0xc917, 0x8}) test$align5(&(0x7f00000000c0)={{0x7, [0x8]}, {0x4, [0x7ac]}, 0x5}) foo$fmt5(&(0x7f0000000100)={0x5}) test$length27(&(0x7f0000000140)={0x6}, 0x2a) serialize1(&(0x7f0000000180)=""/106, 0x6a) test$array0(&(0x7f0000000200)={0x7, [@f1=0xffffffffffff3fcd, @f1=0xffffffff], 0x40}) syz_compare(&(0x7f0000000000)='@\x00', 0x2, &(0x7f0000000040)=@bf1={{0x7, 0x100, 0x1}, 0xffff}, 0x8) syz_compare_int$2(0x2, 0x2bb, 0x5) syz_errno(0xff) syz_execute_func(&(0x7f0000000080)="8fba4d8976c6e121fcb9559d464bd733d7f9eb3904e145878a0330b13323c09b6464f27301db8a6bb6e695a90ca7c3f5b07e") syz_exit(0x5) syz_mmap(&(0x7f0000ffb000/0x3000)=nil, 0x3000) csource_test.go:111: failed to build program: // autogenerated by syzkaller (https://github.com/google/syzkaller) #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include 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; for (i = 0; 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 { pthread_mutex_t mu; pthread_cond_t cv; int state; } event_t; static void event_init(event_t* ev) { if (pthread_mutex_init(&ev->mu, 0)) exit(1); if (pthread_cond_init(&ev->cv, 0)) exit(1); ev->state = 0; } static void event_reset(event_t* ev) { ev->state = 0; } static void event_set(event_t* ev) { pthread_mutex_lock(&ev->mu); if (ev->state) exit(1); ev->state = 1; pthread_mutex_unlock(&ev->mu); pthread_cond_broadcast(&ev->cv); } static void event_wait(event_t* ev) { pthread_mutex_lock(&ev->mu); while (!ev->state) pthread_cond_wait(&ev->cv, &ev->mu); pthread_mutex_unlock(&ev->mu); } static int event_isset(event_t* ev) { pthread_mutex_lock(&ev->mu); int res = ev->state; pthread_mutex_unlock(&ev->mu); return res; } static int event_timedwait(event_t* ev, uint64_t timeout) { uint64_t start = current_time_ms(); uint64_t now = start; pthread_mutex_lock(&ev->mu); for (;;) { if (ev->state) break; uint64_t remain = timeout - (now - start); struct timespec ts; ts.tv_sec = remain / 1000; ts.tv_nsec = (remain % 1000) * 1000 * 1000; pthread_cond_timedwait(&ev->cv, &ev->mu, &ts); now = current_time_ms(); if (now - start > timeout) break; } int res = ev->state; pthread_mutex_unlock(&ev->mu); return res; } #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)))) static long syz_mmap(volatile long a0, volatile long a1) { return (long)mmap((void*)a0, a1, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE | MAP_FIXED, -1, 0); } static long syz_errno(volatile long v) { errno = v; return v == 0 ? 0 : -1; } static long syz_exit(volatile long status) { _exit(status); return 0; } static long syz_compare(volatile long want, volatile long want_len, volatile long got, volatile long got_len) { if (want_len != got_len) { errno = EBADF; return -1; } if (memcmp((void*)want, (void*)got, want_len)) { errno = EINVAL; return -1; } return 0; } static long syz_compare_int(volatile long n, ...) { va_list args; va_start(args, n); long v0 = va_arg(args, long); long v1 = va_arg(args, long); long v2 = va_arg(args, long); long v3 = va_arg(args, long); va_end(args); if (n < 2 || n > 4) return errno = E2BIG, -1; if (n <= 2 && v2 != 0) return errno = EFAULT, -1; if (n <= 3 && v3 != 0) return errno = EFAULT, -1; if (v0 != v1) return errno = EINVAL, -1; if (n > 2 && v0 != v2) return errno = EINVAL, -1; if (n > 3 && v0 != v3) return errno = EINVAL, -1; return 0; } static void loop(); static int do_sandbox_none(void) { loop(); return 0; } static long syz_execute_func(volatile long text) { volatile long p[8] = {0}; (void)p; ((void (*)(void))(text))(); return 0; } 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 < 16; 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); event_timedwait(&th->done, 45); break; } } for (i = 0; i < 100 && __atomic_load_n(&running, __ATOMIC_RELAXED); i++) sleep_ms(1); } static void execute_one(void); static void loop(void) { execute_one(); } #ifndef SYS_foo #define SYS_foo 0 #endif #ifndef SYS_serialize1 #define SYS_serialize1 0 #endif #ifndef SYS_test #define SYS_test 0 #endif void execute_call(int call) { switch (call) { case 0: syscall(SYS_test, 0x401, -1, 5, 8, 0x10001, 0); break; case 1: syz_mmap(0x20ffc000, 0x3000); break; case 2: *(uint8_t*)0x20000000 = -1; memcpy((void*)0x20000001, "\x41\x3e\x9c\x08\x8f\x55\x0b\xb2", 8); syscall(SYS_test, 0x20000000, 0, 0, 0, 0, 0); break; case 3: *(uint16_t*)0x20000040 = 9; *(uint16_t*)0x20000042 = 1; *(uint16_t*)0x20000044 = 7; *(uint16_t*)0x20000046 = 7; *(uint16_t*)0x20000048 = 4; syscall(SYS_test, 0x20000040, 0, 0, 0, 0, 0); break; case 4: *(uint64_t*)0x20000080 = 0xc917; *(uint8_t*)0x20000088 = 8; syscall(SYS_test, 0x20000080, 0, 0, 0, 0, 0); break; case 5: *(uint64_t*)0x200000c0 = 7; *(uint16_t*)0x200000c8 = 8; *(uint64_t*)0x200000ca = 4; *(uint16_t*)0x200000d2 = 0x7ac; *(uint8_t*)0x200000d4 = 5; syscall(SYS_test, 0x200000c0, 0, 0, 0, 0, 0); break; case 6: sprintf((char*)0x20000100, "%020llu", (long long)5); syscall(SYS_foo, 0x20000100, 0); break; case 7: *(uint8_t*)0x20000140 = 6; syscall(SYS_test, 0x20000140, 0x2a, 0, 0, 0, 0); break; case 8: syscall(SYS_serialize1, 0x20000180, 0x6a); break; case 9: *(uint8_t*)0x20000200 = 7; *(uint64_t*)0x20000201 = 0xffffffffffff3fcd; *(uint64_t*)0x20000209 = 0xffffffff; *(uint64_t*)0x20000211 = 0x40; syscall(SYS_test, 0x20000200, 0, 0, 0, 0, 0); break; case 10: memcpy((void*)0x20000000, "@\000", 2); STORE_BY_BITMASK(uint32_t, , 0x20000040, 7, 0, 10); STORE_BY_BITMASK(uint32_t, , 0x20000040, 0x100, 10, 10); STORE_BY_BITMASK(uint32_t, , 0x20000040, 1, 20, 10); *(uint8_t*)0x20000044 = -1; syz_compare(0x20000000, 2, 0x20000040, 8); break; case 11: syz_compare_int(2, 0x2bb, 5, 0, 0); break; case 12: syz_errno(0xff); break; case 13: memcpy((void*)0x20000080, "\x8f\xba\x4d\x89\x76\xc6\xe1\x21\xfc\xb9\x55\x9d\x46\x4b\xd7\x33\xd7\xf9\xeb\x39\x04\xe1\x45\x87\x8a\x03\x30\xb1\x33\x23\xc0\x9b\x64\x64\xf2\x73\x01\xdb\x8a\x6b\xb6\xe6\x95\xa9\x0c\xa7\xc3\xf5\xb0\x7e", 50); syz_execute_func(0x20000080); break; case 14: syz_exit(5); break; case 15: syz_mmap(0x20ffb000, 0x3000); break; } } int main(void) { syz_mmap(0x20000000, 0x1000000); use_temporary_dir(); do_sandbox_none(); return 0; } /usr/local/bin/ld: cannot find -lasan collect2: error: ld returned 1 exit status compiler invocation: gcc [-o /tmp/syz-executor219447659 -DGOOS_test=1 -DGOARCH_64=1 -DHOSTGOOS_freebsd=1 -x c - -O2 -pthread -Wall -Werror -Wparentheses -Wunused-const-variable -Wframe-larger-than=8192 -m64 -fsanitize=address] --- FAIL: TestGenerate/test/64/2 (0.93s) csource_test.go:110: opts: {Threaded:true Collide:false Repeat:true RepeatTimes:0 Procs:0 Sandbox:none Fault:false FaultCall:0 FaultNth:0 Leak:false EnableTun:false EnableNetDev:false EnableNetReset:false EnableCgroups:false EnableBinfmtMisc:false EnableCloseFds:false UseTmpDir:true HandleSegv:false Repro:false Trace:false} program: test$int(0x401, 0x1ff, 0x5, 0x8, 0x10001) syz_mmap(&(0x7f0000ffc000/0x3000)=nil, 0x3000) test$array1(&(0x7f0000000000)={0x7ff, "413e9c088f550bb2"}) test$length6(&(0x7f0000000040)={[0x9, 0x10001, 0x7, 0x7], 0x4}) test$union1(&(0x7f0000000080)={@f0=0xc917, 0x8}) test$align5(&(0x7f00000000c0)={{0x7, [0x8]}, {0x4, [0x7ac]}, 0x5}) foo$fmt5(&(0x7f0000000100)={0x5}) test$length27(&(0x7f0000000140)={0x6}, 0x2a) serialize1(&(0x7f0000000180)=""/106, 0x6a) test$array0(&(0x7f0000000200)={0x7, [@f1=0xffffffffffff3fcd, @f1=0xffffffff], 0x40}) syz_compare(&(0x7f0000000000)='@\x00', 0x2, &(0x7f0000000040)=@bf1={{0x7, 0x100, 0x1}, 0xffff}, 0x8) syz_compare_int$2(0x2, 0x2bb, 0x5) syz_errno(0xff) syz_execute_func(&(0x7f0000000080)="8fba4d8976c6e121fcb9559d464bd733d7f9eb3904e145878a0330b13323c09b6464f27301db8a6bb6e695a90ca7c3f5b07e") syz_exit(0x5) syz_mmap(&(0x7f0000ffb000/0x3000)=nil, 0x3000) csource_test.go:111: failed to build program: // autogenerated by syzkaller (https://github.com/google/syzkaller) #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include 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; for (i = 0; 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 { pthread_mutex_t mu; pthread_cond_t cv; int state; } event_t; static void event_init(event_t* ev) { if (pthread_mutex_init(&ev->mu, 0)) exit(1); if (pthread_cond_init(&ev->cv, 0)) exit(1); ev->state = 0; } static void event_reset(event_t* ev) { ev->state = 0; } static void event_set(event_t* ev) { pthread_mutex_lock(&ev->mu); if (ev->state) exit(1); ev->state = 1; pthread_mutex_unlock(&ev->mu); pthread_cond_broadcast(&ev->cv); } static void event_wait(event_t* ev) { pthread_mutex_lock(&ev->mu); while (!ev->state) pthread_cond_wait(&ev->cv, &ev->mu); pthread_mutex_unlock(&ev->mu); } static int event_isset(event_t* ev) { pthread_mutex_lock(&ev->mu); int res = ev->state; pthread_mutex_unlock(&ev->mu); return res; } static int event_timedwait(event_t* ev, uint64_t timeout) { uint64_t start = current_time_ms(); uint64_t now = start; pthread_mutex_lock(&ev->mu); for (;;) { if (ev->state) break; uint64_t remain = timeout - (now - start); struct timespec ts; ts.tv_sec = remain / 1000; ts.tv_nsec = (remain % 1000) * 1000 * 1000; pthread_cond_timedwait(&ev->cv, &ev->mu, &ts); now = current_time_ms(); if (now - start > timeout) break; } int res = ev->state; pthread_mutex_unlock(&ev->mu); return res; } #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)))) static long syz_mmap(volatile long a0, volatile long a1) { return (long)mmap((void*)a0, a1, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE | MAP_FIXED, -1, 0); } static long syz_errno(volatile long v) { errno = v; return v == 0 ? 0 : -1; } static long syz_exit(volatile long status) { _exit(status); return 0; } static long syz_compare(volatile long want, volatile long want_len, volatile long got, volatile long got_len) { if (want_len != got_len) { errno = EBADF; return -1; } if (memcmp((void*)want, (void*)got, want_len)) { errno = EINVAL; return -1; } return 0; } static long syz_compare_int(volatile long n, ...) { va_list args; va_start(args, n); long v0 = va_arg(args, long); long v1 = va_arg(args, long); long v2 = va_arg(args, long); long v3 = va_arg(args, long); va_end(args); if (n < 2 || n > 4) return errno = E2BIG, -1; if (n <= 2 && v2 != 0) return errno = EFAULT, -1; if (n <= 3 && v3 != 0) return errno = EFAULT, -1; if (v0 != v1) return errno = EINVAL, -1; if (n > 2 && v0 != v2) return errno = EINVAL, -1; if (n > 3 && v0 != v3) return errno = EINVAL, -1; return 0; } static void loop(); static int do_sandbox_none(void) { loop(); return 0; } static long syz_execute_func(volatile long text) { volatile long p[8] = {0}; (void)p; ((void (*)(void))(text))(); return 0; } 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 < 16; 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); event_timedwait(&th->done, 45); break; } } for (i = 0; i < 100 && __atomic_load_n(&running, __ATOMIC_RELAXED); i++) sleep_ms(1); } static void execute_one(void); static void loop(void) { execute_one(); } #ifndef SYS_foo #define SYS_foo 0 #endif #ifndef SYS_serialize1 #define SYS_serialize1 0 #endif #ifndef SYS_test #define SYS_test 0 #endif void execute_call(int call) { switch (call) { case 0: syscall(SYS_test, 0x401, -1, 5, 8, 0x10001, 0); break; case 1: syz_mmap(0x20ffc000, 0x3000); break; case 2: *(uint8_t*)0x20000000 = -1; memcpy((void*)0x20000001, "\x41\x3e\x9c\x08\x8f\x55\x0b\xb2", 8); syscall(SYS_test, 0x20000000, 0, 0, 0, 0, 0); break; case 3: *(uint16_t*)0x20000040 = 9; *(uint16_t*)0x20000042 = 1; *(uint16_t*)0x20000044 = 7; *(uint16_t*)0x20000046 = 7; *(uint16_t*)0x20000048 = 4; syscall(SYS_test, 0x20000040, 0, 0, 0, 0, 0); break; case 4: *(uint64_t*)0x20000080 = 0xc917; *(uint8_t*)0x20000088 = 8; syscall(SYS_test, 0x20000080, 0, 0, 0, 0, 0); break; case 5: *(uint64_t*)0x200000c0 = 7; *(uint16_t*)0x200000c8 = 8; *(uint64_t*)0x200000ca = 4; *(uint16_t*)0x200000d2 = 0x7ac; *(uint8_t*)0x200000d4 = 5; syscall(SYS_test, 0x200000c0, 0, 0, 0, 0, 0); break; case 6: sprintf((char*)0x20000100, "%020llu", (long long)5); syscall(SYS_foo, 0x20000100, 0); break; case 7: *(uint8_t*)0x20000140 = 6; syscall(SYS_test, 0x20000140, 0x2a, 0, 0, 0, 0); break; case 8: syscall(SYS_serialize1, 0x20000180, 0x6a); break; case 9: *(uint8_t*)0x20000200 = 7; *(uint64_t*)0x20000201 = 0xffffffffffff3fcd; *(uint64_t*)0x20000209 = 0xffffffff; *(uint64_t*)0x20000211 = 0x40; syscall(SYS_test, 0x20000200, 0, 0, 0, 0, 0); break; case 10: memcpy((void*)0x20000000, "@\000", 2); STORE_BY_BITMASK(uint32_t, , 0x20000040, 7, 0, 10); STORE_BY_BITMASK(uint32_t, , 0x20000040, 0x100, 10, 10); STORE_BY_BITMASK(uint32_t, , 0x20000040, 1, 20, 10); *(uint8_t*)0x20000044 = -1; syz_compare(0x20000000, 2, 0x20000040, 8); break; case 11: syz_compare_int(2, 0x2bb, 5, 0, 0); break; case 12: syz_errno(0xff); break; case 13: memcpy((void*)0x20000080, "\x8f\xba\x4d\x89\x76\xc6\xe1\x21\xfc\xb9\x55\x9d\x46\x4b\xd7\x33\xd7\xf9\xeb\x39\x04\xe1\x45\x87\x8a\x03\x30\xb1\x33\x23\xc0\x9b\x64\x64\xf2\x73\x01\xdb\x8a\x6b\xb6\xe6\x95\xa9\x0c\xa7\xc3\xf5\xb0\x7e", 50); syz_execute_func(0x20000080); break; case 14: syz_exit(5); break; case 15: syz_mmap(0x20ffb000, 0x3000); break; } } int main(void) { syz_mmap(0x20000000, 0x1000000); use_temporary_dir(); do_sandbox_none(); return 0; } /usr/local/bin/ld: cannot find -lasan collect2: error: ld returned 1 exit status compiler invocation: gcc [-o /tmp/syz-executor131691568 -DGOOS_test=1 -DGOARCH_64=1 -DHOSTGOOS_freebsd=1 -x c - -O2 -pthread -Wall -Werror -Wparentheses -Wunused-const-variable -Wframe-larger-than=8192 -m64 -fsanitize=address] --- FAIL: TestGenerate/test/64/3 (1.16s) csource_test.go:110: opts: {Threaded:true Collide:true Repeat:true RepeatTimes:0 Procs:0 Sandbox:none Fault:false FaultCall:0 FaultNth:0 Leak:false EnableTun:false EnableNetDev:false EnableNetReset:false EnableCgroups:false EnableBinfmtMisc:false EnableCloseFds:false UseTmpDir:true HandleSegv:false Repro:false Trace:false} program: test$int(0x401, 0x1ff, 0x5, 0x8, 0x10001) syz_mmap(&(0x7f0000ffc000/0x3000)=nil, 0x3000) test$array1(&(0x7f0000000000)={0x7ff, "413e9c088f550bb2"}) test$length6(&(0x7f0000000040)={[0x9, 0x10001, 0x7, 0x7], 0x4}) test$union1(&(0x7f0000000080)={@f0=0xc917, 0x8}) test$align5(&(0x7f00000000c0)={{0x7, [0x8]}, {0x4, [0x7ac]}, 0x5}) foo$fmt5(&(0x7f0000000100)={0x5}) test$length27(&(0x7f0000000140)={0x6}, 0x2a) serialize1(&(0x7f0000000180)=""/106, 0x6a) test$array0(&(0x7f0000000200)={0x7, [@f1=0xffffffffffff3fcd, @f1=0xffffffff], 0x40}) syz_compare(&(0x7f0000000000)='@\x00', 0x2, &(0x7f0000000040)=@bf1={{0x7, 0x100, 0x1}, 0xffff}, 0x8) syz_compare_int$2(0x2, 0x2bb, 0x5) syz_errno(0xff) syz_execute_func(&(0x7f0000000080)="8fba4d8976c6e121fcb9559d464bd733d7f9eb3904e145878a0330b13323c09b6464f27301db8a6bb6e695a90ca7c3f5b07e") syz_exit(0x5) syz_mmap(&(0x7f0000ffb000/0x3000)=nil, 0x3000) csource_test.go:111: failed to build program: // autogenerated by syzkaller (https://github.com/google/syzkaller) #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include 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; for (i = 0; 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 { pthread_mutex_t mu; pthread_cond_t cv; int state; } event_t; static void event_init(event_t* ev) { if (pthread_mutex_init(&ev->mu, 0)) exit(1); if (pthread_cond_init(&ev->cv, 0)) exit(1); ev->state = 0; } static void event_reset(event_t* ev) { ev->state = 0; } static void event_set(event_t* ev) { pthread_mutex_lock(&ev->mu); if (ev->state) exit(1); ev->state = 1; pthread_mutex_unlock(&ev->mu); pthread_cond_broadcast(&ev->cv); } static void event_wait(event_t* ev) { pthread_mutex_lock(&ev->mu); while (!ev->state) pthread_cond_wait(&ev->cv, &ev->mu); pthread_mutex_unlock(&ev->mu); } static int event_isset(event_t* ev) { pthread_mutex_lock(&ev->mu); int res = ev->state; pthread_mutex_unlock(&ev->mu); return res; } static int event_timedwait(event_t* ev, uint64_t timeout) { uint64_t start = current_time_ms(); uint64_t now = start; pthread_mutex_lock(&ev->mu); for (;;) { if (ev->state) break; uint64_t remain = timeout - (now - start); struct timespec ts; ts.tv_sec = remain / 1000; ts.tv_nsec = (remain % 1000) * 1000 * 1000; pthread_cond_timedwait(&ev->cv, &ev->mu, &ts); now = current_time_ms(); if (now - start > timeout) break; } int res = ev->state; pthread_mutex_unlock(&ev->mu); return res; } #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)))) static long syz_mmap(volatile long a0, volatile long a1) { return (long)mmap((void*)a0, a1, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE | MAP_FIXED, -1, 0); } static long syz_errno(volatile long v) { errno = v; return v == 0 ? 0 : -1; } static long syz_exit(volatile long status) { _exit(status); return 0; } static long syz_compare(volatile long want, volatile long want_len, volatile long got, volatile long got_len) { if (want_len != got_len) { errno = EBADF; return -1; } if (memcmp((void*)want, (void*)got, want_len)) { errno = EINVAL; return -1; } return 0; } static long syz_compare_int(volatile long n, ...) { va_list args; va_start(args, n); long v0 = va_arg(args, long); long v1 = va_arg(args, long); long v2 = va_arg(args, long); long v3 = va_arg(args, long); va_end(args); if (n < 2 || n > 4) return errno = E2BIG, -1; if (n <= 2 && v2 != 0) return errno = EFAULT, -1; if (n <= 3 && v3 != 0) return errno = EFAULT, -1; if (v0 != v1) return errno = EINVAL, -1; if (n > 2 && v0 != v2) return errno = EINVAL, -1; if (n > 3 && v0 != v3) return errno = EINVAL, -1; return 0; } static void loop(); static int do_sandbox_none(void) { loop(); return 0; } static long syz_execute_func(volatile long text) { volatile long p[8] = {0}; (void)p; ((void (*)(void))(text))(); return 0; } 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; int collide = 0; again: for (call = 0; call < 16; 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 (collide && (call % 2) == 0) break; event_timedwait(&th->done, 45); break; } } for (i = 0; i < 100 && __atomic_load_n(&running, __ATOMIC_RELAXED); i++) sleep_ms(1); if (!collide) { collide = 1; goto again; } } static void execute_one(void); static void loop(void) { execute_one(); } #ifndef SYS_foo #define SYS_foo 0 #endif #ifndef SYS_serialize1 #define SYS_serialize1 0 #endif #ifndef SYS_test #define SYS_test 0 #endif void execute_call(int call) { switch (call) { case 0: syscall(SYS_test, 0x401, -1, 5, 8, 0x10001, 0); break; case 1: syz_mmap(0x20ffc000, 0x3000); break; case 2: *(uint8_t*)0x20000000 = -1; memcpy((void*)0x20000001, "\x41\x3e\x9c\x08\x8f\x55\x0b\xb2", 8); syscall(SYS_test, 0x20000000, 0, 0, 0, 0, 0); break; case 3: *(uint16_t*)0x20000040 = 9; *(uint16_t*)0x20000042 = 1; *(uint16_t*)0x20000044 = 7; *(uint16_t*)0x20000046 = 7; *(uint16_t*)0x20000048 = 4; syscall(SYS_test, 0x20000040, 0, 0, 0, 0, 0); break; case 4: *(uint64_t*)0x20000080 = 0xc917; *(uint8_t*)0x20000088 = 8; syscall(SYS_test, 0x20000080, 0, 0, 0, 0, 0); break; case 5: *(uint64_t*)0x200000c0 = 7; *(uint16_t*)0x200000c8 = 8; *(uint64_t*)0x200000ca = 4; *(uint16_t*)0x200000d2 = 0x7ac; *(uint8_t*)0x200000d4 = 5; syscall(SYS_test, 0x200000c0, 0, 0, 0, 0, 0); break; case 6: sprintf((char*)0x20000100, "%020llu", (long long)5); syscall(SYS_foo, 0x20000100, 0); break; case 7: *(uint8_t*)0x20000140 = 6; syscall(SYS_test, 0x20000140, 0x2a, 0, 0, 0, 0); break; case 8: syscall(SYS_serialize1, 0x20000180, 0x6a); break; case 9: *(uint8_t*)0x20000200 = 7; *(uint64_t*)0x20000201 = 0xffffffffffff3fcd; *(uint64_t*)0x20000209 = 0xffffffff; *(uint64_t*)0x20000211 = 0x40; syscall(SYS_test, 0x20000200, 0, 0, 0, 0, 0); break; case 10: memcpy((void*)0x20000000, "@\000", 2); STORE_BY_BITMASK(uint32_t, , 0x20000040, 7, 0, 10); STORE_BY_BITMASK(uint32_t, , 0x20000040, 0x100, 10, 10); STORE_BY_BITMASK(uint32_t, , 0x20000040, 1, 20, 10); *(uint8_t*)0x20000044 = -1; syz_compare(0x20000000, 2, 0x20000040, 8); break; case 11: syz_compare_int(2, 0x2bb, 5, 0, 0); break; case 12: syz_errno(0xff); break; case 13: memcpy((void*)0x20000080, "\x8f\xba\x4d\x89\x76\xc6\xe1\x21\xfc\xb9\x55\x9d\x46\x4b\xd7\x33\xd7\xf9\xeb\x39\x04\xe1\x45\x87\x8a\x03\x30\xb1\x33\x23\xc0\x9b\x64\x64\xf2\x73\x01\xdb\x8a\x6b\xb6\xe6\x95\xa9\x0c\xa7\xc3\xf5\xb0\x7e", 50); syz_execute_func(0x20000080); break; case 14: syz_exit(5); break; case 15: syz_mmap(0x20ffb000, 0x3000); break; } } int main(void) { syz_mmap(0x20000000, 0x1000000); use_temporary_dir(); do_sandbox_none(); return 0; } /usr/local/bin/ld: cannot find -lasan collect2: error: ld returned 1 exit status compiler invocation: gcc [-o /tmp/syz-executor287124693 -DGOOS_test=1 -DGOARCH_64=1 -DHOSTGOOS_freebsd=1 -x c - -O2 -pthread -Wall -Werror -Wparentheses -Wunused-const-variable -Wframe-larger-than=8192 -m64 -fsanitize=address] --- FAIL: TestGenerate/test/64/1 (0.99s) csource_test.go:110: opts: {Threaded:true Collide:false Repeat:true RepeatTimes:0 Procs:0 Sandbox:none Fault:false FaultCall:0 FaultNth:0 Leak:false EnableTun:false EnableNetDev:false EnableNetReset:false EnableCgroups:false EnableBinfmtMisc:false EnableCloseFds:false UseTmpDir:true HandleSegv:false Repro:false Trace:false} program: test$int(0x401, 0x1ff, 0x5, 0x8, 0x10001) syz_mmap(&(0x7f0000ffc000/0x3000)=nil, 0x3000) test$array1(&(0x7f0000000000)={0x7ff, "413e9c088f550bb2"}) test$length6(&(0x7f0000000040)={[0x9, 0x10001, 0x7, 0x7], 0x4}) test$union1(&(0x7f0000000080)={@f0=0xc917, 0x8}) test$align5(&(0x7f00000000c0)={{0x7, [0x8]}, {0x4, [0x7ac]}, 0x5}) foo$fmt5(&(0x7f0000000100)={0x5}) test$length27(&(0x7f0000000140)={0x6}, 0x2a) serialize1(&(0x7f0000000180)=""/106, 0x6a) test$array0(&(0x7f0000000200)={0x7, [@f1=0xffffffffffff3fcd, @f1=0xffffffff], 0x40}) syz_compare(&(0x7f0000000000)='@\x00', 0x2, &(0x7f0000000040)=@bf1={{0x7, 0x100, 0x1}, 0xffff}, 0x8) syz_compare_int$2(0x2, 0x2bb, 0x5) syz_errno(0xff) syz_execute_func(&(0x7f0000000080)="8fba4d8976c6e121fcb9559d464bd733d7f9eb3904e145878a0330b13323c09b6464f27301db8a6bb6e695a90ca7c3f5b07e") syz_exit(0x5) syz_mmap(&(0x7f0000ffb000/0x3000)=nil, 0x3000) csource_test.go:111: failed to build program: // autogenerated by syzkaller (https://github.com/google/syzkaller) #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include 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; for (i = 0; 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 { pthread_mutex_t mu; pthread_cond_t cv; int state; } event_t; static void event_init(event_t* ev) { if (pthread_mutex_init(&ev->mu, 0)) exit(1); if (pthread_cond_init(&ev->cv, 0)) exit(1); ev->state = 0; } static void event_reset(event_t* ev) { ev->state = 0; } static void event_set(event_t* ev) { pthread_mutex_lock(&ev->mu); if (ev->state) exit(1); ev->state = 1; pthread_mutex_unlock(&ev->mu); pthread_cond_broadcast(&ev->cv); } static void event_wait(event_t* ev) { pthread_mutex_lock(&ev->mu); while (!ev->state) pthread_cond_wait(&ev->cv, &ev->mu); pthread_mutex_unlock(&ev->mu); } static int event_isset(event_t* ev) { pthread_mutex_lock(&ev->mu); int res = ev->state; pthread_mutex_unlock(&ev->mu); return res; } static int event_timedwait(event_t* ev, uint64_t timeout) { uint64_t start = current_time_ms(); uint64_t now = start; pthread_mutex_lock(&ev->mu); for (;;) { if (ev->state) break; uint64_t remain = timeout - (now - start); struct timespec ts; ts.tv_sec = remain / 1000; ts.tv_nsec = (remain % 1000) * 1000 * 1000; pthread_cond_timedwait(&ev->cv, &ev->mu, &ts); now = current_time_ms(); if (now - start > timeout) break; } int res = ev->state; pthread_mutex_unlock(&ev->mu); return res; } #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)))) static long syz_mmap(volatile long a0, volatile long a1) { return (long)mmap((void*)a0, a1, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE | MAP_FIXED, -1, 0); } static long syz_errno(volatile long v) { errno = v; return v == 0 ? 0 : -1; } static long syz_exit(volatile long status) { _exit(status); return 0; } static long syz_compare(volatile long want, volatile long want_len, volatile long got, volatile long got_len) { if (want_len != got_len) { errno = EBADF; return -1; } if (memcmp((void*)want, (void*)got, want_len)) { errno = EINVAL; return -1; } return 0; } static long syz_compare_int(volatile long n, ...) { va_list args; va_start(args, n); long v0 = va_arg(args, long); long v1 = va_arg(args, long); long v2 = va_arg(args, long); long v3 = va_arg(args, long); va_end(args); if (n < 2 || n > 4) return errno = E2BIG, -1; if (n <= 2 && v2 != 0) return errno = EFAULT, -1; if (n <= 3 && v3 != 0) return errno = EFAULT, -1; if (v0 != v1) return errno = EINVAL, -1; if (n > 2 && v0 != v2) return errno = EINVAL, -1; if (n > 3 && v0 != v3) return errno = EINVAL, -1; return 0; } static void loop(); static int do_sandbox_none(void) { loop(); return 0; } static long syz_execute_func(volatile long text) { volatile long p[8] = {0}; (void)p; ((void (*)(void))(text))(); return 0; } 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 < 16; 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); event_timedwait(&th->done, 45); break; } } for (i = 0; i < 100 && __atomic_load_n(&running, __ATOMIC_RELAXED); i++) sleep_ms(1); } static void execute_one(void); static void loop(void) { execute_one(); } #ifndef SYS_foo #define SYS_foo 0 #endif #ifndef SYS_serialize1 #define SYS_serialize1 0 #endif #ifndef SYS_test #define SYS_test 0 #endif void execute_call(int call) { switch (call) { case 0: syscall(SYS_test, 0x401, -1, 5, 8, 0x10001, 0); break; case 1: syz_mmap(0x20ffc000, 0x3000); break; case 2: *(uint8_t*)0x20000000 = -1; memcpy((void*)0x20000001, "\x41\x3e\x9c\x08\x8f\x55\x0b\xb2", 8); syscall(SYS_test, 0x20000000, 0, 0, 0, 0, 0); break; case 3: *(uint16_t*)0x20000040 = 9; *(uint16_t*)0x20000042 = 1; *(uint16_t*)0x20000044 = 7; *(uint16_t*)0x20000046 = 7; *(uint16_t*)0x20000048 = 4; syscall(SYS_test, 0x20000040, 0, 0, 0, 0, 0); break; case 4: *(uint64_t*)0x20000080 = 0xc917; *(uint8_t*)0x20000088 = 8; syscall(SYS_test, 0x20000080, 0, 0, 0, 0, 0); break; case 5: *(uint64_t*)0x200000c0 = 7; *(uint16_t*)0x200000c8 = 8; *(uint64_t*)0x200000ca = 4; *(uint16_t*)0x200000d2 = 0x7ac; *(uint8_t*)0x200000d4 = 5; syscall(SYS_test, 0x200000c0, 0, 0, 0, 0, 0); break; case 6: sprintf((char*)0x20000100, "%020llu", (long long)5); syscall(SYS_foo, 0x20000100, 0); break; case 7: *(uint8_t*)0x20000140 = 6; syscall(SYS_test, 0x20000140, 0x2a, 0, 0, 0, 0); break; case 8: syscall(SYS_serialize1, 0x20000180, 0x6a); break; case 9: *(uint8_t*)0x20000200 = 7; *(uint64_t*)0x20000201 = 0xffffffffffff3fcd; *(uint64_t*)0x20000209 = 0xffffffff; *(uint64_t*)0x20000211 = 0x40; syscall(SYS_test, 0x20000200, 0, 0, 0, 0, 0); break; case 10: memcpy((void*)0x20000000, "@\000", 2); STORE_BY_BITMASK(uint32_t, , 0x20000040, 7, 0, 10); STORE_BY_BITMASK(uint32_t, , 0x20000040, 0x100, 10, 10); STORE_BY_BITMASK(uint32_t, , 0x20000040, 1, 20, 10); *(uint8_t*)0x20000044 = -1; syz_compare(0x20000000, 2, 0x20000040, 8); break; case 11: syz_compare_int(2, 0x2bb, 5, 0, 0); break; case 12: syz_errno(0xff); break; case 13: memcpy((void*)0x20000080, "\x8f\xba\x4d\x89\x76\xc6\xe1\x21\xfc\xb9\x55\x9d\x46\x4b\xd7\x33\xd7\xf9\xeb\x39\x04\xe1\x45\x87\x8a\x03\x30\xb1\x33\x23\xc0\x9b\x64\x64\xf2\x73\x01\xdb\x8a\x6b\xb6\xe6\x95\xa9\x0c\xa7\xc3\xf5\xb0\x7e", 50); syz_execute_func(0x20000080); break; case 14: syz_exit(5); break; case 15: syz_mmap(0x20ffb000, 0x3000); break; } } int main(void) { syz_mmap(0x20000000, 0x1000000); use_temporary_dir(); do_sandbox_none(); return 0; } /usr/local/bin/ld: cannot find -lasan collect2: error: ld returned 1 exit status compiler invocation: gcc [-o /tmp/syz-executor423311311 -DGOOS_test=1 -DGOARCH_64=1 -DHOSTGOOS_freebsd=1 -x c - -O2 -pthread -Wall -Werror -Wparentheses -Wunused-const-variable -Wframe-larger-than=8192 -m64 -fsanitize=address] FAIL FAIL github.com/google/syzkaller/pkg/csource 12.721s ok github.com/google/syzkaller/pkg/db (cached) ok github.com/google/syzkaller/pkg/email (cached) ? github.com/google/syzkaller/pkg/gce [no test files] ? github.com/google/syzkaller/pkg/gcs [no test files] ? github.com/google/syzkaller/pkg/hash [no test files] ok github.com/google/syzkaller/pkg/host 0.030s ? github.com/google/syzkaller/pkg/html [no test files] ok github.com/google/syzkaller/pkg/ifuzz (cached) ? github.com/google/syzkaller/pkg/ifuzz/gen [no test files] ? github.com/google/syzkaller/pkg/ifuzz/generated [no test files] ok github.com/google/syzkaller/pkg/instance 0.349s ok github.com/google/syzkaller/pkg/ipc 7.272s ? github.com/google/syzkaller/pkg/ipc/ipcconfig [no test files] ok github.com/google/syzkaller/pkg/kd (cached) ok github.com/google/syzkaller/pkg/log (cached) ok github.com/google/syzkaller/pkg/mgrconfig 0.032s ok github.com/google/syzkaller/pkg/osutil (cached) ok github.com/google/syzkaller/pkg/report 3.743s ok github.com/google/syzkaller/pkg/repro 0.426s ? github.com/google/syzkaller/pkg/rpctype [no test files] --- FAIL: Test (0.64s) --- FAIL: Test/64_fork (2.07s) run_test.go:44: failed to build program: // Copyright 2017 syzkaller project authors. All rights reserved. // Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file. // +build #include #include #include #include #include #include #include #include #include #include #include #include "defs.h" #if defined(__GNUC__) #define SYSCALLAPI #define NORETURN __attribute__((noreturn)) #define ALIGNED(N) __attribute__((aligned(N))) #define PRINTF(fmt, args) __attribute__((format(printf, fmt, args))) #else // Assuming windows/cl. #define SYSCALLAPI WINAPI #define NORETURN __declspec(noreturn) #define ALIGNED(N) __declspec(align(N)) #define PRINTF(fmt, args) #endif #ifndef GIT_REVISION #define GIT_REVISION "unknown" #endif #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) // uint64 is impossible to printf without using the clumsy and verbose "%" PRId64. // So we define and use uint64. Note: pkg/csource does s/uint64/uint64/. // Also define uint32/16/8 for consistency. typedef unsigned long long uint64; typedef unsigned int uint32; typedef unsigned short uint16; typedef unsigned char uint8; // exit/_exit do not necessary work (e.g. if fuzzer sets seccomp filter that prohibits exit_group). // Use doexit instead. We must redefine exit to something that exists in stdlib, // because some standard libraries contain "using ::exit;", but has different signature. #define exit vsnprintf // Note: zircon max fd is 256. // Some common_OS.h files know about this constant for RLIMIT_NOFILE. const int kMaxFd = 250; const int kMaxThreads = 16; const int kInPipeFd = kMaxFd - 1; // remapped from stdin const int kOutPipeFd = kMaxFd - 2; // remapped from stdout const int kCoverFd = kOutPipeFd - kMaxThreads; const int kMaxArgs = 9; const int kCoverSize = 256 << 10; const int kFailStatus = 67; // Logical error (e.g. invalid input program), use as an assert() alternative. static NORETURN PRINTF(1, 2) void fail(const char* msg, ...); // Just exit (e.g. due to temporal ENOMEM error). static NORETURN PRINTF(1, 2) void exitf(const char* msg, ...); static NORETURN void doexit(int status); // Print debug output, does not add \n at the end of msg as opposed to the previous functions. static PRINTF(1, 2) void debug(const char* msg, ...); void debug_dump_data(const char* data, int length); #if 0 #define debug_verbose(...) debug(__VA_ARGS__) #else #define debug_verbose(...) (void)0 #endif static void receive_execute(); static void reply_execute(int status); #if GOOS_akaros static void resend_execute(int fd); #endif #if SYZ_EXECUTOR_USES_FORK_SERVER static void receive_handshake(); static void reply_handshake(); #endif #if SYZ_EXECUTOR_USES_SHMEM const int kMaxOutput = 16 << 20; const int kInFd = 3; const int kOutFd = 4; static uint32* output_data; static uint32* output_pos; static uint32* write_output(uint32 v); static void write_completed(uint32 completed); static uint32 hash(uint32 a); static bool dedup(uint32 sig); #endif enum sandbox_type { sandbox_none, sandbox_setuid, sandbox_namespace, sandbox_android_untrusted_app }; uint64 start_time_ms = 0; static bool flag_debug; static bool flag_cover; static sandbox_type flag_sandbox; static bool flag_extra_cover; static bool flag_enable_tun; static bool flag_enable_net_dev; static bool flag_enable_net_reset; static bool flag_enable_cgroups; static bool flag_enable_close_fds; static bool flag_collect_cover; static bool flag_dedup_cover; static bool flag_threaded; static bool flag_collide; // If true, then executor should write the comparisons data to fuzzer. static bool flag_collect_comps; // Inject fault into flag_fault_nth-th operation in flag_fault_call-th syscall. static bool flag_inject_fault; static int flag_fault_call; static int flag_fault_nth; #define SYZ_EXECUTOR 1 #include "common.h" const int kMaxCommands = 1000; const int kMaxInput = 2 << 20; const uint64 instr_eof = -1; const uint64 instr_copyin = -2; const uint64 instr_copyout = -3; const uint64 arg_const = 0; const uint64 arg_result = 1; const uint64 arg_data = 2; const uint64 arg_csum = 3; const uint64 binary_format_native = 0; const uint64 binary_format_bigendian = 1; const uint64 binary_format_strdec = 2; const uint64 binary_format_strhex = 3; const uint64 binary_format_stroct = 4; const uint64 no_copyout = -1; static int running; static bool collide; uint32 completed; bool is_kernel_64_bit = true; ALIGNED(64 << 10) static char input_data[kMaxInput]; // Checksum kinds. static const uint64 arg_csum_inet = 0; // Checksum chunk kinds. static const uint64 arg_csum_chunk_data = 0; static const uint64 arg_csum_chunk_const = 1; typedef intptr_t(SYSCALLAPI* syscall_t)(intptr_t, intptr_t, intptr_t, intptr_t, intptr_t, intptr_t, intptr_t, intptr_t, intptr_t); struct call_t { const char* name; int sys_nr; syscall_t call; }; struct cover_t { int fd; uint32 size; char* data; char* data_end; }; struct thread_t { int id; bool created; event_t ready; event_t done; uint64* copyout_pos; uint64 copyout_index; bool colliding; bool executing; int call_index; int call_num; int num_args; intptr_t args[kMaxArgs]; intptr_t res; uint32 reserrno; bool fault_injected; cover_t cov; bool extra_cover; }; static thread_t threads[kMaxThreads]; static thread_t* last_scheduled; static cover_t extra_cov; struct res_t { bool executed; uint64 val; }; static res_t results[kMaxCommands]; const uint64 kInMagic = 0xbadc0ffeebadface; const uint32 kOutMagic = 0xbadf00d; struct handshake_req { uint64 magic; uint64 flags; // env flags uint64 pid; }; struct handshake_reply { uint32 magic; }; struct execute_req { uint64 magic; uint64 env_flags; uint64 exec_flags; uint64 pid; uint64 fault_call; uint64 fault_nth; uint64 prog_size; }; struct execute_reply { uint32 magic; uint32 done; uint32 status; }; // call_reply.flags const uint32 call_flag_executed = 1 << 0; const uint32 call_flag_finished = 1 << 1; const uint32 call_flag_blocked = 1 << 2; const uint32 call_flag_fault_injected = 1 << 3; struct call_reply { execute_reply header; uint32 call_index; uint32 call_num; uint32 reserrno; uint32 flags; uint32 signal_size; uint32 cover_size; uint32 comps_size; // signal/cover/comps follow }; enum { KCOV_CMP_CONST = 1, KCOV_CMP_SIZE1 = 0, KCOV_CMP_SIZE2 = 2, KCOV_CMP_SIZE4 = 4, KCOV_CMP_SIZE8 = 6, KCOV_CMP_SIZE_MASK = 6, }; struct kcov_comparison_t { // Note: comparisons are always 64-bits regardless of kernel bitness. uint64 type; uint64 arg1; uint64 arg2; uint64 pc; bool ignore() const; void write(); bool operator==(const struct kcov_comparison_t& other) const; bool operator<(const struct kcov_comparison_t& other) const; }; struct feature_t { const char* name; void (*setup)(); }; static thread_t* schedule_call(int call_index, int call_num, bool colliding, uint64 copyout_index, uint64 num_args, uint64* args, uint64* pos, bool extra_cover); static void handle_completion(thread_t* th); static void copyout_call_results(thread_t* th); static void write_call_output(thread_t* th, bool finished); static void write_extra_output(); static void execute_call(thread_t* th); static void thread_create(thread_t* th, int id); static void* worker_thread(void* arg); static uint64 read_input(uint64** input_posp, bool peek = false); static uint64 read_arg(uint64** input_posp); static uint64 read_const_arg(uint64** input_posp, uint64* size_p, uint64* bf, uint64* bf_off_p, uint64* bf_len_p); static uint64 read_result(uint64** input_posp); static uint64 swap(uint64 v, uint64 size, uint64 bf); static void copyin(char* addr, uint64 val, uint64 size, uint64 bf, uint64 bf_off, uint64 bf_len); static bool copyout(char* addr, uint64 size, uint64* res); static void setup_control_pipes(); static void setup_features(char** enable, int n); #include "syscalls.h" #if GOOS_linux #include "executor_linux.h" #elif GOOS_fuchsia #include "executor_fuchsia.h" #elif GOOS_akaros #include "executor_akaros.h" #elif GOOS_freebsd || GOOS_netbsd || GOOS_openbsd #include "executor_bsd.h" #elif GOOS_windows #include "executor_windows.h" #elif GOOS_test #include "executor_test.h" #else #error "unknown OS" #endif #include "test.h" int main(int argc, char** argv) { if (argc == 2 && strcmp(argv[1], "version") == 0) { puts(GOOS " " GOARCH " " SYZ_REVISION " " GIT_REVISION); return 0; } if (argc >= 2 && strcmp(argv[1], "setup") == 0) { setup_features(argv + 2, argc - 2); return 0; } if (argc >= 2 && strcmp(argv[1], "leak") == 0) { #if SYZ_HAVE_LEAK_CHECK check_leaks(argv + 2, argc - 2); #else fail("leak checking is not implemented"); #endif return 0; } if (argc == 2 && strcmp(argv[1], "test") == 0) return run_tests(); start_time_ms = current_time_ms(); os_init(argc, argv, (void*)SYZ_DATA_OFFSET, SYZ_NUM_PAGES * SYZ_PAGE_SIZE); #if SYZ_EXECUTOR_USES_SHMEM if (mmap(&input_data[0], kMaxInput, PROT_READ, MAP_PRIVATE | MAP_FIXED, kInFd, 0) != &input_data[0]) fail("mmap of input file failed"); // The output region is the only thing in executor process for which consistency matters. // If it is corrupted ipc package will fail to parse its contents and panic. // But fuzzer constantly invents new ways of how to currupt the region, // so we map the region at a (hopefully) hard to guess address with random offset, // surrounded by unmapped pages. // The address chosen must also work on 32-bit kernels with 1GB user address space. void* preferred = (void*)(0x1b2bc20000ull + (1 << 20) * (getpid() % 128)); output_data = (uint32*)mmap(preferred, kMaxOutput, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_FIXED, kOutFd, 0); if (output_data != preferred) fail("mmap of output file failed"); // Prevent test programs to mess with these fds. // Due to races in collider mode, a program can e.g. ftruncate one of these fds, // which will cause fuzzer to crash. close(kInFd); close(kOutFd); #endif use_temporary_dir(); install_segv_handler(); setup_control_pipes(); #if SYZ_EXECUTOR_USES_FORK_SERVER receive_handshake(); #else receive_execute(); #endif if (flag_cover) { for (int i = 0; i < kMaxThreads; i++) { threads[i].cov.fd = kCoverFd + i; cover_open(&threads[i].cov, false); cover_protect(&threads[i].cov); } cover_open(&extra_cov, true); cover_protect(&extra_cov); if (flag_extra_cover) { // Don't enable comps because we don't use them in the fuzzer yet. cover_enable(&extra_cov, false, true); } } int status = 0; switch (flag_sandbox) { case sandbox_none: status = do_sandbox_none(); break; #if SYZ_HAVE_SANDBOX_SETUID case sandbox_setuid: status = do_sandbox_setuid(); break; #endif #if SYZ_HAVE_SANDBOX_NAMESPACE case sandbox_namespace: status = do_sandbox_namespace(); break; #endif #if SYZ_HAVE_SANDBOX_ANDROID_UNTRUSTED_APP case sandbox_android_untrusted_app: status = do_sandbox_android_untrusted_app(); break; #endif default: fail("unknown sandbox type"); } #if SYZ_EXECUTOR_USES_FORK_SERVER fprintf(stderr, "loop exited with status %d\n", status); // Other statuses happen when fuzzer processes manages to kill loop, e.g. with: // ptrace(PTRACE_SEIZE, 1, 0, 0x100040) if (status != kFailStatus) status = 0; // If an external sandbox process wraps executor, the out pipe will be closed // before the sandbox process exits this will make ipc package kill the sandbox. // As the result sandbox process will exit with exit status 9 instead of the executor // exit status (notably kFailStatus). So we duplicate the exit status on the pipe. reply_execute(status); doexit(status); // Unreachable. return 1; #else reply_execute(status); return status; #endif } void setup_control_pipes() { if (dup2(0, kInPipeFd) < 0) fail("dup2(0, kInPipeFd) failed"); if (dup2(1, kOutPipeFd) < 0) fail("dup2(1, kOutPipeFd) failed"); if (dup2(2, 1) < 0) fail("dup2(2, 1) failed"); // We used to close(0), but now we dup stderr to stdin to keep fd numbers // stable across executor and C programs generated by pkg/csource. if (dup2(2, 0) < 0) fail("dup2(2, 0) failed"); } void parse_env_flags(uint64 flags) { // Note: Values correspond to ordering in pkg/ipc/ipc.go, e.g. FlagSandboxNamespace flag_debug = flags & (1 << 0); flag_cover = flags & (1 << 1); flag_sandbox = sandbox_none; if (flags & (1 << 2)) flag_sandbox = sandbox_setuid; else if (flags & (1 << 3)) flag_sandbox = sandbox_namespace; else if (flags & (1 << 4)) flag_sandbox = sandbox_android_untrusted_app; flag_extra_cover = flags & (1 << 5); flag_enable_tun = flags & (1 << 6); flag_enable_net_dev = flags & (1 << 7); flag_enable_net_reset = flags & (1 << 8); flag_enable_cgroups = flags & (1 << 9); flag_enable_close_fds = flags & (1 << 10); } #if SYZ_EXECUTOR_USES_FORK_SERVER void receive_handshake() { handshake_req req = {}; int n = read(kInPipeFd, &req, sizeof(req)); if (n != sizeof(req)) fail("handshake read failed: %d", n); if (req.magic != kInMagic) fail("bad handshake magic 0x%llx", req.magic); parse_env_flags(req.flags); procid = req.pid; } void reply_handshake() { handshake_reply reply = {}; reply.magic = kOutMagic; if (write(kOutPipeFd, &reply, sizeof(reply)) != sizeof(reply)) fail("control pipe write failed"); } #endif static execute_req last_execute_req; void receive_execute() { execute_req& req = last_execute_req; if (read(kInPipeFd, &req, sizeof(req)) != (ssize_t)sizeof(req)) fail("control pipe read failed"); if (req.magic != kInMagic) fail("bad execute request magic 0x%llx", req.magic); if (req.prog_size > kMaxInput) fail("bad execute prog size 0x%llx", req.prog_size); parse_env_flags(req.env_flags); procid = req.pid; flag_collect_cover = req.exec_flags & (1 << 0); flag_dedup_cover = req.exec_flags & (1 << 1); flag_inject_fault = req.exec_flags & (1 << 2); flag_collect_comps = req.exec_flags & (1 << 3); flag_threaded = req.exec_flags & (1 << 4); flag_collide = req.exec_flags & (1 << 5); flag_fault_call = req.fault_call; flag_fault_nth = req.fault_nth; if (!flag_threaded) flag_collide = false; debug("[%llums] exec opts: procid=%llu threaded=%d collide=%d cover=%d comps=%d dedup=%d fault=%d/%d/%d prog=%llu\n", current_time_ms() - start_time_ms, procid, flag_threaded, flag_collide, flag_collect_cover, flag_collect_comps, flag_dedup_cover, flag_inject_fault, flag_fault_call, flag_fault_nth, req.prog_size); if (SYZ_EXECUTOR_USES_SHMEM) { if (req.prog_size) fail("need_prog: no program"); return; } if (req.prog_size == 0) fail("need_prog: no program"); uint64 pos = 0; for (;;) { ssize_t rv = read(kInPipeFd, input_data + pos, sizeof(input_data) - pos); if (rv < 0) fail("read failed"); pos += rv; if (rv == 0 || pos >= req.prog_size) break; } if (pos != req.prog_size) fail("bad input size %lld, want %lld", pos, req.prog_size); } #if GOOS_akaros void resend_execute(int fd) { execute_req& req = last_execute_req; if (write(fd, &req, sizeof(req)) != sizeof(req)) fail("child pipe header write failed"); if (write(fd, input_data, req.prog_size) != (ssize_t)req.prog_size) fail("child pipe program write failed"); } #endif void reply_execute(int status) { execute_reply reply = {}; reply.magic = kOutMagic; reply.done = true; reply.status = status; if (write(kOutPipeFd, &reply, sizeof(reply)) != sizeof(reply)) fail("control pipe write failed"); } // execute_one executes program stored in input_data. void execute_one() { // Duplicate global collide variable on stack. // Fuzzer once come up with ioctl(fd, FIONREAD, 0x920000), // where 0x920000 was exactly collide address, so every iteration reset collide to 0. bool colliding = false; #if SYZ_EXECUTOR_USES_SHMEM output_pos = output_data; write_output(0); // Number of executed syscalls (updated later). #endif uint64 start = current_time_ms(); retry: uint64* input_pos = (uint64*)input_data; if (flag_cover && !colliding) { if (!flag_threaded) cover_enable(&threads[0].cov, flag_collect_comps, false); if (flag_extra_cover) cover_reset(&extra_cov); } int call_index = 0; bool prog_extra_cover = false; int prog_extra_timeout = 0; for (;;) { uint64 call_num = read_input(&input_pos); if (call_num == instr_eof) break; if (call_num == instr_copyin) { char* addr = (char*)read_input(&input_pos); uint64 typ = read_input(&input_pos); switch (typ) { case arg_const: { uint64 size, bf, bf_off, bf_len; uint64 arg = read_const_arg(&input_pos, &size, &bf, &bf_off, &bf_len); copyin(addr, arg, size, bf, bf_off, bf_len); break; } case arg_result: { uint64 meta = read_input(&input_pos); uint64 size = meta & 0xff; uint64 bf = meta >> 8; uint64 val = read_result(&input_pos); copyin(addr, val, size, bf, 0, 0); break; } case arg_data: { uint64 size = read_input(&input_pos); size &= ~(1ull << 63); // readable flag NONFAILING(memcpy(addr, input_pos, size)); // Read out the data. for (uint64 i = 0; i < (size + 7) / 8; i++) read_input(&input_pos); break; } case arg_csum: { debug_verbose("checksum found at %p\n", addr); uint64 size = read_input(&input_pos); char* csum_addr = addr; uint64 csum_kind = read_input(&input_pos); switch (csum_kind) { case arg_csum_inet: { if (size != 2) fail("inet checksum must be 2 bytes, not %llu", size); debug_verbose("calculating checksum for %p\n", csum_addr); struct csum_inet csum; csum_inet_init(&csum); uint64 chunks_num = read_input(&input_pos); uint64 chunk; for (chunk = 0; chunk < chunks_num; chunk++) { uint64 chunk_kind = read_input(&input_pos); uint64 chunk_value = read_input(&input_pos); uint64 chunk_size = read_input(&input_pos); switch (chunk_kind) { case arg_csum_chunk_data: debug_verbose("#%lld: data chunk, addr: %llx, size: %llu\n", chunk, chunk_value, chunk_size); NONFAILING(csum_inet_update(&csum, (const uint8*)chunk_value, chunk_size)); break; case arg_csum_chunk_const: if (chunk_size != 2 && chunk_size != 4 && chunk_size != 8) { fail("bad checksum const chunk size %lld\n", chunk_size); } // Here we assume that const values come to us big endian. debug_verbose("#%lld: const chunk, value: %llx, size: %llu\n", chunk, chunk_value, chunk_size); csum_inet_update(&csum, (const uint8*)&chunk_value, chunk_size); break; default: fail("bad checksum chunk kind %llu", chunk_kind); } } uint16 csum_value = csum_inet_digest(&csum); debug_verbose("writing inet checksum %hx to %p\n", csum_value, csum_addr); copyin(csum_addr, csum_value, 2, binary_format_native, 0, 0); break; } default: fail("bad checksum kind %llu", csum_kind); } break; } default: fail("bad argument type %llu", typ); } continue; } if (call_num == instr_copyout) { read_input(&input_pos); // index read_input(&input_pos); // addr read_input(&input_pos); // size // The copyout will happen when/if the call completes. continue; } // Normal syscall. if (call_num >= ARRAY_SIZE(syscalls)) fail("invalid command number %llu", call_num); bool call_extra_cover = false; // call_extra_timeout must match timeout in pkg/csource/csource.go. int call_extra_timeout = 0; // TODO: find a way to tune timeout values. if (strncmp(syscalls[call_num].name, "syz_usb", strlen("syz_usb")) == 0) { prog_extra_cover = true; call_extra_cover = true; } if (strncmp(syscalls[call_num].name, "syz_usb_connect", strlen("syz_usb_connect")) == 0) { prog_extra_timeout = 2000; call_extra_timeout = 2000; } if (strncmp(syscalls[call_num].name, "syz_usb_control_io", strlen("syz_usb_control_io")) == 0) call_extra_timeout = 300; if (strncmp(syscalls[call_num].name, "syz_usb_ep_write", strlen("syz_usb_ep_write")) == 0) call_extra_timeout = 300; if (strncmp(syscalls[call_num].name, "syz_usb_ep_read", strlen("syz_usb_ep_read")) == 0) call_extra_timeout = 300; if (strncmp(syscalls[call_num].name, "syz_usb_disconnect", strlen("syz_usb_disconnect")) == 0) call_extra_timeout = 300; uint64 copyout_index = read_input(&input_pos); uint64 num_args = read_input(&input_pos); if (num_args > kMaxArgs) fail("command has bad number of arguments %llu", num_args); uint64 args[kMaxArgs] = {}; for (uint64 i = 0; i < num_args; i++) args[i] = read_arg(&input_pos); for (uint64 i = num_args; i < kMaxArgs; i++) args[i] = 0; thread_t* th = schedule_call(call_index++, call_num, colliding, copyout_index, num_args, args, input_pos, call_extra_cover); if (colliding && (call_index % 2) == 0) { // Don't wait for every other call. // We already have results from the previous execution. } else if (flag_threaded) { // Wait for call completion. // Note: sys knows about this 25ms timeout when it generates timespec/timeval values. uint64 timeout_ms = 45 + call_extra_timeout; if (flag_debug && timeout_ms < 1000) timeout_ms = 1000; if (event_timedwait(&th->done, timeout_ms)) handle_completion(th); // Check if any of previous calls have completed. for (int i = 0; i < kMaxThreads; i++) { th = &threads[i]; if (th->executing && event_isset(&th->done)) handle_completion(th); } } else { // Execute directly. if (th != &threads[0]) fail("using non-main thread in non-thread mode"); event_reset(&th->ready); execute_call(th); event_set(&th->done); handle_completion(th); } } if (!colliding && !collide && running > 0) { // Give unfinished syscalls some additional time. last_scheduled = 0; uint64 wait = 100; uint64 wait_start = current_time_ms(); uint64 wait_end = wait_start + wait; if (wait_end < start + 800) wait_end = start + 800; wait_end += prog_extra_timeout; while (running > 0 && current_time_ms() <= wait_end) { sleep_ms(1); for (int i = 0; i < kMaxThreads; i++) { thread_t* th = &threads[i]; if (th->executing && event_isset(&th->done)) handle_completion(th); } } // Write output coverage for unfinished calls. if (running > 0) { for (int i = 0; i < kMaxThreads; i++) { thread_t* th = &threads[i]; if (th->executing) { if (flag_cover) cover_collect(&th->cov); write_call_output(th, false); } } if (prog_extra_cover) write_extra_output(); } } #if SYZ_HAVE_CLOSE_FDS close_fds(); #endif if (prog_extra_cover) { sleep_ms(500); if (!colliding && !collide) write_extra_output(); } if (flag_collide && !flag_inject_fault && !colliding && !collide) { debug("enabling collider\n"); collide = colliding = true; goto retry; } } thread_t* schedule_call(int call_index, int call_num, bool colliding, uint64 copyout_index, uint64 num_args, uint64* args, uint64* pos, bool extra_cover) { // Find a spare thread to execute the call. int i; for (i = 0; i < kMaxThreads; i++) { thread_t* th = &threads[i]; if (!th->created) thread_create(th, i); if (event_isset(&th->done)) { if (th->executing) handle_completion(th); break; } } if (i == kMaxThreads) exitf("out of threads"); thread_t* th = &threads[i]; if (event_isset(&th->ready) || !event_isset(&th->done) || th->executing) fail("bad thread state in schedule: ready=%d done=%d executing=%d", event_isset(&th->ready), event_isset(&th->done), th->executing); last_scheduled = th; th->colliding = colliding; th->copyout_pos = pos; th->copyout_index = copyout_index; event_reset(&th->done); th->executing = true; th->call_index = call_index; th->call_num = call_num; th->num_args = num_args; for (int i = 0; i < kMaxArgs; i++) th->args[i] = args[i]; th->extra_cover = extra_cover; event_set(&th->ready); running++; return th; } #if SYZ_EXECUTOR_USES_SHMEM template void write_coverage_signal(cover_t* cov, uint32* signal_count_pos, uint32* cover_count_pos) { // Write out feedback signals. // Currently it is code edges computed as xor of two subsequent basic block PCs. cover_data_t* cover_data = ((cover_data_t*)cov->data) + 1; uint32 nsig = 0; cover_data_t prev = 0; for (uint32 i = 0; i < cov->size; i++) { cover_data_t pc = cover_data[i]; if (!cover_check(pc)) { debug("got bad pc: 0x%llx\n", (uint64)pc); doexit(0); } cover_data_t sig = pc ^ prev; prev = hash(pc); if (dedup(sig)) continue; write_output(sig); nsig++; } // Write out number of signals. *signal_count_pos = nsig; if (!flag_collect_cover) return; // Write out real coverage (basic block PCs). uint32 cover_size = cov->size; if (flag_dedup_cover) { cover_data_t* end = cover_data + cover_size; cover_unprotect(cov); std::sort(cover_data, end); cover_size = std::unique(cover_data, end) - cover_data; cover_protect(cov); } // Truncate PCs to uint32 assuming that they fit into 32-bits. // True for x86_64 and arm64 without KASLR. for (uint32 i = 0; i < cover_size; i++) write_output(cover_data[i]); *cover_count_pos = cover_size; } #endif void handle_completion(thread_t* th) { if (event_isset(&th->ready) || !event_isset(&th->done) || !th->executing) fail("bad thread state in completion: ready=%d done=%d executing=%d", event_isset(&th->ready), event_isset(&th->done), th->executing); if (th->res != (intptr_t)-1) copyout_call_results(th); if (!collide && !th->colliding) { write_call_output(th, true); if (th->extra_cover) write_extra_output(); } th->executing = false; running--; if (running < 0) fail("running = %d", running); } void copyout_call_results(thread_t* th) { if (th->copyout_index != no_copyout) { if (th->copyout_index >= kMaxCommands) fail("result idx %lld overflows kMaxCommands", th->copyout_index); results[th->copyout_index].executed = true; results[th->copyout_index].val = th->res; } for (bool done = false; !done;) { uint64 instr = read_input(&th->copyout_pos); switch (instr) { case instr_copyout: { uint64 index = read_input(&th->copyout_pos); if (index >= kMaxCommands) fail("result idx %lld overflows kMaxCommands", index); char* addr = (char*)read_input(&th->copyout_pos); uint64 size = read_input(&th->copyout_pos); uint64 val = 0; if (copyout(addr, size, &val)) { results[index].executed = true; results[index].val = val; } debug_verbose("copyout 0x%llx from %p\n", val, addr); break; } default: done = true; break; } } } void write_call_output(thread_t* th, bool finished) { uint32 reserrno = 999; const bool blocked = th != last_scheduled; uint32 call_flags = call_flag_executed | (blocked ? call_flag_blocked : 0); if (finished) { reserrno = th->res != -1 ? 0 : th->reserrno; call_flags |= call_flag_finished | (th->fault_injected ? call_flag_fault_injected : 0); } #if SYZ_EXECUTOR_USES_SHMEM write_output(th->call_index); write_output(th->call_num); write_output(reserrno); write_output(call_flags); uint32* signal_count_pos = write_output(0); // filled in later uint32* cover_count_pos = write_output(0); // filled in later uint32* comps_count_pos = write_output(0); // filled in later if (flag_collect_comps) { // Collect only the comparisons uint32 ncomps = th->cov.size; kcov_comparison_t* start = (kcov_comparison_t*)(th->cov.data + sizeof(uint64)); kcov_comparison_t* end = start + ncomps; if ((char*)end > th->cov.data_end) fail("too many comparisons %u", ncomps); cover_unprotect(&th->cov); std::sort(start, end); ncomps = std::unique(start, end) - start; cover_protect(&th->cov); uint32 comps_size = 0; for (uint32 i = 0; i < ncomps; ++i) { if (start[i].ignore()) continue; comps_size++; start[i].write(); } // Write out number of comparisons. *comps_count_pos = comps_size; } else if (flag_cover) { if (is_kernel_64_bit) write_coverage_signal(&th->cov, signal_count_pos, cover_count_pos); else write_coverage_signal(&th->cov, signal_count_pos, cover_count_pos); } debug_verbose("out #%u: index=%u num=%u errno=%d finished=%d blocked=%d sig=%u cover=%u comps=%u\n", completed, th->call_index, th->call_num, reserrno, finished, blocked, *signal_count_pos, *cover_count_pos, *comps_count_pos); completed++; write_completed(completed); #else call_reply reply; reply.header.magic = kOutMagic; reply.header.done = 0; reply.header.status = 0; reply.call_index = th->call_index; reply.call_num = th->call_num; reply.reserrno = reserrno; reply.flags = call_flags; reply.signal_size = 0; reply.cover_size = 0; reply.comps_size = 0; if (write(kOutPipeFd, &reply, sizeof(reply)) != sizeof(reply)) fail("control pipe call write failed"); debug_verbose("out: index=%u num=%u errno=%d finished=%d blocked=%d\n", th->call_index, th->call_num, reserrno, finished, blocked); #endif } void write_extra_output() { #if SYZ_EXECUTOR_USES_SHMEM if (!flag_cover || !flag_extra_cover || flag_collect_comps) return; cover_collect(&extra_cov); if (!extra_cov.size) return; write_output(-1); // call index write_output(-1); // call num write_output(999); // errno write_output(0); // call flags uint32* signal_count_pos = write_output(0); // filled in later uint32* cover_count_pos = write_output(0); // filled in later write_output(0); // comps_count_pos if (is_kernel_64_bit) write_coverage_signal(&extra_cov, signal_count_pos, cover_count_pos); else write_coverage_signal(&extra_cov, signal_count_pos, cover_count_pos); cover_reset(&extra_cov); debug_verbose("extra: sig=%u cover=%u\n", *signal_count_pos, *cover_count_pos); completed++; write_completed(completed); #endif } void thread_create(thread_t* th, int id) { th->created = true; th->id = id; th->executing = false; event_init(&th->ready); event_init(&th->done); event_set(&th->done); if (flag_threaded) thread_start(worker_thread, th); } void* worker_thread(void* arg) { thread_t* th = (thread_t*)arg; if (flag_cover) cover_enable(&th->cov, flag_collect_comps, false); for (;;) { event_wait(&th->ready); event_reset(&th->ready); execute_call(th); event_set(&th->done); } return 0; } void execute_call(thread_t* th) { const call_t* call = &syscalls[th->call_num]; debug("#%d [%llums] -> %s(", th->id, current_time_ms() - start_time_ms, call->name); for (int i = 0; i < th->num_args; i++) { if (i != 0) debug(", "); debug("0x%llx", (uint64)th->args[i]); } debug(")\n"); int fail_fd = -1; if (flag_inject_fault && th->call_index == flag_fault_call) { if (collide) fail("both collide and fault injection are enabled"); fail_fd = inject_fault(flag_fault_nth); } if (flag_cover) cover_reset(&th->cov); errno = 0; th->res = execute_syscall(call, th->args); th->reserrno = errno; if (th->res == -1 && th->reserrno == 0) th->reserrno = EINVAL; // our syz syscalls may misbehave if (flag_cover) { cover_collect(&th->cov); if (th->cov.size >= kCoverSize) fail("#%d: too much cover %u", th->id, th->cov.size); } th->fault_injected = false; if (flag_inject_fault && th->call_index == flag_fault_call) { th->fault_injected = fault_injected(fail_fd); } debug("#%d [%llums] <- %s=0x%llx errno=%d ", th->id, current_time_ms() - start_time_ms, call->name, (uint64)th->res, th->reserrno); if (flag_cover) debug("cover=%u ", th->cov.size); if (flag_inject_fault && th->call_index == flag_fault_call) debug("fault=%d ", th->fault_injected); debug("\n"); } #if SYZ_EXECUTOR_USES_SHMEM static uint32 hash(uint32 a) { a = (a ^ 61) ^ (a >> 16); a = a + (a << 3); a = a ^ (a >> 4); a = a * 0x27d4eb2d; a = a ^ (a >> 15); return a; } const uint32 dedup_table_size = 8 << 10; uint32 dedup_table[dedup_table_size]; // Poorman's best-effort hashmap-based deduplication. // The hashmap is global which means that we deduplicate across different calls. // This is OK because we are interested only in new signals. static bool dedup(uint32 sig) { for (uint32 i = 0; i < 4; i++) { uint32 pos = (sig + i) % dedup_table_size; if (dedup_table[pos] == sig) return true; if (dedup_table[pos] == 0) { dedup_table[pos] = sig; return false; } } dedup_table[sig % dedup_table_size] = sig; return false; } #endif template void copyin_int(char* addr, uint64 val, uint64 bf, uint64 bf_off, uint64 bf_len) { if (bf_off == 0 && bf_len == 0) { *(T*)addr = swap(val, sizeof(T), bf); return; } T x = swap(*(T*)addr, sizeof(T), bf); x = (x & ~BITMASK(bf_off, bf_len)) | ((val << bf_off) & BITMASK(bf_off, bf_len)); *(T*)addr = swap(x, sizeof(T), bf); } void copyin(char* addr, uint64 val, uint64 size, uint64 bf, uint64 bf_off, uint64 bf_len) { if (bf != binary_format_native && bf != binary_format_bigendian && (bf_off != 0 || bf_len != 0)) fail("bitmask for string format %llu/%llu", bf_off, bf_len); switch (bf) { case binary_format_native: case binary_format_bigendian: NONFAILING(switch (size) { case 1: copyin_int(addr, val, bf, bf_off, bf_len); break; case 2: copyin_int(addr, val, bf, bf_off, bf_len); break; case 4: copyin_int(addr, val, bf, bf_off, bf_len); break; case 8: copyin_int(addr, val, bf, bf_off, bf_len); break; default: fail("copyin: bad argument size %llu", size); }); break; case binary_format_strdec: if (size != 20) fail("bad strdec size %llu", size); NONFAILING(sprintf((char*)addr, "%020llu", val)); break; case binary_format_strhex: if (size != 18) fail("bad strhex size %llu", size); NONFAILING(sprintf((char*)addr, "0x%016llx", val)); break; case binary_format_stroct: if (size != 23) fail("bad stroct size %llu", size); NONFAILING(sprintf((char*)addr, "%023llo", val)); break; default: fail("unknown binary format %llu", bf); } } bool copyout(char* addr, uint64 size, uint64* res) { bool ok = false; NONFAILING( switch (size) { case 1: *res = *(uint8*)addr; break; case 2: *res = *(uint16*)addr; break; case 4: *res = *(uint32*)addr; break; case 8: *res = *(uint64*)addr; break; default: fail("copyout: bad argument size %llu", size); } __atomic_store_n(&ok, true, __ATOMIC_RELEASE);); return ok; } uint64 read_arg(uint64** input_posp) { uint64 typ = read_input(input_posp); switch (typ) { case arg_const: { uint64 size, bf, bf_off, bf_len; uint64 val = read_const_arg(input_posp, &size, &bf, &bf_off, &bf_len); if (bf != binary_format_native && bf != binary_format_bigendian) fail("bad argument binary format %llu", bf); if (bf_off != 0 || bf_len != 0) fail("bad argument bitfield %llu/%llu", bf_off, bf_len); return swap(val, size, bf); } case arg_result: { uint64 meta = read_input(input_posp); uint64 bf = meta >> 8; if (bf != binary_format_native) fail("bad result argument format %llu", bf); return read_result(input_posp); } default: fail("bad argument type %llu", typ); } } uint64 swap(uint64 v, uint64 size, uint64 bf) { if (bf == binary_format_native) return v; if (bf != binary_format_bigendian) fail("bad binary format in swap: %llu", bf); switch (size) { case 2: return htobe16(v); case 4: return htobe32(v); case 8: return htobe64(v); default: fail("bad big-endian int size %llu", size); } } uint64 read_const_arg(uint64** input_posp, uint64* size_p, uint64* bf_p, uint64* bf_off_p, uint64* bf_len_p) { uint64 meta = read_input(input_posp); uint64 val = read_input(input_posp); *size_p = meta & 0xff; uint64 bf = (meta >> 8) & 0xff; *bf_off_p = (meta >> 16) & 0xff; *bf_len_p = (meta >> 24) & 0xff; uint64 pid_stride = meta >> 32; val += pid_stride * procid; *bf_p = bf; return val; } uint64 read_result(uint64** input_posp) { uint64 idx = read_input(input_posp); uint64 op_div = read_input(input_posp); uint64 op_add = read_input(input_posp); uint64 arg = read_input(input_posp); if (idx >= kMaxCommands) fail("command refers to bad result %lld", idx); if (results[idx].executed) { arg = results[idx].val; if (op_div != 0) arg = arg / op_div; arg += op_add; } return arg; } uint64 read_input(uint64** input_posp, bool peek) { uint64* input_pos = *input_posp; if ((char*)input_pos >= input_data + kMaxInput) fail("input command overflows input %p: [%p:%p)", input_pos, input_data, input_data + kMaxInput); if (!peek) *input_posp = input_pos + 1; return *input_pos; } #if SYZ_EXECUTOR_USES_SHMEM uint32* write_output(uint32 v) { if (output_pos < output_data || (char*)output_pos >= (char*)output_data + kMaxOutput) fail("output overflow: pos=%p region=[%p:%p]", output_pos, output_data, (char*)output_data + kMaxOutput); *output_pos = v; return output_pos++; } void write_completed(uint32 completed) { __atomic_store_n(output_data, completed, __ATOMIC_RELEASE); } #endif #if SYZ_EXECUTOR_USES_SHMEM void kcov_comparison_t::write() { // Write order: type arg1 arg2 pc. write_output((uint32)type); // KCOV converts all arguments of size x first to uintx_t and then to // uint64. We want to properly extend signed values, e.g we want // int8 c = 0xfe to be represented as 0xfffffffffffffffe. // Note that uint8 c = 0xfe will be represented the same way. // This is ok because during hints processing we will anyways try // the value 0x00000000000000fe. switch (type & KCOV_CMP_SIZE_MASK) { case KCOV_CMP_SIZE1: arg1 = (uint64)(long long)(signed char)arg1; arg2 = (uint64)(long long)(signed char)arg2; break; case KCOV_CMP_SIZE2: arg1 = (uint64)(long long)(short)arg1; arg2 = (uint64)(long long)(short)arg2; break; case KCOV_CMP_SIZE4: arg1 = (uint64)(long long)(int)arg1; arg2 = (uint64)(long long)(int)arg2; break; } bool is_size_8 = (type & KCOV_CMP_SIZE_MASK) == KCOV_CMP_SIZE8; if (!is_size_8) { write_output((uint32)arg1); write_output((uint32)arg2); return; } // If we have 64 bits arguments then write them in Little-endian. write_output((uint32)(arg1 & 0xFFFFFFFF)); write_output((uint32)(arg1 >> 32)); write_output((uint32)(arg2 & 0xFFFFFFFF)); write_output((uint32)(arg2 >> 32)); } bool kcov_comparison_t::ignore() const { // Comparisons with 0 are not interesting, fuzzer should be able to guess 0's without help. if (arg1 == 0 && (arg2 == 0 || (type & KCOV_CMP_CONST))) return true; if ((type & KCOV_CMP_SIZE_MASK) == KCOV_CMP_SIZE8) { // This can be a pointer (assuming 64-bit kernel). // First of all, we want avert fuzzer from our output region. // Without this fuzzer manages to discover and corrupt it. uint64 out_start = (uint64)output_data; uint64 out_end = out_start + kMaxOutput; if (arg1 >= out_start && arg1 <= out_end) return true; if (arg2 >= out_start && arg2 <= out_end) return true; #if defined(GOOS_linux) // Filter out kernel physical memory addresses. // These are internal kernel comparisons and should not be interesting. // The range covers first 1TB of physical mapping. uint64 kmem_start = (uint64)0xffff880000000000ull; uint64 kmem_end = (uint64)0xffff890000000000ull; bool kptr1 = arg1 >= kmem_start && arg1 <= kmem_end; bool kptr2 = arg2 >= kmem_start && arg2 <= kmem_end; if (kptr1 && kptr2) return true; if (kptr1 && arg2 == 0) return true; if (kptr2 && arg1 == 0) return true; #endif } return false; } bool kcov_comparison_t::operator==(const struct kcov_comparison_t& other) const { // We don't check for PC equality now, because it is not used. return type == other.type && arg1 == other.arg1 && arg2 == other.arg2; } bool kcov_comparison_t::operator<(const struct kcov_comparison_t& other) const { if (type != other.type) return type < other.type; if (arg1 != other.arg1) return arg1 < other.arg1; // We don't check for PC equality now, because it is not used. return arg2 < other.arg2; } #endif void setup_features(char** enable, int n) { // This does any one-time setup for the requested features on the machine. // Note: this can be called multiple times and must be idempotent. for (int i = 0; i < n; i++) { bool found = false; #if SYZ_HAVE_FEATURES for (unsigned f = 0; f < sizeof(features) / sizeof(features[0]); f++) { if (strcmp(enable[i], features[f].name) == 0) { features[f].setup(); found = true; break; } } #endif if (!found) fail("unknown feature %s", enable[i]); } } 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(kFailStatus); } 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(0); } void debug(const char* msg, ...) { if (!flag_debug) return; va_list args; va_start(args, msg); vfprintf(stderr, msg, args); va_end(args); fflush(stderr); } void debug_dump_data(const char* data, int length) { if (!flag_debug) return; int i; for (i = 0; i < length; i++) { debug("%02x ", data[i] & 0xff); if (i % 16 == 15) debug("\n"); } if (i % 16 != 0) debug("\n"); } /usr/local/bin/ld: cannot find -lasan collect2: error: ld returned 1 exit status compiler invocation: gcc [-o /tmp/syz-executor971702853 -DGOOS_test=1 -DGOARCH_64_fork=1 -DHOSTGOOS_freebsd=1 ../../executor/executor.cc -O2 -pthread -Wall -Werror -Wparentheses -Wunused-const-variable -Wframe-larger-than=8192 -m64 -fsanitize=address] --- FAIL: Test/64 (2.16s) run_test.go:44: failed to build program: // Copyright 2017 syzkaller project authors. All rights reserved. // Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file. // +build #include #include #include #include #include #include #include #include #include #include #include #include "defs.h" #if defined(__GNUC__) #define SYSCALLAPI #define NORETURN __attribute__((noreturn)) #define ALIGNED(N) __attribute__((aligned(N))) #define PRINTF(fmt, args) __attribute__((format(printf, fmt, args))) #else // Assuming windows/cl. #define SYSCALLAPI WINAPI #define NORETURN __declspec(noreturn) #define ALIGNED(N) __declspec(align(N)) #define PRINTF(fmt, args) #endif #ifndef GIT_REVISION #define GIT_REVISION "unknown" #endif #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) // uint64 is impossible to printf without using the clumsy and verbose "%" PRId64. // So we define and use uint64. Note: pkg/csource does s/uint64/uint64/. // Also define uint32/16/8 for consistency. typedef unsigned long long uint64; typedef unsigned int uint32; typedef unsigned short uint16; typedef unsigned char uint8; // exit/_exit do not necessary work (e.g. if fuzzer sets seccomp filter that prohibits exit_group). // Use doexit instead. We must redefine exit to something that exists in stdlib, // because some standard libraries contain "using ::exit;", but has different signature. #define exit vsnprintf // Note: zircon max fd is 256. // Some common_OS.h files know about this constant for RLIMIT_NOFILE. const int kMaxFd = 250; const int kMaxThreads = 16; const int kInPipeFd = kMaxFd - 1; // remapped from stdin const int kOutPipeFd = kMaxFd - 2; // remapped from stdout const int kCoverFd = kOutPipeFd - kMaxThreads; const int kMaxArgs = 9; const int kCoverSize = 256 << 10; const int kFailStatus = 67; // Logical error (e.g. invalid input program), use as an assert() alternative. static NORETURN PRINTF(1, 2) void fail(const char* msg, ...); // Just exit (e.g. due to temporal ENOMEM error). static NORETURN PRINTF(1, 2) void exitf(const char* msg, ...); static NORETURN void doexit(int status); // Print debug output, does not add \n at the end of msg as opposed to the previous functions. static PRINTF(1, 2) void debug(const char* msg, ...); void debug_dump_data(const char* data, int length); #if 0 #define debug_verbose(...) debug(__VA_ARGS__) #else #define debug_verbose(...) (void)0 #endif static void receive_execute(); static void reply_execute(int status); #if GOOS_akaros static void resend_execute(int fd); #endif #if SYZ_EXECUTOR_USES_FORK_SERVER static void receive_handshake(); static void reply_handshake(); #endif #if SYZ_EXECUTOR_USES_SHMEM const int kMaxOutput = 16 << 20; const int kInFd = 3; const int kOutFd = 4; static uint32* output_data; static uint32* output_pos; static uint32* write_output(uint32 v); static void write_completed(uint32 completed); static uint32 hash(uint32 a); static bool dedup(uint32 sig); #endif enum sandbox_type { sandbox_none, sandbox_setuid, sandbox_namespace, sandbox_android_untrusted_app }; uint64 start_time_ms = 0; static bool flag_debug; static bool flag_cover; static sandbox_type flag_sandbox; static bool flag_extra_cover; static bool flag_enable_tun; static bool flag_enable_net_dev; static bool flag_enable_net_reset; static bool flag_enable_cgroups; static bool flag_enable_close_fds; static bool flag_collect_cover; static bool flag_dedup_cover; static bool flag_threaded; static bool flag_collide; // If true, then executor should write the comparisons data to fuzzer. static bool flag_collect_comps; // Inject fault into flag_fault_nth-th operation in flag_fault_call-th syscall. static bool flag_inject_fault; static int flag_fault_call; static int flag_fault_nth; #define SYZ_EXECUTOR 1 #include "common.h" const int kMaxCommands = 1000; const int kMaxInput = 2 << 20; const uint64 instr_eof = -1; const uint64 instr_copyin = -2; const uint64 instr_copyout = -3; const uint64 arg_const = 0; const uint64 arg_result = 1; const uint64 arg_data = 2; const uint64 arg_csum = 3; const uint64 binary_format_native = 0; const uint64 binary_format_bigendian = 1; const uint64 binary_format_strdec = 2; const uint64 binary_format_strhex = 3; const uint64 binary_format_stroct = 4; const uint64 no_copyout = -1; static int running; static bool collide; uint32 completed; bool is_kernel_64_bit = true; ALIGNED(64 << 10) static char input_data[kMaxInput]; // Checksum kinds. static const uint64 arg_csum_inet = 0; // Checksum chunk kinds. static const uint64 arg_csum_chunk_data = 0; static const uint64 arg_csum_chunk_const = 1; typedef intptr_t(SYSCALLAPI* syscall_t)(intptr_t, intptr_t, intptr_t, intptr_t, intptr_t, intptr_t, intptr_t, intptr_t, intptr_t); struct call_t { const char* name; int sys_nr; syscall_t call; }; struct cover_t { int fd; uint32 size; char* data; char* data_end; }; struct thread_t { int id; bool created; event_t ready; event_t done; uint64* copyout_pos; uint64 copyout_index; bool colliding; bool executing; int call_index; int call_num; int num_args; intptr_t args[kMaxArgs]; intptr_t res; uint32 reserrno; bool fault_injected; cover_t cov; bool extra_cover; }; static thread_t threads[kMaxThreads]; static thread_t* last_scheduled; static cover_t extra_cov; struct res_t { bool executed; uint64 val; }; static res_t results[kMaxCommands]; const uint64 kInMagic = 0xbadc0ffeebadface; const uint32 kOutMagic = 0xbadf00d; struct handshake_req { uint64 magic; uint64 flags; // env flags uint64 pid; }; struct handshake_reply { uint32 magic; }; struct execute_req { uint64 magic; uint64 env_flags; uint64 exec_flags; uint64 pid; uint64 fault_call; uint64 fault_nth; uint64 prog_size; }; struct execute_reply { uint32 magic; uint32 done; uint32 status; }; // call_reply.flags const uint32 call_flag_executed = 1 << 0; const uint32 call_flag_finished = 1 << 1; const uint32 call_flag_blocked = 1 << 2; const uint32 call_flag_fault_injected = 1 << 3; struct call_reply { execute_reply header; uint32 call_index; uint32 call_num; uint32 reserrno; uint32 flags; uint32 signal_size; uint32 cover_size; uint32 comps_size; // signal/cover/comps follow }; enum { KCOV_CMP_CONST = 1, KCOV_CMP_SIZE1 = 0, KCOV_CMP_SIZE2 = 2, KCOV_CMP_SIZE4 = 4, KCOV_CMP_SIZE8 = 6, KCOV_CMP_SIZE_MASK = 6, }; struct kcov_comparison_t { // Note: comparisons are always 64-bits regardless of kernel bitness. uint64 type; uint64 arg1; uint64 arg2; uint64 pc; bool ignore() const; void write(); bool operator==(const struct kcov_comparison_t& other) const; bool operator<(const struct kcov_comparison_t& other) const; }; struct feature_t { const char* name; void (*setup)(); }; static thread_t* schedule_call(int call_index, int call_num, bool colliding, uint64 copyout_index, uint64 num_args, uint64* args, uint64* pos, bool extra_cover); static void handle_completion(thread_t* th); static void copyout_call_results(thread_t* th); static void write_call_output(thread_t* th, bool finished); static void write_extra_output(); static void execute_call(thread_t* th); static void thread_create(thread_t* th, int id); static void* worker_thread(void* arg); static uint64 read_input(uint64** input_posp, bool peek = false); static uint64 read_arg(uint64** input_posp); static uint64 read_const_arg(uint64** input_posp, uint64* size_p, uint64* bf, uint64* bf_off_p, uint64* bf_len_p); static uint64 read_result(uint64** input_posp); static uint64 swap(uint64 v, uint64 size, uint64 bf); static void copyin(char* addr, uint64 val, uint64 size, uint64 bf, uint64 bf_off, uint64 bf_len); static bool copyout(char* addr, uint64 size, uint64* res); static void setup_control_pipes(); static void setup_features(char** enable, int n); #include "syscalls.h" #if GOOS_linux #include "executor_linux.h" #elif GOOS_fuchsia #include "executor_fuchsia.h" #elif GOOS_akaros #include "executor_akaros.h" #elif GOOS_freebsd || GOOS_netbsd || GOOS_openbsd #include "executor_bsd.h" #elif GOOS_windows #include "executor_windows.h" #elif GOOS_test #include "executor_test.h" #else #error "unknown OS" #endif #include "test.h" int main(int argc, char** argv) { if (argc == 2 && strcmp(argv[1], "version") == 0) { puts(GOOS " " GOARCH " " SYZ_REVISION " " GIT_REVISION); return 0; } if (argc >= 2 && strcmp(argv[1], "setup") == 0) { setup_features(argv + 2, argc - 2); return 0; } if (argc >= 2 && strcmp(argv[1], "leak") == 0) { #if SYZ_HAVE_LEAK_CHECK check_leaks(argv + 2, argc - 2); #else fail("leak checking is not implemented"); #endif return 0; } if (argc == 2 && strcmp(argv[1], "test") == 0) return run_tests(); start_time_ms = current_time_ms(); os_init(argc, argv, (void*)SYZ_DATA_OFFSET, SYZ_NUM_PAGES * SYZ_PAGE_SIZE); #if SYZ_EXECUTOR_USES_SHMEM if (mmap(&input_data[0], kMaxInput, PROT_READ, MAP_PRIVATE | MAP_FIXED, kInFd, 0) != &input_data[0]) fail("mmap of input file failed"); // The output region is the only thing in executor process for which consistency matters. // If it is corrupted ipc package will fail to parse its contents and panic. // But fuzzer constantly invents new ways of how to currupt the region, // so we map the region at a (hopefully) hard to guess address with random offset, // surrounded by unmapped pages. // The address chosen must also work on 32-bit kernels with 1GB user address space. void* preferred = (void*)(0x1b2bc20000ull + (1 << 20) * (getpid() % 128)); output_data = (uint32*)mmap(preferred, kMaxOutput, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_FIXED, kOutFd, 0); if (output_data != preferred) fail("mmap of output file failed"); // Prevent test programs to mess with these fds. // Due to races in collider mode, a program can e.g. ftruncate one of these fds, // which will cause fuzzer to crash. close(kInFd); close(kOutFd); #endif use_temporary_dir(); install_segv_handler(); setup_control_pipes(); #if SYZ_EXECUTOR_USES_FORK_SERVER receive_handshake(); #else receive_execute(); #endif if (flag_cover) { for (int i = 0; i < kMaxThreads; i++) { threads[i].cov.fd = kCoverFd + i; cover_open(&threads[i].cov, false); cover_protect(&threads[i].cov); } cover_open(&extra_cov, true); cover_protect(&extra_cov); if (flag_extra_cover) { // Don't enable comps because we don't use them in the fuzzer yet. cover_enable(&extra_cov, false, true); } } int status = 0; switch (flag_sandbox) { case sandbox_none: status = do_sandbox_none(); break; #if SYZ_HAVE_SANDBOX_SETUID case sandbox_setuid: status = do_sandbox_setuid(); break; #endif #if SYZ_HAVE_SANDBOX_NAMESPACE case sandbox_namespace: status = do_sandbox_namespace(); break; #endif #if SYZ_HAVE_SANDBOX_ANDROID_UNTRUSTED_APP case sandbox_android_untrusted_app: status = do_sandbox_android_untrusted_app(); break; #endif default: fail("unknown sandbox type"); } #if SYZ_EXECUTOR_USES_FORK_SERVER fprintf(stderr, "loop exited with status %d\n", status); // Other statuses happen when fuzzer processes manages to kill loop, e.g. with: // ptrace(PTRACE_SEIZE, 1, 0, 0x100040) if (status != kFailStatus) status = 0; // If an external sandbox process wraps executor, the out pipe will be closed // before the sandbox process exits this will make ipc package kill the sandbox. // As the result sandbox process will exit with exit status 9 instead of the executor // exit status (notably kFailStatus). So we duplicate the exit status on the pipe. reply_execute(status); doexit(status); // Unreachable. return 1; #else reply_execute(status); return status; #endif } void setup_control_pipes() { if (dup2(0, kInPipeFd) < 0) fail("dup2(0, kInPipeFd) failed"); if (dup2(1, kOutPipeFd) < 0) fail("dup2(1, kOutPipeFd) failed"); if (dup2(2, 1) < 0) fail("dup2(2, 1) failed"); // We used to close(0), but now we dup stderr to stdin to keep fd numbers // stable across executor and C programs generated by pkg/csource. if (dup2(2, 0) < 0) fail("dup2(2, 0) failed"); } void parse_env_flags(uint64 flags) { // Note: Values correspond to ordering in pkg/ipc/ipc.go, e.g. FlagSandboxNamespace flag_debug = flags & (1 << 0); flag_cover = flags & (1 << 1); flag_sandbox = sandbox_none; if (flags & (1 << 2)) flag_sandbox = sandbox_setuid; else if (flags & (1 << 3)) flag_sandbox = sandbox_namespace; else if (flags & (1 << 4)) flag_sandbox = sandbox_android_untrusted_app; flag_extra_cover = flags & (1 << 5); flag_enable_tun = flags & (1 << 6); flag_enable_net_dev = flags & (1 << 7); flag_enable_net_reset = flags & (1 << 8); flag_enable_cgroups = flags & (1 << 9); flag_enable_close_fds = flags & (1 << 10); } #if SYZ_EXECUTOR_USES_FORK_SERVER void receive_handshake() { handshake_req req = {}; int n = read(kInPipeFd, &req, sizeof(req)); if (n != sizeof(req)) fail("handshake read failed: %d", n); if (req.magic != kInMagic) fail("bad handshake magic 0x%llx", req.magic); parse_env_flags(req.flags); procid = req.pid; } void reply_handshake() { handshake_reply reply = {}; reply.magic = kOutMagic; if (write(kOutPipeFd, &reply, sizeof(reply)) != sizeof(reply)) fail("control pipe write failed"); } #endif static execute_req last_execute_req; void receive_execute() { execute_req& req = last_execute_req; if (read(kInPipeFd, &req, sizeof(req)) != (ssize_t)sizeof(req)) fail("control pipe read failed"); if (req.magic != kInMagic) fail("bad execute request magic 0x%llx", req.magic); if (req.prog_size > kMaxInput) fail("bad execute prog size 0x%llx", req.prog_size); parse_env_flags(req.env_flags); procid = req.pid; flag_collect_cover = req.exec_flags & (1 << 0); flag_dedup_cover = req.exec_flags & (1 << 1); flag_inject_fault = req.exec_flags & (1 << 2); flag_collect_comps = req.exec_flags & (1 << 3); flag_threaded = req.exec_flags & (1 << 4); flag_collide = req.exec_flags & (1 << 5); flag_fault_call = req.fault_call; flag_fault_nth = req.fault_nth; if (!flag_threaded) flag_collide = false; debug("[%llums] exec opts: procid=%llu threaded=%d collide=%d cover=%d comps=%d dedup=%d fault=%d/%d/%d prog=%llu\n", current_time_ms() - start_time_ms, procid, flag_threaded, flag_collide, flag_collect_cover, flag_collect_comps, flag_dedup_cover, flag_inject_fault, flag_fault_call, flag_fault_nth, req.prog_size); if (SYZ_EXECUTOR_USES_SHMEM) { if (req.prog_size) fail("need_prog: no program"); return; } if (req.prog_size == 0) fail("need_prog: no program"); uint64 pos = 0; for (;;) { ssize_t rv = read(kInPipeFd, input_data + pos, sizeof(input_data) - pos); if (rv < 0) fail("read failed"); pos += rv; if (rv == 0 || pos >= req.prog_size) break; } if (pos != req.prog_size) fail("bad input size %lld, want %lld", pos, req.prog_size); } #if GOOS_akaros void resend_execute(int fd) { execute_req& req = last_execute_req; if (write(fd, &req, sizeof(req)) != sizeof(req)) fail("child pipe header write failed"); if (write(fd, input_data, req.prog_size) != (ssize_t)req.prog_size) fail("child pipe program write failed"); } #endif void reply_execute(int status) { execute_reply reply = {}; reply.magic = kOutMagic; reply.done = true; reply.status = status; if (write(kOutPipeFd, &reply, sizeof(reply)) != sizeof(reply)) fail("control pipe write failed"); } // execute_one executes program stored in input_data. void execute_one() { // Duplicate global collide variable on stack. // Fuzzer once come up with ioctl(fd, FIONREAD, 0x920000), // where 0x920000 was exactly collide address, so every iteration reset collide to 0. bool colliding = false; #if SYZ_EXECUTOR_USES_SHMEM output_pos = output_data; write_output(0); // Number of executed syscalls (updated later). #endif uint64 start = current_time_ms(); retry: uint64* input_pos = (uint64*)input_data; if (flag_cover && !colliding) { if (!flag_threaded) cover_enable(&threads[0].cov, flag_collect_comps, false); if (flag_extra_cover) cover_reset(&extra_cov); } int call_index = 0; bool prog_extra_cover = false; int prog_extra_timeout = 0; for (;;) { uint64 call_num = read_input(&input_pos); if (call_num == instr_eof) break; if (call_num == instr_copyin) { char* addr = (char*)read_input(&input_pos); uint64 typ = read_input(&input_pos); switch (typ) { case arg_const: { uint64 size, bf, bf_off, bf_len; uint64 arg = read_const_arg(&input_pos, &size, &bf, &bf_off, &bf_len); copyin(addr, arg, size, bf, bf_off, bf_len); break; } case arg_result: { uint64 meta = read_input(&input_pos); uint64 size = meta & 0xff; uint64 bf = meta >> 8; uint64 val = read_result(&input_pos); copyin(addr, val, size, bf, 0, 0); break; } case arg_data: { uint64 size = read_input(&input_pos); size &= ~(1ull << 63); // readable flag NONFAILING(memcpy(addr, input_pos, size)); // Read out the data. for (uint64 i = 0; i < (size + 7) / 8; i++) read_input(&input_pos); break; } case arg_csum: { debug_verbose("checksum found at %p\n", addr); uint64 size = read_input(&input_pos); char* csum_addr = addr; uint64 csum_kind = read_input(&input_pos); switch (csum_kind) { case arg_csum_inet: { if (size != 2) fail("inet checksum must be 2 bytes, not %llu", size); debug_verbose("calculating checksum for %p\n", csum_addr); struct csum_inet csum; csum_inet_init(&csum); uint64 chunks_num = read_input(&input_pos); uint64 chunk; for (chunk = 0; chunk < chunks_num; chunk++) { uint64 chunk_kind = read_input(&input_pos); uint64 chunk_value = read_input(&input_pos); uint64 chunk_size = read_input(&input_pos); switch (chunk_kind) { case arg_csum_chunk_data: debug_verbose("#%lld: data chunk, addr: %llx, size: %llu\n", chunk, chunk_value, chunk_size); NONFAILING(csum_inet_update(&csum, (const uint8*)chunk_value, chunk_size)); break; case arg_csum_chunk_const: if (chunk_size != 2 && chunk_size != 4 && chunk_size != 8) { fail("bad checksum const chunk size %lld\n", chunk_size); } // Here we assume that const values come to us big endian. debug_verbose("#%lld: const chunk, value: %llx, size: %llu\n", chunk, chunk_value, chunk_size); csum_inet_update(&csum, (const uint8*)&chunk_value, chunk_size); break; default: fail("bad checksum chunk kind %llu", chunk_kind); } } uint16 csum_value = csum_inet_digest(&csum); debug_verbose("writing inet checksum %hx to %p\n", csum_value, csum_addr); copyin(csum_addr, csum_value, 2, binary_format_native, 0, 0); break; } default: fail("bad checksum kind %llu", csum_kind); } break; } default: fail("bad argument type %llu", typ); } continue; } if (call_num == instr_copyout) { read_input(&input_pos); // index read_input(&input_pos); // addr read_input(&input_pos); // size // The copyout will happen when/if the call completes. continue; } // Normal syscall. if (call_num >= ARRAY_SIZE(syscalls)) fail("invalid command number %llu", call_num); bool call_extra_cover = false; // call_extra_timeout must match timeout in pkg/csource/csource.go. int call_extra_timeout = 0; // TODO: find a way to tune timeout values. if (strncmp(syscalls[call_num].name, "syz_usb", strlen("syz_usb")) == 0) { prog_extra_cover = true; call_extra_cover = true; } if (strncmp(syscalls[call_num].name, "syz_usb_connect", strlen("syz_usb_connect")) == 0) { prog_extra_timeout = 2000; call_extra_timeout = 2000; } if (strncmp(syscalls[call_num].name, "syz_usb_control_io", strlen("syz_usb_control_io")) == 0) call_extra_timeout = 300; if (strncmp(syscalls[call_num].name, "syz_usb_ep_write", strlen("syz_usb_ep_write")) == 0) call_extra_timeout = 300; if (strncmp(syscalls[call_num].name, "syz_usb_ep_read", strlen("syz_usb_ep_read")) == 0) call_extra_timeout = 300; if (strncmp(syscalls[call_num].name, "syz_usb_disconnect", strlen("syz_usb_disconnect")) == 0) call_extra_timeout = 300; uint64 copyout_index = read_input(&input_pos); uint64 num_args = read_input(&input_pos); if (num_args > kMaxArgs) fail("command has bad number of arguments %llu", num_args); uint64 args[kMaxArgs] = {}; for (uint64 i = 0; i < num_args; i++) args[i] = read_arg(&input_pos); for (uint64 i = num_args; i < kMaxArgs; i++) args[i] = 0; thread_t* th = schedule_call(call_index++, call_num, colliding, copyout_index, num_args, args, input_pos, call_extra_cover); if (colliding && (call_index % 2) == 0) { // Don't wait for every other call. // We already have results from the previous execution. } else if (flag_threaded) { // Wait for call completion. // Note: sys knows about this 25ms timeout when it generates timespec/timeval values. uint64 timeout_ms = 45 + call_extra_timeout; if (flag_debug && timeout_ms < 1000) timeout_ms = 1000; if (event_timedwait(&th->done, timeout_ms)) handle_completion(th); // Check if any of previous calls have completed. for (int i = 0; i < kMaxThreads; i++) { th = &threads[i]; if (th->executing && event_isset(&th->done)) handle_completion(th); } } else { // Execute directly. if (th != &threads[0]) fail("using non-main thread in non-thread mode"); event_reset(&th->ready); execute_call(th); event_set(&th->done); handle_completion(th); } } if (!colliding && !collide && running > 0) { // Give unfinished syscalls some additional time. last_scheduled = 0; uint64 wait = 100; uint64 wait_start = current_time_ms(); uint64 wait_end = wait_start + wait; if (wait_end < start + 800) wait_end = start + 800; wait_end += prog_extra_timeout; while (running > 0 && current_time_ms() <= wait_end) { sleep_ms(1); for (int i = 0; i < kMaxThreads; i++) { thread_t* th = &threads[i]; if (th->executing && event_isset(&th->done)) handle_completion(th); } } // Write output coverage for unfinished calls. if (running > 0) { for (int i = 0; i < kMaxThreads; i++) { thread_t* th = &threads[i]; if (th->executing) { if (flag_cover) cover_collect(&th->cov); write_call_output(th, false); } } if (prog_extra_cover) write_extra_output(); } } #if SYZ_HAVE_CLOSE_FDS close_fds(); #endif if (prog_extra_cover) { sleep_ms(500); if (!colliding && !collide) write_extra_output(); } if (flag_collide && !flag_inject_fault && !colliding && !collide) { debug("enabling collider\n"); collide = colliding = true; goto retry; } } thread_t* schedule_call(int call_index, int call_num, bool colliding, uint64 copyout_index, uint64 num_args, uint64* args, uint64* pos, bool extra_cover) { // Find a spare thread to execute the call. int i; for (i = 0; i < kMaxThreads; i++) { thread_t* th = &threads[i]; if (!th->created) thread_create(th, i); if (event_isset(&th->done)) { if (th->executing) handle_completion(th); break; } } if (i == kMaxThreads) exitf("out of threads"); thread_t* th = &threads[i]; if (event_isset(&th->ready) || !event_isset(&th->done) || th->executing) fail("bad thread state in schedule: ready=%d done=%d executing=%d", event_isset(&th->ready), event_isset(&th->done), th->executing); last_scheduled = th; th->colliding = colliding; th->copyout_pos = pos; th->copyout_index = copyout_index; event_reset(&th->done); th->executing = true; th->call_index = call_index; th->call_num = call_num; th->num_args = num_args; for (int i = 0; i < kMaxArgs; i++) th->args[i] = args[i]; th->extra_cover = extra_cover; event_set(&th->ready); running++; return th; } #if SYZ_EXECUTOR_USES_SHMEM template void write_coverage_signal(cover_t* cov, uint32* signal_count_pos, uint32* cover_count_pos) { // Write out feedback signals. // Currently it is code edges computed as xor of two subsequent basic block PCs. cover_data_t* cover_data = ((cover_data_t*)cov->data) + 1; uint32 nsig = 0; cover_data_t prev = 0; for (uint32 i = 0; i < cov->size; i++) { cover_data_t pc = cover_data[i]; if (!cover_check(pc)) { debug("got bad pc: 0x%llx\n", (uint64)pc); doexit(0); } cover_data_t sig = pc ^ prev; prev = hash(pc); if (dedup(sig)) continue; write_output(sig); nsig++; } // Write out number of signals. *signal_count_pos = nsig; if (!flag_collect_cover) return; // Write out real coverage (basic block PCs). uint32 cover_size = cov->size; if (flag_dedup_cover) { cover_data_t* end = cover_data + cover_size; cover_unprotect(cov); std::sort(cover_data, end); cover_size = std::unique(cover_data, end) - cover_data; cover_protect(cov); } // Truncate PCs to uint32 assuming that they fit into 32-bits. // True for x86_64 and arm64 without KASLR. for (uint32 i = 0; i < cover_size; i++) write_output(cover_data[i]); *cover_count_pos = cover_size; } #endif void handle_completion(thread_t* th) { if (event_isset(&th->ready) || !event_isset(&th->done) || !th->executing) fail("bad thread state in completion: ready=%d done=%d executing=%d", event_isset(&th->ready), event_isset(&th->done), th->executing); if (th->res != (intptr_t)-1) copyout_call_results(th); if (!collide && !th->colliding) { write_call_output(th, true); if (th->extra_cover) write_extra_output(); } th->executing = false; running--; if (running < 0) fail("running = %d", running); } void copyout_call_results(thread_t* th) { if (th->copyout_index != no_copyout) { if (th->copyout_index >= kMaxCommands) fail("result idx %lld overflows kMaxCommands", th->copyout_index); results[th->copyout_index].executed = true; results[th->copyout_index].val = th->res; } for (bool done = false; !done;) { uint64 instr = read_input(&th->copyout_pos); switch (instr) { case instr_copyout: { uint64 index = read_input(&th->copyout_pos); if (index >= kMaxCommands) fail("result idx %lld overflows kMaxCommands", index); char* addr = (char*)read_input(&th->copyout_pos); uint64 size = read_input(&th->copyout_pos); uint64 val = 0; if (copyout(addr, size, &val)) { results[index].executed = true; results[index].val = val; } debug_verbose("copyout 0x%llx from %p\n", val, addr); break; } default: done = true; break; } } } void write_call_output(thread_t* th, bool finished) { uint32 reserrno = 999; const bool blocked = th != last_scheduled; uint32 call_flags = call_flag_executed | (blocked ? call_flag_blocked : 0); if (finished) { reserrno = th->res != -1 ? 0 : th->reserrno; call_flags |= call_flag_finished | (th->fault_injected ? call_flag_fault_injected : 0); } #if SYZ_EXECUTOR_USES_SHMEM write_output(th->call_index); write_output(th->call_num); write_output(reserrno); write_output(call_flags); uint32* signal_count_pos = write_output(0); // filled in later uint32* cover_count_pos = write_output(0); // filled in later uint32* comps_count_pos = write_output(0); // filled in later if (flag_collect_comps) { // Collect only the comparisons uint32 ncomps = th->cov.size; kcov_comparison_t* start = (kcov_comparison_t*)(th->cov.data + sizeof(uint64)); kcov_comparison_t* end = start + ncomps; if ((char*)end > th->cov.data_end) fail("too many comparisons %u", ncomps); cover_unprotect(&th->cov); std::sort(start, end); ncomps = std::unique(start, end) - start; cover_protect(&th->cov); uint32 comps_size = 0; for (uint32 i = 0; i < ncomps; ++i) { if (start[i].ignore()) continue; comps_size++; start[i].write(); } // Write out number of comparisons. *comps_count_pos = comps_size; } else if (flag_cover) { if (is_kernel_64_bit) write_coverage_signal(&th->cov, signal_count_pos, cover_count_pos); else write_coverage_signal(&th->cov, signal_count_pos, cover_count_pos); } debug_verbose("out #%u: index=%u num=%u errno=%d finished=%d blocked=%d sig=%u cover=%u comps=%u\n", completed, th->call_index, th->call_num, reserrno, finished, blocked, *signal_count_pos, *cover_count_pos, *comps_count_pos); completed++; write_completed(completed); #else call_reply reply; reply.header.magic = kOutMagic; reply.header.done = 0; reply.header.status = 0; reply.call_index = th->call_index; reply.call_num = th->call_num; reply.reserrno = reserrno; reply.flags = call_flags; reply.signal_size = 0; reply.cover_size = 0; reply.comps_size = 0; if (write(kOutPipeFd, &reply, sizeof(reply)) != sizeof(reply)) fail("control pipe call write failed"); debug_verbose("out: index=%u num=%u errno=%d finished=%d blocked=%d\n", th->call_index, th->call_num, reserrno, finished, blocked); #endif } void write_extra_output() { #if SYZ_EXECUTOR_USES_SHMEM if (!flag_cover || !flag_extra_cover || flag_collect_comps) return; cover_collect(&extra_cov); if (!extra_cov.size) return; write_output(-1); // call index write_output(-1); // call num write_output(999); // errno write_output(0); // call flags uint32* signal_count_pos = write_output(0); // filled in later uint32* cover_count_pos = write_output(0); // filled in later write_output(0); // comps_count_pos if (is_kernel_64_bit) write_coverage_signal(&extra_cov, signal_count_pos, cover_count_pos); else write_coverage_signal(&extra_cov, signal_count_pos, cover_count_pos); cover_reset(&extra_cov); debug_verbose("extra: sig=%u cover=%u\n", *signal_count_pos, *cover_count_pos); completed++; write_completed(completed); #endif } void thread_create(thread_t* th, int id) { th->created = true; th->id = id; th->executing = false; event_init(&th->ready); event_init(&th->done); event_set(&th->done); if (flag_threaded) thread_start(worker_thread, th); } void* worker_thread(void* arg) { thread_t* th = (thread_t*)arg; if (flag_cover) cover_enable(&th->cov, flag_collect_comps, false); for (;;) { event_wait(&th->ready); event_reset(&th->ready); execute_call(th); event_set(&th->done); } return 0; } void execute_call(thread_t* th) { const call_t* call = &syscalls[th->call_num]; debug("#%d [%llums] -> %s(", th->id, current_time_ms() - start_time_ms, call->name); for (int i = 0; i < th->num_args; i++) { if (i != 0) debug(", "); debug("0x%llx", (uint64)th->args[i]); } debug(")\n"); int fail_fd = -1; if (flag_inject_fault && th->call_index == flag_fault_call) { if (collide) fail("both collide and fault injection are enabled"); fail_fd = inject_fault(flag_fault_nth); } if (flag_cover) cover_reset(&th->cov); errno = 0; th->res = execute_syscall(call, th->args); th->reserrno = errno; if (th->res == -1 && th->reserrno == 0) th->reserrno = EINVAL; // our syz syscalls may misbehave if (flag_cover) { cover_collect(&th->cov); if (th->cov.size >= kCoverSize) fail("#%d: too much cover %u", th->id, th->cov.size); } th->fault_injected = false; if (flag_inject_fault && th->call_index == flag_fault_call) { th->fault_injected = fault_injected(fail_fd); } debug("#%d [%llums] <- %s=0x%llx errno=%d ", th->id, current_time_ms() - start_time_ms, call->name, (uint64)th->res, th->reserrno); if (flag_cover) debug("cover=%u ", th->cov.size); if (flag_inject_fault && th->call_index == flag_fault_call) debug("fault=%d ", th->fault_injected); debug("\n"); } #if SYZ_EXECUTOR_USES_SHMEM static uint32 hash(uint32 a) { a = (a ^ 61) ^ (a >> 16); a = a + (a << 3); a = a ^ (a >> 4); a = a * 0x27d4eb2d; a = a ^ (a >> 15); return a; } const uint32 dedup_table_size = 8 << 10; uint32 dedup_table[dedup_table_size]; // Poorman's best-effort hashmap-based deduplication. // The hashmap is global which means that we deduplicate across different calls. // This is OK because we are interested only in new signals. static bool dedup(uint32 sig) { for (uint32 i = 0; i < 4; i++) { uint32 pos = (sig + i) % dedup_table_size; if (dedup_table[pos] == sig) return true; if (dedup_table[pos] == 0) { dedup_table[pos] = sig; return false; } } dedup_table[sig % dedup_table_size] = sig; return false; } #endif template void copyin_int(char* addr, uint64 val, uint64 bf, uint64 bf_off, uint64 bf_len) { if (bf_off == 0 && bf_len == 0) { *(T*)addr = swap(val, sizeof(T), bf); return; } T x = swap(*(T*)addr, sizeof(T), bf); x = (x & ~BITMASK(bf_off, bf_len)) | ((val << bf_off) & BITMASK(bf_off, bf_len)); *(T*)addr = swap(x, sizeof(T), bf); } void copyin(char* addr, uint64 val, uint64 size, uint64 bf, uint64 bf_off, uint64 bf_len) { if (bf != binary_format_native && bf != binary_format_bigendian && (bf_off != 0 || bf_len != 0)) fail("bitmask for string format %llu/%llu", bf_off, bf_len); switch (bf) { case binary_format_native: case binary_format_bigendian: NONFAILING(switch (size) { case 1: copyin_int(addr, val, bf, bf_off, bf_len); break; case 2: copyin_int(addr, val, bf, bf_off, bf_len); break; case 4: copyin_int(addr, val, bf, bf_off, bf_len); break; case 8: copyin_int(addr, val, bf, bf_off, bf_len); break; default: fail("copyin: bad argument size %llu", size); }); break; case binary_format_strdec: if (size != 20) fail("bad strdec size %llu", size); NONFAILING(sprintf((char*)addr, "%020llu", val)); break; case binary_format_strhex: if (size != 18) fail("bad strhex size %llu", size); NONFAILING(sprintf((char*)addr, "0x%016llx", val)); break; case binary_format_stroct: if (size != 23) fail("bad stroct size %llu", size); NONFAILING(sprintf((char*)addr, "%023llo", val)); break; default: fail("unknown binary format %llu", bf); } } bool copyout(char* addr, uint64 size, uint64* res) { bool ok = false; NONFAILING( switch (size) { case 1: *res = *(uint8*)addr; break; case 2: *res = *(uint16*)addr; break; case 4: *res = *(uint32*)addr; break; case 8: *res = *(uint64*)addr; break; default: fail("copyout: bad argument size %llu", size); } __atomic_store_n(&ok, true, __ATOMIC_RELEASE);); return ok; } uint64 read_arg(uint64** input_posp) { uint64 typ = read_input(input_posp); switch (typ) { case arg_const: { uint64 size, bf, bf_off, bf_len; uint64 val = read_const_arg(input_posp, &size, &bf, &bf_off, &bf_len); if (bf != binary_format_native && bf != binary_format_bigendian) fail("bad argument binary format %llu", bf); if (bf_off != 0 || bf_len != 0) fail("bad argument bitfield %llu/%llu", bf_off, bf_len); return swap(val, size, bf); } case arg_result: { uint64 meta = read_input(input_posp); uint64 bf = meta >> 8; if (bf != binary_format_native) fail("bad result argument format %llu", bf); return read_result(input_posp); } default: fail("bad argument type %llu", typ); } } uint64 swap(uint64 v, uint64 size, uint64 bf) { if (bf == binary_format_native) return v; if (bf != binary_format_bigendian) fail("bad binary format in swap: %llu", bf); switch (size) { case 2: return htobe16(v); case 4: return htobe32(v); case 8: return htobe64(v); default: fail("bad big-endian int size %llu", size); } } uint64 read_const_arg(uint64** input_posp, uint64* size_p, uint64* bf_p, uint64* bf_off_p, uint64* bf_len_p) { uint64 meta = read_input(input_posp); uint64 val = read_input(input_posp); *size_p = meta & 0xff; uint64 bf = (meta >> 8) & 0xff; *bf_off_p = (meta >> 16) & 0xff; *bf_len_p = (meta >> 24) & 0xff; uint64 pid_stride = meta >> 32; val += pid_stride * procid; *bf_p = bf; return val; } uint64 read_result(uint64** input_posp) { uint64 idx = read_input(input_posp); uint64 op_div = read_input(input_posp); uint64 op_add = read_input(input_posp); uint64 arg = read_input(input_posp); if (idx >= kMaxCommands) fail("command refers to bad result %lld", idx); if (results[idx].executed) { arg = results[idx].val; if (op_div != 0) arg = arg / op_div; arg += op_add; } return arg; } uint64 read_input(uint64** input_posp, bool peek) { uint64* input_pos = *input_posp; if ((char*)input_pos >= input_data + kMaxInput) fail("input command overflows input %p: [%p:%p)", input_pos, input_data, input_data + kMaxInput); if (!peek) *input_posp = input_pos + 1; return *input_pos; } #if SYZ_EXECUTOR_USES_SHMEM uint32* write_output(uint32 v) { if (output_pos < output_data || (char*)output_pos >= (char*)output_data + kMaxOutput) fail("output overflow: pos=%p region=[%p:%p]", output_pos, output_data, (char*)output_data + kMaxOutput); *output_pos = v; return output_pos++; } void write_completed(uint32 completed) { __atomic_store_n(output_data, completed, __ATOMIC_RELEASE); } #endif #if SYZ_EXECUTOR_USES_SHMEM void kcov_comparison_t::write() { // Write order: type arg1 arg2 pc. write_output((uint32)type); // KCOV converts all arguments of size x first to uintx_t and then to // uint64. We want to properly extend signed values, e.g we want // int8 c = 0xfe to be represented as 0xfffffffffffffffe. // Note that uint8 c = 0xfe will be represented the same way. // This is ok because during hints processing we will anyways try // the value 0x00000000000000fe. switch (type & KCOV_CMP_SIZE_MASK) { case KCOV_CMP_SIZE1: arg1 = (uint64)(long long)(signed char)arg1; arg2 = (uint64)(long long)(signed char)arg2; break; case KCOV_CMP_SIZE2: arg1 = (uint64)(long long)(short)arg1; arg2 = (uint64)(long long)(short)arg2; break; case KCOV_CMP_SIZE4: arg1 = (uint64)(long long)(int)arg1; arg2 = (uint64)(long long)(int)arg2; break; } bool is_size_8 = (type & KCOV_CMP_SIZE_MASK) == KCOV_CMP_SIZE8; if (!is_size_8) { write_output((uint32)arg1); write_output((uint32)arg2); return; } // If we have 64 bits arguments then write them in Little-endian. write_output((uint32)(arg1 & 0xFFFFFFFF)); write_output((uint32)(arg1 >> 32)); write_output((uint32)(arg2 & 0xFFFFFFFF)); write_output((uint32)(arg2 >> 32)); } bool kcov_comparison_t::ignore() const { // Comparisons with 0 are not interesting, fuzzer should be able to guess 0's without help. if (arg1 == 0 && (arg2 == 0 || (type & KCOV_CMP_CONST))) return true; if ((type & KCOV_CMP_SIZE_MASK) == KCOV_CMP_SIZE8) { // This can be a pointer (assuming 64-bit kernel). // First of all, we want avert fuzzer from our output region. // Without this fuzzer manages to discover and corrupt it. uint64 out_start = (uint64)output_data; uint64 out_end = out_start + kMaxOutput; if (arg1 >= out_start && arg1 <= out_end) return true; if (arg2 >= out_start && arg2 <= out_end) return true; #if defined(GOOS_linux) // Filter out kernel physical memory addresses. // These are internal kernel comparisons and should not be interesting. // The range covers first 1TB of physical mapping. uint64 kmem_start = (uint64)0xffff880000000000ull; uint64 kmem_end = (uint64)0xffff890000000000ull; bool kptr1 = arg1 >= kmem_start && arg1 <= kmem_end; bool kptr2 = arg2 >= kmem_start && arg2 <= kmem_end; if (kptr1 && kptr2) return true; if (kptr1 && arg2 == 0) return true; if (kptr2 && arg1 == 0) return true; #endif } return false; } bool kcov_comparison_t::operator==(const struct kcov_comparison_t& other) const { // We don't check for PC equality now, because it is not used. return type == other.type && arg1 == other.arg1 && arg2 == other.arg2; } bool kcov_comparison_t::operator<(const struct kcov_comparison_t& other) const { if (type != other.type) return type < other.type; if (arg1 != other.arg1) return arg1 < other.arg1; // We don't check for PC equality now, because it is not used. return arg2 < other.arg2; } #endif void setup_features(char** enable, int n) { // This does any one-time setup for the requested features on the machine. // Note: this can be called multiple times and must be idempotent. for (int i = 0; i < n; i++) { bool found = false; #if SYZ_HAVE_FEATURES for (unsigned f = 0; f < sizeof(features) / sizeof(features[0]); f++) { if (strcmp(enable[i], features[f].name) == 0) { features[f].setup(); found = true; break; } } #endif if (!found) fail("unknown feature %s", enable[i]); } } 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(kFailStatus); } 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(0); } void debug(const char* msg, ...) { if (!flag_debug) return; va_list args; va_start(args, msg); vfprintf(stderr, msg, args); va_end(args); fflush(stderr); } void debug_dump_data(const char* data, int length) { if (!flag_debug) return; int i; for (i = 0; i < length; i++) { debug("%02x ", data[i] & 0xff); if (i % 16 == 15) debug("\n"); } if (i % 16 != 0) debug("\n"); } /usr/local/bin/ld: cannot find -lasan collect2: error: ld returned 1 exit status compiler invocation: gcc [-o /tmp/syz-executor820163808 -DGOOS_test=1 -DGOARCH_64=1 -DHOSTGOOS_freebsd=1 ../../executor/executor.cc -O2 -pthread -Wall -Werror -Wparentheses -Wunused-const-variable -Wframe-larger-than=8192 -m64 -fsanitize=address] FAIL FAIL github.com/google/syzkaller/pkg/runtest 2.846s ok github.com/google/syzkaller/pkg/serializer (cached) ? github.com/google/syzkaller/pkg/signal [no test files] ok github.com/google/syzkaller/pkg/symbolizer 0.275s ok github.com/google/syzkaller/pkg/vcs 7.729s ok github.com/google/syzkaller/prog 13.864s ok github.com/google/syzkaller/prog/test 0.790s ? github.com/google/syzkaller/sys [no test files] ? github.com/google/syzkaller/sys/akaros [no test files] ? github.com/google/syzkaller/sys/akaros/gen [no test files] ? github.com/google/syzkaller/sys/freebsd [no test files] ? github.com/google/syzkaller/sys/freebsd/gen [no test files] ? github.com/google/syzkaller/sys/fuchsia [no test files] ? github.com/google/syzkaller/sys/fuchsia/fidlgen [no test files] ? github.com/google/syzkaller/sys/fuchsia/gen [no test files] ? github.com/google/syzkaller/sys/fuchsia/layout [no test files] ok github.com/google/syzkaller/sys/linux 0.061s ? github.com/google/syzkaller/sys/linux/gen [no test files] ? github.com/google/syzkaller/sys/netbsd [no test files] ? github.com/google/syzkaller/sys/netbsd/gen [no test files] ok github.com/google/syzkaller/sys/openbsd 0.039s ? github.com/google/syzkaller/sys/openbsd/gen [no test files] ? github.com/google/syzkaller/sys/syz-extract [no test files] ? github.com/google/syzkaller/sys/syz-sysgen [no test files] ? github.com/google/syzkaller/sys/targets [no test files] ? github.com/google/syzkaller/sys/test [no test files] ? github.com/google/syzkaller/sys/test/gen [no test files] ? github.com/google/syzkaller/sys/trusty [no test files] ? github.com/google/syzkaller/sys/trusty/gen [no test files] ? github.com/google/syzkaller/sys/windows [no test files] ? github.com/google/syzkaller/sys/windows/gen [no test files] ok github.com/google/syzkaller/syz-ci 0.275s ? github.com/google/syzkaller/syz-fuzzer [no test files] ok github.com/google/syzkaller/syz-hub 0.045s ok github.com/google/syzkaller/syz-hub/state (cached) ? github.com/google/syzkaller/syz-manager [no test files] ? github.com/google/syzkaller/tools/syz-benchcmp [no test files] ? github.com/google/syzkaller/tools/syz-bisect [no test files] ? github.com/google/syzkaller/tools/syz-cover [no test files] ? github.com/google/syzkaller/tools/syz-crush [no test files] ? github.com/google/syzkaller/tools/syz-db [no test files] ? github.com/google/syzkaller/tools/syz-env [no test files] ? github.com/google/syzkaller/tools/syz-execprog [no test files] ? github.com/google/syzkaller/tools/syz-fmt [no test files] ? github.com/google/syzkaller/tools/syz-imagegen [no test files] ? github.com/google/syzkaller/tools/syz-mutate [no test files] ? github.com/google/syzkaller/tools/syz-prog2c [no test files] ? github.com/google/syzkaller/tools/syz-repro [no test files] ? github.com/google/syzkaller/tools/syz-runtest [no test files] ? github.com/google/syzkaller/tools/syz-stress [no test files] ? github.com/google/syzkaller/tools/syz-symbolize [no test files] ? github.com/google/syzkaller/tools/syz-testbuild [no test files] ? github.com/google/syzkaller/tools/syz-trace2syz [no test files] ok github.com/google/syzkaller/tools/syz-trace2syz/parser 0.021s ok github.com/google/syzkaller/tools/syz-trace2syz/proggen 0.168s ? github.com/google/syzkaller/tools/syz-tty [no test files] ? github.com/google/syzkaller/tools/syz-upgrade [no test files] ? github.com/google/syzkaller/tools/syz-usbgen [no test files] ok github.com/google/syzkaller/vm 8.532s ? github.com/google/syzkaller/vm/adb [no test files] ? github.com/google/syzkaller/vm/bhyve [no test files] ? github.com/google/syzkaller/vm/gce [no test files] ? github.com/google/syzkaller/vm/gvisor [no test files] ? github.com/google/syzkaller/vm/isolated [no test files] ? github.com/google/syzkaller/vm/kvm [no test files] ? github.com/google/syzkaller/vm/odroid [no test files] ? github.com/google/syzkaller/vm/qemu [no test files] ok github.com/google/syzkaller/vm/vmimpl (cached) ? github.com/google/syzkaller/vm/vmm [no test files]