aboutsummaryrefslogtreecommitdiffstats
path: root/syz-manager/hub.go
diff options
context:
space:
mode:
authorDmitry Vyukov <dvyukov@google.com>2020-12-02 17:24:59 +0100
committerDmitry Vyukov <dvyukov@google.com>2020-12-03 10:01:52 +0100
commit15ab7140c0419b3ca8c88e153d9876b3c8aae0eb (patch)
tree6011ed8e432d53f2c9cb06368f57391254702b58 /syz-manager/hub.go
parent8c9190ef9ef69993519136740a4e67c74f45fdb3 (diff)
syz-hub: support input domains
Hub input domain identifier (optional). The domain is used to avoid duplicate work (input minimization, smashing) across multiple managers testing similar kernels and connected to the same hub. If two managers are in the same domain, they will not do input minimization after each other. If additionally they are in the same smashing sub-domain, they will also not do smashing after each other. By default (empty domain) all managers testing the same OS are placed into the same domain, this is a reasonable setting if managers test roughly the same kernel. In this case they will not do minimization nor smashing after each other. The setting can be either a single identifier (e.g. "foo") which will affect both minimization and smashing; or two identifiers separated with '/' (e.g. "foo/bar"), in this case the first identifier affects minimization and both affect smashing. For example, if managers test different Linux kernel versions with different tools, a reasonable use of domains on these managers can be: - "upstream/kasan" - "upstream/kmsan" - "upstream/kcsan" - "5.4/kasan" - "5.4/kcsan" - "4.19/kasan" Fixes #2095
Diffstat (limited to 'syz-manager/hub.go')
-rw-r--r--syz-manager/hub.go62
1 files changed, 51 insertions, 11 deletions
diff --git a/syz-manager/hub.go b/syz-manager/hub.go
index 9028f0233..2dd0cdf34 100644
--- a/syz-manager/hub.go
+++ b/syz-manager/hub.go
@@ -4,6 +4,7 @@
package main
import (
+ "strings"
"time"
"github.com/google/syzkaller/pkg/hash"
@@ -21,6 +22,7 @@ func (mgr *Manager) hubSyncLoop() {
cfg: mgr.cfg,
target: mgr.target,
stats: mgr.stats,
+ domain: mgr.cfg.TargetOS + "/" + mgr.cfg.HubDomain,
enabledCalls: mgr.targetEnabledSyscalls,
leak: mgr.checkResult.Features[host.FeatureLeak].Enabled,
fresh: mgr.fresh,
@@ -37,6 +39,7 @@ type HubConnector struct {
cfg *mgrconfig.Config
target *prog.Target
stats *Stats
+ domain string
enabledCalls map[*prog.Syscall]bool
leak bool
fresh bool
@@ -49,7 +52,7 @@ type HubConnector struct {
// HubManagerView restricts interface between HubConnector and Manager.
type HubManagerView interface {
getMinimizedCorpus() (corpus, repros [][]byte)
- addNewCandidates(progs [][]byte)
+ addNewCandidates(candidates []rpctype.RPCCandidate)
}
func (hc *HubConnector) loop() {
@@ -143,7 +146,7 @@ func (hc *HubConnector) sync(hub *rpctype.RPCClient, corpus [][]byte) error {
if err := hub.Call("Hub.Sync", a, r); err != nil {
return err
}
- progDropped := hc.processProgs(r.Progs)
+ minimized, smashed, progDropped := hc.processProgs(r.Inputs)
reproDropped := hc.processRepros(r.Repros)
hc.stats.hubSendProgAdd.add(len(a.Add))
hc.stats.hubSendProgDel.add(len(a.Del))
@@ -153,9 +156,10 @@ func (hc *HubConnector) sync(hub *rpctype.RPCClient, corpus [][]byte) error {
hc.stats.hubRecvRepro.add(len(r.Repros) - reproDropped)
hc.stats.hubRecvReproDrop.add(reproDropped)
log.Logf(0, "hub sync: send: add %v, del %v, repros %v;"+
- " recv: progs %v, repros %v; more %v",
+ " recv: progs %v (min %v, smash %v), repros %v; more %v",
len(a.Add), len(a.Del), len(a.Repros),
- len(r.Progs)-progDropped, len(r.Repros)-reproDropped, r.More)
+ len(r.Progs)-progDropped, minimized, smashed,
+ len(r.Repros)-reproDropped, r.More)
a.Add = nil
a.Del = nil
a.Repros = nil
@@ -167,21 +171,57 @@ func (hc *HubConnector) sync(hub *rpctype.RPCClient, corpus [][]byte) error {
}
}
-func (hc *HubConnector) processProgs(progs [][]byte) int {
- dropped := 0
- candidates := make([][]byte, 0, len(progs))
- for _, inp := range progs {
- bad, disabled := checkProgram(hc.target, hc.enabledCalls, inp)
+func (hc *HubConnector) processProgs(inputs []rpctype.HubInput) (minimized, smashed, dropped int) {
+ candidates := make([]rpctype.RPCCandidate, 0, len(inputs))
+ for _, inp := range inputs {
+ bad, disabled := checkProgram(hc.target, hc.enabledCalls, inp.Prog)
if bad || disabled {
log.Logf(0, "rejecting program from hub (bad=%v, disabled=%v):\n%s",
bad, disabled, inp)
dropped++
continue
}
- candidates = append(candidates, inp)
+ min, smash := matchDomains(hc.domain, inp.Domain)
+ if min {
+ minimized++
+ }
+ if smash {
+ smashed++
+ }
+ candidates = append(candidates, rpctype.RPCCandidate{
+ Prog: inp.Prog,
+ Minimized: min,
+ Smashed: smash,
+ })
}
hc.mgr.addNewCandidates(candidates)
- return dropped
+ return
+}
+
+func matchDomains(self, input string) (bool, bool) {
+ if self == "" || input == "" {
+ return true, true
+ }
+ min0, smash0 := splitDomains(self)
+ min1, smash1 := splitDomains(input)
+ min := min0 != min1
+ smash := min || smash0 != smash1
+ return min, smash
+}
+
+func splitDomains(domain string) (string, string) {
+ delim0 := strings.IndexByte(domain, '/')
+ if delim0 == -1 {
+ return domain, ""
+ }
+ if delim0 == len(domain)-1 {
+ return domain[:delim0], ""
+ }
+ delim1 := strings.IndexByte(domain[delim0+1:], '/')
+ if delim1 == -1 {
+ return domain, ""
+ }
+ return domain[:delim0+delim1+1], domain[delim0+delim1+2:]
}
func (hc *HubConnector) processRepros(repros [][]byte) int {