diff options
| author | Dmitry Vyukov <dvyukov@google.com> | 2017-09-22 11:09:53 +0200 |
|---|---|---|
| committer | Dmitry Vyukov <dvyukov@google.com> | 2017-09-22 13:10:55 +0200 |
| commit | 913d592f973a0155647473eaa032711fe956f8a5 (patch) | |
| tree | 29b1b2083c00d199cf4d9a30917411d923b49ef4 /pkg | |
| parent | c26ea367cfa790e86800ac025638ad50f95b8287 (diff) | |
all: more assorted fuchsia support
Diffstat (limited to 'pkg')
| -rw-r--r-- | pkg/compiler/compiler.go | 7 | ||||
| -rw-r--r-- | pkg/compiler/compiler_test.go | 9 | ||||
| -rw-r--r-- | pkg/compiler/consts.go | 5 | ||||
| -rw-r--r-- | pkg/csource/common.go | 295 | ||||
| -rw-r--r-- | pkg/csource/csource.go | 2 | ||||
| -rw-r--r-- | pkg/csource/csource_test.go | 4 | ||||
| -rw-r--r-- | pkg/ipc/ipc.go | 8 | ||||
| -rw-r--r-- | pkg/ipc/ipc_fuchsia.go | 82 | ||||
| -rw-r--r-- | pkg/ipc/ipc_linux.go | 19 | ||||
| -rw-r--r-- | pkg/osutil/osutil.go | 20 | ||||
| -rw-r--r-- | pkg/osutil/osutil_fuchsia.go | 17 | ||||
| -rw-r--r-- | pkg/osutil/osutil_unix.go | 20 |
12 files changed, 298 insertions, 190 deletions
diff --git a/pkg/compiler/compiler.go b/pkg/compiler/compiler.go index d54ac4678..d250eda68 100644 --- a/pkg/compiler/compiler.go +++ b/pkg/compiler/compiler.go @@ -13,6 +13,7 @@ import ( "github.com/google/syzkaller/pkg/ast" "github.com/google/syzkaller/prog" + "github.com/google/syzkaller/sys/targets" ) // Overview of compilation process: @@ -41,14 +42,15 @@ type Prog struct { } // Compile compiles sys description. -func Compile(desc *ast.Description, consts map[string]uint64, ptrSize uint64, eh ast.ErrorHandler) *Prog { +func Compile(desc *ast.Description, consts map[string]uint64, target *targets.Target, eh ast.ErrorHandler) *Prog { if eh == nil { eh = ast.LoggingHandler } comp := &compiler{ desc: ast.Clone(desc), + target: target, eh: eh, - ptrSize: ptrSize, + ptrSize: target.PtrSize, unsupported: make(map[string]bool), resources: make(map[string]*ast.Resource), structs: make(map[string]*ast.Struct), @@ -79,6 +81,7 @@ func Compile(desc *ast.Description, consts map[string]uint64, ptrSize uint64, eh type compiler struct { desc *ast.Description + target *targets.Target eh ast.ErrorHandler errors int warnings []warn diff --git a/pkg/compiler/compiler_test.go b/pkg/compiler/compiler_test.go index d82dd4775..be803bae9 100644 --- a/pkg/compiler/compiler_test.go +++ b/pkg/compiler/compiler_test.go @@ -9,6 +9,7 @@ import ( "testing" "github.com/google/syzkaller/pkg/ast" + "github.com/google/syzkaller/sys/targets" ) func TestCompileAll(t *testing.T) { @@ -24,7 +25,7 @@ func TestCompileAll(t *testing.T) { if consts == nil { t.Fatalf("reading consts failed") } - prog := Compile(desc, consts, 8, eh) + prog := Compile(desc, consts, targets.List["linux"]["amd64"], eh) if prog == nil { t.Fatalf("compilation failed") } @@ -47,7 +48,7 @@ func TestErrors(t *testing.T) { t.Fatalf("parsing failed") } ExtractConsts(desc, em.ErrorHandler) - Compile(desc, consts, 8, em.ErrorHandler) + Compile(desc, consts, targets.List["linux"]["amd64"], em.ErrorHandler) em.Check(t) }) } @@ -67,7 +68,7 @@ func TestFuzz(t *testing.T) { for _, data := range inputs { desc := ast.Parse([]byte(data), "", eh) if desc != nil { - Compile(desc, consts, 8, eh) + Compile(desc, consts, targets.List["linux"]["amd64"], eh) } } } @@ -94,7 +95,7 @@ s2 { if desc == nil { t.Fatal("failed to parse") } - p := Compile(desc, map[string]uint64{"__NR_foo": 1}, 8, nil) + p := Compile(desc, map[string]uint64{"__NR_foo": 1}, targets.List["linux"]["amd64"], nil) if p == nil { t.Fatal("failed to compile") } diff --git a/pkg/compiler/consts.go b/pkg/compiler/consts.go index f64f4ed7f..4cb68e773 100644 --- a/pkg/compiler/consts.go +++ b/pkg/compiler/consts.go @@ -14,6 +14,7 @@ import ( "strings" "github.com/google/syzkaller/pkg/ast" + "github.com/google/syzkaller/sys/targets" ) type ConstInfo struct { @@ -125,6 +126,10 @@ func (comp *compiler) assignSyscallNumbers(consts map[string]uint64) { top = append(top, decl) continue } + if !targets.OSList[comp.target.OS].SyscallNumbers { + top = append(top, decl) + continue + } // Lookup in consts. str := "__NR_" + c.CallName nr, ok := consts[str] diff --git a/pkg/csource/common.go b/pkg/csource/common.go index fc5fd8782..588a0cd45 100644 --- a/pkg/csource/common.go +++ b/pkg/csource/common.go @@ -1,4 +1,4 @@ -// AUTOGENERATED FROM executor/common.h +// AUTOGENERATED FROM executor/common_linux.h package csource var commonHeader = ` @@ -8,35 +8,10 @@ var commonHeader = ` #define _GNU_SOURCE #endif -#include <stdint.h> -#include <string.h> #include <sys/syscall.h> #include <unistd.h> -#if defined(SYZ_EXECUTOR) || defined(SYZ_THREADED) || defined(SYZ_COLLIDE) -#include <pthread.h> -#include <stdlib.h> -#endif -#if defined(SYZ_EXECUTOR) || defined(SYZ_HANDLE_SEGV) -#include <setjmp.h> -#include <signal.h> -#include <string.h> -#endif -#if defined(SYZ_EXECUTOR) || defined(SYZ_USE_TMP_DIR) -#include <errno.h> -#include <stdarg.h> -#include <stdio.h> -#include <stdlib.h> -#include <sys/stat.h> -#endif #if defined(SYZ_EXECUTOR) || (defined(SYZ_REPEAT) && defined(SYZ_WAIT_REPEAT)) -#include <errno.h> -#include <signal.h> -#include <stdarg.h> -#include <stdio.h> #include <sys/prctl.h> -#include <sys/time.h> -#include <sys/wait.h> -#include <time.h> #endif #if defined(SYZ_EXECUTOR) || (defined(SYZ_REPEAT) && defined(SYZ_WAIT_REPEAT) && defined(SYZ_USE_TMP_DIR)) #include <dirent.h> @@ -89,28 +64,24 @@ var commonHeader = ` #include <stdio.h> #include <sys/stat.h> #endif -#if defined(SYZ_EXECUTOR) || defined(SYZ_DEBUG) -#include <stdarg.h> -#include <stdio.h> -#endif -#ifdef __NR_syz_open_dev +#if defined(SYZ_EXECUTOR) || defined(__NR_syz_open_dev) #include <fcntl.h> #include <stdio.h> #include <sys/stat.h> #endif -#if defined(__NR_syz_fuse_mount) || defined(__NR_syz_fuseblk_mount) +#if defined(SYZ_EXECUTOR) || defined(__NR_syz_fuse_mount) || defined(__NR_syz_fuseblk_mount) #include <fcntl.h> #include <stdio.h> #include <sys/stat.h> #include <sys/sysmacros.h> #endif -#ifdef __NR_syz_open_pts +#if defined(SYZ_EXECUTOR) || defined(__NR_syz_open_pts) #include <fcntl.h> #include <stdio.h> #include <sys/ioctl.h> #include <sys/stat.h> #endif -#ifdef __NR_syz_kvm_setup_cpu +#if defined(SYZ_EXECUTOR) || defined(__NR_syz_kvm_setup_cpu) #include <errno.h> #include <fcntl.h> #include <linux/kvm.h> @@ -121,21 +92,10 @@ var commonHeader = ` #include <sys/stat.h> #endif -#if defined(SYZ_EXECUTOR) || (defined(SYZ_REPEAT) && defined(SYZ_WAIT_REPEAT)) || defined(SYZ_USE_TMP_DIR) || \ - defined(SYZ_TUN_ENABLE) || defined(SYZ_SANDBOX_NAMESPACE) || defined(SYZ_SANDBOX_SETUID) || \ - defined(SYZ_FAULT_INJECTION) || defined(__NR_syz_kvm_setup_cpu) -const int kFailStatus = 67; -const int kRetryStatus = 69; -#endif - -#if defined(SYZ_EXECUTOR) -const int kErrorStatus = 68; -#endif - -#if defined(SYZ_EXECUTOR) || (defined(SYZ_REPEAT) && defined(SYZ_WAIT_REPEAT)) || defined(SYZ_USE_TMP_DIR) || \ - defined(SYZ_HANDLE_SEGV) || defined(SYZ_TUN_ENABLE) || defined(SYZ_SANDBOX_NAMESPACE) || \ - defined(SYZ_SANDBOX_SETUID) || defined(SYZ_SANDBOX_NONE) || defined(SYZ_FAULT_INJECTION) || \ - defined(__NR_syz_kvm_setup_cpu) +#if defined(SYZ_EXECUTOR) || (defined(SYZ_REPEAT) && defined(SYZ_WAIT_REPEAT)) || \ + defined(SYZ_USE_TMP_DIR) || defined(SYZ_HANDLE_SEGV) || defined(SYZ_TUN_ENABLE) || \ + defined(SYZ_SANDBOX_NAMESPACE) || defined(SYZ_SANDBOX_SETUID) || \ + defined(SYZ_SANDBOX_NONE) || defined(SYZ_FAULT_INJECTION) || defined(__NR_syz_kvm_setup_cpu) __attribute__((noreturn)) static void doexit(int status) { volatile unsigned i; @@ -150,9 +110,67 @@ __attribute__((noreturn)) static void doexit(int status) #define _exit use_doexit_instead #endif -#if defined(SYZ_EXECUTOR) || (defined(SYZ_REPEAT) && defined(SYZ_WAIT_REPEAT)) || defined(SYZ_USE_TMP_DIR) || \ - defined(SYZ_TUN_ENABLE) || defined(SYZ_SANDBOX_NAMESPACE) || defined(SYZ_SANDBOX_SETUID) || \ - defined(SYZ_FAULT_INJECTION) || defined(__NR_syz_kvm_setup_cpu) + + +#include <stdint.h> +#include <string.h> +#if defined(SYZ_EXECUTOR) || defined(SYZ_THREADED) || defined(SYZ_COLLIDE) +#include <pthread.h> +#include <stdlib.h> +#endif +#if defined(SYZ_EXECUTOR) || defined(SYZ_USE_TMP_DIR) +#include <errno.h> +#include <stdarg.h> +#include <stdio.h> +#include <stdlib.h> +#include <sys/stat.h> +#endif +#if defined(SYZ_EXECUTOR) || defined(SYZ_HANDLE_SEGV) +#include <setjmp.h> +#include <signal.h> +#include <string.h> +#endif +#if defined(SYZ_EXECUTOR) || (defined(SYZ_REPEAT) && defined(SYZ_WAIT_REPEAT)) +#include <errno.h> +#include <signal.h> +#include <stdarg.h> +#include <stdio.h> +#include <sys/time.h> +#include <sys/wait.h> +#include <time.h> +#endif +#if defined(SYZ_EXECUTOR) || defined(SYZ_DEBUG) +#include <stdarg.h> +#include <stdio.h> +#endif + +#if defined(SYZ_EXECUTOR) +typedef long (*syscall_t)(long, long, long, long, long, long, long, long, long); + +struct call_t { + const char* name; + int sys_nr; + syscall_t call; +}; + +extern call_t syscalls[]; +extern unsigned syscall_count; +#endif + +#if defined(SYZ_EXECUTOR) || (defined(SYZ_REPEAT) && defined(SYZ_WAIT_REPEAT)) || \ + defined(SYZ_USE_TMP_DIR) || defined(SYZ_TUN_ENABLE) || defined(SYZ_SANDBOX_NAMESPACE) || \ + defined(SYZ_SANDBOX_SETUID) || defined(SYZ_FAULT_INJECTION) || defined(__NR_syz_kvm_setup_cpu) +const int kFailStatus = 67; +const int kRetryStatus = 69; +#endif + +#if defined(SYZ_EXECUTOR) +const int kErrorStatus = 68; +#endif + +#if defined(SYZ_EXECUTOR) || (defined(SYZ_REPEAT) && defined(SYZ_WAIT_REPEAT)) || \ + defined(SYZ_USE_TMP_DIR) || defined(SYZ_TUN_ENABLE) || defined(SYZ_SANDBOX_NAMESPACE) || \ + defined(SYZ_SANDBOX_SETUID) || defined(SYZ_FAULT_INJECTION) || defined(__NR_syz_kvm_setup_cpu) __attribute__((noreturn)) static void fail(const char* msg, ...) { int e = errno; @@ -243,6 +261,60 @@ static void segv_handler(int sig, siginfo_t* info, void* uctx) } } +#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); \ + } +#endif + +#if defined(SYZ_EXECUTOR) || defined(SYZ_USE_CHECKSUMS) +struct csum_inet { + uint32_t acc; +}; + +static void csum_inet_init(struct csum_inet* csum) +{ + csum->acc = 0; +} + +static void csum_inet_update(struct csum_inet* csum, const uint8_t* data, size_t length) +{ + if (length == 0) + return; + + size_t i; + for (i = 0; i < length - 1; i += 2) + csum->acc += *(uint16_t*)&data[i]; + + if (length & 1) + csum->acc += (uint16_t)data[length - 1]; + + while (csum->acc > 0xffff) + csum->acc = (csum->acc & 0xffff) + (csum->acc >> 16); +} + +static uint16_t csum_inet_digest(struct csum_inet* csum) +{ + return ~csum->acc; +} +#endif + +#if defined(SYZ_EXECUTOR) || (defined(SYZ_REPEAT) && defined(SYZ_WAIT_REPEAT)) +static uint64_t current_time_ms() +{ + struct timespec ts; + + if (clock_gettime(CLOCK_MONOTONIC, &ts)) + fail("clock_gettime failed"); + return (uint64_t)ts.tv_sec * 1000 + (uint64_t)ts.tv_nsec / 1000000; +} +#endif + +#if defined(SYZ_EXECUTOR) || defined(SYZ_HANDLE_SEGV) static void install_segv_handler() { struct sigaction sa; @@ -258,15 +330,6 @@ static void install_segv_handler() 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); \ - } #endif #if defined(SYZ_EXECUTOR) || defined(SYZ_USE_TMP_DIR) @@ -419,38 +482,6 @@ static void debug_dump_data(const char* data, int length) } #endif -#if defined(SYZ_EXECUTOR) || defined(SYZ_USE_CHECKSUMS) -struct csum_inet { - uint32_t acc; -}; - -static void csum_inet_init(struct csum_inet* csum) -{ - csum->acc = 0; -} - -static void csum_inet_update(struct csum_inet* csum, const uint8_t* data, size_t length) -{ - if (length == 0) - return; - - size_t i; - for (i = 0; i < length - 1; i += 2) - csum->acc += *(uint16_t*)&data[i]; - - if (length & 1) - csum->acc += (uint16_t)data[length - 1]; - - while (csum->acc > 0xffff) - csum->acc = (csum->acc & 0xffff) + (csum->acc >> 16); -} - -static uint16_t csum_inet_digest(struct csum_inet* csum) -{ - return ~csum->acc; -} -#endif - #if defined(SYZ_EXECUTOR) || (defined(__NR_syz_emit_ethernet) && defined(SYZ_TUN_ENABLE)) static uintptr_t syz_emit_ethernet(uintptr_t a0, uintptr_t a1) { @@ -545,7 +576,7 @@ static uintptr_t syz_extract_tcp_res(uintptr_t a0, uintptr_t a1, uintptr_t a2) } #endif -#ifdef __NR_syz_open_dev +#if defined(SYZ_EXECUTOR) || defined(__NR_syz_open_dev) static uintptr_t syz_open_dev(uintptr_t a0, uintptr_t a1, uintptr_t a2) { if (a0 == 0xc || a0 == 0xb) { @@ -566,7 +597,7 @@ static uintptr_t syz_open_dev(uintptr_t a0, uintptr_t a1, uintptr_t a2) } #endif -#ifdef __NR_syz_open_pts +#if defined(SYZ_EXECUTOR) || defined(__NR_syz_open_pts) static uintptr_t syz_open_pts(uintptr_t a0, uintptr_t a1) { int ptyno = 0; @@ -578,7 +609,7 @@ static uintptr_t syz_open_pts(uintptr_t a0, uintptr_t a1) } #endif -#ifdef __NR_syz_fuse_mount +#if defined(SYZ_EXECUTOR) || defined(__NR_syz_fuse_mount) static uintptr_t syz_fuse_mount(uintptr_t a0, uintptr_t a1, uintptr_t a2, uintptr_t a3, uintptr_t a4, uintptr_t a5) { uint64_t target = a0; @@ -604,7 +635,7 @@ static uintptr_t syz_fuse_mount(uintptr_t a0, uintptr_t a1, uintptr_t a2, uintpt } #endif -#ifdef __NR_syz_fuseblk_mount +#if defined(SYZ_EXECUTOR) || defined(__NR_syz_fuseblk_mount) static uintptr_t syz_fuseblk_mount(uintptr_t a0, uintptr_t a1, uintptr_t a2, uintptr_t a3, uintptr_t a4, uintptr_t a5, uintptr_t a6, uintptr_t a7) { uint64_t target = a0; @@ -636,7 +667,7 @@ static uintptr_t syz_fuseblk_mount(uintptr_t a0, uintptr_t a1, uintptr_t a2, uin } #endif -#ifdef __NR_syz_kvm_setup_cpu +#if defined(SYZ_EXECUTOR) || defined(__NR_syz_kvm_setup_cpu) #if defined(__x86_64__) @@ -1600,45 +1631,10 @@ static uintptr_t syz_kvm_setup_cpu(uintptr_t a0, uintptr_t a1, uintptr_t a2, uin #endif #endif -#ifdef SYZ_EXECUTOR -static uintptr_t execute_syscall(int nr, uintptr_t a0, uintptr_t a1, uintptr_t a2, uintptr_t a3, uintptr_t a4, uintptr_t a5, uintptr_t a6, uintptr_t a7, uintptr_t a8) +#if defined(SYZ_EXECUTOR) +static uintptr_t syz_test() { - switch (nr) { - default: - return syscall(nr, a0, a1, a2, a3, a4, a5); -#ifdef __NR_syz_test - case __NR_syz_test: - return 0; -#endif -#ifdef __NR_syz_open_dev - case __NR_syz_open_dev: - return syz_open_dev(a0, a1, a2); -#endif -#ifdef __NR_syz_open_pts - case __NR_syz_open_pts: - return syz_open_pts(a0, a1); -#endif -#ifdef __NR_syz_fuse_mount - case __NR_syz_fuse_mount: - return syz_fuse_mount(a0, a1, a2, a3, a4, a5); -#endif -#ifdef __NR_syz_fuseblk_mount - case __NR_syz_fuseblk_mount: - return syz_fuseblk_mount(a0, a1, a2, a3, a4, a5, a6, a7); -#endif -#ifdef __NR_syz_emit_ethernet - case __NR_syz_emit_ethernet: - return syz_emit_ethernet(a0, a1); -#endif -#ifdef __NR_syz_extract_tcp_res - case __NR_syz_extract_tcp_res: - return syz_extract_tcp_res(a0, a1, a2); -#endif -#ifdef __NR_syz_kvm_setup_cpu - case __NR_syz_kvm_setup_cpu: - return syz_kvm_setup_cpu(a0, a1, a2, a3, a4, a5, a6, a7); -#endif - } + return 0; } #endif @@ -1887,17 +1883,6 @@ retry: } #endif -#if defined(SYZ_EXECUTOR) || (defined(SYZ_REPEAT) && defined(SYZ_WAIT_REPEAT)) -static uint64_t current_time_ms() -{ - struct timespec ts; - - if (clock_gettime(CLOCK_MONOTONIC, &ts)) - fail("clock_gettime failed"); - return (uint64_t)ts.tv_sec * 1000 + (uint64_t)ts.tv_nsec / 1000000; -} -#endif - #if defined(SYZ_EXECUTOR) || defined(SYZ_FAULT_INJECTION) static int inject_fault(int nth) { @@ -1915,6 +1900,22 @@ static int inject_fault(int nth) } #endif +#if defined(SYZ_EXECUTOR) +static int fault_injected(int fail_fd) +{ + char buf[16]; + int n = read(fail_fd, buf, sizeof(buf) - 1); + if (n <= 0) + fail("failed to read /proc/self/task/tid/fail-nth"); + int res = n == 2 && buf[0] == '0' && buf[1] == '\n'; + buf[0] = '0'; + if (write(fail_fd, buf, 1) != 1) + fail("failed to write /proc/self/task/tid/fail-nth"); + close(fail_fd); + return res; +} +#endif + #if defined(SYZ_REPEAT) static void test(); diff --git a/pkg/csource/csource.go b/pkg/csource/csource.go index 7ead83deb..1bd818962 100644 --- a/pkg/csource/csource.go +++ b/pkg/csource/csource.go @@ -2,7 +2,7 @@ // Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file. // I heard you like shell... -//go:generate bash -c "echo -e '// AUTOGENERATED FROM executor/common.h\npackage csource\nvar commonHeader = `' > common.go; cat ../../executor/common.h | sed -e '/#include \"common_kvm_amd64.h\"/ {' -e 'r ../../executor/common_kvm_amd64.h' -e 'd' -e '}' - | sed -e '/#include \"common_kvm_arm64.h\"/ {' -e 'r ../../executor/common_kvm_arm64.h' -e 'd' -e '}' - | sed -e '/#include \"kvm.h\"/ {' -e 'r ../../executor/kvm.h' -e 'd' -e '}' - | sed -e '/#include \"kvm.S.h\"/ {' -e 'r ../../executor/kvm.S.h' -e 'd' -e '}' - | egrep -v '^[ ]*//' | sed '/^[ ]*\\/\\/.*/d' | sed 's#[ ]*//.*##g' >> common.go; echo '`' >> common.go" +//go:generate bash -c "echo -e '// AUTOGENERATED FROM executor/common_linux.h\npackage csource\nvar commonHeader = `' > common.go; cat ../../executor/common_linux.h | sed -e '/#include \"common.h\"/ {' -e 'r ../../executor/common.h' -e 'd' -e '}' - | sed -e '/#include \"common_kvm_amd64.h\"/ {' -e 'r ../../executor/common_kvm_amd64.h' -e 'd' -e '}' - | sed -e '/#include \"common_kvm_arm64.h\"/ {' -e 'r ../../executor/common_kvm_arm64.h' -e 'd' -e '}' - | sed -e '/#include \"kvm.h\"/ {' -e 'r ../../executor/kvm.h' -e 'd' -e '}' - | sed -e '/#include \"kvm.S.h\"/ {' -e 'r ../../executor/kvm.S.h' -e 'd' -e '}' - | egrep -v '^[ ]*//' | sed '/^[ ]*\\/\\/.*/d' | sed 's#[ ]*//.*##g' >> common.go; echo '`' >> common.go" //go:generate go fmt common.go package csource diff --git a/pkg/csource/csource_test.go b/pkg/csource/csource_test.go index 2ac048da2..be3c4b4c4 100644 --- a/pkg/csource/csource_test.go +++ b/pkg/csource/csource_test.go @@ -100,6 +100,10 @@ func TestOne(t *testing.T) { UseTmpDir: true, } for _, target := range prog.AllTargets() { + if target.OS == "fuchsia" { + // TODO(dvyukov): support fuchsia + continue + } target := target t.Run(target.OS+"/"+target.Arch, func(t *testing.T) { if target.OS == "linux" && target.Arch == "arm" { diff --git a/pkg/ipc/ipc.go b/pkg/ipc/ipc.go index a7e79b033..bae83806c 100644 --- a/pkg/ipc/ipc.go +++ b/pkg/ipc/ipc.go @@ -31,6 +31,14 @@ const ( FlagCollectComps // collect KCOV comparisons ) +const ( + outputSize = 16 << 20 + + statusFail = 67 + statusError = 68 + statusRetry = 69 +) + var ( flagThreaded = flag.Bool("threaded", true, "use threaded mode in executor") flagCollide = flag.Bool("collide", true, "collide syscalls to provoke data races") diff --git a/pkg/ipc/ipc_fuchsia.go b/pkg/ipc/ipc_fuchsia.go index a95a47f85..7f576b1c2 100644 --- a/pkg/ipc/ipc_fuchsia.go +++ b/pkg/ipc/ipc_fuchsia.go @@ -6,18 +6,54 @@ package ipc import ( + "bytes" + "encoding/binary" + "fmt" + "io/ioutil" + "os" + "os/exec" + "path/filepath" + "strings" + "time" + + "github.com/google/syzkaller/pkg/osutil" "github.com/google/syzkaller/prog" ) type Env struct { - In []byte + bin []string + pid int + config Config StatExecs uint64 StatRestarts uint64 } func MakeEnv(bin string, pid int, config Config) (*Env, error) { - env := &Env{} + if config.Timeout < 7*time.Second { + config.Timeout = 7 * time.Second + } + env := &Env{ + bin: strings.Split(bin, " "), + pid: pid, + config: config, + } + if len(env.bin) == 0 { + return nil, fmt.Errorf("binary is empty string") + } + if false { + env.bin[0] = osutil.Abs(env.bin[0]) + base := filepath.Base(env.bin[0]) + pidStr := fmt.Sprint(pid) + if len(base)+len(pidStr) >= 16 { + // TASK_COMM_LEN is currently set to 16 + base = base[:15-len(pidStr)] + } + binCopy := filepath.Join(filepath.Dir(env.bin[0]), base+pidStr) + if err := os.Link(env.bin[0], binCopy); err == nil { + env.bin[0] = binCopy + } + } return env, nil } @@ -26,5 +62,47 @@ func (env *Env) Close() error { } func (env *Env) Exec(opts *ExecOpts, p *prog.Prog) (output []byte, info []CallInfo, failed, hanged bool, err0 error) { + dir, err := ioutil.TempDir("./", "syzkaller-testdir") + if err != nil { + err0 = fmt.Errorf("failed to create temp dir: %v", err) + return + } + defer os.RemoveAll(dir) + + data := make([]byte, prog.ExecBufferSize) + if err := p.SerializeForExec(data, env.pid); err != nil { + err0 = err + return + } + inbuf := new(bytes.Buffer) + binary.Write(inbuf, binary.LittleEndian, uint64(env.config.Flags)) + binary.Write(inbuf, binary.LittleEndian, uint64(opts.Flags)) + binary.Write(inbuf, binary.LittleEndian, uint64(env.pid)) + inbuf.Write(data) + + cmd := exec.Command(env.bin[0], env.bin[1:]...) + cmd.Env = []string{} + cmd.Dir = dir + cmd.Stdin = inbuf + if env.config.Flags&FlagDebug != 0 { + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stdout + } + if err := cmd.Start(); err != nil { + err0 = err + return + } + done := make(chan error) + go func() { + done <- cmd.Wait() + }() + t := time.NewTimer(env.config.Timeout) + select { + case <-done: + t.Stop() + case <-t.C: + cmd.Process.Kill() + <-done + } return } diff --git a/pkg/ipc/ipc_linux.go b/pkg/ipc/ipc_linux.go index 3023ac0a6..793611b91 100644 --- a/pkg/ipc/ipc_linux.go +++ b/pkg/ipc/ipc_linux.go @@ -22,7 +22,7 @@ import ( ) type Env struct { - In []byte + in []byte out []byte cmd *command @@ -37,12 +37,6 @@ type Env struct { } const ( - outputSize = 16 << 20 - - statusFail = 67 - statusError = 68 - statusRetry = 69 - // Comparison types masks taken from KCOV headers. compSizeMask = 6 compSize8 = 6 @@ -77,7 +71,7 @@ func MakeEnv(bin string, pid int, config Config) (*Env, error) { serializeUint64(inmem[8:], uint64(pid)) inmem = inmem[16:] env := &Env{ - In: inmem, + in: inmem, out: outmem, inFile: inf, outFile: outf, @@ -88,10 +82,7 @@ func MakeEnv(bin string, pid int, config Config) (*Env, error) { if len(env.bin) == 0 { return nil, fmt.Errorf("binary is empty string") } - env.bin[0], err = filepath.Abs(env.bin[0]) // we are going to chdir - if err != nil { - return nil, fmt.Errorf("filepath.Abs failed: %v", err) - } + env.bin[0] = osutil.Abs(env.bin[0]) // we are going to chdir // Append pid to binary name. // E.g. if binary is 'syz-executor' and pid=15, // we create a link from 'syz-executor15' to 'syz-executor' and use 'syz-executor15' as binary. @@ -116,7 +107,7 @@ func (env *Env) Close() error { if env.cmd != nil { env.cmd.close() } - err1 := closeMapping(env.inFile, env.In) + err1 := closeMapping(env.inFile, env.in) err2 := closeMapping(env.outFile, env.out) switch { case err1 != nil: @@ -137,7 +128,7 @@ func (env *Env) Close() error { func (env *Env) Exec(opts *ExecOpts, p *prog.Prog) (output []byte, info []CallInfo, failed, hanged bool, err0 error) { if p != nil { // Copy-in serialized program. - if err := p.SerializeForExec(env.In, env.pid); err != nil { + if err := p.SerializeForExec(env.in, env.pid); err != nil { err0 = fmt.Errorf("executor %v: failed to serialize: %v", env.pid, err) return } diff --git a/pkg/osutil/osutil.go b/pkg/osutil/osutil.go index 4fbd04506..79cd455c2 100644 --- a/pkg/osutil/osutil.go +++ b/pkg/osutil/osutil.go @@ -55,26 +55,6 @@ func runCmd(timeout time.Duration, env []string, dir, bin string, args ...string return output.Bytes(), nil } -var wd string - -func init() { - var err error - wd, err = os.Getwd() - if err != nil { - panic(fmt.Sprintf("failed to get wd: %v", err)) - } -} - -func Abs(path string) string { - if wd1, err := os.Getwd(); err == nil && wd1 != wd { - panic("don't mess with wd in a concurrent program") - } - if path == "" || filepath.IsAbs(path) { - return path - } - return filepath.Join(wd, path) -} - // IsExist returns true if the file name exists. func IsExist(name string) bool { _, err := os.Stat(name) diff --git a/pkg/osutil/osutil_fuchsia.go b/pkg/osutil/osutil_fuchsia.go new file mode 100644 index 000000000..75cdad843 --- /dev/null +++ b/pkg/osutil/osutil_fuchsia.go @@ -0,0 +1,17 @@ +// 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 fuchsia + +package osutil + +func HandleInterrupts(shutdown chan struct{}) { +} + +func Abs(path string) string { + // Getwd is not implemented. Let's hope for best. + if path == "" { + return "" + } + return "./" + path +} diff --git a/pkg/osutil/osutil_unix.go b/pkg/osutil/osutil_unix.go index 01eabc15b..27482b99a 100644 --- a/pkg/osutil/osutil_unix.go +++ b/pkg/osutil/osutil_unix.go @@ -90,3 +90,23 @@ func LongPipe() (io.ReadCloser, io.WriteCloser, error) { prolongPipe(r, w) return r, w, err } + +var wd string + +func init() { + var err error + wd, err = os.Getwd() + if err != nil { + panic(fmt.Sprintf("failed to get wd: %v", err)) + } +} + +func Abs(path string) string { + if wd1, err := os.Getwd(); err == nil && wd1 != wd { + panic("don't mess with wd in a concurrent program") + } + if path == "" || filepath.IsAbs(path) { + return path + } + return filepath.Join(wd, path) +} |
