diff options
| author | Taras Madan <tarasmadan@gmail.com> | 2021-10-14 14:47:55 +0000 |
|---|---|---|
| committer | tarasmadan <89859571+tarasmadan@users.noreply.github.com> | 2021-10-15 09:52:17 +0200 |
| commit | 115b2d95e56f01373ebe1c3f8f5a4d8c3c4d33e4 (patch) | |
| tree | d5ae7da0e49e35a24d66aae7551330ca06e7f86f /syz-verifier/execresult.go | |
| parent | fc538d9dc19d1d8d0c0301ca73f269e71d978c85 (diff) | |
syz-verifier: rename verifier.go and Result to better reflect internals
Diffstat (limited to 'syz-verifier/execresult.go')
| -rw-r--r-- | syz-verifier/execresult.go | 139 |
1 files changed, 139 insertions, 0 deletions
diff --git a/syz-verifier/execresult.go b/syz-verifier/execresult.go new file mode 100644 index 000000000..d3db18882 --- /dev/null +++ b/syz-verifier/execresult.go @@ -0,0 +1,139 @@ +// 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 main + +import ( + "fmt" + "syscall" + + "github.com/google/syzkaller/pkg/ipc" + "github.com/google/syzkaller/prog" +) + +// ExecResult stores the results of executing a program. +type ExecResult 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 + // Crashed is set to true if a crash occurred while executing the program. + Crashed bool + + RunIdx int +} + +type ResultReport struct { + // Prog is the serialized program. + Prog string + // Reports contains information about each system call. + Reports []*CallReport +} + +type CallReport struct { + // Call is the name of the system call. + Call string + // States is a map between pools and their return state when executing the system call. + States map[int]ReturnState + // Mismatch is set to true if the returned error codes were not the same. + Mismatch bool +} + +// ReturnState stores the results of executing a system call. +type ReturnState struct { + // Errno is returned by executing the system call. + Errno int + // Flags stores the call flags (see pkg/ipc/ipc.go). + Flags ipc.CallFlags + // Crashed is set to true if the kernel crashed while executing the program + // that contains the system call. + Crashed bool +} + +func (s ReturnState) String() string { + state := "" + + if s.Crashed { + return "Crashed" + } + + state += fmt.Sprintf("Flags: %d, ", s.Flags) + errDesc := "success" + if s.Errno != 0 { + errDesc = syscall.Errno(s.Errno).Error() + } + state += fmt.Sprintf("Errno: %d (%s)", s.Errno, errDesc) + return state +} + +// VeifyRerun compares the results obtained from rerunning a program with what +// was reported in the initial result report. +func VerifyRerun(res []*ExecResult, rr *ResultReport) bool { + for idx, cr := range rr.Reports { + for _, r := range res { + var state ReturnState + if r.Crashed { + state = ReturnState{Crashed: true} + } else { + ci := r.Info.Calls[idx] + state = ReturnState{Errno: ci.Errno, Flags: ci.Flags} + } + if state != cr.States[r.Pool] { + return false + } + } + } + return true +} + +// Verify checks whether the Results of the same program, executed on different +// kernels, are the same. If that's not the case, it returns a ResultReport, +// highlighting the differences. +func Verify(res []*ExecResult, prog *prog.Prog, s *Stats) *ResultReport { + rr := &ResultReport{ + Prog: string(prog.Serialize()), + } + + // Build the CallReport for each system call in the program. + for idx, call := range prog.Calls { + cn := call.Meta.Name + s.Calls[cn].Occurrences++ + + cr := &CallReport{ + Call: cn, + States: map[int]ReturnState{}, + } + + for _, r := range res { + if r.Crashed { + cr.States[r.Pool] = ReturnState{Crashed: true} + continue + } + + ci := r.Info.Calls[idx] + cr.States[r.Pool] = ReturnState{Errno: ci.Errno, Flags: ci.Flags} + } + rr.Reports = append(rr.Reports, cr) + } + + var send bool + pool0 := res[0].Pool + for _, cr := range rr.Reports { + for _, state := range cr.States { + // For each CallReport, verify whether the ReturnStates from all + // the pools that executed the program are the same + if state0 := cr.States[pool0]; state0 != state { + cr.Mismatch = true + send = true + } + } + } + + if send { + return rr + } + return nil +} |
