Exemplo n.º 1
0
func main() {
	os.Args = append(append([]string{}, os.Args[0], "-v=10"), os.Args[1:]...)
	flag.Parse()
	cfg, _, err := config.Parse(*flagConfig)
	if err != nil {
		Fatalf("%v", err)
	}
	if *flagCount > 0 {
		cfg.Count = *flagCount
	}
	if cfg.Count > 4 {
		cfg.Count = 4
	}
	if len(flag.Args()) != 1 {
		Fatalf("usage: syz-repro -config=config.file execution.log")
	}
	data, err := ioutil.ReadFile(flag.Args()[0])
	if err != nil {
		Fatalf("failed to open log file: %v", err)
	}
	vmIndexes := make([]int, cfg.Count)
	for i := range vmIndexes {
		vmIndexes[i] = i
	}

	go func() {
		c := make(chan os.Signal, 2)
		signal.Notify(c, syscall.SIGINT)
		<-c
		close(vm.Shutdown)
		Logf(-1, "shutting down...")
		<-c
		Fatalf("terminating")
	}()

	res, err := repro.Run(data, cfg, vmIndexes)
	if err != nil {
		Logf(0, "reproduction failed: %v", err)
	}
	if res == nil {
		return
	}

	fmt.Printf("opts: %+v crepro: %v\n\n", res.Opts, res.CRepro)
	fmt.Printf("%s\n", res.Prog.Serialize())
	if res.CRepro {
		src, err := csource.Write(res.Prog, res.Opts)
		if err != nil {
			Fatalf("failed to generate C repro: %v", err)
		}
		if formatted, err := csource.Format(src); err == nil {
			src = formatted
		}
		fmt.Printf("%s\n", src)
	}
}
Exemplo n.º 2
0
func (mgr *Manager) vmLoop() {
	Logf(0, "booting test machines...")
	reproInstances := 4
	if reproInstances > mgr.cfg.Count {
		reproInstances = mgr.cfg.Count
	}
	instances := make([]int, mgr.cfg.Count)
	for i := range instances {
		instances[i] = mgr.cfg.Count - i - 1
	}
	runDone := make(chan *RunResult, 1)
	pendingRepro := make(map[*Crash]bool)
	reproducing := make(map[string]bool)
	var reproQueue []*Crash
	reproDone := make(chan *ReproResult, 1)
	stopPending := false
	shutdown := vm.Shutdown
	for {
		for crash := range pendingRepro {
			if reproducing[crash.desc] {
				continue
			}
			delete(pendingRepro, crash)
			if !mgr.needRepro(crash.desc) {
				continue
			}
			Logf(1, "loop: add to repro queue '%v'", crash.desc)
			reproducing[crash.desc] = true
			reproQueue = append(reproQueue, crash)
		}

		Logf(1, "loop: shutdown=%v instances=%v/%v %+v repro: pending=%v reproducing=%v queued=%v",
			shutdown == nil, len(instances), mgr.cfg.Count, instances,
			len(pendingRepro), len(reproducing), len(reproQueue))
		if shutdown == nil {
			if len(instances) == mgr.cfg.Count {
				return
			}
		} else {
			for len(reproQueue) != 0 && len(instances) >= reproInstances {
				last := len(reproQueue) - 1
				crash := reproQueue[last]
				reproQueue[last] = nil
				reproQueue = reproQueue[:last]
				vmIndexes := append([]int{}, instances[len(instances)-reproInstances:]...)
				instances = instances[:len(instances)-reproInstances]
				Logf(1, "loop: starting repro of '%v' on instances %+v", crash.desc, vmIndexes)
				go func() {
					res, err := repro.Run(crash.output, mgr.cfg, vmIndexes)
					reproDone <- &ReproResult{vmIndexes, crash, res, err}
				}()
			}
			for len(reproQueue) == 0 && len(instances) != 0 {
				last := len(instances) - 1
				idx := instances[last]
				instances = instances[:last]
				Logf(1, "loop: starting instance %v", idx)
				go func() {
					vmCfg, err := config.CreateVMConfig(mgr.cfg, idx)
					if err != nil {
						Fatalf("failed to create VM config: %v", err)
					}
					crash, err := mgr.runInstance(vmCfg, idx == 0)
					runDone <- &RunResult{idx, crash, err}
				}()
			}
		}

		var stopRequest chan bool
		if len(reproQueue) != 0 && !stopPending {
			stopRequest = mgr.vmStop
		}

		select {
		case stopRequest <- true:
			Logf(1, "loop: issued stop request")
			stopPending = true
		case res := <-runDone:
			Logf(1, "loop: instance %v finished, crash=%v", res.idx, res.crash != nil)
			if res.err != nil && shutdown != nil {
				Logf(0, "%v", res.err)
			}
			stopPending = false
			instances = append(instances, res.idx)
			// On shutdown qemu crashes with "qemu: terminating on signal 2",
			// which we detect as "lost connection". Don't save that as crash.
			if shutdown != nil && res.crash != nil && !mgr.isSuppressed(res.crash) {
				mgr.saveCrash(res.crash)
				if mgr.needRepro(res.crash.desc) {
					Logf(1, "loop: add pending repro for '%v'", res.crash.desc)
					pendingRepro[res.crash] = true
				}
			}
		case res := <-reproDone:
			crepro := false
			if res.res != nil {
				crepro = res.res.CRepro
			}
			Logf(1, "loop: repro on instances %+v finished '%v', repro=%v crepro=%v",
				res.instances, res.crash.desc, res.res != nil, crepro)
			if res.err != nil {
				Logf(0, "repro failed: %v", res.err)
			}
			delete(reproducing, res.crash.desc)
			instances = append(instances, res.instances...)
			mgr.saveRepro(res.crash, res.res)
		case <-shutdown:
			Logf(1, "loop: shutting down...")
			shutdown = nil
		}
	}
}