aboutsummaryrefslogtreecommitdiffstats
path: root/master
diff options
context:
space:
mode:
authorDmitry Vyukov <dvyukov@google.com>2015-12-17 16:06:33 +0100
committerDmitry Vyukov <dvyukov@google.com>2015-12-17 16:06:33 +0100
commit8e7ca7c5ff18e17cab7b6b3ae569565224f95fcc (patch)
tree613bbb3f12f7f2f63ad225648f6971a1393d3703 /master
parent06e67265374faa677dba2dbd2577054278f19823 (diff)
remove master and naming overhaul
Remove master process entirely, it is not useful in its current form. We first need to understand what we want from it, and them re-implement it. Prefix all binaries with syz- to avoid name clashes.
Diffstat (limited to 'master')
-rw-r--r--master/html.go95
-rw-r--r--master/master.go170
-rw-r--r--master/persistent.go129
3 files changed, 0 insertions, 394 deletions
diff --git a/master/html.go b/master/html.go
deleted file mode 100644
index 40159d156..000000000
--- a/master/html.go
+++ /dev/null
@@ -1,95 +0,0 @@
-// Copyright 2015 syzkaller project authors. All rights reserved.
-// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
-
-package main
-
-import (
- "encoding/json"
- "fmt"
- "html/template"
- "io/ioutil"
- "net/http"
-)
-
-func (m *Master) httpInfo(w http.ResponseWriter, r *http.Request) {
- m.mu.Lock()
- defer m.mu.Unlock()
-
- data := &UIData{
- CorpusLen: len(m.corpus.m),
- }
- for _, mgr := range m.managers {
- data.Managers = append(data.Managers, UIManager{
- Name: mgr.name,
- Http: mgr.http,
- })
- }
- if err := htmlTemplate.Execute(w, data); err != nil {
- http.Error(w, fmt.Sprintf("failed to execute template: %v", err), http.StatusInternalServerError)
- }
-}
-
-func (m *Master) httpMinimize(w http.ResponseWriter, r *http.Request) {
- corpus := make(map[string]bool)
- for _, mgr := range m.managers {
- resp, err := http.Get("http://" + mgr.http + "/current_corpus")
- if err != nil {
- http.Error(w, fmt.Sprintf("failed to query corpus from %v: %v", mgr.name, err), http.StatusInternalServerError)
- return
- }
- defer resp.Body.Close()
- data, err := ioutil.ReadAll(resp.Body)
- if err != nil {
- http.Error(w, fmt.Sprintf("failed to query corpus from %v: %v", mgr.name, err), http.StatusInternalServerError)
- return
- }
- var hashes []string
- err = json.Unmarshal(data, &hashes)
- if err != nil || len(hashes) == 0 {
- http.Error(w, fmt.Sprintf("failed to parse corpus from %v: %v", mgr.name, err), http.StatusInternalServerError)
- return
- }
- for _, hash := range hashes {
- corpus[hash] = true
- }
- }
-
- m.mu.Lock()
- defer m.mu.Unlock()
-
- orig := len(m.corpus.m)
- m.corpus.minimize(corpus)
- fmt.Printf("minimized: %v -> %v -> %v\n", orig, len(corpus), len(m.corpus.m))
- for _, mgr := range m.managers {
- mgr.input = 0
- }
-}
-
-type UIData struct {
- CorpusLen int
- Managers []UIManager
-}
-
-type UIManager struct {
- Name string
- Http string
-}
-
-var htmlTemplate = template.Must(template.New("").Parse(`
-<!doctype html>
-<html>
-<head>
- <title>syzkaller master</title>
-</head>
-<body>
-Corpus: {{.CorpusLen}} <br>
-{{if .Managers}}
- Managers:<br>
- {{range $mgr := $.Managers}}
- <a href='http://{{$mgr.Http}}'>{{$mgr.Name}}</a><br>
- {{end}}
-{{else}}
- No managers connected<br>
-{{end}}
-</body></html>
-`))
diff --git a/master/master.go b/master/master.go
deleted file mode 100644
index c1a427732..000000000
--- a/master/master.go
+++ /dev/null
@@ -1,170 +0,0 @@
-// Copyright 2015 syzkaller project authors. All rights reserved.
-// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
-
-package main
-
-import (
- "flag"
- "fmt"
- "log"
- "net"
- "net/http"
- "net/rpc"
- "path/filepath"
- "sync"
- "time"
-
- "github.com/google/syzkaller/prog"
- . "github.com/google/syzkaller/rpctype"
-)
-
-var (
- flagWorkdir = flag.String("workdir", "", "dir with persistent artifacts")
- flagAddr = flag.String("addr", "", "RPC listen address to connect managers")
- flagHTTP = flag.String("http", "", "HTTP server listen address")
- flagV = flag.Int("v", 0, "verbosity")
-)
-
-// Master manages persistent fuzzer state (input corpus and crashers).
-type Master struct {
- mu sync.Mutex
- managers map[string]*Manager
- corpus *PersistentSet
- crashers *PersistentSet
- startTime time.Time
- lastInput time.Time
-}
-
-type Manager struct {
- name string
- http string
- input int
-}
-
-func main() {
- flag.Parse()
- if *flagWorkdir == "" {
- fatalf("-workdir is not set")
- }
- if *flagAddr == "" {
- fatalf("-addr is not set")
- }
- if *flagHTTP == "" {
- fatalf("-http is not set")
- }
- ln, err := net.Listen("tcp", *flagAddr)
- if err != nil {
- fatalf("failed to listen: %v", err)
- }
-
- m := &Master{}
- m.managers = make(map[string]*Manager)
- m.startTime = time.Now()
- m.lastInput = time.Now()
- logf(0, "loading corpus...")
- m.corpus = newPersistentSet(filepath.Join(*flagWorkdir, "corpus"), func(data []byte) bool {
- if _, err := prog.Deserialize(data); err != nil {
- logf(0, "deleting broken program: %v\n%s", err, data)
- return false
- }
- return true
- })
- m.crashers = newPersistentSet(filepath.Join(*flagWorkdir, "crashers"), nil)
-
- http.HandleFunc("/", m.httpInfo)
- http.HandleFunc("/minimize", m.httpMinimize)
- go func() {
- logf(0, "serving http on http://%v", *flagHTTP)
- panic(http.ListenAndServe(*flagHTTP, nil))
- }()
-
- logf(0, "serving rpc on tcp://%v", *flagAddr)
- s := rpc.NewServer()
- s.Register(m)
- go s.Accept(ln)
-
- m.loop()
-}
-
-func (m *Master) loop() {
- for range time.NewTicker(1 * time.Second).C {
- }
-}
-
-// Connect attaches new manager to master.
-func (m *Master) Connect(a *MasterConnectArgs, r *MasterConnectRes) error {
- logf(1, "connect from %v (http://%v)", a.Name, a.Http)
- m.mu.Lock()
- defer m.mu.Unlock()
-
- mgr := &Manager{
- name: a.Name,
- http: a.Http,
- }
- m.managers[a.Name] = mgr
- r.Http = *flagHTTP
- return nil
-}
-
-// NewInput saves new interesting input on master.
-func (m *Master) NewInput(a *NewMasterInputArgs, r *int) error {
- p, err := prog.Deserialize(a.Prog)
- if err != nil {
- logf(0, "bogus new input from %v: %v\n%s\n", a.Name, err, a.Prog)
- return fmt.Errorf("the program is bogus: %v", err)
- }
- m.mu.Lock()
- defer m.mu.Unlock()
-
- if !m.corpus.add(a.Prog) {
- return nil
- }
- m.lastInput = time.Now()
- logf(1, "new input from %v: %s", a.Name, p)
- return nil
-}
-
-type NewCrasherArgs struct {
- Name string
- Text []byte
- Suppression []byte
- Prog []byte
-}
-
-// NewCrasher saves new crasher input on master.
-func (m *Master) NewCrasher(a *NewCrasherArgs, r *int) error {
- logf(0, "new crasher from %v", a.Name)
- m.mu.Lock()
- defer m.mu.Unlock()
-
- if !m.crashers.add(a.Text) {
- return nil // Already have this.
- }
- return nil
-}
-
-func (m *Master) PollInputs(a *MasterPollArgs, r *MasterPollRes) error {
- logf(2, "poll from %v", a.Name)
- m.mu.Lock()
- defer m.mu.Unlock()
-
- mgr := m.managers[a.Name]
- if mgr == nil {
- return fmt.Errorf("manager is not connected")
- }
- for i := 0; i < 100 && mgr.input < len(m.corpus.a); i++ {
- r.Inputs = append(r.Inputs, m.corpus.a[mgr.input])
- mgr.input++
- }
- return nil
-}
-
-func logf(v int, msg string, args ...interface{}) {
- if *flagV >= v {
- log.Printf(msg, args...)
- }
-}
-
-func fatalf(msg string, args ...interface{}) {
- log.Fatalf(msg, args...)
-}
diff --git a/master/persistent.go b/master/persistent.go
deleted file mode 100644
index 12f4bbdc8..000000000
--- a/master/persistent.go
+++ /dev/null
@@ -1,129 +0,0 @@
-// Copyright 2015 syzkaller project authors. All rights reserved.
-// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
-
-package main
-
-import (
- "crypto/sha1"
- "encoding/hex"
- "fmt"
- "io/ioutil"
- "log"
- "os"
- "path/filepath"
-)
-
-type Sig [sha1.Size]byte
-
-// PersistentSet is a set of binary blobs with a persistent mirror on disk.
-type PersistentSet struct {
- dir string
- m map[Sig][]byte
- a [][]byte
-}
-
-func hash(data []byte) Sig {
- return Sig(sha1.Sum(data))
-}
-
-func newPersistentSet(dir string, verify func(data []byte) bool) *PersistentSet {
- ps := &PersistentSet{
- dir: dir,
- m: make(map[Sig][]byte),
- }
- os.MkdirAll(dir, 0770)
- filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
- if err != nil {
- log.Fatalf("error during dir walk: %v\n", err)
- }
- if info.IsDir() {
- return nil
- }
- data, err := ioutil.ReadFile(path)
- if err != nil {
- log.Fatalf("error during file read: %v\n", err)
- return nil
- }
- sig := hash(data)
- if _, ok := ps.m[sig]; ok {
- return nil
- }
- name := info.Name()
- if len(data) == 0 {
- // This can happen is master runs on machine-under-test,
- // and it has crashed midway.
- log.Printf("removing empty file %v", name)
- os.Remove(path)
- return nil
- }
- const hexLen = 2 * sha1.Size
- if len(name) > hexLen+1 && isHexString(name[:hexLen]) && name[hexLen] == '.' {
- return nil // description file
- }
- if len(name) != hexLen || !isHexString(name) {
- log.Fatalf("unknown file in persistent dir %v: %v", dir, name)
- }
- if verify != nil && !verify(data) {
- os.Remove(path)
- return nil
- }
- if name != hex.EncodeToString(sig[:]) {
- log.Printf("bad hash in persistent dir %v for file %v, expect %v", dir, name, hex.EncodeToString(sig[:]))
- if err := ioutil.WriteFile(filepath.Join(ps.dir, hex.EncodeToString(sig[:])), data, 0660); err != nil {
- log.Fatalf("failed to write file: %v", err)
- }
- os.Remove(path)
- }
- ps.m[sig] = data
- ps.a = append(ps.a, data)
- return nil
- })
- return ps
-}
-
-func isHexString(s string) bool {
- for _, v := range []byte(s) {
- if v >= '0' && v <= '9' || v >= 'a' && v <= 'f' {
- continue
- }
- return false
- }
- return true
-}
-
-func (ps *PersistentSet) add(data []byte) bool {
- sig := hash(data)
- if _, ok := ps.m[sig]; ok {
- return false
- }
- data = append([]byte{}, data...)
- ps.m[sig] = data
- ps.a = append(ps.a, data)
- fname := filepath.Join(ps.dir, hex.EncodeToString(sig[:]))
- if err := ioutil.WriteFile(fname, data, 0660); err != nil {
- log.Fatalf("failed to write file: %v", err)
- }
- return true
-}
-
-// addDescription creates a complementary to data file on disk.
-func (ps *PersistentSet) addDescription(data []byte, desc []byte, typ string) {
- sig := hash(data)
- fname := filepath.Join(ps.dir, fmt.Sprintf("%v.%v", hex.EncodeToString(sig[:]), typ))
- if err := ioutil.WriteFile(fname, desc, 0660); err != nil {
- log.Fatalf("failed to write file: %v", err)
- }
-}
-
-func (ps *PersistentSet) minimize(set map[string]bool) {
- ps.a = nil
- for sig, data := range ps.m {
- s := hex.EncodeToString(sig[:])
- if set[s] {
- ps.a = append(ps.a, data)
- } else {
- delete(ps.m, sig)
- os.Remove(filepath.Join(ps.dir, s))
- }
- }
-}