diff options
| author | Dmitry Vyukov <dvyukov@google.com> | 2015-12-17 16:06:33 +0100 |
|---|---|---|
| committer | Dmitry Vyukov <dvyukov@google.com> | 2015-12-17 16:06:33 +0100 |
| commit | 8e7ca7c5ff18e17cab7b6b3ae569565224f95fcc (patch) | |
| tree | 613bbb3f12f7f2f63ad225648f6971a1393d3703 /master | |
| parent | 06e67265374faa677dba2dbd2577054278f19823 (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.go | 95 | ||||
| -rw-r--r-- | master/master.go | 170 | ||||
| -rw-r--r-- | master/persistent.go | 129 |
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)) - } - } -} |
