aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCheng-Min Chiang <chmnchiang@google.com>2020-09-02 17:23:49 -0700
committerDmitry Vyukov <dvyukov@google.com>2020-09-14 15:00:02 +0200
commit9eff3337ee5c407d4156eccb7bdea4d666e492fc (patch)
treea1e61c38d1d4f47bc7017a8e5c8e9d9b06fce6d8
parentdf4f5a9c4a22ded414b447d4d790c53d4d2a86e2 (diff)
dashboard/app: send machine information to dashboard
- Change syz-manager so that it will send machine info the first time a crash occurs. - Add a field in entities.Crash to store machine info. - Add a field in dashapi.BugReport to store machine info. - Change the HTML template and struct uiCrash to display machine info. - Add a test to make sure that the link to machine info appears on the webpage. Update #466
-rw-r--r--dashboard/app/api.go3
-rw-r--r--dashboard/app/entities.go2
-rw-r--r--dashboard/app/jobs.go31
-rw-r--r--dashboard/app/main.go30
-rw-r--r--dashboard/app/reporting.go42
-rw-r--r--dashboard/app/reporting_test.go45
-rw-r--r--dashboard/app/templates.html1
-rw-r--r--dashboard/dashapi/dashapi.go3
-rw-r--r--syz-manager/manager.go13
9 files changed, 117 insertions, 53 deletions
diff --git a/dashboard/app/api.go b/dashboard/app/api.go
index f30c87174..12f3c7e1c 100644
--- a/dashboard/app/api.go
+++ b/dashboard/app/api.go
@@ -810,6 +810,9 @@ func saveCrash(c context.Context, ns string, req *dashapi.Crash, bugKey *db.Key,
if crash.ReproC, err = putText(c, ns, textReproC, req.ReproC, false); err != nil {
return err
}
+ if crash.MachineInfo, err = putText(c, ns, textMachineInfo, req.MachineInfo, false); err != nil {
+ return err
+ }
crashKey := db.NewIncompleteKey(c, "Crash", bugKey)
if _, err = db.Put(c, crashKey, crash); err != nil {
return fmt.Errorf("failed to put crash: %v", err)
diff --git a/dashboard/app/entities.go b/dashboard/app/entities.go
index ef54c8565..d00d90f11 100644
--- a/dashboard/app/entities.go
+++ b/dashboard/app/entities.go
@@ -131,6 +131,7 @@ type Crash struct {
ReproOpts []byte `datastore:",noindex"`
ReproSyz int64 // reference to ReproSyz text entity
ReproC int64 // reference to ReproC text entity
+ MachineInfo int64 // Reference to MachineInfo text entity.
// Custom crash priority for reporting (greater values are higher priority).
// For example, a crash in mainline kernel has higher priority than a crash in a side branch.
// For historical reasons this is called ReportLen.
@@ -232,6 +233,7 @@ const (
textCrashReport = "CrashReport"
textReproSyz = "ReproSyz"
textReproC = "ReproC"
+ textMachineInfo = "MachineInfo"
textKernelConfig = "KernelConfig"
textPatch = "Patch"
textLog = "Log"
diff --git a/dashboard/app/jobs.go b/dashboard/app/jobs.go
index e46684b21..6d5fd3ff3 100644
--- a/dashboard/app/jobs.go
+++ b/dashboard/app/jobs.go
@@ -668,21 +668,22 @@ func createBugReportForJob(c context.Context, job *Job, jobKey *db.Key, config i
}
kernelRepo := kernelRepoInfo(build)
rep := &dashapi.BugReport{
- Type: typ,
- Config: reportingConfig,
- JobID: extJobID(jobKey),
- ExtID: job.ExtID,
- CC: append(job.CC, kernelRepo.CC...),
- Log: crashLog,
- LogLink: externalLink(c, textCrashLog, job.CrashLog),
- Report: report,
- ReportLink: externalLink(c, textCrashReport, job.CrashReport),
- ReproCLink: externalLink(c, textReproC, crash.ReproC),
- ReproSyzLink: externalLink(c, textReproSyz, crash.ReproSyz),
- CrashTitle: job.CrashTitle,
- Error: jobError,
- ErrorLink: externalLink(c, textError, job.Error),
- PatchLink: externalLink(c, textPatch, job.Patch),
+ Type: typ,
+ Config: reportingConfig,
+ JobID: extJobID(jobKey),
+ ExtID: job.ExtID,
+ CC: append(job.CC, kernelRepo.CC...),
+ Log: crashLog,
+ LogLink: externalLink(c, textCrashLog, job.CrashLog),
+ Report: report,
+ ReportLink: externalLink(c, textCrashReport, job.CrashReport),
+ ReproCLink: externalLink(c, textReproC, crash.ReproC),
+ ReproSyzLink: externalLink(c, textReproSyz, crash.ReproSyz),
+ MachineInfoLink: externalLink(c, textMachineInfo, crash.MachineInfo),
+ CrashTitle: job.CrashTitle,
+ Error: jobError,
+ ErrorLink: externalLink(c, textError, job.Error),
+ PatchLink: externalLink(c, textPatch, job.Patch),
}
if job.Type == JobBisectCause || job.Type == JobBisectFix {
rep.Maintainers = append(crash.Maintainers, kernelRepo.Maintainers...)
diff --git a/dashboard/app/main.go b/dashboard/app/main.go
index 9c6144082..422cebd9c 100644
--- a/dashboard/app/main.go
+++ b/dashboard/app/main.go
@@ -165,13 +165,14 @@ type uiBug struct {
}
type uiCrash struct {
- Manager string
- Time time.Time
- Maintainers string
- LogLink string
- ReportLink string
- ReproSyzLink string
- ReproCLink string
+ Manager string
+ Time time.Time
+ Maintainers string
+ LogLink string
+ ReportLink string
+ ReproSyzLink string
+ ReproCLink string
+ MachineInfoLink string
*uiBuild
}
@@ -917,13 +918,14 @@ func loadFixBisectionsForBug(c context.Context, bug *Bug) ([]*uiCrash, error) {
func makeUICrash(crash *Crash, build *Build) *uiCrash {
ui := &uiCrash{
- Manager: crash.Manager,
- Time: crash.Time,
- Maintainers: strings.Join(crash.Maintainers, ", "),
- LogLink: textLink(textCrashLog, crash.Log),
- ReportLink: textLink(textCrashReport, crash.Report),
- ReproSyzLink: textLink(textReproSyz, crash.ReproSyz),
- ReproCLink: textLink(textReproC, crash.ReproC),
+ Manager: crash.Manager,
+ Time: crash.Time,
+ Maintainers: strings.Join(crash.Maintainers, ", "),
+ LogLink: textLink(textCrashLog, crash.Log),
+ ReportLink: textLink(textCrashReport, crash.Report),
+ ReproSyzLink: textLink(textReproSyz, crash.ReproSyz),
+ ReproCLink: textLink(textReproC, crash.ReproC),
+ MachineInfoLink: textLink(textMachineInfo, crash.MachineInfo),
}
if build != nil {
ui.uiBuild = makeUIBuild(build)
diff --git a/dashboard/app/reporting.go b/dashboard/app/reporting.go
index 23703c78b..dc32fbbe8 100644
--- a/dashboard/app/reporting.go
+++ b/dashboard/app/reporting.go
@@ -391,6 +391,10 @@ func createBugReport(c context.Context, bug *Bug, crash *Crash, crashKey *db.Key
if err != nil {
return nil, err
}
+ machineInfo, _, err := getText(c, textMachineInfo, crash.MachineInfo)
+ if err != nil {
+ return nil, err
+ }
if len(reproSyz) != 0 {
buf := new(bytes.Buffer)
buf.WriteString(syzReproPrefix)
@@ -411,24 +415,26 @@ func createBugReport(c context.Context, bug *Bug, crash *Crash, crashKey *db.Key
kernelRepo := kernelRepoInfo(build)
rep := &dashapi.BugReport{
- Type: typ,
- Config: reportingConfig,
- ExtID: bugReporting.ExtID,
- First: bugReporting.Reported.IsZero(),
- Moderation: reporting.moderation,
- Log: crashLog,
- LogLink: externalLink(c, textCrashLog, crash.Log),
- Report: report,
- ReportLink: externalLink(c, textCrashReport, crash.Report),
- CC: kernelRepo.CC,
- Maintainers: append(crash.Maintainers, kernelRepo.Maintainers...),
- ReproC: reproC,
- ReproCLink: externalLink(c, textReproC, crash.ReproC),
- ReproSyz: reproSyz,
- ReproSyzLink: externalLink(c, textReproSyz, crash.ReproSyz),
- CrashID: crashKey.IntID(),
- NumCrashes: bug.NumCrashes,
- HappenedOn: managersToRepos(c, bug.Namespace, bug.HappenedOn),
+ Type: typ,
+ Config: reportingConfig,
+ ExtID: bugReporting.ExtID,
+ First: bugReporting.Reported.IsZero(),
+ Moderation: reporting.moderation,
+ Log: crashLog,
+ LogLink: externalLink(c, textCrashLog, crash.Log),
+ Report: report,
+ ReportLink: externalLink(c, textCrashReport, crash.Report),
+ CC: kernelRepo.CC,
+ Maintainers: append(crash.Maintainers, kernelRepo.Maintainers...),
+ ReproC: reproC,
+ ReproCLink: externalLink(c, textReproC, crash.ReproC),
+ ReproSyz: reproSyz,
+ ReproSyzLink: externalLink(c, textReproSyz, crash.ReproSyz),
+ MachineInfo: machineInfo,
+ MachineInfoLink: externalLink(c, textMachineInfo, crash.MachineInfo),
+ CrashID: crashKey.IntID(),
+ NumCrashes: bug.NumCrashes,
+ HappenedOn: managersToRepos(c, bug.Namespace, bug.HappenedOn),
}
if bugReporting.CC != "" {
rep.CC = append(rep.CC, strings.Split(bugReporting.CC, "|")...)
diff --git a/dashboard/app/reporting_test.go b/dashboard/app/reporting_test.go
index 427f3bf15..1bb985b55 100644
--- a/dashboard/app/reporting_test.go
+++ b/dashboard/app/reporting_test.go
@@ -5,6 +5,7 @@ package main
import (
"fmt"
+ "regexp"
"testing"
"time"
@@ -460,3 +461,47 @@ func TestReportingFilter(t *testing.T) {
rep4 := c.client.pollBug()
c.expectEQ(string(rep4.Config), `{"Index":2}`)
}
+
+func TestMachineInfo(t *testing.T) {
+ c := NewCtx(t)
+ defer c.Close()
+
+ build := testBuild(1)
+ c.client.UploadBuild(build)
+
+ machineInfo := []byte("info1")
+
+ // Create a crash with machine information and check the returned machine
+ // information field is equal.
+ crash := &dashapi.Crash{
+ BuildID: "build1",
+ Title: "title1",
+ Maintainers: []string{`"Foo Bar" <foo@bar.com>`, `bar@foo.com`},
+ Log: []byte("log1"),
+ Report: []byte("report1"),
+ MachineInfo: machineInfo,
+ }
+ c.client.ReportCrash(crash)
+ rep := c.client.pollBug()
+ c.expectEQ(machineInfo, rep.MachineInfo)
+
+ // Check that a link to machine information page is created on the dashboard,
+ // and the content is correct.
+ indexPage, err := c.AuthGET(AccessAdmin, "/test1")
+ c.expectOK(err)
+ bugLinkRegex := regexp.MustCompile(`<a href="(/bug\?id=[^"]+)">title1</a>`)
+ bugLinkSubmatch := bugLinkRegex.FindSubmatch(indexPage)
+ c.expectEQ(len(bugLinkSubmatch), 2)
+ bugURL := string(bugLinkSubmatch[1])
+
+ bugPage, err := c.AuthGET(AccessAdmin, bugURL)
+ c.expectOK(err)
+ infoLinkRegex := regexp.MustCompile(`<a href="(/text\?tag=MachineInfo[^"]+)">machine info</a>`)
+ infoLinkSubmatch := infoLinkRegex.FindSubmatch(bugPage)
+ c.expectEQ(len(infoLinkSubmatch), 2)
+ infoURL := string(infoLinkSubmatch[1])
+
+ receivedInfo, err := c.AuthGET(AccessAdmin, infoURL)
+ c.expectOK(err)
+ c.expectEQ(receivedInfo, machineInfo)
+}
diff --git a/dashboard/app/templates.html b/dashboard/app/templates.html
index 5743368a1..c07ef4cfb 100644
--- a/dashboard/app/templates.html
+++ b/dashboard/app/templates.html
@@ -342,6 +342,7 @@ Use of this source code is governed by Apache 2 LICENSE that can be found in the
<td class="repro">{{if $b.ReportLink}}<a href="{{$b.ReportLink}}">report</a>{{end}}</td>
<td class="repro">{{if $b.ReproSyzLink}}<a href="{{$b.ReproSyzLink}}">syz</a>{{end}}</td>
<td class="repro">{{if $b.ReproCLink}}<a href="{{$b.ReproCLink}}">C</a>{{end}}</td>
+ <td class="repro">{{if $b.MachineInfoLink}}<a href="{{$b.MachineInfoLink}}">machine info</a>{{end}}</td>
{{if $.HasMaintainers}}
<td class="maintainers" title="{{$b.Maintainers}}">{{$b.Maintainers}}</td>
{{end}}
diff --git a/dashboard/dashapi/dashapi.go b/dashboard/dashapi/dashapi.go
index 2c2a993ea..4748905b4 100644
--- a/dashboard/dashapi/dashapi.go
+++ b/dashboard/dashapi/dashapi.go
@@ -241,6 +241,7 @@ type Crash struct {
Recipients Recipients
Log []byte
Report []byte
+ MachineInfo []byte
// The following is optional and is filled only after repro.
ReproOpts []byte
ReproSyz []byte
@@ -333,6 +334,8 @@ type BugReport struct {
ReproCLink string
ReproSyz []byte
ReproSyzLink string
+ MachineInfo []byte
+ MachineInfoLink string
CrashID int64 // returned back in BugUpdate
NumCrashes int64
HappenedOn []string // list of kernel repo aliases
diff --git a/syz-manager/manager.go b/syz-manager/manager.go
index 4abd27a30..05af6d30b 100644
--- a/syz-manager/manager.go
+++ b/syz-manager/manager.go
@@ -695,12 +695,13 @@ func (mgr *Manager) saveCrash(crash *Crash) bool {
return true
}
dc := &dashapi.Crash{
- BuildID: mgr.cfg.Tag,
- Title: crash.Title,
- Corrupted: crash.Corrupted,
- Recipients: crash.Recipients.ToDash(),
- Log: crash.Output,
- Report: crash.Report.Report,
+ BuildID: mgr.cfg.Tag,
+ Title: crash.Title,
+ Corrupted: crash.Corrupted,
+ Recipients: crash.Recipients.ToDash(),
+ Log: crash.Output,
+ Report: crash.Report.Report,
+ MachineInfo: crash.machineInfo,
}
resp, err := mgr.dash.ReportCrash(dc)
if err != nil {