aboutsummaryrefslogtreecommitdiffstats
path: root/pkg
diff options
context:
space:
mode:
authorDmitry Vyukov <dvyukov@google.com>2017-09-22 11:09:53 +0200
committerDmitry Vyukov <dvyukov@google.com>2017-09-22 13:10:55 +0200
commit913d592f973a0155647473eaa032711fe956f8a5 (patch)
tree29b1b2083c00d199cf4d9a30917411d923b49ef4 /pkg
parentc26ea367cfa790e86800ac025638ad50f95b8287 (diff)
all: more assorted fuchsia support
Diffstat (limited to 'pkg')
-rw-r--r--pkg/compiler/compiler.go7
-rw-r--r--pkg/compiler/compiler_test.go9
-rw-r--r--pkg/compiler/consts.go5
-rw-r--r--pkg/csource/common.go295
-rw-r--r--pkg/csource/csource.go2
-rw-r--r--pkg/csource/csource_test.go4
-rw-r--r--pkg/ipc/ipc.go8
-rw-r--r--pkg/ipc/ipc_fuchsia.go82
-rw-r--r--pkg/ipc/ipc_linux.go19
-rw-r--r--pkg/osutil/osutil.go20
-rw-r--r--pkg/osutil/osutil_fuchsia.go17
-rw-r--r--pkg/osutil/osutil_unix.go20
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)
+}