diff options
| author | Dmitry Vyukov <dvyukov@google.com> | 2017-09-15 10:15:00 +0200 |
|---|---|---|
| committer | Dmitry Vyukov <dvyukov@google.com> | 2017-09-15 16:02:37 +0200 |
| commit | 539e603206f427ff6549cde661fef0205a4c9034 (patch) | |
| tree | de4cd1db71fc293582ad495f4d8cc16f196c6827 | |
| parent | 19f9bc13d374058b83b2712f119bb42559b35c0c (diff) | |
syz-manager, syz-fuzzer, executor: ensure that binaries are consistent
Check that manager/fuzzer/executor are build on the same git revision,
use the same syscall descriptions and the same target arch.
Update #336
| -rw-r--r-- | Makefile | 12 | ||||
| -rw-r--r-- | executor/executor.cc | 9 | ||||
| -rw-r--r-- | executor/syscalls.h | 10 | ||||
| -rw-r--r-- | pkg/rpctype/rpctype.go | 5 | ||||
| -rw-r--r-- | prog/target.go | 1 | ||||
| -rw-r--r-- | sys/linux/386.go | 4 | ||||
| -rw-r--r-- | sys/linux/amd64.go | 4 | ||||
| -rw-r--r-- | sys/linux/arm.go | 4 | ||||
| -rw-r--r-- | sys/linux/arm64.go | 4 | ||||
| -rw-r--r-- | sys/linux/init.go | 3 | ||||
| -rw-r--r-- | sys/linux/ppc64le.go | 4 | ||||
| -rw-r--r-- | sys/sys.go | 3 | ||||
| -rw-r--r-- | sys/syz-sysgen/sysgen.go | 27 | ||||
| -rw-r--r-- | syz-fuzzer/fuzzer.go | 14 | ||||
| -rw-r--r-- | syz-manager/manager.go | 14 |
15 files changed, 100 insertions, 18 deletions
@@ -15,6 +15,13 @@ endif android \ format tidy test arch cross-compile presubmit clean +GITREV=$(shell git rev-parse HEAD) +ifeq ($(`git diff --shortstat`), "") + REV=$(GITREV) +else + REV=$(GITREV)+ +endif + all: $(MAKE) main $(MAKE) tools @@ -29,13 +36,14 @@ tools: execprog mutate prog2c stress repro upgrade db # executor uses stacks of limited size, so no jumbo frames. executor: - $(CC) -o ./bin/syz-executor executor/executor.cc -pthread -Wall -Wframe-larger-than=8192 -Wparentheses -Werror -O1 -g $(STATIC_FLAG) $(CFLAGS) + $(CC) -o ./bin/syz-executor executor/executor.cc -pthread -Wall -Wframe-larger-than=8192 \ + -Wparentheses -Werror -O1 -g $(STATIC_FLAG) $(CFLAGS) -DGIT_REVISION=\"$(REV)\" # Don't generate symbol table and DWARF debug info. # Reduces build time and binary sizes considerably. # That's only needed if you use gdb or nm. # If you need that, build manually without these flags. -GOFLAGS="-ldflags=-s -w" +GOFLAGS="-ldflags=-s -w -X github.com/google/syzkaller/sys.GitRevision=$(REV)" manager: go build $(GOFLAGS) -o ./bin/syz-manager github.com/google/syzkaller/syz-manager diff --git a/executor/executor.cc b/executor/executor.cc index 87a597253..ce8d0ed2f 100644 --- a/executor/executor.cc +++ b/executor/executor.cc @@ -228,8 +228,17 @@ uint64_t read_cover_size(thread_t* th); static uint32_t hash(uint32_t a); static bool dedup(uint32_t sig); +#ifndef GIT_REVISION +#define GIT_REVISION "unknown" +#endif + int main(int argc, char** argv) { + if (argc == 2 && strcmp(argv[1], "version") == 0) { + puts("linux " GOARCH " " SYZ_REVISION " " GIT_REVISION); + return 0; + } + prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0); if (mmap(&input_data[0], kMaxInput, PROT_READ, MAP_PRIVATE | MAP_FIXED, kInFd, 0) != &input_data[0]) fail("mmap of input file failed"); diff --git a/executor/syscalls.h b/executor/syscalls.h index 68446e9a0..c530a1359 100644 --- a/executor/syscalls.h +++ b/executor/syscalls.h @@ -6,6 +6,8 @@ struct call_t { }; #if defined(__i386__) || 0 +#define GOARCH "386" +#define SYZ_REVISION "fb26afa29ccd7317f2c0796cf1386b493eeb955f" #define __NR_syz_emit_ethernet 1000000 #define __NR_syz_extract_tcp_res 1000001 #define __NR_syz_fuse_mount 1000002 @@ -1564,6 +1566,8 @@ static call_t syscalls[] = { #endif #if defined(__x86_64__) || 0 +#define GOARCH "amd64" +#define SYZ_REVISION "c14ec0f07c2984481a0bf1453ea928549382eb25" #define __NR_syz_emit_ethernet 1000000 #define __NR_syz_extract_tcp_res 1000001 #define __NR_syz_fuse_mount 1000002 @@ -3122,6 +3126,8 @@ static call_t syscalls[] = { #endif #if defined(__arm__) || 0 +#define GOARCH "arm" +#define SYZ_REVISION "f73cb445fdead3417b165eec037a0d892cc3253e" #define __NR_syz_emit_ethernet 1000000 #define __NR_syz_extract_tcp_res 1000001 #define __NR_syz_fuse_mount 1000002 @@ -4680,6 +4686,8 @@ static call_t syscalls[] = { #endif #if defined(__aarch64__) || 0 +#define GOARCH "arm64" +#define SYZ_REVISION "72353a7ede1fe6cb903fcb02eb5eb11407bea5d8" #define __NR_syz_emit_ethernet 1000000 #define __NR_syz_extract_tcp_res 1000001 #define __NR_syz_fuse_mount 1000002 @@ -6238,6 +6246,8 @@ static call_t syscalls[] = { #endif #if defined(__ppc64__) || defined(__PPC64__) || defined(__powerpc64__) || 0 +#define GOARCH "ppc64le" +#define SYZ_REVISION "cec4f3697757a69ac044be83bac5ba45df7f2fbf" #define __NR_syz_emit_ethernet 1000000 #define __NR_syz_extract_tcp_res 1000001 #define __NR_syz_fuse_mount 1000002 diff --git a/pkg/rpctype/rpctype.go b/pkg/rpctype/rpctype.go index 90da1e7fe..78f8938f8 100644 --- a/pkg/rpctype/rpctype.go +++ b/pkg/rpctype/rpctype.go @@ -39,6 +39,11 @@ type CheckArgs struct { UserNamespaces bool CompsSupported bool Calls []string + FuzzerGitRev string + FuzzerSyzRev string + ExecutorGitRev string + ExecutorSyzRev string + ExecutorArch string } type NewInputArgs struct { diff --git a/prog/target.go b/prog/target.go index 83cf1a77c..1a099bf8e 100644 --- a/prog/target.go +++ b/prog/target.go @@ -12,6 +12,7 @@ import ( type Target struct { OS string Arch string + Revision string // unique hash representing revision of the descriptions PtrSize uint64 PageSize uint64 DataOffset uint64 diff --git a/sys/linux/386.go b/sys/linux/386.go index 60842fd78..edce34ee9 100644 --- a/sys/linux/386.go +++ b/sys/linux/386.go @@ -4,7 +4,7 @@ package linux import . "github.com/google/syzkaller/prog" func init() { - initArch(syscalls_386, resources_386, structDescs_386, consts_386, "386", 4) + initArch(revision_386, syscalls_386, resources_386, structDescs_386, consts_386, "386", 4) } var resources_386 = []*ResourceDesc{ @@ -17186,3 +17186,5 @@ var consts_386 = []ConstValue{ {Name: "__WCLONE", Value: 2147483648}, {Name: "__WNOTHREAD", Value: 536870912}, } + +const revision_386 = "fb26afa29ccd7317f2c0796cf1386b493eeb955f" diff --git a/sys/linux/amd64.go b/sys/linux/amd64.go index 5a64db3e7..53f1aacc4 100644 --- a/sys/linux/amd64.go +++ b/sys/linux/amd64.go @@ -4,7 +4,7 @@ package linux import . "github.com/google/syzkaller/prog" func init() { - initArch(syscalls_amd64, resources_amd64, structDescs_amd64, consts_amd64, "amd64", 8) + initArch(revision_amd64, syscalls_amd64, resources_amd64, structDescs_amd64, consts_amd64, "amd64", 8) } var resources_amd64 = []*ResourceDesc{ @@ -17268,3 +17268,5 @@ var consts_amd64 = []ConstValue{ {Name: "__WCLONE", Value: 2147483648}, {Name: "__WNOTHREAD", Value: 536870912}, } + +const revision_amd64 = "c14ec0f07c2984481a0bf1453ea928549382eb25" diff --git a/sys/linux/arm.go b/sys/linux/arm.go index 3eb900c60..b364bdc71 100644 --- a/sys/linux/arm.go +++ b/sys/linux/arm.go @@ -4,7 +4,7 @@ package linux import . "github.com/google/syzkaller/prog" func init() { - initArch(syscalls_arm, resources_arm, structDescs_arm, consts_arm, "arm", 4) + initArch(revision_arm, syscalls_arm, resources_arm, structDescs_arm, consts_arm, "arm", 4) } var resources_arm = []*ResourceDesc{ @@ -17140,3 +17140,5 @@ var consts_arm = []ConstValue{ {Name: "__WCLONE", Value: 2147483648}, {Name: "__WNOTHREAD", Value: 536870912}, } + +const revision_arm = "f73cb445fdead3417b165eec037a0d892cc3253e" diff --git a/sys/linux/arm64.go b/sys/linux/arm64.go index f82fa3974..8f90a0822 100644 --- a/sys/linux/arm64.go +++ b/sys/linux/arm64.go @@ -4,7 +4,7 @@ package linux import . "github.com/google/syzkaller/prog" func init() { - initArch(syscalls_arm64, resources_arm64, structDescs_arm64, consts_arm64, "arm64", 8) + initArch(revision_arm64, syscalls_arm64, resources_arm64, structDescs_arm64, consts_arm64, "arm64", 8) } var resources_arm64 = []*ResourceDesc{ @@ -17182,3 +17182,5 @@ var consts_arm64 = []ConstValue{ {Name: "__WCLONE", Value: 2147483648}, {Name: "__WNOTHREAD", Value: 536870912}, } + +const revision_arm64 = "72353a7ede1fe6cb903fcb02eb5eb11407bea5d8" diff --git a/sys/linux/init.go b/sys/linux/init.go index cbf93e963..509e2ab04 100644 --- a/sys/linux/init.go +++ b/sys/linux/init.go @@ -9,12 +9,13 @@ import ( "github.com/google/syzkaller/prog" ) -func initArch(syscalls []*prog.Syscall, resources []*prog.ResourceDesc, +func initArch(rev string, syscalls []*prog.Syscall, resources []*prog.ResourceDesc, structDescs []*prog.KeyedStruct, consts []prog.ConstValue, archName string, ptrSize uint64) { arch := makeArch(syscalls, resources, structDescs, consts, archName) target := &prog.Target{ OS: "linux", Arch: archName, + Revision: rev, PtrSize: ptrSize, PageSize: pageSize, DataOffset: dataOffset, diff --git a/sys/linux/ppc64le.go b/sys/linux/ppc64le.go index b1b9459ed..aa0f691a7 100644 --- a/sys/linux/ppc64le.go +++ b/sys/linux/ppc64le.go @@ -4,7 +4,7 @@ package linux import . "github.com/google/syzkaller/prog" func init() { - initArch(syscalls_ppc64le, resources_ppc64le, structDescs_ppc64le, consts_ppc64le, "ppc64le", 8) + initArch(revision_ppc64le, syscalls_ppc64le, resources_ppc64le, structDescs_ppc64le, consts_ppc64le, "ppc64le", 8) } var resources_ppc64le = []*ResourceDesc{ @@ -17172,3 +17172,5 @@ var consts_ppc64le = []ConstValue{ {Name: "__WCLONE", Value: 2147483648}, {Name: "__WNOTHREAD", Value: 536870912}, } + +const revision_ppc64le = "cec4f3697757a69ac044be83bac5ba45df7f2fbf" diff --git a/sys/sys.go b/sys/sys.go index 7f52504fe..3ab982fdb 100644 --- a/sys/sys.go +++ b/sys/sys.go @@ -74,3 +74,6 @@ func init() { } } } + +// Emitted by Makefile. +var GitRevision string diff --git a/sys/syz-sysgen/sysgen.go b/sys/syz-sysgen/sysgen.go index ce88cb539..ea3e3e110 100644 --- a/sys/syz-sysgen/sysgen.go +++ b/sys/syz-sysgen/sysgen.go @@ -21,6 +21,7 @@ import ( "github.com/google/syzkaller/pkg/ast" "github.com/google/syzkaller/pkg/compiler" + "github.com/google/syzkaller/pkg/hash" "github.com/google/syzkaller/pkg/serializer" "github.com/google/syzkaller/prog" "github.com/google/syzkaller/sys" @@ -79,9 +80,11 @@ func main() { sysFile := filepath.Join("sys", OS, job.Target.Arch+".go") out := new(bytes.Buffer) generate(job.Target, prog, consts, out) + rev := hash.String(out.Bytes()) + fmt.Fprintf(out, "const revision_%v = %q\n", job.Target.Arch, rev) writeSource(sysFile, out.Bytes()) - job.ArchData = generateExecutorSyscalls(job.Target, prog.Syscalls) + job.ArchData = generateExecutorSyscalls(job.Target, prog.Syscalls, rev) job.OK = true }() } @@ -132,8 +135,8 @@ func generate(target *sys.Target, prg *compiler.Prog, consts map[string]uint64, fmt.Fprintf(out, "import . \"github.com/google/syzkaller/prog\"\n\n") fmt.Fprintf(out, "func init() {\n") - fmt.Fprintf(out, "\tinitArch(syscalls_%v, resources_%v, structDescs_%v, consts_%v, %q, %v)\n", - target.Arch, target.Arch, target.Arch, target.Arch, target.Arch, target.PtrSize) + fmt.Fprintf(out, "\tinitArch(revision_%v, syscalls_%v, resources_%v, structDescs_%v, consts_%v, %q, %v)\n", + target.Arch, target.Arch, target.Arch, target.Arch, target.Arch, target.Arch, target.PtrSize) fmt.Fprintf(out, "}\n\n") fmt.Fprintf(out, "var resources_%v = ", target.Arch) @@ -157,21 +160,25 @@ func generate(target *sys.Target, prg *compiler.Prog, consts map[string]uint64, }) fmt.Fprintf(out, "var consts_%v = ", target.Arch) serializer.Write(out, constArr) - fmt.Fprintf(out, "\n") + fmt.Fprintf(out, "\n\n") } -func generateExecutorSyscalls(target *sys.Target, syscalls []*prog.Syscall) []byte { +func generateExecutorSyscalls(target *sys.Target, syscalls []*prog.Syscall, rev string) []byte { type SyscallData struct { Name string NR int32 } type ArchData struct { - CARCH []string - Calls []SyscallData - Fake []SyscallData + Revision string + GOARCH string + CARCH []string + Calls []SyscallData + Fake []SyscallData } data := ArchData{ - CARCH: target.CArch, + Revision: rev, + GOARCH: target.Arch, + CARCH: target.CArch, } fake := make(map[string]uint64) for _, c := range syscalls { @@ -247,6 +254,8 @@ struct call_t { var archTempl = template.Must(template.New("").Parse(` #if {{range $cdef := $.CARCH}}defined({{$cdef}}) || {{end}}0 +#define GOARCH "{{.GOARCH}}" +#define SYZ_REVISION "{{.Revision}}" {{range $c := $.Fake}}#define __NR_{{$c.Name}} {{$c.NR}} {{end}} static call_t syscalls[] = { diff --git a/syz-fuzzer/fuzzer.go b/syz-fuzzer/fuzzer.go index f41296c9b..8c94c7d49 100644 --- a/syz-fuzzer/fuzzer.go +++ b/syz-fuzzer/fuzzer.go @@ -29,6 +29,7 @@ import ( "github.com/google/syzkaller/pkg/osutil" . "github.com/google/syzkaller/pkg/rpctype" "github.com/google/syzkaller/prog" + "github.com/google/syzkaller/sys" "github.com/google/syzkaller/sys/linux" ) @@ -175,9 +176,22 @@ func main() { kcov, compsSupported := checkCompsSupported() Logf(1, "KCOV_CHECK: compsSupported=%v", compsSupported) if r.NeedCheck { + out, err := osutil.RunCmd(time.Minute, "", *flagExecutor, "version") + if err != nil { + panic(err) + } + vers := strings.Split(strings.TrimSpace(string(out)), " ") + if len(vers) != 4 { + panic(fmt.Sprintf("bad executor version: %q", string(out))) + } a := &CheckArgs{ Name: *flagName, UserNamespaces: osutil.IsExist("/proc/self/ns/user"), + FuzzerGitRev: sys.GitRevision, + FuzzerSyzRev: target.Revision, + ExecutorGitRev: vers[3], + ExecutorSyzRev: vers[2], + ExecutorArch: vers[1], } a.Kcov = kcov if fd, err := syscall.Open("/sys/kernel/debug/kmemleak", syscall.O_RDWR, 0); err == nil { diff --git a/syz-manager/manager.go b/syz-manager/manager.go index 368ca2e8f..d20048130 100644 --- a/syz-manager/manager.go +++ b/syz-manager/manager.go @@ -29,7 +29,7 @@ import ( "github.com/google/syzkaller/pkg/repro" . "github.com/google/syzkaller/pkg/rpctype" "github.com/google/syzkaller/prog" - _ "github.com/google/syzkaller/sys" + "github.com/google/syzkaller/sys" "github.com/google/syzkaller/syz-manager/mgrconfig" "github.com/google/syzkaller/vm" ) @@ -870,6 +870,18 @@ func (mgr *Manager) Check(a *CheckArgs, r *int) error { if mgr.cfg.Sandbox == "namespace" && !a.UserNamespaces { Fatalf("/proc/self/ns/user is missing or permission is denied. Requested namespace sandbox but user namespaces are not enabled. Enable CONFIG_USER_NS") } + if mgr.target.Arch != a.ExecutorArch { + Fatalf("mismatching target/executor arch: target=%v executor=%v", + mgr.target.Arch, a.ExecutorArch) + } + if sys.GitRevision != a.FuzzerGitRev || sys.GitRevision != a.ExecutorGitRev { + Fatalf("mismatching git revisions:\nmanager= %v\nfuzzer= %v\nexecutor=%v", + sys.GitRevision, a.FuzzerGitRev, a.ExecutorGitRev) + } + if mgr.target.Revision != a.FuzzerSyzRev || mgr.target.Revision != a.ExecutorSyzRev { + Fatalf("mismatching syscall descriptions:\nmanager= %v\nfuzzer= %v\nexecutor=%v", + mgr.target.Revision, a.FuzzerSyzRev, a.ExecutorSyzRev) + } mgr.vmChecked = true mgr.enabledCalls = a.Calls return nil |
