func main() { flag.Parse() if flag.NArg() != 1 { fmt.Fprintf(os.Stderr, "usage: mutate program\n") os.Exit(1) } data, err := ioutil.ReadFile(flag.Arg(0)) if err != nil { fmt.Fprintf(os.Stderr, "failed to read prog file: %v\n", err) os.Exit(1) } p, err := prog.Deserialize(data) if err != nil { fmt.Fprintf(os.Stderr, "failed to deserialize the program: %v\n", err) os.Exit(1) } prios := prog.CalculatePriorities(nil) ct := prog.BuildChoiceTable(prios, nil) seed := time.Now().UnixNano() if *flagSeed != -1 { seed = int64(*flagSeed) } rs := rand.NewSource(seed) p.Mutate(rs, len(p.Calls)+10, ct) fmt.Printf("%s\n", p.Serialize()) }
func main() { flag.Parse() corpus := readCorpus() log.Printf("parsed %v programs", len(corpus)) calls := buildCallList() prios := prog.CalculatePriorities(corpus) ct := prog.BuildChoiceTable(prios, calls) var flags uint64 if *flagThreaded { flags |= ipc.FlagThreaded } if *flagCollide { flags |= ipc.FlagCollide } if *flagNobody { flags |= ipc.FlagDropPrivs } if *flagDebug { flags |= ipc.FlagDebug } if *flagNoPgid { flags |= ipc.FlagNoSetpgid } gate = ipc.NewGate(2 * *flagProcs) for pid := 0; pid < *flagProcs; pid++ { pid := pid go func() { env, err := ipc.MakeEnv(*flagExecutor, *flagTimeout, flags) if err != nil { failf("failed to create execution environment: %v", err) } rs := rand.NewSource(time.Now().UnixNano() + int64(pid)*1e12) rnd := rand.New(rs) for i := 0; ; i++ { var p *prog.Prog if len(corpus) == 0 || i%4 != 0 { p = prog.Generate(rs, programLength, ct) execute(pid, env, p) p.Mutate(rs, programLength, ct) execute(pid, env, p) } else { p = corpus[rnd.Intn(len(corpus))].Clone() p.Mutate(rs, programLength, ct) execute(pid, env, p) p.Mutate(rs, programLength, ct) execute(pid, env, p) } } }() } for range time.NewTicker(5 * time.Second).C { log.Printf("executed %v programs", atomic.LoadUint64(&statExec)) } }
func main() { flag.Parse() corpus := readCorpus() Logf(0, "parsed %v programs", len(corpus)) calls := buildCallList() prios := prog.CalculatePriorities(corpus) ct := prog.BuildChoiceTable(prios, calls) flags, timeout, err := ipc.DefaultFlags() if err != nil { Fatalf("%v", err) } gate = ipc.NewGate(2**flagProcs, nil) for pid := 0; pid < *flagProcs; pid++ { pid := pid go func() { env, err := ipc.MakeEnv(*flagExecutor, timeout, flags, pid) if err != nil { Fatalf("failed to create execution environment: %v", err) } rs := rand.NewSource(time.Now().UnixNano() + int64(pid)*1e12) rnd := rand.New(rs) for i := 0; ; i++ { var p *prog.Prog if len(corpus) == 0 || i%4 != 0 { p = prog.Generate(rs, programLength, ct) execute(pid, env, p) p.Mutate(rs, programLength, ct, corpus) execute(pid, env, p) } else { p = corpus[rnd.Intn(len(corpus))].Clone() p.Mutate(rs, programLength, ct, corpus) execute(pid, env, p) p.Mutate(rs, programLength, ct, corpus) execute(pid, env, p) } } }() } for range time.NewTicker(5 * time.Second).C { Logf(0, "executed %v programs", atomic.LoadUint64(&statExec)) } }
func main() { debug.SetGCPercent(50) flag.Parse() logf(0, "started") var calls []*sys.Call if *flagSyscalls != "" { for _, id := range strings.Split(*flagSyscalls, ",") { n, err := strconv.ParseUint(id, 10, 64) if err != nil || n >= uint64(len(sys.Calls)) { panic(fmt.Sprintf("invalid syscall in -calls flag: '%v", id)) } calls = append(calls, sys.Calls[n]) } } corpusCover = make([]cover.Cover, sys.CallCount) maxCover = make([]cover.Cover, sys.CallCount) corpusHashes = make(map[Sig]struct{}) conn, err := rpc.Dial("tcp", *flagManager) if err != nil { panic(err) } manager = conn a := &ManagerConnectArgs{*flagName} r := &ManagerConnectRes{} if err := manager.Call("Manager.Connect", a, r); err != nil { panic(err) } ct = prog.BuildChoiceTable(r.Prios, calls) flags := ipc.FlagCover | ipc.FlagDedupCover if *flagStrace { flags |= ipc.FlagStrace } env, err := ipc.MakeEnv(*flagExecutor, 4*time.Second, flags) if err != nil { panic(err) } rs := rand.NewSource(time.Now().UnixNano()) rnd := rand.New(rs) var lastPoll time.Time var lastPrint time.Time for i := 0; ; i++ { if !*flagSaveProg && time.Since(lastPrint) > 10*time.Second { // Keep-alive for manager. logf(0, "#%v: alive", i) lastPrint = time.Now() } if len(triage) != 0 { last := len(triage) - 1 inp := triage[last] triage = triage[:last] logf(1, "#%v: triaging : %s", i, inp.p) triageInput(env, inp) continue } if time.Since(lastPoll) > 10*time.Second { a := &ManagerPollArgs{*flagName} r := &ManagerPollRes{} if err := manager.Call("Manager.Poll", a, r); err != nil { panic(err) } for _, inp := range r.NewInputs { addInput(inp) } for _, data := range r.Candidates { p, err := prog.Deserialize(data) if err != nil { panic(err) } execute(env, p) } if len(r.NewInputs) == 0 && len(r.Candidates) == 0 { lastPoll = time.Now() } continue } if len(corpus) == 0 || i%10 == 0 { p := prog.Generate(rnd, programLength, ct) logf(1, "#%v: generated: %s", i, p) execute(env, p) p.Mutate(rnd, programLength, ct) logf(1, "#%v: mutated: %s", i, p) execute(env, p) } else { inp := corpus[rnd.Intn(len(corpus))] p := inp.p.Clone() p.Mutate(rs, programLength, ct) logf(1, "#%v: mutated: %s <- %s", i, p, inp.p) execute(env, p) } } }
func main() { debug.SetGCPercent(50) flag.Parse() switch *flagOutput { case "none", "stdout", "dmesg", "file": default: fmt.Fprintf(os.Stderr, "-output flag must be one of none/stdout/dmesg/file\n") os.Exit(1) } logf(0, "started") corpusCover = make([]cover.Cover, sys.CallCount) maxCover = make([]cover.Cover, sys.CallCount) corpusHashes = make(map[Sig]struct{}) logf(0, "dialing manager at %v", *flagManager) conn, err := jsonrpc.Dial("tcp", *flagManager) if err != nil { panic(err) } manager = conn a := &ConnectArgs{*flagName} r := &ConnectRes{} if err := manager.Call("Manager.Connect", a, r); err != nil { panic(err) } calls := buildCallList(r.EnabledCalls) ct := prog.BuildChoiceTable(r.Prios, calls) kmemleakInit() flags, timeout := ipc.DefaultFlags() noCover = flags&ipc.FlagCover == 0 if !noCover { fd, err := syscall.Open("/sys/kernel/debug/kcov", syscall.O_RDWR, 0) if err != nil { log.Fatalf("BUG: /sys/kernel/debug/kcov is missing (%v). Enable CONFIG_KCOV and mount debugfs.", err) } syscall.Close(fd) } gate = ipc.NewGate(2 * *flagProcs) envs := make([]*ipc.Env, *flagProcs) for pid := 0; pid < *flagProcs; pid++ { env, err := ipc.MakeEnv(*flagExecutor, timeout, flags) if err != nil { panic(err) } envs[pid] = env pid := pid go func() { rs := rand.NewSource(time.Now().UnixNano() + int64(pid)*1e12) rnd := rand.New(rs) for i := 0; ; i++ { triageMu.RLock() if len(triage) != 0 || len(candidates) != 0 { triageMu.RUnlock() triageMu.Lock() if len(triage) != 0 { last := len(triage) - 1 inp := triage[last] triage = triage[:last] triageMu.Unlock() logf(1, "triaging : %s", inp.p) triageInput(pid, env, inp) continue } else if len(candidates) != 0 { last := len(candidates) - 1 p := candidates[last] candidates = candidates[:last] triageMu.Unlock() execute(pid, env, p, &statExecCandidate) continue } else { triageMu.Unlock() } } else { triageMu.RUnlock() } corpusMu.RLock() if len(corpus) == 0 || i%10 == 0 { corpusMu.RUnlock() p := prog.Generate(rnd, programLength, ct) logf(1, "#%v: generated: %s", i, p) execute(pid, env, p, &statExecGen) p.Mutate(rnd, programLength, ct) logf(1, "#%v: mutated: %s", i, p) execute(pid, env, p, &statExecFuzz) } else { p0 := corpus[rnd.Intn(len(corpus))] corpusMu.RUnlock() p := p0.Clone() p.Mutate(rs, programLength, ct) logf(1, "#%v: mutated: %s <- %s", i, p, p0) execute(pid, env, p, &statExecFuzz) } } }() } var lastPoll time.Time var lastPrint time.Time for range time.NewTicker(3 * time.Second).C { if *flagOutput != "stdout" && time.Since(lastPrint) > 10*time.Second { // Keep-alive for manager. logf(0, "alive") lastPrint = time.Now() } if time.Since(lastPoll) > 10*time.Second { triageMu.RLock() if len(candidates) != 0 { triageMu.RUnlock() continue } triageMu.RUnlock() a := &PollArgs{ Name: *flagName, Stats: make(map[string]uint64), } for _, env := range envs { a.Stats["exec total"] += atomic.SwapUint64(&env.StatExecs, 0) a.Stats["executor restarts"] += atomic.SwapUint64(&env.StatRestarts, 0) } a.Stats["exec gen"] = atomic.SwapUint64(&statExecGen, 0) a.Stats["exec fuzz"] = atomic.SwapUint64(&statExecFuzz, 0) a.Stats["exec candidate"] = atomic.SwapUint64(&statExecCandidate, 0) a.Stats["exec triage"] = atomic.SwapUint64(&statExecTriage, 0) a.Stats["exec minimize"] = atomic.SwapUint64(&statExecMinimize, 0) a.Stats["fuzzer new inputs"] = atomic.SwapUint64(&statNewInput, 0) r := &PollRes{} if err := manager.Call("Manager.Poll", a, r); err != nil { panic(err) } for _, inp := range r.NewInputs { addInput(inp) } for _, data := range r.Candidates { p, err := prog.Deserialize(data) if err != nil { panic(err) } if noCover { corpusMu.Lock() corpus = append(corpus, p) corpusMu.Unlock() } else { triageMu.Lock() candidates = append(candidates, p) triageMu.Unlock() } } if len(r.Candidates) == 0 { if atomic.LoadUint32(&allTriaged) == 0 { if *flagLeak { kmemleakScan(false) } atomic.StoreUint32(&allTriaged, 1) } } if len(r.NewInputs) == 0 && len(r.Candidates) == 0 { lastPoll = time.Now() } } } }
func main() { debug.SetGCPercent(50) flag.Parse() logf(0, "started") var calls []*sys.Call if *flagSyscalls != "" { for _, id := range strings.Split(*flagSyscalls, ",") { n, err := strconv.ParseUint(id, 10, 64) if err != nil || n >= uint64(len(sys.Calls)) { panic(fmt.Sprintf("invalid syscall in -calls flag: '%v", id)) } calls = append(calls, sys.Calls[n]) } } corpusCover = make([]cover.Cover, sys.CallCount) maxCover = make([]cover.Cover, sys.CallCount) corpusHashes = make(map[Sig]struct{}) conn, err := rpc.Dial("tcp", *flagManager) if err != nil { panic(err) } manager = conn a := &ManagerConnectArgs{*flagName} r := &ManagerConnectRes{} if err := manager.Call("Manager.Connect", a, r); err != nil { panic(err) } ct = prog.BuildChoiceTable(r.Prios, calls) if *flagParallel <= 0 { *flagParallel = 1 } flags := ipc.FlagCover | ipc.FlagDedupCover if *flagStrace { flags |= ipc.FlagStrace } workerIn = make(chan *prog.Prog, *flagParallel+10) workerOut = make(chan []Input, *flagParallel) for i := 0; i < *flagParallel; i++ { env, err := ipc.MakeEnv(*flagExecutor, 4*time.Second, flags) if err != nil { panic(err) } workerId := i + 1 go func() { for p := range workerIn { workerOut <- execute(env, p, workerId) } }() } env, err := ipc.MakeEnv(*flagExecutor, 4*time.Second, flags) if err != nil { panic(err) } rs := rand.NewSource(time.Now().UnixNano()) rnd := rand.New(rs) var lastPoll time.Time var lastPrint time.Time secondTicker := time.NewTicker(100 * time.Millisecond).C for i := 0; ; i++ { if !*flagSaveProg && time.Since(lastPrint) > 10*time.Second { // Keep-alive for manager. logf(0, "#%v: alive", i) lastPrint = time.Now() } if len(triage) != 0 { last := len(triage) - 1 inp := triage[last] triage = triage[:last] logf(1, "#%v: triaging : %s", i, inp.p) triageInput(env, inp) continue } if time.Since(lastPoll) > 10*time.Second { a := &ManagerPollArgs{*flagName} r := &ManagerPollRes{} if err := manager.Call("Manager.Poll", a, r); err != nil { panic(err) } for _, inp := range r.NewInputs { addInput(inp) } for _, data := range r.Candidates { p, err := prog.Deserialize(data) if err != nil { panic(err) } inputs := execute(env, p, 0) for _, inp := range inputs { call := inp.p.Calls[inp.call].Meta maxCover[call.CallID] = cover.Union(maxCover[call.CallID], inp.cover) triage = append(triage, inp) } } if len(r.NewInputs) == 0 && len(r.Candidates) == 0 { lastPoll = time.Now() } continue } // Parallel part. pending := 0 for ; ; i++ { if !(!*flagSaveProg && time.Since(lastPrint) > 10*time.Second) && !(len(triage) != 0) && !(time.Since(lastPoll) > 10*time.Second) { // No need to do any work above. // Send new inputs to workers, if they need some. for len(workerIn) < *flagParallel { if len(corpus) == 0 || i%10 == 0 { p := prog.Generate(rnd, programLength, ct) logf(1, "#%v: generated: %s", i, p) workerIn <- p pending++ p = p.Clone() p.Mutate(rnd, programLength, ct) logf(1, "#%v: mutated: %s", i, p) workerIn <- p pending++ } else { inp := corpus[rnd.Intn(len(corpus))] p := inp.p.Clone() p.Mutate(rs, programLength, ct) logf(1, "#%v: mutated: %s <- %s", i, p, inp.p) workerIn <- p pending++ } } } else if pending == 0 { // Need to do some work above. // Break if collected all pending results. break } // Collect results. select { case inputs := <-workerOut: pending-- for _, inp := range inputs { triage = append(triage, inp) } case <-secondTicker: } } // Do this after the parallel section because workers access maxCover. for _, inp := range triage { call := inp.p.Calls[inp.call].Meta maxCover[call.CallID] = cover.Union(maxCover[call.CallID], inp.cover) } } }
func main() { debug.SetGCPercent(50) flag.Parse() switch *flagOutput { case "none", "stdout", "dmesg", "file": default: fmt.Fprintf(os.Stderr, "-output flag must be one of none/stdout/dmesg/file\n") os.Exit(1) } Logf(0, "fuzzer started") go func() { // Handles graceful preemption on GCE. c := make(chan os.Signal, 1) signal.Notify(c, syscall.SIGINT, syscall.SIGTERM) <-c Logf(0, "SYZ-FUZZER: PREEMPTED") os.Exit(1) }() corpusCover = make([]cover.Cover, sys.CallCount) maxCover = make([]cover.Cover, sys.CallCount) corpusHashes = make(map[Sig]struct{}) Logf(0, "dialing manager at %v", *flagManager) conn, err := jsonrpc.Dial("tcp", *flagManager) if err != nil { panic(err) } manager = conn a := &ConnectArgs{*flagName} r := &ConnectRes{} if err := manager.Call("Manager.Connect", a, r); err != nil { panic(err) } calls := buildCallList(r.EnabledCalls) ct := prog.BuildChoiceTable(r.Prios, calls) if r.NeedCheck { a := &CheckArgs{Name: *flagName} if fd, err := syscall.Open("/sys/kernel/debug/kcov", syscall.O_RDWR, 0); err == nil { syscall.Close(fd) a.Kcov = true } for c := range calls { a.Calls = append(a.Calls, c.Name) } if err := manager.Call("Manager.Check", a, nil); err != nil { panic(err) } } kmemleakInit() flags, timeout, err := ipc.DefaultFlags() if err != nil { panic(err) } if _, ok := calls[sys.CallMap["syz_emit_ethernet"]]; ok { flags |= ipc.FlagEnableTun } noCover = flags&ipc.FlagCover == 0 leakCallback := func() { if atomic.LoadUint32(&allTriaged) != 0 { // Scan for leaks once in a while (it is damn slow). kmemleakScan(true) } } if !*flagLeak { leakCallback = nil } gate = ipc.NewGate(2**flagProcs, leakCallback) needPoll := make(chan struct{}, 1) needPoll <- struct{}{} envs := make([]*ipc.Env, *flagProcs) for pid := 0; pid < *flagProcs; pid++ { env, err := ipc.MakeEnv(*flagExecutor, timeout, flags, pid) if err != nil { panic(err) } envs[pid] = env pid := pid go func() { rs := rand.NewSource(time.Now().UnixNano() + int64(pid)*1e12) rnd := rand.New(rs) for i := 0; ; i++ { triageMu.RLock() if len(triage) != 0 || len(candidates) != 0 { triageMu.RUnlock() triageMu.Lock() if len(triage) != 0 { last := len(triage) - 1 inp := triage[last] triage = triage[:last] wakePoll := len(triage) < *flagProcs triageMu.Unlock() if wakePoll { select { case needPoll <- struct{}{}: default: } } Logf(1, "triaging : %s", inp.p) triageInput(pid, env, inp) continue } else if len(candidates) != 0 { last := len(candidates) - 1 p := candidates[last] candidates = candidates[:last] triageMu.Unlock() execute(pid, env, p, &statExecCandidate) continue } else { triageMu.Unlock() } } else { triageMu.RUnlock() } corpusMu.RLock() if len(corpus) == 0 || i%10 == 0 { // Generate a new prog. corpusMu.RUnlock() p := prog.Generate(rnd, programLength, ct) Logf(1, "#%v: generated: %s", i, p) execute(pid, env, p, &statExecGen) p.Mutate(rnd, programLength, ct, nil) Logf(1, "#%v: mutated: %s", i, p) execute(pid, env, p, &statExecFuzz) } else { // Mutate an existing prog. p0 := corpus[rnd.Intn(len(corpus))] p := p0.Clone() p.Mutate(rs, programLength, ct, corpus) corpusMu.RUnlock() Logf(1, "#%v: mutated: %s <- %s", i, p, p0) execute(pid, env, p, &statExecFuzz) } } }() } var lastPoll time.Time var lastPrint time.Time ticker := time.NewTicker(3 * time.Second).C for { poll := false select { case <-ticker: case <-needPoll: poll = true } if *flagOutput != "stdout" && time.Since(lastPrint) > 10*time.Second { // Keep-alive for manager. Logf(0, "alive") lastPrint = time.Now() } if poll || time.Since(lastPoll) > 10*time.Second { triageMu.RLock() if len(candidates) > *flagProcs { triageMu.RUnlock() continue } triageMu.RUnlock() a := &PollArgs{ Name: *flagName, Stats: make(map[string]uint64), } for _, env := range envs { a.Stats["exec total"] += atomic.SwapUint64(&env.StatExecs, 0) a.Stats["executor restarts"] += atomic.SwapUint64(&env.StatRestarts, 0) } a.Stats["exec gen"] = atomic.SwapUint64(&statExecGen, 0) a.Stats["exec fuzz"] = atomic.SwapUint64(&statExecFuzz, 0) a.Stats["exec candidate"] = atomic.SwapUint64(&statExecCandidate, 0) a.Stats["exec triage"] = atomic.SwapUint64(&statExecTriage, 0) a.Stats["exec minimize"] = atomic.SwapUint64(&statExecMinimize, 0) a.Stats["fuzzer new inputs"] = atomic.SwapUint64(&statNewInput, 0) r := &PollRes{} if err := manager.Call("Manager.Poll", a, r); err != nil { panic(err) } for _, inp := range r.NewInputs { addInput(inp) } for _, data := range r.Candidates { p, err := prog.Deserialize(data) if err != nil { panic(err) } if noCover { corpusMu.Lock() corpus = append(corpus, p) corpusMu.Unlock() } else { triageMu.Lock() candidates = append(candidates, p) triageMu.Unlock() } } if len(r.Candidates) == 0 && atomic.LoadUint32(&allTriaged) == 0 { if *flagLeak { kmemleakScan(false) } atomic.StoreUint32(&allTriaged, 1) } if len(r.NewInputs) == 0 && len(r.Candidates) == 0 { lastPoll = time.Now() } } } }