aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--syz-cluster/dashboard/templates/series.html6
-rw-r--r--syz-cluster/pkg/api/api.go8
-rw-r--r--syz-cluster/pkg/api/client.go9
-rw-r--r--syz-cluster/pkg/controller/api.go8
-rw-r--r--syz-cluster/pkg/service/session.go10
-rw-r--r--syz-cluster/pkg/workflow/template.yaml2
-rw-r--r--syz-cluster/workflow/triage-step/main.go38
7 files changed, 41 insertions, 40 deletions
diff --git a/syz-cluster/dashboard/templates/series.html b/syz-cluster/dashboard/templates/series.html
index 35961d1ba..31eaebc8f 100644
--- a/syz-cluster/dashboard/templates/series.html
+++ b/syz-cluster/dashboard/templates/series.html
@@ -96,11 +96,11 @@
<th>Status</th>
<td>{{.Status}}</td>
</tr>
- {{if not .SkipReason.IsNull}}
+ {{if or (not .SkipReason.IsNull) .TriageLogURI}}
<tr>
- <th>Skipped</th>
+ <th>Triaged</th>
<td>
- {{.SkipReason.StringVal}}
+ {{if not .SkipReason.IsNull}}Skipped: {{.SkipReason.StringVal}}{{else}}OK{{end}}
{{if .TriageLogURI}}
<a href="/sessions/{{.ID}}/triage_log">[Log]</a>
{{end}}
diff --git a/syz-cluster/pkg/api/api.go b/syz-cluster/pkg/api/api.go
index 33d83684e..481554a50 100644
--- a/syz-cluster/pkg/api/api.go
+++ b/syz-cluster/pkg/api/api.go
@@ -5,18 +5,14 @@ package api
import "time"
+// The output passed to other workflow steps.
type TriageResult struct {
// If set, ignore the patch series completely.
- Skip *SkipRequest `json:"skip"`
+ SkipReason string `json:"skip_reason"`
// Fuzzing configuration to try (NULL if nothing).
Fuzz *FuzzConfig `json:"fuzz"`
}
-type SkipRequest struct {
- Reason string `json:"reason"`
- TriageLog []byte `json:"log"`
-}
-
// The data layout faclitates the simplicity of the workflow definition.
type FuzzConfig struct {
Base BuildRequest `json:"base"`
diff --git a/syz-cluster/pkg/api/client.go b/syz-cluster/pkg/api/client.go
index 787748e51..43da4b512 100644
--- a/syz-cluster/pkg/api/client.go
+++ b/syz-cluster/pkg/api/client.go
@@ -30,8 +30,13 @@ func (client Client) GetSeries(ctx context.Context, seriesID string) (*Series, e
return getJSON[Series](ctx, client.baseURL+"/series/"+seriesID)
}
-func (client Client) SkipSession(ctx context.Context, sessionID string, req *SkipRequest) error {
- _, err := postJSON[SkipRequest, any](ctx, client.baseURL+"/sessions/"+sessionID+"/skip", req)
+type UploadTriageResultReq struct {
+ SkipReason string `json:"skip_reason"`
+ Log []byte `json:"log"`
+}
+
+func (client Client) UploadTriageResult(ctx context.Context, sessionID string, req *UploadTriageResultReq) error {
+ _, err := postJSON[UploadTriageResultReq, any](ctx, client.baseURL+"/sessions/"+sessionID+"/triage_result", req)
return err
}
diff --git a/syz-cluster/pkg/controller/api.go b/syz-cluster/pkg/controller/api.go
index 6dbdc4889..a20860d6f 100644
--- a/syz-cluster/pkg/controller/api.go
+++ b/syz-cluster/pkg/controller/api.go
@@ -42,7 +42,7 @@ func (c APIServer) Mux() *http.ServeMux {
mux.HandleFunc("/series/{series_id}", c.getSeries)
mux.HandleFunc("/sessions/upload", c.uploadSession)
mux.HandleFunc("/sessions/{session_id}/series", c.getSessionSeries)
- mux.HandleFunc("/sessions/{session_id}/skip", c.skipSession)
+ mux.HandleFunc("/sessions/{session_id}/triage_result", c.triageResult)
mux.HandleFunc("/tests/upload_artifacts", c.uploadTestArtifact)
mux.HandleFunc("/tests/upload", c.uploadTest)
mux.HandleFunc("/trees", c.getTrees)
@@ -61,12 +61,12 @@ func (c APIServer) getSessionSeries(w http.ResponseWriter, r *http.Request) {
api.ReplyJSON(w, resp)
}
-func (c APIServer) skipSession(w http.ResponseWriter, r *http.Request) {
- req := api.ParseJSON[api.SkipRequest](w, r)
+func (c APIServer) triageResult(w http.ResponseWriter, r *http.Request) {
+ req := api.ParseJSON[api.UploadTriageResultReq](w, r)
if req == nil {
return
}
- err := c.sessionService.SkipSession(r.Context(), r.PathValue("session_id"), req)
+ err := c.sessionService.TriageResult(r.Context(), r.PathValue("session_id"), req)
if errors.Is(err, service.ErrSessionNotFound) {
http.Error(w, fmt.Sprint(err), http.StatusNotFound)
return
diff --git a/syz-cluster/pkg/service/session.go b/syz-cluster/pkg/service/session.go
index 446b431f4..62f959699 100644
--- a/syz-cluster/pkg/service/session.go
+++ b/syz-cluster/pkg/service/session.go
@@ -32,18 +32,20 @@ func NewSessionService(env *app.AppEnvironment) *SessionService {
var ErrSessionNotFound = errors.New("session not found")
-func (s *SessionService) SkipSession(ctx context.Context, sessionID string, skip *api.SkipRequest) error {
+func (s *SessionService) TriageResult(ctx context.Context, sessionID string, req *api.UploadTriageResultReq) error {
var triageLogURI string
- if len(skip.TriageLog) > 0 {
+ if len(req.Log) > 0 {
var err error
- triageLogURI, err = s.blobStorage.Write(bytes.NewReader(skip.TriageLog), "Session", sessionID, "triage_log")
+ triageLogURI, err = s.blobStorage.Write(bytes.NewReader(req.Log), "Session", sessionID, "triage_log")
if err != nil {
return fmt.Errorf("failed to save the triage log: %w", err)
}
}
err := s.sessionRepo.Update(ctx, sessionID, func(session *db.Session) error {
session.TriageLogURI = triageLogURI
- session.SetSkipReason(skip.Reason)
+ if req.SkipReason != "" {
+ session.SetSkipReason(req.SkipReason)
+ }
return nil
})
if errors.Is(err, db.ErrEntityNotFound) {
diff --git a/syz-cluster/pkg/workflow/template.yaml b/syz-cluster/pkg/workflow/template.yaml
index 53752787e..d9107799c 100644
--- a/syz-cluster/pkg/workflow/template.yaml
+++ b/syz-cluster/pkg/workflow/template.yaml
@@ -38,7 +38,7 @@ spec:
template: triage-step
- - name: abort-on-skip-outcome
template: exit-workflow
- when: "{{=jsonpath(steps['run-triage'].outputs.parameters.result, '$.skip') != nil}}"
+ when: "{{=jsonpath(steps['run-triage'].outputs.parameters.result, '$.skip_reason') != ''}}"
- - name: run-process-fuzz
template: process-fuzz
arguments:
diff --git a/syz-cluster/workflow/triage-step/main.go b/syz-cluster/workflow/triage-step/main.go
index b412947a2..9fa7a50bd 100644
--- a/syz-cluster/workflow/triage-step/main.go
+++ b/syz-cluster/workflow/triage-step/main.go
@@ -8,13 +8,12 @@ import (
"context"
"flag"
"fmt"
+
"github.com/google/syzkaller/pkg/debugtracer"
"github.com/google/syzkaller/pkg/osutil"
"github.com/google/syzkaller/syz-cluster/pkg/api"
"github.com/google/syzkaller/syz-cluster/pkg/app"
"github.com/google/syzkaller/syz-cluster/pkg/triage"
- "io"
- "os"
)
var (
@@ -35,15 +34,18 @@ func main() {
app.Fatalf("failed to initialize the repository: %v", err)
}
ctx := context.Background()
- verdict, err := getVerdict(ctx, client, repo)
+ output := new(bytes.Buffer)
+ tracer := &debugtracer.GenericTracer{WithTime: true, TraceWriter: output}
+ verdict, err := getVerdict(ctx, tracer, client, repo)
if err != nil {
app.Fatalf("failed to get the verdict: %v", err)
}
- if verdict.Skip != nil {
- err := client.SkipSession(context.Background(), *flagSession, verdict.Skip)
- if err != nil {
- app.Fatalf("failed to upload the skip reason: %v", err)
- }
+ err = client.UploadTriageResult(ctx, *flagSession, &api.UploadTriageResultReq{
+ SkipReason: verdict.SkipReason,
+ Log: output.Bytes(),
+ })
+ if err != nil {
+ app.Fatalf("failed to upload triage results: %v", err)
}
if *flagVerdict != "" {
osutil.WriteJSON(*flagVerdict, verdict)
@@ -54,7 +56,8 @@ func main() {
// 2. What if controller does not reply? Let Argo just restart the step.
}
-func getVerdict(ctx context.Context, client *api.Client, ops triage.TreeOps) (*api.TriageResult, error) {
+func getVerdict(ctx context.Context, tracer debugtracer.DebugTracer, client *api.Client,
+ ops triage.TreeOps) (*api.TriageResult, error) {
series, err := client.GetSessionSeries(ctx, *flagSession)
if err != nil {
// TODO: the workflow step must be retried.
@@ -67,11 +70,10 @@ func getVerdict(ctx context.Context, client *api.Client, ops triage.TreeOps) (*a
tree := triage.SelectTree(series, trees.Trees)
if tree == nil {
return &api.TriageResult{
- Skip: &api.SkipRequest{
- Reason: "no suitable base kernel tree found",
- },
+ SkipReason: "no suitable base kernel tree found",
}, nil
}
+ tracer.Log("selected tree %q", tree.Name)
arch := "amd64"
lastBuild, err := client.LastBuild(ctx, &api.LastBuildReq{
Arch: arch,
@@ -83,22 +85,18 @@ func getVerdict(ctx context.Context, client *api.Client, ops triage.TreeOps) (*a
// TODO: the workflow step must be retried.
return nil, fmt.Errorf("failed to query the last build: %w", err)
}
- var buf bytes.Buffer
- selector := triage.NewCommitSelector(ops, &debugtracer.GenericTracer{
- TraceWriter: io.MultiWriter(os.Stderr, &buf),
- })
+ tracer.Log("last build: %q", lastBuild)
+ selector := triage.NewCommitSelector(ops, tracer)
result, err := selector.Select(series, tree, lastBuild)
if err != nil {
// TODO: the workflow step must be retried.
return nil, fmt.Errorf("failed to run the commit selector: %w", err)
} else if result.Commit == "" {
return &api.TriageResult{
- Skip: &api.SkipRequest{
- Reason: "failed to find the base commit: " + result.Reason,
- TriageLog: buf.Bytes(),
- },
+ SkipReason: "failed to find the base commit: " + result.Reason,
}, nil
}
+ tracer.Log("selected base commit: %s", result.Commit)
base := api.BuildRequest{
TreeName: tree.Name,
TreeURL: tree.URL,