github.com/google/syzkaller@v0.0.0-20240517125934-c0f1611a36d6/tools/syz-hubtool/hubtool.go (about) 1 // Copyright 2020 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 // syz-hubtool uploads local reproducers to syz-hub. 5 package main 6 7 import ( 8 "flag" 9 "log" 10 "net/http" 11 "os" 12 "path/filepath" 13 "runtime" 14 "time" 15 16 "github.com/google/syzkaller/pkg/auth" 17 "github.com/google/syzkaller/pkg/db" 18 "github.com/google/syzkaller/pkg/rpctype" 19 "github.com/google/syzkaller/prog" 20 _ "github.com/google/syzkaller/sys" 21 ) 22 23 func main() { 24 var ( 25 flagOS = flag.String("os", runtime.GOOS, "target OS") 26 flagArch = flag.String("arch", runtime.GOARCH, "target Arch") 27 flagHubAddress = flag.String("addr", "", "hub address") 28 flagHubClient = flag.String("client", "", "hub API client") 29 flagHubKey = flag.String("key", "", "hub API key") 30 flagHubManager = flag.String("manager", "", "manager name to upload on behalf of") 31 flagRepro = flag.String("repro", "", "reproducer glob pattern to upload") 32 flagCorpus = flag.String("corpus", "", "coprpus file to upload") 33 flagCorpusProgs = flag.String("corpus_progs", "", "a glob pattern of progs to add to corpus") 34 flagWorkdir = flag.String("workdir", "", "workdir to upload coprpus and reproducers") 35 flagDrain = flag.Bool("drain", false, "drain hub corpus and reproducers for the given manager") 36 ) 37 flag.Parse() 38 target, err := prog.GetTarget(*flagOS, *flagArch) 39 if err != nil { 40 log.Fatal(err) 41 } 42 if *flagWorkdir != "" { 43 *flagRepro = filepath.Join(*flagWorkdir, "crashes", "*", "repro.prog") 44 *flagCorpus = filepath.Join(*flagWorkdir, "corpus.db") 45 } 46 var repros, corpus [][]byte 47 if *flagRepro != "" { 48 repros = loadProgs(target, *flagRepro) 49 } 50 if *flagCorpus != "" { 51 corpus = loadCorpus(target, *flagCorpus) 52 } else if *flagCorpusProgs != "" { 53 corpus = loadProgs(target, *flagCorpusProgs) 54 } 55 log.Printf("loaded %v reproducers, %v corpus programs", len(repros), len(corpus)) 56 if len(repros)+len(corpus) == 0 && !*flagDrain { 57 return 58 } 59 log.Printf("connecting to hub at %v...", *flagHubAddress) 60 conn, err := rpctype.NewRPCClient(*flagHubAddress) 61 if err != nil { 62 log.Fatalf("failed to connect to hub: %v", err) 63 } 64 key := *flagHubKey 65 if *flagHubKey == "" { 66 tokenCache, err := auth.MakeCache(http.NewRequest, http.DefaultClient.Do) 67 if err != nil { 68 log.Fatalf("failed to make auth cache %v", err) 69 } 70 key, err = tokenCache.Get(time.Now()) 71 if err != nil { 72 log.Fatalf("failed to get a token %v", err) 73 } 74 } 75 connectArgs := &rpctype.HubConnectArgs{ 76 Client: *flagHubClient, 77 Key: key, 78 Manager: *flagHubManager, 79 Fresh: false, 80 Calls: nil, 81 Corpus: corpus, 82 } 83 if err := conn.Call("Hub.Connect", connectArgs, nil); err != nil { 84 log.Fatalf("Hub.Connect failed: %v", err) 85 } 86 log.Printf("uploaded %v corpus programs", len(corpus)) 87 if len(repros) != 0 { 88 syncArgs := &rpctype.HubSyncArgs{ 89 Client: *flagHubClient, 90 Key: key, 91 Manager: *flagHubManager, 92 Repros: repros, 93 } 94 if err := conn.Call("Hub.Sync", syncArgs, new(rpctype.HubSyncRes)); err != nil { 95 log.Fatalf("Hub.Sync failed: %v", err) 96 } 97 log.Printf("uploaded %v reproducers", len(repros)) 98 } 99 for *flagDrain { 100 syncArgs := &rpctype.HubSyncArgs{ 101 Client: *flagHubClient, 102 Key: key, 103 Manager: *flagHubManager, 104 NeedRepros: true, 105 } 106 resp := new(rpctype.HubSyncRes) 107 if err := conn.Call("Hub.Sync", syncArgs, resp); err != nil { 108 log.Fatalf("Hub.Sync failed: %v", err) 109 } 110 log.Printf("received %v progs, %v repros, %v more", len(resp.Progs), len(resp.Repros), resp.More) 111 if len(resp.Progs)+len(resp.Repros) == 0 { 112 break 113 } 114 } 115 } 116 117 func loadProgs(target *prog.Target, reproGlob string) [][]byte { 118 files, err := filepath.Glob(reproGlob) 119 if err != nil { 120 log.Fatal(err) 121 } 122 var repros [][]byte 123 dedup := make(map[string]bool) 124 for _, file := range files { 125 data, err := os.ReadFile(file) 126 if err != nil { 127 log.Fatal(err) 128 } 129 if _, err := target.Deserialize(data, prog.NonStrict); err != nil { 130 log.Printf("failed to deserialize %v: %v", file, err) 131 continue 132 } 133 if dedup[string(data)] { 134 log.Printf("%v is a duplicate", file) 135 continue 136 } 137 dedup[string(data)] = true 138 repros = append(repros, data) 139 } 140 return repros 141 } 142 143 func loadCorpus(target *prog.Target, corpusDB string) [][]byte { 144 progs, err := db.ReadCorpus(corpusDB, target) 145 if err != nil { 146 log.Fatal(err) 147 } 148 var corpus [][]byte 149 for _, p := range progs { 150 corpus = append(corpus, p.Serialize()) 151 } 152 return corpus 153 }