func (mgr *Manager) httpCover(w http.ResponseWriter, r *http.Request) { mgr.mu.Lock() defer mgr.mu.Unlock() var cov cover.Cover call := r.FormValue("call") unique := r.FormValue("unique") != "" && call != "" perCall := false if n, err := strconv.Atoi(call); err == nil && n < len(mgr.corpus) { cov = mgr.corpus[n].Cover } else { perCall = true for _, inp := range mgr.corpus { if call == "" || call == inp.Call { cov = cover.Union(cov, cover.Cover(inp.Cover)) } } } if unique { cov = cover.Intersection(cov, mgr.uniqueCover(perCall)) } if err := generateCoverHtml(w, mgr.cfg.Vmlinux, cov); err != nil { http.Error(w, fmt.Sprintf("failed to generate coverage profile: %v", err), http.StatusInternalServerError) return } runtime.GC() }
func (mgr *Manager) httpInfo(w http.ResponseWriter, r *http.Request) { mgr.mu.Lock() defer mgr.mu.Unlock() uptime := time.Since(mgr.startTime) data := &UIData{ CorpusSize: len(mgr.corpus), TriageQueue: len(mgr.candidates), Uptime: fmt.Sprintf("%v", uptime), } type CallCov struct { count int cov cover.Cover } calls := make(map[string]*CallCov) for _, inp := range mgr.corpus { if calls[inp.Call] == nil { calls[inp.Call] = new(CallCov) } cc := calls[inp.Call] cc.count++ cc.cov = cover.Union(cc.cov, cover.Cover(inp.Cover)) data.CorpusCoverMem += len(inp.Cover) * int(unsafe.Sizeof(inp.Cover[0])) } for _, cov := range mgr.corpusCover { data.CallCoverMem += len(cov) * int(unsafe.Sizeof(cov[0])) } secs := uint64(uptime) / 1e9 for k, v := range mgr.stats { val := "" if x := v / secs; x >= 10 { val = fmt.Sprintf("%v/sec", x) } else if x := v * 60 / secs; x >= 10 { val = fmt.Sprintf("%v/min", x) } else { x := v * 60 * 60 / secs val = fmt.Sprintf("%v/hour", x) } data.Stats = append(data.Stats, UIStat{Name: k, Value: val}) } sort.Sort(UIStatArray(data.Stats)) var cov cover.Cover for c, cc := range calls { cov = cover.Union(cov, cc.cov) data.Calls = append(data.Calls, UICallType{c, cc.count, len(cc.cov)}) } sort.Sort(UICallTypeArray(data.Calls)) data.CoverSize = len(cov) if err := htmlTemplate.Execute(w, data); err != nil { http.Error(w, fmt.Sprintf("failed to execute template: %v", err), http.StatusInternalServerError) } }
func execute1(env *ipc.Env, p *prog.Prog, stat *uint64) []cover.Cover { if *flagSaveProg { f, err := os.Create(fmt.Sprintf("%v.prog", *flagName)) if err == nil { f.Write(p.Serialize()) f.Close() } } else { // The following output helps to understand what program crashed kernel. // It must not be intermixed. logMu.Lock() log.Printf("executing program:\n%s", p.Serialize()) logMu.Unlock() } try := 0 retry: *stat++ output, strace, rawCover, failed, hanged, err := env.Exec(p) if err != nil { if try > 10 { panic(err) } try++ debug.FreeOSMemory() time.Sleep(time.Second) goto retry } logf(4, "result failed=%v hanged=%v:\n%v\n", failed, hanged, string(output)) if len(strace) != 0 { logf(4, "strace:\n%s\n", strace) } cov := make([]cover.Cover, len(p.Calls)) for i, c := range rawCover { cov[i] = cover.Cover(c) } return cov }
func (mgr *Manager) httpInfo(w http.ResponseWriter, r *http.Request) { mgr.mu.Lock() defer mgr.mu.Unlock() type CallCov struct { count int cov cover.Cover } calls := make(map[string]*CallCov) for _, inp := range mgr.corpus { if calls[inp.Call] == nil { calls[inp.Call] = new(CallCov) } cc := calls[inp.Call] cc.count++ cc.cov = cover.Union(cc.cov, cover.Cover(inp.Cover)) } data := &UIData{ Name: mgr.cfg.Name, MasterHttp: mgr.masterHttp, MasterCorpusSize: len(mgr.masterCorpus), CorpusSize: len(mgr.corpus), } var cov cover.Cover for c, cc := range calls { cov = cover.Union(cov, cc.cov) data.Calls = append(data.Calls, UICallType{c, cc.count, len(cc.cov)}) } sort.Sort(UICallTypeArray(data.Calls)) data.CoverSize = len(cov) if err := htmlTemplate.Execute(w, data); err != nil { http.Error(w, fmt.Sprintf("failed to execute template: %v", err), http.StatusInternalServerError) } }
func execute1(pid int, env *ipc.Env, p *prog.Prog, stat *uint64) []cover.Cover { if false { // For debugging, this function must not be executed with locks held. corpusMu.Lock() corpusMu.Unlock() coverMu.Lock() coverMu.Unlock() triageMu.Lock() triageMu.Unlock() } // Limit concurrency window and do leak checking once in a while. idx := gate.Enter() defer gate.Leave(idx, func() { if idx == 0 && *flagLeak && atomic.LoadUint32(&allTriaged) != 0 { // Scan for leaks once in a while (it is damn slow). kmemleakScan(true) } }) // The following output helps to understand what program crashed kernel. // It must not be intermixed. switch *flagOutput { case "none": // This case intentionally left blank. case "stdout": data := p.Serialize() logMu.Lock() log.Printf("executing program %v:\n%s", pid, data) logMu.Unlock() case "dmesg": fd, err := syscall.Open("/dev/kmsg", syscall.O_WRONLY, 0) if err == nil { buf := new(bytes.Buffer) fmt.Fprintf(buf, "syzkaller: executing program %v:\n%s", pid, p.Serialize()) syscall.Write(fd, buf.Bytes()) syscall.Close(fd) } case "file": f, err := os.Create(fmt.Sprintf("%v-%v.prog", *flagName, pid)) if err == nil { f.Write(p.Serialize()) f.Close() } } try := 0 retry: atomic.AddUint64(stat, 1) output, rawCover, errnos, failed, hanged, err := env.Exec(p) _ = errnos if failed { // BUG in output should be recognized by manager. logf(0, "BUG: executor-detected bug:\n%s", output) // Don't return any cover so that the input is not added to corpus. return make([]cover.Cover, len(p.Calls)) } if err != nil { if try > 10 { panic(err) } try++ debug.FreeOSMemory() time.Sleep(time.Second) goto retry } logf(4, "result failed=%v hanged=%v:\n%v\n", failed, hanged, string(output)) cov := make([]cover.Cover, len(p.Calls)) for i, c := range rawCover { cov[i] = cover.Cover(c) } return cov }
func (mgr *Manager) httpSummary(w http.ResponseWriter, r *http.Request) { mgr.mu.Lock() defer mgr.mu.Unlock() data := &UISummaryData{ Name: mgr.cfg.Name, } data.Stats = append(data.Stats, UIStat{Name: "uptime", Value: fmt.Sprint(time.Since(mgr.startTime) / 1e9 * 1e9)}) data.Stats = append(data.Stats, UIStat{Name: "corpus", Value: fmt.Sprint(len(mgr.corpus))}) data.Stats = append(data.Stats, UIStat{Name: "triage queue", Value: fmt.Sprint(len(mgr.candidates))}) var err error if data.Crashes, err = mgr.collectCrashes(); err != nil { http.Error(w, fmt.Sprintf("failed to collect crashes: %v", err), http.StatusInternalServerError) return } type CallCov struct { count int cov cover.Cover } calls := make(map[string]*CallCov) for _, inp := range mgr.corpus { if calls[inp.Call] == nil { calls[inp.Call] = new(CallCov) } cc := calls[inp.Call] cc.count++ cc.cov = cover.Union(cc.cov, cover.Cover(inp.Cover)) } secs := uint64(1) if !mgr.firstConnect.IsZero() { secs = uint64(time.Since(mgr.firstConnect))/1e9 + 1 } var cov cover.Cover totalUnique := mgr.uniqueCover(true) for c, cc := range calls { cov = cover.Union(cov, cc.cov) unique := cover.Intersection(cc.cov, totalUnique) data.Calls = append(data.Calls, UICallType{ Name: c, Inputs: cc.count, Cover: len(cc.cov), UniqueCover: len(unique), }) } sort.Sort(UICallTypeArray(data.Calls)) data.Stats = append(data.Stats, UIStat{Name: "cover", Value: fmt.Sprint(len(cov)), Link: "/cover"}) var intStats []UIStat for k, v := range mgr.stats { val := fmt.Sprintf("%v", v) if x := v / secs; x >= 10 { val += fmt.Sprintf(" (%v/sec)", x) } else if x := v * 60 / secs; x >= 10 { val += fmt.Sprintf(" (%v/min)", x) } else { x := v * 60 * 60 / secs val += fmt.Sprintf(" (%v/hour)", x) } intStats = append(intStats, UIStat{Name: k, Value: val}) } sort.Sort(UIStatArray(intStats)) data.Stats = append(data.Stats, intStats...) data.Log = CachedLogOutput() if err := summaryTemplate.Execute(w, data); err != nil { http.Error(w, fmt.Sprintf("failed to execute template: %v", err), http.StatusInternalServerError) return } }