Пример #1
0
func execute(pid int, env *ipc.Env, p *prog.Prog, stat *uint64) {
	allCover := execute1(pid, env, p, stat)
	coverMu.RLock()
	defer coverMu.RUnlock()
	for i, cov := range allCover {
		if len(cov) == 0 {
			continue
		}
		c := p.Calls[i].Meta
		diff := cover.Difference(cov, maxCover[c.CallID])
		diff = cover.Difference(diff, flakes)
		if len(diff) != 0 {
			coverMu.RUnlock()
			coverMu.Lock()
			maxCover[c.CallID] = cover.Union(maxCover[c.CallID], diff)
			coverMu.Unlock()
			coverMu.RLock()

			inp := Input{p.Clone(), i, cover.Copy(cov)}
			triageMu.Lock()
			triage = append(triage, inp)
			triageMu.Unlock()
		}
	}
}
Пример #2
0
func addInput(inp RpcInput) {
	p, err := prog.Deserialize(inp.Prog)
	if err != nil {
		panic(err)
	}
	if inp.CallIndex < 0 || inp.CallIndex >= len(p.Calls) {
		panic("bad call index")
	}
	call := p.Calls[inp.CallIndex].Meta
	sig := hash(inp.Prog)
	if _, ok := corpusHashes[sig]; ok {
		return
	}
	cov := cover.Canonicalize(inp.Cover)
	diff := cover.Difference(cov, maxCover[call.CallID])
	diff = cover.Difference(diff, flakes)
	if len(diff) == 0 {
		return
	}
	inp1 := Input{p, inp.CallIndex, cov}
	corpus = append(corpus, inp1)
	corpusCover[call.CallID] = cover.Union(corpusCover[call.CallID], cov)
	maxCover[call.CallID] = cover.Union(maxCover[call.CallID], cov)
	corpusHashes[hash(inp.Prog)] = struct{}{}
}
Пример #3
0
func addInput(inp RpcInput) {
	corpusMu.Lock()
	defer corpusMu.Unlock()
	coverMu.Lock()
	defer coverMu.Unlock()

	if noCover {
		panic("should not be called when coverage is disabled")
	}
	p, err := prog.Deserialize(inp.Prog)
	if err != nil {
		panic(err)
	}
	if inp.CallIndex < 0 || inp.CallIndex >= len(p.Calls) {
		panic("bad call index")
	}
	call := p.Calls[inp.CallIndex].Meta
	sig := hash(inp.Prog)
	if _, ok := corpusHashes[sig]; ok {
		return
	}
	cov := cover.Canonicalize(inp.Cover)
	diff := cover.Difference(cov, maxCover[call.CallID])
	diff = cover.Difference(diff, flakes)
	if len(diff) == 0 {
		return
	}
	corpus = append(corpus, p)
	corpusCover[call.CallID] = cover.Union(corpusCover[call.CallID], cov)
	maxCover[call.CallID] = cover.Union(maxCover[call.CallID], cov)
	corpusHashes[hash(inp.Prog)] = struct{}{}
}
Пример #4
0
func triageInput(env *ipc.Env, inp Input) {
	if *flagNoCover {
		panic("should not be called when coverage is disabled")
	}
	call := inp.p.Calls[inp.call].Meta
	newCover := cover.Difference(inp.cover, corpusCover[call.CallID])
	newCover = cover.Difference(newCover, flakes)
	if len(newCover) == 0 {
		return
	}

	if _, ok := corpusHashes[hash(inp.p.Serialize())]; ok {
		return
	}

	minCover := inp.cover
	for i := 0; i < 3; i++ {
		allCover := execute1(env, inp.p, &statExecTriage)
		if len(allCover[inp.call]) == 0 {
			// The call was not executed. Happens sometimes, reason unknown.
			continue
		}
		cov := allCover[inp.call]
		diff := cover.SymmetricDifference(inp.cover, cov)
		if len(diff) != 0 {
			flakes = cover.Union(flakes, diff)
		}
		minCover = cover.Intersection(minCover, cov)
	}
	stableNewCover := cover.Intersection(newCover, minCover)
	if len(stableNewCover) == 0 {
		return
	}
	inp.p, inp.call = prog.Minimize(inp.p, inp.call, func(p1 *prog.Prog, call1 int) bool {
		allCover := execute1(env, p1, &statExecMinimize)
		if len(allCover[call1]) == 0 {
			return false // The call was not executed.
		}
		cov := allCover[call1]
		if len(cover.Intersection(stableNewCover, cov)) != len(stableNewCover) {
			return false
		}
		minCover = cover.Intersection(minCover, cov)
		return true
	})
	inp.cover = minCover
	corpusCover[call.CallID] = cover.Union(corpusCover[call.CallID], minCover)
	corpus = append(corpus, inp)
	data := inp.p.Serialize()
	corpusHashes[hash(data)] = struct{}{}

	logf(2, "added new input for %v to corpus:\n%s", call.CallName, data)

	statNewInput++
	a := &NewManagerInputArgs{*flagName, RpcInput{call.CallName, inp.p.Serialize(), inp.call, []uint32(inp.cover)}}
	if err := manager.Call("Manager.NewInput", a, nil); err != nil {
		panic(err)
	}
}
Пример #5
0
func execute(env *ipc.Env, p *prog.Prog) {
	allCover := execute1(env, p)
	for i, cov := range allCover {
		if len(cov) == 0 {
			continue
		}
		c := p.Calls[i].Meta
		diff := cover.Difference(cov, maxCover[c.CallID])
		diff = cover.Difference(diff, flakes)
		if len(diff) != 0 {
			triage = append(triage, Input{p.Clone(), i, cover.Copy(cov)})
		}
	}
}
Пример #6
0
func (mgr *Manager) NewInput(a *NewManagerInputArgs, r *int) error {
	logf(2, "new input from fuzzer %v", a.Name)
	mgr.mu.Lock()
	defer mgr.mu.Unlock()

	call := sys.CallID[a.Call]
	if len(cover.Difference(a.Cover, mgr.corpusCover[call])) == 0 {
		return nil
	}
	mgr.corpusCover[call] = cover.Union(mgr.corpusCover[call], a.Cover)
	mgr.corpus = append(mgr.corpus, a.RpcInput)
	mgr.stats["manager new inputs"]++

	sig := hash(a.Prog)
	if _, ok := mgr.masterHashes[sig]; !ok {
		mgr.masterHashes[sig] = struct{}{}
		mgr.masterCorpus = append(mgr.masterCorpus, a.Prog)

		a1 := &NewMasterInputArgs{mgr.cfg.Name, a.Prog}
		if err := mgr.master.Call("Master.NewInput", a1, nil); err != nil {
			fatalf("call Master.NewInput failed: %v", err)
		}
	}

	return nil
}
Пример #7
0
func (mgr *Manager) NewInput(a *NewInputArgs, r *int) error {
	Logf(2, "new input from %v for syscall %v", a.Name, a.Call)
	mgr.mu.Lock()
	defer mgr.mu.Unlock()

	f := mgr.fuzzers[a.Name]
	if f == nil {
		Fatalf("fuzzer %v is not connected", a.Name)
	}

	call := sys.CallID[a.Call]
	if len(cover.Difference(a.Cover, mgr.corpusCover[call])) == 0 {
		return nil
	}
	mgr.corpusCover[call] = cover.Union(mgr.corpusCover[call], a.Cover)
	mgr.corpus = append(mgr.corpus, a.RpcInput)
	mgr.stats["manager new inputs"]++
	mgr.persistentCorpus.add(a.RpcInput.Prog)
	for _, f1 := range mgr.fuzzers {
		if f1 == f {
			continue
		}
		f1.inputs = append(f1.inputs, a.RpcInput)
	}
	return nil
}
Пример #8
0
func execute(env *ipc.Env, p *prog.Prog, workerId int) []Input {
	allCover := execute1(env, p, workerId)
	var inputs []Input
	for i, cov := range allCover {
		if len(cov) == 0 {
			continue
		}
		c := p.Calls[i].Meta
		diff := cover.Difference(cov, maxCover[c.CallID])
		diff = cover.Difference(diff, flakes)
		if len(diff) != 0 {
			p1 := p.Clone()
			p1.TrimAfter(i)
			inputs = append(inputs, Input{p1, i, cover.Copy(cov)})
		}
	}
	return inputs
}
Пример #9
0
func (mgr *Manager) NewInput(a *NewInputArgs, r *int) error {
	Logf(2, "new input from %v for syscall %v", a.Name, a.Call)
	mgr.mu.Lock()
	defer mgr.mu.Unlock()

	call := sys.CallID[a.Call]
	if len(cover.Difference(a.Cover, mgr.corpusCover[call])) == 0 {
		return nil
	}
	mgr.corpusCover[call] = cover.Union(mgr.corpusCover[call], a.Cover)
	mgr.corpus = append(mgr.corpus, a.RpcInput)
	mgr.stats["manager new inputs"]++
	mgr.persistentCorpus.add(a.RpcInput.Prog)
	return nil
}
Пример #10
0
func triageInput(pid int, env *ipc.Env, inp Input) {
	if noCover {
		panic("should not be called when coverage is disabled")
	}

	call := inp.p.Calls[inp.call].Meta
	coverMu.RLock()
	newCover := cover.Difference(inp.cover, corpusCover[call.CallID])
	newCover = cover.Difference(newCover, flakes)
	coverMu.RUnlock()
	if len(newCover) == 0 {
		return
	}

	corpusMu.RLock()
	if _, ok := corpusHashes[hash(inp.p.Serialize())]; ok {
		corpusMu.RUnlock()
		return
	}
	corpusMu.RUnlock()

	minCover := inp.cover
	for i := 0; i < 3; i++ {
		allCover := execute1(pid, env, inp.p, &statExecTriage)
		if len(allCover[inp.call]) == 0 {
			// The call was not executed. Happens sometimes, reason unknown.
			continue
		}
		coverMu.RLock()
		cov := allCover[inp.call]
		diff := cover.SymmetricDifference(inp.cover, cov)
		minCover = cover.Intersection(minCover, cov)
		updateFlakes := len(diff) != 0 && len(cover.Difference(diff, flakes)) != 0
		coverMu.RUnlock()
		if updateFlakes {
			coverMu.Lock()
			flakes = cover.Union(flakes, diff)
			coverMu.Unlock()
		}
	}
	stableNewCover := cover.Intersection(newCover, minCover)
	if len(stableNewCover) == 0 {
		return
	}
	inp.p, inp.call = prog.Minimize(inp.p, inp.call, func(p1 *prog.Prog, call1 int) bool {
		allCover := execute1(pid, env, p1, &statExecMinimize)
		coverMu.RLock()
		defer coverMu.RUnlock()

		if len(allCover[call1]) == 0 {
			return false // The call was not executed.
		}
		cov := allCover[call1]
		if len(cover.Intersection(stableNewCover, cov)) != len(stableNewCover) {
			return false
		}
		minCover = cover.Intersection(minCover, cov)
		return true
	}, false)
	inp.cover = minCover

	atomic.AddUint64(&statNewInput, 1)
	data := inp.p.Serialize()
	Logf(2, "added new input for %v to corpus:\n%s", call.CallName, data)
	a := &NewInputArgs{*flagName, RpcInput{call.CallName, data, inp.call, []uint32(inp.cover)}}
	if err := manager.Call("Manager.NewInput", a, nil); err != nil {
		panic(err)
	}

	corpusMu.Lock()
	defer corpusMu.Unlock()
	coverMu.Lock()
	defer coverMu.Unlock()

	corpusCover[call.CallID] = cover.Union(corpusCover[call.CallID], minCover)
	corpus = append(corpus, inp.p)
	corpusHashes[hash(data)] = struct{}{}
}