Esempio n. 1
0
func testProg(cfg *config.Config, p *prog.Prog, multiplier int, threaded, collide bool) (res bool) {
	log.Printf("booting VM")
	inst := <-instances
	defer func() {
		returnInstance(inst, res)
	}()

	pstr := p.Serialize()
	progFile, err := fileutil.WriteTempFile(pstr)
	if err != nil {
		log.Fatalf("%v", err)
	}
	defer os.Remove(progFile)
	bin, err := inst.Copy(progFile)
	if err != nil {
		log.Fatalf("failed to copy to VM: %v", err)
	}

	repeat := 100
	timeoutSec := 10 * repeat / cfg.Procs
	if threaded {
		repeat *= 10
		timeoutSec *= 1
	}
	repeat *= multiplier
	timeoutSec *= multiplier
	timeout := time.Duration(timeoutSec) * time.Second
	command := fmt.Sprintf("%v -executor %v -cover=0 -procs=%v -repeat=%v -threaded=%v -collide=%v %v",
		inst.execprogBin, inst.executorBin, cfg.Procs, repeat, threaded, collide, bin)
	log.Printf("testing program (threaded=%v, collide=%v, repeat=%v, timeout=%v):\n%s\n",
		threaded, collide, repeat, timeout, pstr)
	return testImpl(inst, command, timeout)
}
Esempio n. 2
0
func execute(pid int, env *ipc.Env, p *prog.Prog) {
	if *flagExecutor == "" {
		return
	}
	atomic.AddUint64(&statExec, 1)
	if *flagLogProg {
		ticket := gate.Enter()
		defer gate.Leave(ticket)
		outMu.Lock()
		fmt.Printf("executing program %v\n%s\n", pid, p.Serialize())
		outMu.Unlock()
	}

	output, _, _, failed, hanged, err := env.Exec(p)
	if err != nil {
		fmt.Printf("failed to execute executor: %v\n", err)
	}
	paniced := failedRe.Match(output)
	if failed || hanged || paniced || err != nil {
		fmt.Printf("PROGRAM:\n%s\n", p.Serialize())
	}
	if failed || hanged || paniced || err != nil || *flagOutput {
		os.Stdout.Write(output)
	}
}
Esempio n. 3
0
func (ctx *context) testProg(p *prog.Prog, duration time.Duration, opts csource.Options, reboot bool) (crashed bool, err error) {
	inst := <-ctx.instances
	if inst == nil {
		return false, fmt.Errorf("all VMs failed to boot")
	}
	defer func() {
		ctx.returnInstance(inst, reboot, crashed)
	}()

	pstr := p.Serialize()
	progFile, err := fileutil.WriteTempFile(pstr)
	if err != nil {
		return false, err
	}
	defer os.Remove(progFile)
	vmProgFile, err := inst.Copy(progFile)
	if err != nil {
		return false, fmt.Errorf("failed to copy to VM: %v", err)
	}

	repeat := "1"
	if opts.Repeat {
		repeat = "0"
	}
	command := fmt.Sprintf("%v -executor %v -cover=0 -procs=%v -repeat=%v -sandbox %v -threaded=%v -collide=%v %v",
		inst.execprogBin, inst.executorBin, opts.Procs, repeat, opts.Sandbox, opts.Threaded, opts.Collide, vmProgFile)
	Logf(2, "reproducing crash '%v': testing program (duration=%v, %+v): %s",
		ctx.crashDesc, duration, opts, p)
	return ctx.testImpl(inst, command, duration)
}
Esempio n. 4
0
func testOne(t *testing.T, p *prog.Prog, opts Options) {
	src := Write(p, opts)
	srcf, err := fileutil.WriteTempFile(src)
	if err != nil {
		t.Logf("program:\n%s\n", p.Serialize())
		t.Fatalf("%v", err)
	}
	defer os.Remove(srcf)
	bin, err := Build(srcf)
	if err != nil {
		t.Logf("program:\n%s\n", p.Serialize())
		t.Fatalf("%v", err)
	}
	defer os.Remove(bin)
}
Esempio n. 5
0
func execute(env *ipc.Env, p *prog.Prog) {
	if *flagExecutor == "" {
		return
	}
	output, _, _, _, _, err := env.Exec(p)
	if err != nil {
		fmt.Printf("failed to execute executor: %v\n", err)
	}
	failed := failedRe.Match(output)
	if failed {
		fmt.Printf("PROGRAM:\n%s\n", p.Serialize())
	}
	if failed || *flagOutput {
		os.Stdout.Write(output)
	}
}
Esempio n. 6
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
}
Esempio n. 7
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
}