Пример #1
0
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()
}
Пример #2
0
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)
	}
}
Пример #3
0
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
}
Пример #4
0
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)
	}
}
Пример #5
0
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
}
Пример #6
0
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
	}
}