aboutsummaryrefslogtreecommitdiffstats
path: root/syz-verifier
diff options
context:
space:
mode:
authorTaras Madan <tarasmadan@gmail.com>2021-10-14 12:49:19 +0000
committertarasmadan <89859571+tarasmadan@users.noreply.github.com>2021-10-15 09:52:17 +0200
commit0bd8b1dd5124f72465a85feea4044d98b2571d6d (patch)
tree939fc34b82e87820468f45983e04e8f1dc6286e1 /syz-verifier
parentaab7690b6ed50129a4236a2b1d346b9944a478d1 (diff)
syz-verifier: remove verifier, io and os/signal from the stats dependencies
Diffstat (limited to 'syz-verifier')
-rwxr-xr-xsyz-verifier/main.go36
-rw-r--r--syz-verifier/stats.go110
-rw-r--r--syz-verifier/stats_test.go18
3 files changed, 91 insertions, 73 deletions
diff --git a/syz-verifier/main.go b/syz-verifier/main.go
index 7065f5d7c..b7b11b5c6 100755
--- a/syz-verifier/main.go
+++ b/syz-verifier/main.go
@@ -2,16 +2,18 @@
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
// package main starts the syz-verifier tool. High-level documentation can be
-// found in docs/syz_verfier.md.
+// found in docs/syz_verifier.md.
package main
import (
+ "errors"
"flag"
"fmt"
"io"
"math/rand"
"net"
"os"
+ "os/signal"
"path/filepath"
"strconv"
"strings"
@@ -239,6 +241,31 @@ func main() {
vrf.startInstances()
}
+// SetPrintStatAtSIGINT asks Stats object to report verification
+// statistics when an os.Interrupt occurs and Exit().
+func (vrf *Verifier) SetPrintStatAtSIGINT() error {
+ if vrf.stats == nil {
+ return errors.New("verifier.stats is nil")
+ }
+
+ osSignalChannel := make(chan os.Signal)
+ signal.Notify(osSignalChannel, os.Interrupt)
+
+ go func() {
+ <-osSignalChannel
+ defer os.Exit(0)
+
+ totalExecutionTime := time.Since(vrf.stats.StartTime).Minutes()
+ if vrf.stats.TotalMismatches < 0 {
+ fmt.Fprint(vrf.statsWrite, "No mismatches occurred until syz-verifier was stopped.")
+ }else{
+ fmt.Fprintf(vrf.statsWrite, vrf.stats.GetTextDescription(totalExecutionTime))
+ }
+ }()
+
+ return nil
+}
+
func (vrf *Verifier) startInstances() {
for idx, pi := range vrf.pools {
go func(pi *poolInfo, idx int) {
@@ -282,6 +309,8 @@ func (vrf *Verifier) createAndManageInstance(pi *poolInfo, idx int) {
}
inst.MonitorExecution(outc, errc, pi.Reporter, vm.ExitTimeout)
+
+ log.Logf(0, "reboot the VM in pool %d", idx)
}
func startRPCServer(vrf *Verifier) (*RPCServer, error) {
@@ -340,7 +369,10 @@ func (srv *RPCServer) UpdateUnsupported(a *rpctype.UpdateUnsupportedArgs, r *int
srv.notChecked--
if srv.notChecked == 0 {
vrf.finalizeCallSet(os.Stdout)
- vrf.stats = InitStats(vrf.calls, vrf.statsWrite)
+
+ vrf.stats = InitStats(vrf.calls)
+ vrf.SetPrintStatAtSIGINT()
+
vrf.choiceTable = vrf.target.BuildChoiceTable(nil, vrf.calls)
srv.cond.Signal()
}
diff --git a/syz-verifier/stats.go b/syz-verifier/stats.go
index 804b6ec75..a6d00a0d2 100644
--- a/syz-verifier/stats.go
+++ b/syz-verifier/stats.go
@@ -5,10 +5,8 @@ package main
import (
"fmt"
- "io"
- "os"
- "os/signal"
"sort"
+ "strings"
"time"
"github.com/google/syzkaller/prog"
@@ -31,7 +29,7 @@ type Stats struct {
type CallStats struct {
// Name is the system call name.
Name string
- // Mismatches stores the number of errno mismatches identifed in the
+ // Mismatches stores the number of errno mismatches identified in the
// verified programs for this system call.
Mismatches int
// Occurrences is the number of times the system call appeared in a
@@ -41,85 +39,71 @@ type CallStats struct {
States map[ReturnState]bool
}
-// InitStats creates a stats object that will report verification
-// statistics when an os.Interrupt occurs.
-func InitStats(calls map[*prog.Syscall]bool, w io.Writer) *Stats {
- s := &Stats{
+// InitStats creates a stats object.
+func InitStats(calls map[*prog.Syscall]bool) *Stats {
+ stats := &Stats{
Calls: make(map[string]*CallStats),
StartTime: time.Now(),
}
- for c := range calls {
- s.Calls[c.Name] = &CallStats{
- Name: c.Name,
+
+ for syscall := range calls {
+ stats.Calls[syscall.Name] = &CallStats{
+ Name: syscall.Name,
States: make(map[ReturnState]bool)}
}
- c := make(chan os.Signal)
- signal.Notify(c, os.Interrupt)
- go func() {
- <-c
- dt := time.Since(s.StartTime).Minutes()
- if s.TotalMismatches < 0 {
- fmt.Fprint(w, "No mismatches occurred until syz-verifier was stopped.")
- os.Exit(0)
- }
- s.ReportGlobalStats(w, dt)
- os.Exit(0)
- }()
+ return stats
+}
+
+// ReportGlobalStats creates a report with statistics about all the
+// supported system calls for which errno mismatches were identified in
+// the verified programs, shown in decreasing order.
+func (stats *Stats) GetTextDescription(deltaTime float64) string {
+ var result strings.Builder
+
+ tc := stats.totalCallsExecuted()
+ fmt.Fprintf(&result, "total number of mismatches / total number of calls "+
+ "executed: %d / %d (%0.2f %%)\n\n", stats.TotalMismatches, tc, getPercentage(stats.TotalMismatches, tc))
+ fmt.Fprintf(&result, "programs / minute: %0.2f\n\n", float64(stats.TotalProgs)/deltaTime)
+ fmt.Fprintf(&result, "true mismatching programs: %d / total number of programs: %d (%0.2f %%)\n",
+ stats.MismatchingProgs, stats.TotalProgs, getPercentage(stats.MismatchingProgs, stats.TotalProgs))
+ fmt.Fprintf(&result, "flaky programs: %d / total number of programs: %d (%0.2f %%)\n\n",
+ stats.FlakyProgs, stats.TotalProgs, getPercentage(stats.FlakyProgs, stats.TotalProgs))
+ cs := stats.getOrderedStats()
+ for _, c := range cs {
+ fmt.Fprintf(&result, "%s\n", stats.getCallStatsTextDescription(c.Name))
+ }
- return s
+ return result.String()
}
-// ReportCallStats creates a report with the current statistics for call.
-func (s *Stats) ReportCallStats(call string) string {
- cs, ok := s.Calls[call]
+// getCallStatsTextDescription creates a report with the current statistics for call.
+func (stats *Stats) getCallStatsTextDescription(call string) string {
+ syscallStat, ok := stats.Calls[call]
if !ok {
return ""
}
- name, m, o := cs.Name, cs.Mismatches, cs.Occurrences
- data := fmt.Sprintf("statistics for %s:\n"+
+ syscallName, mismatches, occurrences := syscallStat.Name, syscallStat.Mismatches, syscallStat.Occurrences
+ return fmt.Sprintf("statistics for %s:\n"+
"\t↳ mismatches of %s / occurrences of %s: %d / %d (%0.2f %%)\n"+
"\t↳ mismatches of %s / total number of mismatches: "+
"%d / %d (%0.2f %%)\n"+
- "\t↳ %d distinct states identified: %v\n", name, name, name, m, o,
- getPercentage(m, o), name, m, s.TotalMismatches,
- getPercentage(m, s.TotalMismatches), len(cs.States), s.getOrderedStates(name))
- return data
-}
-
-func getPercentage(value, total int) float64 {
- return float64(value) / float64(total) * 100
-}
-
-// ReportGlobalStats creates a report with statistics about all the
-// supported system calls for which errno mismatches were identified in
-// the verified programs, shown in decreasing order.
-func (s *Stats) ReportGlobalStats(w io.Writer, deltaTime float64) {
- tc := s.totalCallsExecuted()
- fmt.Fprintf(w, "total number of mismatches / total number of calls "+
- "executed: %d / %d (%0.2f %%)\n\n", s.TotalMismatches, tc, getPercentage(s.TotalMismatches, tc))
- fmt.Fprintf(w, "programs / minute: %0.2f\n\n", float64(s.TotalProgs)/deltaTime)
- fmt.Fprintf(w, "true mismatching programs: %d / total number of programs: %d (%0.2f %%)\n",
- s.MismatchingProgs, s.TotalProgs, getPercentage(s.MismatchingProgs, s.TotalProgs))
- fmt.Fprintf(w, "flaky programs: %d / total number of programs: %d (%0.2f %%)\n\n",
- s.FlakyProgs, s.TotalProgs, getPercentage(s.FlakyProgs, s.TotalProgs))
- cs := s.getOrderedStats()
- for _, c := range cs {
- fmt.Fprintf(w, "%s\n", s.ReportCallStats(c.Name))
- }
+ "\t↳ %d distinct states identified: %v\n", syscallName, syscallName, syscallName, mismatches, occurrences,
+ getPercentage(mismatches, occurrences), syscallName, mismatches, stats.TotalMismatches,
+ getPercentage(mismatches, stats.TotalMismatches), len(syscallStat.States), stats.getOrderedStates(syscallName))
}
-func (s *Stats) totalCallsExecuted() int {
+func (stats *Stats) totalCallsExecuted() int {
t := 0
- for _, cs := range s.Calls {
+ for _, cs := range stats.Calls {
t += cs.Occurrences
}
return t
}
-func (s *Stats) getOrderedStats() []*CallStats {
+func (stats *Stats) getOrderedStats() []*CallStats {
css := make([]*CallStats, 0)
- for _, cs := range s.Calls {
+ for _, cs := range stats.Calls {
if cs.Mismatches > 0 {
css = append(css, cs)
}
@@ -132,8 +116,8 @@ func (s *Stats) getOrderedStats() []*CallStats {
return css
}
-func (s *Stats) getOrderedStates(call string) []string {
- states := s.Calls[call].States
+func (stats *Stats) getOrderedStates(call string) []string {
+ states := stats.Calls[call].States
ss := make([]string, 0, len(states))
for s := range states {
ss = append(ss, fmt.Sprintf("%q", s))
@@ -141,3 +125,7 @@ func (s *Stats) getOrderedStates(call string) []string {
sort.Strings(ss)
return ss
}
+
+func getPercentage(value, total int) float64 {
+ return float64(value) / float64(total) * 100
+}
diff --git a/syz-verifier/stats_test.go b/syz-verifier/stats_test.go
index 38f4f4661..e553e3827 100644
--- a/syz-verifier/stats_test.go
+++ b/syz-verifier/stats_test.go
@@ -3,7 +3,6 @@
package main
import (
- "bytes"
"testing"
"github.com/google/go-cmp/cmp"
@@ -32,7 +31,7 @@ func dummyStats() *Stats {
}
}
-func TestReportCallStats(t *testing.T) {
+func TestGetCallStatsTextDescription(t *testing.T) {
tests := []struct {
name, call, report string
}{
@@ -55,19 +54,18 @@ func TestReportCallStats(t *testing.T) {
for _, test := range tests {
s := dummyStats()
t.Run(test.name, func(t *testing.T) {
- got, want := s.ReportCallStats(test.call), test.report
+ got, want := s.getCallStatsTextDescription(test.call), test.report
if diff := cmp.Diff(want, got); diff != "" {
- t.Errorf("s.ReportCallStats mismatch (-want +got):\n%s", diff)
+ t.Errorf("s.getCallStatsTextDescription mismatch (-want +got):\n%s", diff)
}
})
}
}
-func TestReportGlobalStats(t *testing.T) {
- s := dummyStats()
- out := bytes.Buffer{}
- s.ReportGlobalStats(&out, float64(10))
- got, want := out.String(),
+func TestGetTextDescription(t *testing.T) {
+ stats := dummyStats()
+
+ got, want := stats.GetTextDescription(float64(10)),
"total number of mismatches / total number of calls "+
"executed: 10 / 20 (50.00 %)\n\n"+
"programs / minute: 2.40\n\n"+
@@ -93,6 +91,6 @@ func TestReportGlobalStats(t *testing.T) {
"[\"Flags: 7, Errno: 1 (operation not permitted)\" \"Flags: 7, Errno: 3 (no such process)\"]\n\n"
if diff := cmp.Diff(want, got); diff != "" {
- t.Errorf("s.ReportGlobalStats mismatch (-want +got):\n%s", diff)
+ t.Errorf("s.GetTextDescription mismatch (-want +got):\n%s", diff)
}
}