aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDmitry Vyukov <dvyukov@google.com>2024-03-28 18:11:09 +0100
committerDmitry Vyukov <dvyukov@google.com>2024-04-02 09:54:48 +0000
commitf861ecca8b4dbdc9f71c3271d1eb6dbc0f71b5c6 (patch)
tree859cab799bcd1fa814af51fb807ce950ad7b0d2f
parent6baf506947ba27ed9ce775cf9351cb0886166083 (diff)
syz-fuzzer: use of monotonic time for latency measurement
time.Now/Since may reject to use monotonic time if the fuzzer messes with system time badly enough. Enforce use of monotonic time.
-rw-r--r--pkg/osutil/osutil.go12
-rw-r--r--pkg/osutil/osutil_test.go10
-rw-r--r--syz-fuzzer/fuzzer.go4
-rw-r--r--tools/syz-linter/linter.go2
4 files changed, 25 insertions, 3 deletions
diff --git a/pkg/osutil/osutil.go b/pkg/osutil/osutil.go
index 478c091dc..a619f9169 100644
--- a/pkg/osutil/osutil.go
+++ b/pkg/osutil/osutil.go
@@ -17,6 +17,7 @@ import (
"sync"
"syscall"
"time"
+ _ "unsafe" // required to use go:linkname
)
const (
@@ -337,3 +338,14 @@ func Abs(path string) string {
}
return filepath.Join(wd, path)
}
+
+// MonotonicNano returns monotonic time in nanoseconds from some unspecified point in time.
+// Useful mostly to measure time intervals.
+// This function should be used inside of tested VMs b/c time.Now may reject to use monotonic time
+// if the fuzzer messes with system time (sets time past Y2157, see comments in time/time.go).
+// This is a hacky way to use the private runtime function.
+// If this ever breaks, we can either provide specializations for different Go versions
+// using build tags, or fall back to time.Now.
+//
+//go:linkname MonotonicNano runtime.nanotime
+func MonotonicNano() time.Duration
diff --git a/pkg/osutil/osutil_test.go b/pkg/osutil/osutil_test.go
index 713a62c14..7d5913b4a 100644
--- a/pkg/osutil/osutil_test.go
+++ b/pkg/osutil/osutil_test.go
@@ -9,6 +9,7 @@ import (
"path/filepath"
"strings"
"testing"
+ "time"
)
func TestIsExist(t *testing.T) {
@@ -119,3 +120,12 @@ func TestCopyFiles(t *testing.T) {
})
}
}
+
+func TestMonotonicNano(t *testing.T) {
+ start := MonotonicNano()
+ time.Sleep(100 * time.Millisecond)
+ diff := MonotonicNano() - start
+ if diff <= 0 || diff > 10*time.Second {
+ t.Fatalf("diff %v", diff)
+ }
+}
diff --git a/syz-fuzzer/fuzzer.go b/syz-fuzzer/fuzzer.go
index f539de6f6..fb7f57b30 100644
--- a/syz-fuzzer/fuzzer.go
+++ b/syz-fuzzer/fuzzer.go
@@ -347,11 +347,11 @@ func (tool *FuzzerTool) exchangeDataCall(needProgs int, results []executionResul
a.Results = append(a.Results, tool.convertExecutionResult(result))
}
r := &rpctype.ExchangeInfoReply{}
- start := time.Now()
+ start := osutil.MonotonicNano()
if err := tool.manager.Call("Manager.ExchangeInfo", a, r); err != nil {
log.SyzFatalf("Manager.ExchangeInfo call failed: %v", err)
}
- latency = time.Since(start)
+ latency = osutil.MonotonicNano() - start
if needProgs != len(r.Requests) {
log.SyzFatalf("manager returned wrong number of requests: %v/%v", needProgs, len(r.Requests))
}
diff --git a/tools/syz-linter/linter.go b/tools/syz-linter/linter.go
index 76168c7c9..542d040e6 100644
--- a/tools/syz-linter/linter.go
+++ b/tools/syz-linter/linter.go
@@ -139,7 +139,7 @@ var (
noPeriodComment = regexp.MustCompile(`^// [A-Z][a-z].+[a-z]$`)
lowerCaseComment = regexp.MustCompile(`^// [a-z]+ `)
onelineExceptions = regexp.MustCompile(`// want \"|http:|https:`)
- specialComment = regexp.MustCompile(`//go:generate|//go:build|//go:embed|// nolint:`)
+ specialComment = regexp.MustCompile(`//go:generate|//go:build|//go:embed|//go:linkname|// nolint:`)
)
// checkStringLenCompare checks for string len comparisons with 0.