aboutsummaryrefslogtreecommitdiffstats
path: root/pkg
diff options
context:
space:
mode:
Diffstat (limited to 'pkg')
-rw-r--r--pkg/host/features.go2
-rw-r--r--pkg/host/features_linux.go62
-rw-r--r--pkg/host/host_freebsd.go1
-rw-r--r--pkg/host/host_netbsd.go1
-rw-r--r--pkg/host/host_openbsd.go1
-rw-r--r--pkg/ipc/ipc.go1
-rw-r--r--pkg/runtest/run.go3
7 files changed, 57 insertions, 14 deletions
diff --git a/pkg/host/features.go b/pkg/host/features.go
index f3f4af30c..d2105b203 100644
--- a/pkg/host/features.go
+++ b/pkg/host/features.go
@@ -19,6 +19,7 @@ const (
FeatureCoverage = iota
FeatureComparisons
FeatureExtraCoverage
+ FeatureDelayKcovMmap
FeatureSandboxSetuid
FeatureSandboxNamespace
FeatureSandboxAndroid
@@ -60,6 +61,7 @@ func Check(target *prog.Target) (*Features, error) {
FeatureCoverage: {Name: "code coverage", Reason: unsupported},
FeatureComparisons: {Name: "comparison tracing", Reason: unsupported},
FeatureExtraCoverage: {Name: "extra coverage", Reason: unsupported},
+ FeatureDelayKcovMmap: {Name: "delay kcov mmap", Reason: unsupported},
FeatureSandboxSetuid: {Name: "setuid sandbox", Reason: unsupported},
FeatureSandboxNamespace: {Name: "namespace sandbox", Reason: unsupported},
FeatureSandboxAndroid: {Name: "Android sandbox", Reason: unsupported},
diff --git a/pkg/host/features_linux.go b/pkg/host/features_linux.go
index 5c45bdcc1..de04e7a4d 100644
--- a/pkg/host/features_linux.go
+++ b/pkg/host/features_linux.go
@@ -7,6 +7,7 @@ import (
"fmt"
"regexp"
"runtime"
+ "runtime/debug"
"strconv"
"syscall"
"unsafe"
@@ -21,6 +22,7 @@ func init() {
checkFeature[FeatureCoverage] = checkCoverage
checkFeature[FeatureComparisons] = checkComparisons
checkFeature[FeatureExtraCoverage] = checkExtraCoverage
+ checkFeature[FeatureDelayKcovMmap] = checkDelayKcovMmap
checkFeature[FeatureSandboxSetuid] = unconditionallyEnabled
checkFeature[FeatureSandboxNamespace] = checkSandboxNamespace
checkFeature[FeatureSandboxAndroid] = checkSandboxAndroid
@@ -57,6 +59,39 @@ func checkExtraCoverage() (reason string) {
return checkCoverageFeature(FeatureExtraCoverage)
}
+func checkDelayKcovMmap() string {
+ // The kcov implementation in Linux (currently) does not adequately handle subsequent
+ // mmap invocations on the same descriptor. When that problem is fixed, we want
+ // syzkaller to differentiate between distributions as this allows to noticeably speed
+ // up fuzzing.
+ return checkCoverageFeature(FeatureDelayKcovMmap)
+}
+
+func kcovTestMmap(fd int, coverSize uintptr) (reason string) {
+ mem, err := syscall.Mmap(fd, 0, int(coverSize*unsafe.Sizeof(uintptr(0))),
+ syscall.PROT_READ|syscall.PROT_WRITE, syscall.MAP_SHARED)
+ if err != nil {
+ return fmt.Sprintf("KCOV mmap failed: %v", err)
+ }
+ defer func() {
+ if err := syscall.Munmap(mem); err != nil {
+ reason = fmt.Sprintf("munmap failed: %v", err)
+ }
+ }()
+ // Now the tricky part - mmap may say it has succeeded, but the memory is
+ // in fact not allocated.
+ // We try to access it. If go does not panic, everything is fine.
+ prevValue := debug.SetPanicOnFault(true)
+ defer debug.SetPanicOnFault(prevValue)
+ defer func() {
+ if r := recover(); r != nil {
+ reason = "mmap returned an invalid pointer"
+ }
+ }()
+ mem[0] = 0
+ return ""
+}
+
func checkCoverageFeature(feature int) (reason string) {
if reason = checkDebugFS(); reason != "" {
return reason
@@ -80,16 +115,15 @@ func checkCoverageFeature(feature int) (reason string) {
if errno != 0 {
return fmt.Sprintf("ioctl(KCOV_INIT_TRACE) failed: %v", errno)
}
- mem, err := syscall.Mmap(fd, 0, int(coverSize*unsafe.Sizeof(uintptr(0))),
- syscall.PROT_READ|syscall.PROT_WRITE, syscall.MAP_SHARED)
- if err != nil {
- return fmt.Sprintf("KCOV mmap failed: %v", err)
+ if reason = kcovTestMmap(fd, coverSize); reason != "" {
+ return reason
}
- defer func() {
- if err := syscall.Munmap(mem); err != nil {
- reason = fmt.Sprintf("munmap failed: %v", err)
+ disableKcov := func() {
+ _, _, errno = syscall.Syscall(syscall.SYS_IOCTL, uintptr(fd), linux.KCOV_DISABLE, 0)
+ if errno != 0 {
+ reason = fmt.Sprintf("ioctl(KCOV_DISABLE) failed: %v", errno)
}
- }()
+ }
switch feature {
case FeatureComparisons:
_, _, errno = syscall.Syscall(syscall.SYS_IOCTL,
@@ -100,6 +134,7 @@ func checkCoverageFeature(feature int) (reason string) {
}
return fmt.Sprintf("ioctl(KCOV_TRACE_CMP) failed: %v", errno)
}
+ defer disableKcov()
case FeatureExtraCoverage:
arg := KcovRemoteArg{
TraceMode: uint32(linux.KCOV_TRACE_PC),
@@ -115,15 +150,14 @@ func checkCoverageFeature(feature int) (reason string) {
}
return fmt.Sprintf("ioctl(KCOV_REMOTE_ENABLE) failed: %v", errno)
}
+ defer disableKcov()
+ case FeatureDelayKcovMmap:
+ if reason = kcovTestMmap(fd, coverSize); reason != "" {
+ return reason
+ }
default:
panic("unknown feature in checkCoverageFeature")
}
- defer func() {
- _, _, errno = syscall.Syscall(syscall.SYS_IOCTL, uintptr(fd), linux.KCOV_DISABLE, 0)
- if errno != 0 {
- reason = fmt.Sprintf("ioctl(KCOV_DISABLE) failed: %v", errno)
- }
- }()
return ""
}
diff --git a/pkg/host/host_freebsd.go b/pkg/host/host_freebsd.go
index 0f86a1f9c..726429c18 100644
--- a/pkg/host/host_freebsd.go
+++ b/pkg/host/host_freebsd.go
@@ -14,5 +14,6 @@ func isSupported(c *prog.Syscall, target *prog.Target, sandbox string) (bool, st
func init() {
checkFeature[FeatureCoverage] = unconditionallyEnabled
checkFeature[FeatureComparisons] = unconditionallyEnabled
+ checkFeature[FeatureDelayKcovMmap] = unconditionallyEnabled
checkFeature[FeatureNetInjection] = unconditionallyEnabled
}
diff --git a/pkg/host/host_netbsd.go b/pkg/host/host_netbsd.go
index aa0a6e88a..e4de2d408 100644
--- a/pkg/host/host_netbsd.go
+++ b/pkg/host/host_netbsd.go
@@ -23,6 +23,7 @@ func init() {
checkFeature[FeatureComparisons] = unconditionallyEnabled
checkFeature[FeatureUSBEmulation] = checkUSBEmulation
checkFeature[FeatureExtraCoverage] = checkUSBEmulation
+ checkFeature[FeatureDelayKcovMmap] = unconditionallyEnabled
checkFeature[FeatureFault] = checkFault
}
diff --git a/pkg/host/host_openbsd.go b/pkg/host/host_openbsd.go
index 23e219115..3099bc771 100644
--- a/pkg/host/host_openbsd.go
+++ b/pkg/host/host_openbsd.go
@@ -32,6 +32,7 @@ func init() {
checkFeature[FeatureCoverage] = unconditionallyEnabled
checkFeature[FeatureComparisons] = unconditionallyEnabled
checkFeature[FeatureExtraCoverage] = unconditionallyEnabled
+ checkFeature[FeatureDelayKcovMmap] = unconditionallyEnabled
checkFeature[FeatureNetInjection] = unconditionallyEnabled
checkFeature[FeatureSandboxSetuid] = unconditionallyEnabled
}
diff --git a/pkg/ipc/ipc.go b/pkg/ipc/ipc.go
index f6bf3f61f..03b28e4ce 100644
--- a/pkg/ipc/ipc.go
+++ b/pkg/ipc/ipc.go
@@ -42,6 +42,7 @@ const (
FlagEnableDevlinkPCI // setup devlink PCI device
FlagEnableVhciInjection // setup and use /dev/vhci for hci packet injection
FlagEnableWifi // setup and use mac80211_hwsim for wifi emulation
+ FlagDelayKcovMmap // manage kcov memory in an optimized way
)
// Per-exec flags for ExecOpts.Flags.
diff --git a/pkg/runtest/run.go b/pkg/runtest/run.go
index 5a071676a..1d3412cb0 100644
--- a/pkg/runtest/run.go
+++ b/pkg/runtest/run.go
@@ -412,6 +412,9 @@ func (ctx *Context) createSyzTest(p *prog.Prog, sandbox string, threaded, cov bo
if ctx.Features[host.FeatureExtraCoverage].Enabled {
cfg.Flags |= ipc.FlagExtraCover
}
+ if ctx.Features[host.FeatureDelayKcovMmap].Enabled {
+ cfg.Flags |= ipc.FlagDelayKcovMmap
+ }
if ctx.Features[host.FeatureNetInjection].Enabled {
cfg.Flags |= ipc.FlagEnableTun
}