github.com/google/syzkaller@v0.0.0-20240517125934-c0f1611a36d6/dashboard/app/kcidb.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 package main 5 6 import ( 7 "context" 8 "fmt" 9 "net/http" 10 "time" 11 12 "github.com/google/syzkaller/pkg/kcidb" 13 "google.golang.org/appengine/v2" 14 db "google.golang.org/appengine/v2/datastore" 15 "google.golang.org/appengine/v2/log" 16 ) 17 18 func initKcidb() { 19 http.HandleFunc("/cron/kcidb_poll", handleKcidbPoll) 20 } 21 22 func handleKcidbPoll(w http.ResponseWriter, r *http.Request) { 23 c := appengine.NewContext(r) 24 for ns, cfg := range getConfig(c).Namespaces { 25 if cfg.Kcidb == nil { 26 continue 27 } 28 if err := handleKcidbNamespce(c, ns, cfg.Kcidb); err != nil { 29 log.Errorf(c, "kcidb: %v failed: %v", ns, err) 30 } 31 } 32 } 33 34 func handleKcidbNamespce(c context.Context, ns string, cfg *KcidbConfig) error { 35 client, err := kcidb.NewClient(c, cfg.Origin, cfg.Project, cfg.Topic, cfg.Credentials) 36 if err != nil { 37 return err 38 } 39 defer client.Close() 40 41 filter := func(query *db.Query) *db.Query { 42 return query.Filter("Namespace=", ns). 43 Filter("Status=", BugStatusOpen) 44 } 45 reported := 0 46 return foreachBug(c, filter, func(bug *Bug, bugKey *db.Key) error { 47 if reported >= 30 { 48 return nil 49 } 50 ok, err := publishKcidbBug(c, client, bug, bugKey) 51 if err != nil { 52 return err 53 } 54 if ok { 55 reported++ 56 } 57 return nil 58 }) 59 } 60 61 func publishKcidbBug(c context.Context, client *kcidb.Client, bug *Bug, bugKey *db.Key) (bool, error) { 62 if bug.KcidbStatus != 0 || 63 bug.sanitizeAccess(c, AccessPublic) > AccessPublic || 64 bug.Reporting[len(bug.Reporting)-1].Reported.IsZero() || 65 bug.Status != BugStatusOpen && timeSince(c, bug.LastTime) > 7*24*time.Hour { 66 return false, nil 67 } 68 rep, err := loadBugReport(c, bug) 69 if err != nil { 70 return false, err 71 } 72 publish := true 73 if rep.KernelCommit == "" || len(rep.KernelConfig) == 0 { 74 // This should happen only for syzkaller build/test errors, which we don't want to publish. 75 // But if this ever happens for a kernel bug, then we also don't want to publish such bugs 76 // with missing critical info. 77 publish = false 78 } 79 if publish { 80 if err := client.Publish(rep); err != nil { 81 return false, err 82 } 83 } 84 tx := func(c context.Context) error { 85 bug := new(Bug) 86 if err := db.Get(c, bugKey, bug); err != nil { 87 return err 88 } 89 bug.KcidbStatus = 1 90 if !publish { 91 bug.KcidbStatus = 2 92 } 93 if _, err := db.Put(c, bugKey, bug); err != nil { 94 return fmt.Errorf("failed to put bug: %w", err) 95 } 96 return nil 97 } 98 if err := db.RunInTransaction(c, tx, nil); err != nil { 99 return false, err 100 } 101 log.Infof(c, "published bug to kcidb: %v:%v '%v'", bug.Namespace, bugKey.StringID(), bug.displayTitle()) 102 return publish, nil 103 }