mirror of
https://github.com/reactos/syzkaller.git
synced 2025-02-15 00:57:35 +00:00
446 lines
13 KiB
Go
446 lines
13 KiB
Go
// Copyright 2017 syzkaller project authors. All rights reserved.
|
|
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
|
|
|
|
// +build aetest
|
|
|
|
package dash
|
|
|
|
import (
|
|
"fmt"
|
|
"strings"
|
|
"testing"
|
|
|
|
"github.com/google/syzkaller/dashboard/dashapi"
|
|
"github.com/google/syzkaller/pkg/email"
|
|
)
|
|
|
|
func TestEmailReport(t *testing.T) {
|
|
c := NewCtx(t)
|
|
defer c.Close()
|
|
|
|
build := testBuild(1)
|
|
c.expectOK(c.API(client2, key2, "upload_build", build, nil))
|
|
|
|
crash := testCrash(build, 1)
|
|
crash.Maintainers = []string{`"Foo Bar" <foo@bar.com>`, `bar@foo.com`}
|
|
c.expectOK(c.API(client2, key2, "report_crash", crash, nil))
|
|
|
|
// Report the crash over email and check all fields.
|
|
sender0 := ""
|
|
{
|
|
c.expectOK(c.GET("/email_poll"))
|
|
c.expectEQ(len(c.emailSink), 1)
|
|
msg := <-c.emailSink
|
|
sender0 = msg.Sender
|
|
sender, _, err := email.RemoveAddrContext(msg.Sender)
|
|
if err != nil {
|
|
t.Fatalf("failed to remove sender context: %v", err)
|
|
}
|
|
c.expectEQ(sender, fromAddr(c.ctx))
|
|
to := config.Namespaces["test2"].Reporting[0].Config.(*EmailConfig).Email
|
|
c.expectEQ(msg.To, []string{to})
|
|
c.expectEQ(msg.Subject, crash.Title)
|
|
c.expectEQ(len(msg.Attachments), 2)
|
|
c.expectEQ(msg.Attachments[0].Name, "config.txt")
|
|
c.expectEQ(msg.Attachments[0].Data, build.KernelConfig)
|
|
c.expectEQ(msg.Attachments[1].Name, "raw.log")
|
|
c.expectEQ(msg.Attachments[1].Data, crash.Log)
|
|
body := `Hello,
|
|
|
|
syzkaller hit the following crash on kernel_commit1
|
|
repo1/branch1
|
|
compiler: compiler1
|
|
.config is attached
|
|
Raw console output is attached.
|
|
|
|
|
|
CC: [bar@foo.com foo@bar.com]
|
|
|
|
report1
|
|
|
|
---
|
|
This bug is generated by a dumb bot. It may contain errors.
|
|
See https://goo.gl/tpsmEJ for details.
|
|
Direct all questions to syzkaller@googlegroups.com.
|
|
Please credit me with: Reported-by: syzbot <syzkaller@googlegroups.com>
|
|
|
|
syzbot will keep track of this bug report.
|
|
Once a fix for this bug is committed, please reply to this email with:
|
|
#syz fix: exact-commit-title
|
|
To mark this as a duplicate of another syzbot report, please reply with:
|
|
#syz dup: exact-subject-of-another-report
|
|
If it's a one-off invalid bug report, please reply with:
|
|
#syz invalid
|
|
Note: if the crash happens again, it will cause creation of a new bug report.
|
|
Note: all commands must start from beginning of the line.
|
|
To upstream this report, please reply with:
|
|
#syz upstream`
|
|
c.expectEQ(msg.Body, body)
|
|
}
|
|
|
|
// Emulate receive of the report from a mailing list.
|
|
// This should update the bug with the link/Message-ID.
|
|
incoming1 := fmt.Sprintf(`Sender: syzkaller@googlegroups.com
|
|
Date: Tue, 15 Aug 2017 14:59:00 -0700
|
|
Message-ID: <1234>
|
|
Subject: crash1
|
|
From: %v
|
|
To: foo@bar.com
|
|
Content-Type: text/plain
|
|
|
|
Hello
|
|
|
|
syzbot will keep track of this bug report.
|
|
Once a fix for this bug is committed, please reply to this email with:
|
|
#syz fix: exact-commit-title
|
|
To mark this as a duplicate of another syzbot report, please reply with:
|
|
#syz dup: exact-subject-of-another-report
|
|
If it's a one-off invalid bug report, please reply with:
|
|
#syz invalid
|
|
|
|
--
|
|
You received this message because you are subscribed to the Google Groups "syzkaller" group.
|
|
To unsubscribe from this group and stop receiving emails from it, send an email to syzkaller+unsubscribe@googlegroups.com.
|
|
To post to this group, send email to syzkaller@googlegroups.com.
|
|
To view this discussion on the web visit https://groups.google.com/d/msgid/syzkaller/1234@google.com.
|
|
For more options, visit https://groups.google.com/d/optout.
|
|
`, sender0)
|
|
|
|
c.expectOK(c.POST("/_ah/mail/", incoming1))
|
|
|
|
// Now report syz reproducer and check updated email.
|
|
crash.ReproOpts = []byte("repro opts")
|
|
crash.ReproSyz = []byte("getpid()")
|
|
syzRepro := []byte(fmt.Sprintf("#%s\n%s", crash.ReproOpts, crash.ReproSyz))
|
|
c.expectOK(c.API(client2, key2, "report_crash", crash, nil))
|
|
|
|
{
|
|
c.expectOK(c.GET("/email_poll"))
|
|
c.expectEQ(len(c.emailSink), 1)
|
|
msg := <-c.emailSink
|
|
c.expectEQ(msg.Sender, sender0)
|
|
sender, _, err := email.RemoveAddrContext(msg.Sender)
|
|
if err != nil {
|
|
t.Fatalf("failed to remove sender context: %v", err)
|
|
}
|
|
c.expectEQ(sender, fromAddr(c.ctx))
|
|
var to []string
|
|
to = append(to, "foo@bar.com")
|
|
to = append(to, config.Namespaces["test2"].Reporting[0].Config.(*EmailConfig).Email)
|
|
c.expectEQ(msg.To, to)
|
|
c.expectEQ(msg.Subject, crash.Title)
|
|
c.expectEQ(len(msg.Attachments), 3)
|
|
c.expectEQ(msg.Attachments[0].Name, "config.txt")
|
|
c.expectEQ(msg.Attachments[0].Data, build.KernelConfig)
|
|
c.expectEQ(msg.Attachments[1].Name, "raw.log")
|
|
c.expectEQ(msg.Attachments[1].Data, crash.Log)
|
|
c.expectEQ(msg.Attachments[2].Name, "repro.txt")
|
|
c.expectEQ(msg.Attachments[2].Data, syzRepro)
|
|
c.expectEQ(msg.Headers["In-Reply-To"], []string{"<1234>"})
|
|
body := `syzkaller has found reproducer for the following crash on kernel_commit1
|
|
repo1/branch1
|
|
compiler: compiler1
|
|
.config is attached
|
|
Raw console output is attached.
|
|
|
|
syzkaller reproducer is attached. See https://goo.gl/kgGztJ
|
|
for information about syzkaller reproducers
|
|
CC: [bar@foo.com foo@bar.com]
|
|
|
|
report1
|
|
`
|
|
c.expectEQ(msg.Body, body)
|
|
}
|
|
|
|
// Now upstream the bug and check that it reaches the next reporting.
|
|
incoming2 := fmt.Sprintf(`Sender: syzkaller@googlegroups.com
|
|
Date: Tue, 15 Aug 2017 14:59:00 -0700
|
|
Message-ID: <1234>
|
|
Subject: crash1
|
|
From: foo@bar.com
|
|
To: foo@bar.com
|
|
Cc: %v
|
|
Content-Type: text/plain
|
|
|
|
#syz upstream
|
|
`, sender0)
|
|
|
|
c.expectOK(c.POST("/_ah/mail/", incoming2))
|
|
|
|
sender1 := ""
|
|
{
|
|
c.expectOK(c.GET("/email_poll"))
|
|
c.expectEQ(len(c.emailSink), 1)
|
|
msg := <-c.emailSink
|
|
sender1 = msg.Sender
|
|
if sender1 == sender0 {
|
|
t.Fatalf("same ID in different reporting")
|
|
}
|
|
sender, _, err := email.RemoveAddrContext(msg.Sender)
|
|
if err != nil {
|
|
t.Fatalf("failed to remove sender context: %v", err)
|
|
}
|
|
c.expectEQ(sender, fromAddr(c.ctx))
|
|
c.expectEQ(msg.To, []string{"bar@foo.com", "bugs@syzkaller.com", "foo@bar.com"})
|
|
c.expectEQ(msg.Subject, crash.Title)
|
|
c.expectEQ(len(msg.Attachments), 3)
|
|
c.expectEQ(msg.Attachments[0].Name, "config.txt")
|
|
c.expectEQ(msg.Attachments[0].Data, build.KernelConfig)
|
|
c.expectEQ(msg.Attachments[1].Name, "raw.log")
|
|
c.expectEQ(msg.Attachments[1].Data, crash.Log)
|
|
c.expectEQ(msg.Attachments[2].Name, "repro.txt")
|
|
c.expectEQ(msg.Attachments[2].Data, syzRepro)
|
|
body := `Hello,
|
|
|
|
syzkaller hit the following crash on kernel_commit1
|
|
repo1/branch1
|
|
compiler: compiler1
|
|
.config is attached
|
|
Raw console output is attached.
|
|
|
|
syzkaller reproducer is attached. See https://goo.gl/kgGztJ
|
|
for information about syzkaller reproducers
|
|
|
|
|
|
report1
|
|
|
|
---
|
|
This bug is generated by a dumb bot. It may contain errors.
|
|
See https://goo.gl/tpsmEJ for details.
|
|
Direct all questions to syzkaller@googlegroups.com.
|
|
Please credit me with: Reported-by: syzbot <syzkaller@googlegroups.com>
|
|
|
|
syzbot will keep track of this bug report.
|
|
Once a fix for this bug is committed, please reply to this email with:
|
|
#syz fix: exact-commit-title
|
|
To mark this as a duplicate of another syzbot report, please reply with:
|
|
#syz dup: exact-subject-of-another-report
|
|
If it's a one-off invalid bug report, please reply with:
|
|
#syz invalid
|
|
Note: if the crash happens again, it will cause creation of a new bug report.
|
|
Note: all commands must start from beginning of the line.
|
|
`
|
|
c.expectEQ(msg.Body, body)
|
|
}
|
|
|
|
// Model that somebody adds more emails to CC list.
|
|
incoming3 := fmt.Sprintf(`Sender: syzkaller@googlegroups.com
|
|
Date: Tue, 15 Aug 2017 14:59:00 -0700
|
|
Message-ID: <1234>
|
|
Subject: crash1
|
|
From: foo@bar.com
|
|
To: %v
|
|
CC: new@new.com, "another" <another@another.com>, bar@foo.com, bugs@syzkaller.com, foo@bar.com
|
|
Content-Type: text/plain
|
|
|
|
+more people
|
|
`, sender1)
|
|
|
|
c.expectOK(c.POST("/_ah/mail/", incoming3))
|
|
|
|
// Now upload a C reproducer.
|
|
crash.ReproC = []byte("int main() {}")
|
|
crash.Maintainers = []string{"\"qux\" <qux@qux.com>"}
|
|
c.expectOK(c.API(client2, key2, "report_crash", crash, nil))
|
|
|
|
{
|
|
c.expectOK(c.GET("/email_poll"))
|
|
c.expectEQ(len(c.emailSink), 1)
|
|
msg := <-c.emailSink
|
|
c.expectEQ(msg.Sender, sender1)
|
|
sender, _, err := email.RemoveAddrContext(msg.Sender)
|
|
if err != nil {
|
|
t.Fatalf("failed to remove sender context: %v", err)
|
|
}
|
|
c.expectEQ(sender, fromAddr(c.ctx))
|
|
c.expectEQ(msg.To, []string{"another@another.com", "bar@foo.com", "bugs@syzkaller.com", "foo@bar.com", "new@new.com", "qux@qux.com"})
|
|
c.expectEQ(msg.Subject, crash.Title)
|
|
c.expectEQ(len(msg.Attachments), 4)
|
|
c.expectEQ(msg.Attachments[0].Name, "config.txt")
|
|
c.expectEQ(msg.Attachments[0].Data, build.KernelConfig)
|
|
c.expectEQ(msg.Attachments[1].Name, "raw.log")
|
|
c.expectEQ(msg.Attachments[1].Data, crash.Log)
|
|
c.expectEQ(msg.Attachments[2].Name, "repro.txt")
|
|
c.expectEQ(msg.Attachments[2].Data, syzRepro)
|
|
c.expectEQ(msg.Attachments[3].Name, "repro.c")
|
|
c.expectEQ(msg.Attachments[3].Data, crash.ReproC)
|
|
body := `syzkaller has found reproducer for the following crash on kernel_commit1
|
|
repo1/branch1
|
|
compiler: compiler1
|
|
.config is attached
|
|
Raw console output is attached.
|
|
C reproducer is attached
|
|
syzkaller reproducer is attached. See https://goo.gl/kgGztJ
|
|
for information about syzkaller reproducers
|
|
|
|
|
|
report1
|
|
`
|
|
c.expectEQ(msg.Body, body)
|
|
}
|
|
|
|
// Send an invalid command.
|
|
incoming4 := fmt.Sprintf(`Sender: syzkaller@googlegroups.com
|
|
Date: Tue, 15 Aug 2017 14:59:00 -0700
|
|
Message-ID: <abcdef>
|
|
Subject: title1
|
|
From: foo@bar.com
|
|
To: %v
|
|
Content-Type: text/plain
|
|
|
|
#syz bad-command
|
|
`, sender1)
|
|
|
|
c.expectOK(c.POST("/_ah/mail/", incoming4))
|
|
|
|
{
|
|
c.expectOK(c.GET("/email_poll"))
|
|
c.expectEQ(len(c.emailSink), 1)
|
|
msg := <-c.emailSink
|
|
c.expectEQ(msg.To, []string{"<foo@bar.com>"})
|
|
c.expectEQ(msg.Subject, crash.Title)
|
|
c.expectEQ(msg.Headers["In-Reply-To"], []string{"<abcdef>"})
|
|
if !strings.Contains(msg.Body, `> #syz bad-command
|
|
|
|
unknown command "bad-command"
|
|
`) {
|
|
t.Fatal("no unknown command reply for bad command")
|
|
}
|
|
}
|
|
|
|
// Now mark the bug as invalid.
|
|
incoming5 := fmt.Sprintf(`Sender: syzkaller@googlegroups.com
|
|
Date: Tue, 15 Aug 2017 14:59:00 -0700
|
|
Message-ID: <abcdef>
|
|
Subject: title1
|
|
From: foo@bar.com
|
|
To: %v
|
|
Content-Type: text/plain
|
|
|
|
#syz fix: some: commit title
|
|
`, sender1)
|
|
c.expectOK(c.POST("/_ah/mail/", incoming5))
|
|
c.expectOK(c.GET("/email_poll"))
|
|
c.expectEQ(len(c.emailSink), 0)
|
|
|
|
// Check that the commit is now passed to builders.
|
|
builderPollReq := &dashapi.BuilderPollReq{build.Manager}
|
|
builderPollResp := new(dashapi.BuilderPollResp)
|
|
c.expectOK(c.API(client2, key2, "builder_poll", builderPollReq, builderPollResp))
|
|
c.expectEQ(len(builderPollResp.PendingCommits), 1)
|
|
c.expectEQ(builderPollResp.PendingCommits[0], "some: commit title")
|
|
|
|
build2 := testBuild(2)
|
|
build2.Manager = build.Manager
|
|
build2.Commits = []string{"some: commit title"}
|
|
c.expectOK(c.API(client2, key2, "upload_build", build2, nil))
|
|
|
|
// New crash must produce new bug in the first reporting.
|
|
c.expectOK(c.API(client2, key2, "report_crash", crash, nil))
|
|
{
|
|
c.expectOK(c.GET("/email_poll"))
|
|
c.expectEQ(len(c.emailSink), 1)
|
|
msg := <-c.emailSink
|
|
c.expectEQ(msg.Subject, crash.Title+" (2)")
|
|
if msg.Sender == sender0 {
|
|
t.Fatalf("same reporting ID for new bug")
|
|
}
|
|
}
|
|
}
|
|
|
|
// Bug must not be mailed to maintainers if maintainers list is empty.
|
|
func TestEmailNoMaintainers(t *testing.T) {
|
|
c := NewCtx(t)
|
|
defer c.Close()
|
|
|
|
build := testBuild(1)
|
|
c.expectOK(c.API(client2, key2, "upload_build", build, nil))
|
|
|
|
crash := testCrash(build, 1)
|
|
c.expectOK(c.API(client2, key2, "report_crash", crash, nil))
|
|
|
|
c.expectOK(c.GET("/email_poll"))
|
|
c.expectEQ(len(c.emailSink), 1)
|
|
sender := (<-c.emailSink).Sender
|
|
|
|
incoming1 := fmt.Sprintf(`Sender: syzkaller@googlegroups.com
|
|
Date: Tue, 15 Aug 2017 14:59:00 -0700
|
|
Message-ID: <1234>
|
|
Subject: crash1
|
|
From: %v
|
|
To: foo@bar.com
|
|
Content-Type: text/plain
|
|
|
|
#syz upstream
|
|
`, sender)
|
|
c.expectOK(c.POST("/_ah/mail/", incoming1))
|
|
|
|
c.expectOK(c.GET("/email_poll"))
|
|
c.expectEQ(len(c.emailSink), 0)
|
|
}
|
|
|
|
// Basic dup scenario: mark one bug as dup of another.
|
|
func TestEmailDup(t *testing.T) {
|
|
c := NewCtx(t)
|
|
defer c.Close()
|
|
|
|
build := testBuild(1)
|
|
c.expectOK(c.API(client2, key2, "upload_build", build, nil))
|
|
|
|
crash1 := testCrash(build, 1)
|
|
crash1.Title = "BUG: slightly more elaborate title"
|
|
c.expectOK(c.API(client2, key2, "report_crash", crash1, nil))
|
|
|
|
crash2 := testCrash(build, 2)
|
|
crash1.Title = "KASAN: another title"
|
|
c.expectOK(c.API(client2, key2, "report_crash", crash2, nil))
|
|
|
|
c.expectOK(c.GET("/email_poll"))
|
|
c.expectEQ(len(c.emailSink), 2)
|
|
msg1 := <-c.emailSink
|
|
msg2 := <-c.emailSink
|
|
|
|
// Dup crash2 to crash1.
|
|
incoming1 := fmt.Sprintf(`Sender: syzkaller@googlegroups.com
|
|
Date: Tue, 15 Aug 2017 14:59:00 -0700
|
|
Message-ID: <12345>
|
|
Subject: title1
|
|
From: foo@bar.com
|
|
To: %v
|
|
Content-Type: text/plain
|
|
|
|
#syz dup: BUG: slightly more elaborate title
|
|
`, msg2.Sender)
|
|
c.expectOK(c.POST("/_ah/mail/", incoming1))
|
|
c.expectOK(c.GET("/email_poll"))
|
|
c.expectEQ(len(c.emailSink), 0)
|
|
|
|
// Second crash happens again
|
|
crash2.ReproC = []byte("int main() {}")
|
|
c.expectOK(c.API(client2, key2, "report_crash", crash2, nil))
|
|
c.expectOK(c.GET("/email_poll"))
|
|
c.expectEQ(len(c.emailSink), 0)
|
|
|
|
// Now close the original bug, and check that new bugs for dup are now created.
|
|
incoming2 := fmt.Sprintf(`Sender: syzkaller@googlegroups.com
|
|
Date: Tue, 15 Aug 2017 14:59:00 -0700
|
|
Message-ID: <12345>
|
|
Subject: title1
|
|
From: foo@bar.com
|
|
To: %v
|
|
Content-Type: text/plain
|
|
|
|
#syz invalid
|
|
`, msg1.Sender)
|
|
c.expectOK(c.POST("/_ah/mail/", incoming2))
|
|
|
|
// New crash must produce new bug in the first reporting.
|
|
c.expectOK(c.API(client2, key2, "report_crash", crash2, nil))
|
|
{
|
|
c.expectOK(c.GET("/email_poll"))
|
|
c.expectEQ(len(c.emailSink), 1)
|
|
msg := <-c.emailSink
|
|
c.expectEQ(msg.Subject, crash2.Title+" (2)")
|
|
}
|
|
}
|