github.com/google/syzkaller@v0.0.0-20240517125934-c0f1611a36d6/tools/syz-mutate/mutate.go (about) 1 // Copyright 2015 syzkaller project authors. All rights reserved. 2 // Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file. 3 4 // mutates mutates a given program and prints result. 5 package main 6 7 import ( 8 "flag" 9 "fmt" 10 "math/rand" 11 "os" 12 "runtime" 13 "strings" 14 "time" 15 16 "github.com/google/syzkaller/pkg/db" 17 "github.com/google/syzkaller/pkg/mgrconfig" 18 "github.com/google/syzkaller/prog" 19 _ "github.com/google/syzkaller/sys" 20 ) 21 22 var ( 23 flagOS = flag.String("os", runtime.GOOS, "target os") 24 flagArch = flag.String("arch", runtime.GOARCH, "target arch") 25 flagSeed = flag.Int("seed", -1, "prng seed") 26 flagLen = flag.Int("len", prog.RecommendedCalls, "number of calls in programs") 27 flagEnable = flag.String("enable", "", "comma-separated list of enabled syscalls") 28 flagCorpus = flag.String("corpus", "", "name of the corpus file") 29 flagHintCall = flag.Int("hint-call", -1, "mutate the specified call with hints in hint-src/cmp flags") 30 flagHintSrc = flag.Uint64("hint-src", 0, "compared value in the program") 31 flagHintCmp = flag.Uint64("hint-cmp", 0, "compare operand in the kernel") 32 flagStrict = flag.Bool("strict", true, "parse input program in strict mode") 33 ) 34 35 func main() { 36 flag.Parse() 37 target, err := prog.GetTarget(*flagOS, *flagArch) 38 if err != nil { 39 fmt.Fprintf(os.Stderr, "%v\n", err) 40 os.Exit(1) 41 } 42 var syscalls map[*prog.Syscall]bool 43 if *flagEnable != "" { 44 enabled := strings.Split(*flagEnable, ",") 45 syscallsIDs, err := mgrconfig.ParseEnabledSyscalls(target, enabled, nil) 46 if err != nil { 47 fmt.Fprintf(os.Stderr, "failed to parse enabled syscalls: %v\n", err) 48 os.Exit(1) 49 } 50 syscalls = make(map[*prog.Syscall]bool) 51 for _, id := range syscallsIDs { 52 syscalls[target.Syscalls[id]] = true 53 } 54 var disabled map[*prog.Syscall]string 55 syscalls, disabled = target.TransitivelyEnabledCalls(syscalls) 56 for c, reason := range disabled { 57 fmt.Fprintf(os.Stderr, "disabling %v: %v\n", c.Name, reason) 58 } 59 } 60 seed := time.Now().UnixNano() 61 if *flagSeed != -1 { 62 seed = int64(*flagSeed) 63 } 64 corpus, err := db.ReadCorpus(*flagCorpus, target) 65 if err != nil { 66 fmt.Fprintf(os.Stderr, "failed to read corpus: %v\n", err) 67 os.Exit(1) 68 } 69 rs := rand.NewSource(seed) 70 ct := target.BuildChoiceTable(corpus, syscalls) 71 var p *prog.Prog 72 if flag.NArg() == 0 { 73 p = target.Generate(rs, *flagLen, ct) 74 } else { 75 data, err := os.ReadFile(flag.Arg(0)) 76 if err != nil { 77 fmt.Fprintf(os.Stderr, "failed to read prog file: %v\n", err) 78 os.Exit(1) 79 } 80 mode := prog.NonStrict 81 if *flagStrict { 82 mode = prog.Strict 83 } 84 p, err = target.Deserialize(data, mode) 85 if err != nil { 86 fmt.Fprintf(os.Stderr, "failed to deserialize the program: %v\n", err) 87 os.Exit(1) 88 } 89 if *flagHintCall != -1 { 90 comps := make(prog.CompMap) 91 comps.AddComp(*flagHintSrc, *flagHintCmp) 92 p.MutateWithHints(*flagHintCall, comps, func(p *prog.Prog) bool { 93 fmt.Printf("%s\n\n", p.Serialize()) 94 return true 95 }) 96 return 97 } else { 98 p.Mutate(rs, *flagLen, ct, nil, corpus) 99 } 100 } 101 fmt.Printf("%s\n", p.Serialize()) 102 }