aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMara Mihali <maramihali@google.com>2021-06-23 16:24:21 +0000
committerDmitry Vyukov <dvyukov@google.com>2021-06-30 09:35:14 +0200
commitf96cd674af0bf3997d17277fa0a028bede05ca54 (patch)
treed7ecbf345d41d7854ed44dba712adf2f09a29b89
parentbf86d29b9edb7e1346978c74ea837b5ec3683b2d (diff)
syz-verifier/verf: add the first version of the Verifier
This checks whether the errno returned by a program's system call executed by different Runners are the same.
-rw-r--r--syz-verifier/verf/verifier.go45
-rw-r--r--syz-verifier/verf/verifier_test.go86
2 files changed, 131 insertions, 0 deletions
diff --git a/syz-verifier/verf/verifier.go b/syz-verifier/verf/verifier.go
new file mode 100644
index 000000000..2678af23b
--- /dev/null
+++ b/syz-verifier/verf/verifier.go
@@ -0,0 +1,45 @@
+// Copyright 2021 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.
+
+// Package verf contains utilities for verifying the execution of the same
+// program on different kernels yield the same results.
+package verf
+
+import (
+ "github.com/google/syzkaller/pkg/ipc"
+ "github.com/google/syzkaller/prog"
+)
+
+// Result stores the results of executing a program.
+type Result struct {
+ // Pool is the index of the pool.
+ Pool int
+ // Hanged is set to true when a program was killed due to hanging.
+ Hanged bool
+ // Info contains information about the execution of each system call
+ // in the generated programs.
+ Info ipc.ProgInfo
+}
+
+// Verify checks whether the Results of the same program, executed on different
+// kernels are the same. If that's the case, it returns true, otherwise it
+// returns false.
+func Verify(res []*Result, prog *prog.Prog) bool {
+ for i := 1; i < len(res); i++ {
+ if !VerifyErrnos(res[0].Info.Calls, res[i].Info.Calls) {
+ return false
+ }
+ }
+ return true
+}
+
+// VerifyErrnos checks whether the returned system call errnos of the same
+// program, executed on two different kernels, are the same.
+func VerifyErrnos(c1, c2 []ipc.CallInfo) bool {
+ for idx, c := range c1 {
+ if c.Errno != c2[idx].Errno {
+ return false
+ }
+ }
+ return true
+}
diff --git a/syz-verifier/verf/verifier_test.go b/syz-verifier/verf/verifier_test.go
new file mode 100644
index 000000000..c9a25acb5
--- /dev/null
+++ b/syz-verifier/verf/verifier_test.go
@@ -0,0 +1,86 @@
+// Copyright 2021 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.
+package verf
+
+import (
+ "testing"
+
+ "github.com/google/syzkaller/pkg/ipc"
+)
+
+func TestVerify(t *testing.T) {
+ tests := []struct {
+ name string
+ res []*Result
+ wantMatch bool
+ }{
+ {
+
+ name: "results should match",
+ res: []*Result{
+ {2, false, ipc.ProgInfo{
+ Calls: []ipc.CallInfo{{Errno: 1}, {Errno: 2}, {Errno: 3}}, Extra: ipc.CallInfo{},
+ },
+ },
+ {4, false, ipc.ProgInfo{
+ Calls: []ipc.CallInfo{{Errno: 1}, {Errno: 2}, {Errno: 3}},
+ Extra: ipc.CallInfo{},
+ },
+ },
+ },
+
+ wantMatch: true,
+ },
+ {
+ name: "results should not match",
+ res: []*Result{
+ {4, false, ipc.ProgInfo{
+ Calls: []ipc.CallInfo{{Errno: 1}, {Errno: 2}, {Errno: 5}},
+ },
+ },
+ {8, false, ipc.ProgInfo{
+ Calls: []ipc.CallInfo{{Errno: 1}, {Errno: 3}, {Errno: 5}},
+ },
+ },
+ },
+ wantMatch: false,
+ },
+ }
+
+ for _, test := range tests {
+ t.Run(test.name, func(t *testing.T) {
+ if got, want := Verify(test.res, nil), test.wantMatch; got != want {
+ t.Errorf("Verify: got %v, want %v", got, want)
+ }
+ })
+ }
+}
+
+func TestVerifyErrno(t *testing.T) {
+ tests := []struct {
+ name string
+ c1, c2 []ipc.CallInfo
+ wantMatch bool
+ }{
+ {
+ name: "errno should match",
+ c1: []ipc.CallInfo{{Errno: 1}, {Errno: 2}, {Errno: 5}},
+ c2: []ipc.CallInfo{{Errno: 1}, {Errno: 2}, {Errno: 5}},
+ wantMatch: true,
+ },
+ {
+ name: "errno should not match",
+ c1: []ipc.CallInfo{{Errno: 1}, {Errno: 2}, {Errno: 5}},
+ c2: []ipc.CallInfo{{Errno: 1}, {Errno: 4}, {Errno: 5}},
+ wantMatch: false,
+ },
+ }
+
+ for _, test := range tests {
+ t.Run(test.name, func(t *testing.T) {
+ if got, want := VerifyErrnos(test.c1, test.c2), test.wantMatch; got != want {
+ t.Errorf("VerifyErrno: got %v, want %v", got, want)
+ }
+ })
+ }
+}