aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDmitry Vyukov <dvyukov@google.com>2017-06-29 16:01:03 +0200
committerDmitry Vyukov <dvyukov@google.com>2017-06-29 17:50:44 +0200
commitc5b6fcddca80153daba328334bc48caa3a546ab5 (patch)
treeffe7680d084c29bec80f912a087b155981392e79
parentae33f0dff59bbd493d48eabe521b33981a785271 (diff)
syz-hub: split client name and manager name
This allows to reduce number of hub clients by grouping managers and creating one client per such group.
-rw-r--r--Makefile5
-rw-r--r--docs/hub.md (renamed from docs/connecting_several_managers.md)17
-rw-r--r--pkg/rpctype/rpctype.go30
-rw-r--r--syz-hub/hub.go64
-rw-r--r--syz-manager/manager.go21
-rw-r--r--syz-manager/mgrconfig/mgrconfig.go16
6 files changed, 89 insertions, 64 deletions
diff --git a/Makefile b/Makefile
index 9ff948f78..9b719780b 100644
--- a/Makefile
+++ b/Makefile
@@ -6,7 +6,7 @@ ifeq ($(NOSTATIC), 0)
STATIC_FLAG=-static
endif
-.PHONY: all format tidy clean manager fuzzer executor execprog ci mutate prog2c stress extract generate repro db bin/syz-extract bin/syz-sysgen android
+.PHONY: all format tidy clean manager fuzzer executor execprog ci hub mutate prog2c stress extract generate repro db bin/syz-extract bin/syz-sysgen android
all:
go install ./syz-manager ./syz-fuzzer
@@ -39,6 +39,9 @@ execprog:
ci:
go build $(GOFLAGS) -o ./bin/syz-ci github.com/google/syzkaller/syz-ci
+hub:
+ go build $(GOFLAGS) -o ./bin/syz-hub github.com/google/syzkaller/syz-hub
+
repro:
go build $(GOFLAGS) -o ./bin/syz-repro github.com/google/syzkaller/tools/syz-repro
diff --git a/docs/connecting_several_managers.md b/docs/hub.md
index 9925bbfb6..7b7cb3f8c 100644
--- a/docs/connecting_several_managers.md
+++ b/docs/hub.md
@@ -1,15 +1,16 @@
-# How to connect several managers via Hub
+# Connecting several managers via Hub
-`syz-hub` program can be used to connect several `syz-manager`'s together and allow them to exchange programs.
+`syz-hub` program can be used to connect several `syz-manager`'s together and
+allow them to exchange programs.
-Build `syz-hub` with `go install github.com/google/syzkaller/syz-hub`. Then create a config file along the lines of:
+Build `syz-hub` with `make hub`. Then create a config file along the lines of:
```
{
"http": ":80",
"rpc": ":55555",
"workdir": "/syzkaller/workdir",
- "managers": [
+ "clients": [
{"name": "manager1", "key": "6sCFsJVfyFQVhWVKJpKhHcHxpCH0gAxL"},
{"name": "manager2", "key": "FZFSjthHHf8nKm2cqqAcAYKM5a3XM4Ao"},
{"name": "manager3", "key": "fTrIBQCmkEq8NsvQXZiOUyop6uWLBuzf"}
@@ -17,12 +18,16 @@ Build `syz-hub` with `go install github.com/google/syzkaller/syz-hub`. Then crea
}
```
-And start it with `$GOPATH/syz-hub -config hub.cfg`. Then add the following additional parameters to `syz-manager` config files of each manager:
+And start it with `bin/syz-hub -config hub.cfg`. Then add the following
+additional parameters to `syz-manager` config files of each manager:
```
"name": "manager1",
+ "hub_client": "manager1",
"hub_addr": "1.2.3.4:55555",
"hub_key": "6sCFsJVfyFQVhWVKJpKhHcHxpCH0gAxL",
```
-And start managers. Once they triage local corpus, they will connect to the hub and start exchanging inputs. Both hub and manager web pages will show how many inputs they send/receive from the hub.
+And start managers. Once they triage local corpus, they will connect to the hub
+and start exchanging inputs. Both hub and manager web pages will show how many
+inputs they send/receive from the hub.
diff --git a/pkg/rpctype/rpctype.go b/pkg/rpctype/rpctype.go
index 8b251b717..ab3f2243a 100644
--- a/pkg/rpctype/rpctype.go
+++ b/pkg/rpctype/rpctype.go
@@ -58,21 +58,35 @@ type PollRes struct {
}
type HubConnectArgs struct {
- Name string
+ // Client/Key are used for authentication.
+ Client string
Key string
- Fresh bool
- Calls []string
+ // Manager name, must start with Client.
+ Manager string
+ // Manager has started with an empty corpus and requests whole hub corpus.
+ Fresh bool
+ // Set of system call names supported by this manager.
+ // Used to filter out programs with unsupported calls.
+ Calls []string
+ // Current manager corpus.
Corpus [][]byte
}
type HubSyncArgs struct {
- Name string
- Key string
- Add [][]byte
- Del []string
+ // see HubConnectArgs.
+ Client string
+ Key string
+ Manager string
+ // Programs added to corpus since last sync or connect.
+ Add [][]byte
+ // Hashed of programs removed from corpus since last sync or connect.
+ Del []string
}
type HubSyncRes struct {
+ // Set of programs from other managers.
Inputs [][]byte
- More int
+ // Number of remaining pending programs,
+ // if >0 manager should do sync again.
+ More int
}
diff --git a/syz-hub/hub.go b/syz-hub/hub.go
index 410660f9f..6e44c51cd 100644
--- a/syz-hub/hub.go
+++ b/syz-hub/hub.go
@@ -4,12 +4,12 @@
package main
import (
- "encoding/json"
"flag"
"fmt"
- "io/ioutil"
+ "strings"
"sync"
+ "github.com/google/syzkaller/pkg/config"
. "github.com/google/syzkaller/pkg/log"
. "github.com/google/syzkaller/pkg/rpctype"
"github.com/google/syzkaller/syz-hub/state"
@@ -17,15 +17,13 @@ import (
var (
flagConfig = flag.String("config", "", "config file")
-
- cfg *Config
)
type Config struct {
- Http string
- Rpc string
- Workdir string
- Managers []struct {
+ Http string
+ Rpc string
+ Workdir string
+ Clients []struct {
Name string
Key string
}
@@ -39,7 +37,10 @@ type Hub struct {
func main() {
flag.Parse()
- cfg = readConfig(*flagConfig)
+ cfg := new(Config)
+ if err := config.LoadFile(*flagConfig, cfg); err != nil {
+ Fatal(err)
+ }
EnableLogCaching(1000, 1<<20)
st, err := state.Make(cfg.Workdir)
@@ -50,7 +51,7 @@ func main() {
st: st,
keys: make(map[string]string),
}
- for _, mgr := range cfg.Managers {
+ for _, mgr := range cfg.Clients {
hub.keys[mgr.Name] = mgr.Key
}
@@ -65,15 +66,16 @@ func main() {
}
func (hub *Hub) Connect(a *HubConnectArgs, r *int) error {
- if key, ok := hub.keys[a.Name]; !ok || key != a.Key {
- Logf(0, "connect from unauthorized manager %v", a.Name)
- return fmt.Errorf("unauthorized manager")
+ name, err := hub.auth(a.Client, a.Key, a.Manager)
+ if err != nil {
+ return err
}
hub.mu.Lock()
defer hub.mu.Unlock()
- Logf(0, "connect from %v: fresh=%v calls=%v corpus=%v", a.Name, a.Fresh, len(a.Calls), len(a.Corpus))
- if err := hub.st.Connect(a.Name, a.Fresh, a.Calls, a.Corpus); err != nil {
+ Logf(0, "connect from %v: fresh=%v calls=%v corpus=%v",
+ name, a.Fresh, len(a.Calls), len(a.Corpus))
+ if err := hub.st.Connect(name, a.Fresh, a.Calls, a.Corpus); err != nil {
Logf(0, "connect error: %v", err)
return err
}
@@ -81,35 +83,35 @@ func (hub *Hub) Connect(a *HubConnectArgs, r *int) error {
}
func (hub *Hub) Sync(a *HubSyncArgs, r *HubSyncRes) error {
- if key, ok := hub.keys[a.Name]; !ok || key != a.Key {
- Logf(0, "sync from unauthorized manager %v", a.Name)
- return fmt.Errorf("unauthorized manager")
+ name, err := hub.auth(a.Client, a.Key, a.Manager)
+ if err != nil {
+ return err
}
hub.mu.Lock()
defer hub.mu.Unlock()
- inputs, more, err := hub.st.Sync(a.Name, a.Add, a.Del)
+ inputs, more, err := hub.st.Sync(name, a.Add, a.Del)
if err != nil {
Logf(0, "sync error: %v", err)
return err
}
r.Inputs = inputs
r.More = more
- Logf(0, "sync from %v: add=%v del=%v new=%v pending=%v", a.Name, len(a.Add), len(a.Del), len(inputs), more)
+ Logf(0, "sync from %v: add=%v del=%v new=%v pending=%v",
+ name, len(a.Add), len(a.Del), len(inputs), more)
return nil
}
-func readConfig(filename string) *Config {
- if filename == "" {
- Fatalf("supply config in -config flag")
+func (hub *Hub) auth(client, key, manager string) (string, error) {
+ if key, ok := hub.keys[client]; !ok || key != key {
+ Logf(0, "connect from unauthorized client %v", client)
+ return "", fmt.Errorf("unauthorized manager")
}
- data, err := ioutil.ReadFile(filename)
- if err != nil {
- Fatalf("failed to read config file: %v", err)
- }
- cfg := new(Config)
- if err := json.Unmarshal(data, cfg); err != nil {
- Fatalf("failed to parse config file: %v", err)
+ if manager == "" {
+ manager = client
+ } else if !strings.HasPrefix(manager, client) {
+ Logf(0, "manager %v does not have client prefix %v", manager, client)
+ return "", fmt.Errorf("unauthorized manager")
}
- return cfg
+ return manager, nil
}
diff --git a/syz-manager/manager.go b/syz-manager/manager.go
index 0b4ae3dc2..68e4a4348 100644
--- a/syz-manager/manager.go
+++ b/syz-manager/manager.go
@@ -280,7 +280,7 @@ func RunManager(cfg *mgrconfig.Config, syscalls map[int]bool) {
}()
}
- if mgr.cfg.Hub_Addr != "" {
+ if mgr.cfg.Hub_Client != "" {
go func() {
for {
time.Sleep(time.Minute)
@@ -858,7 +858,7 @@ func (mgr *Manager) Poll(a *PollArgs, r *PollRes) error {
if len(mgr.candidates) == 0 {
mgr.candidates = nil
if mgr.phase == phaseInit {
- if mgr.cfg.Hub_Addr != "" {
+ if mgr.cfg.Hub_Client != "" {
mgr.phase = phaseTriagedCorpus
} else {
mgr.phase = phaseTriagedHub
@@ -891,10 +891,11 @@ func (mgr *Manager) hubSync() {
mgr.minimizeCorpus()
if mgr.hub == nil {
a := &HubConnectArgs{
- Name: mgr.cfg.Name,
- Key: mgr.cfg.Hub_Key,
- Fresh: mgr.fresh,
- Calls: mgr.enabledCalls,
+ Client: mgr.cfg.Hub_Client,
+ Key: mgr.cfg.Hub_Key,
+ Manager: mgr.cfg.Name,
+ Fresh: mgr.fresh,
+ Calls: mgr.enabledCalls,
}
hubCorpus := make(map[hash.Sig]bool)
for _, inp := range mgr.corpus {
@@ -924,8 +925,9 @@ func (mgr *Manager) hubSync() {
}
a := &HubSyncArgs{
- Name: mgr.cfg.Name,
- Key: mgr.cfg.Hub_Key,
+ Client: mgr.cfg.Hub_Client,
+ Key: mgr.cfg.Hub_Key,
+ Manager: mgr.cfg.Name,
}
corpus := make(map[hash.Sig]bool)
for _, inp := range mgr.corpus {
@@ -971,7 +973,8 @@ func (mgr *Manager) hubSync() {
mgr.stats["hub del"] += uint64(len(a.Del))
mgr.stats["hub drop"] += uint64(dropped)
mgr.stats["hub new"] += uint64(len(r.Inputs) - dropped)
- Logf(0, "hub sync: add %v, del %v, drop %v, new %v, more %v", len(a.Add), len(a.Del), dropped, len(r.Inputs)-dropped, r.More)
+ Logf(0, "hub sync: add %v, del %v, drop %v, new %v, more %v",
+ len(a.Add), len(a.Del), dropped, len(r.Inputs)-dropped, r.More)
if len(r.Inputs)+r.More == 0 {
break
}
diff --git a/syz-manager/mgrconfig/mgrconfig.go b/syz-manager/mgrconfig/mgrconfig.go
index d6e2b4a2e..7a7aad74f 100644
--- a/syz-manager/mgrconfig/mgrconfig.go
+++ b/syz-manager/mgrconfig/mgrconfig.go
@@ -26,8 +26,9 @@ type Config struct {
Image string // linux image for VMs
Sshkey string // root ssh key for the image (may be empty for some VM types)
- Hub_Addr string
- Hub_Key string
+ Hub_Client string
+ Hub_Addr string
+ Hub_Key string
Dashboard_Addr string
Dashboard_Key string
@@ -126,14 +127,11 @@ func load(data []byte, filename string) (*Config, map[int]bool, error) {
return nil, nil, err
}
- if (cfg.Hub_Addr != "" || cfg.Dashboard_Addr != "") && cfg.Name == "" {
- return nil, nil, fmt.Errorf("hub_addr//dashboard_addr is set, but name is empty")
+ if cfg.Hub_Client != "" && (cfg.Name == "" || cfg.Hub_Addr == "" || cfg.Hub_Key == "") {
+ return nil, nil, fmt.Errorf("hub_client is set, but name/hub_addr/hub_key is empty")
}
- if cfg.Hub_Addr != "" && cfg.Hub_Key == "" {
- return nil, nil, fmt.Errorf("hub_addr is set, but hub_key is empty")
- }
- if cfg.Dashboard_Addr != "" && cfg.Dashboard_Key == "" {
- return nil, nil, fmt.Errorf("dashboard_addr is set, but dashboard_key is empty")
+ if cfg.Dashboard_Addr != "" && (cfg.Name == "" || cfg.Dashboard_Key == "") {
+ return nil, nil, fmt.Errorf("dashboard_addr is set, but name/dashboard_key is empty")
}
return cfg, syscalls, nil