aboutsummaryrefslogtreecommitdiffstats
path: root/pkg/repro/strace.go
blob: ceb31de9399683d0f5549c677e80a98b03813af8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
// Copyright 2022 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.

package repro

import (
	"context"
	"fmt"

	"github.com/google/syzkaller/pkg/instance"
	"github.com/google/syzkaller/pkg/log"
	"github.com/google/syzkaller/pkg/mgrconfig"
	"github.com/google/syzkaller/pkg/report"
	"github.com/google/syzkaller/vm"
	"github.com/google/syzkaller/vm/dispatcher"
)

type StraceResult struct {
	Report *report.Report
	Output []byte
	Error  error
}

const (
	straceOutputLogSize = 2048 << 10
)

func RunStrace(result *Result, cfg *mgrconfig.Config, reporter *report.Reporter, pool *vm.Dispatcher) *StraceResult {
	if cfg.StraceBin == "" {
		return straceFailed(fmt.Errorf("strace binary is not set in the config"))
	}
	var runRes *instance.RunResult
	var err error
	runErr := pool.Run(context.Background(), func(ctx context.Context, inst *vm.Instance, updInfo dispatcher.UpdateInfo) {
		updInfo(func(info *dispatcher.Info) {
			info.Status = "running strace"
		})
		ret, setupErr := instance.SetupExecProg(inst, cfg, reporter,
			&instance.OptionalConfig{
				StraceBin:        cfg.StraceBin,
				BeforeContextLen: straceOutputLogSize,
			})
		if setupErr != nil {
			err = fmt.Errorf("failed to set up instance: %w", setupErr)
			return
		}
		params := instance.ExecParams{
			Opts:     result.Opts,
			Duration: result.Duration,
		}
		if result.CRepro {
			log.Logf(1, "running C repro under strace")
			params.CProg = result.Prog
			runRes, err = ret.RunCProg(params)
		} else {
			log.Logf(1, "running syz repro under strace")
			params.SyzProg = result.Prog.Serialize()
			runRes, err = ret.RunSyzProg(params)
		}
	})
	if runErr != nil {
		return straceFailed(runErr)
	} else if err != nil {
		return straceFailed(err)
	}
	return &StraceResult{
		Report: runRes.Report,
		Output: runRes.Output,
	}
}

func straceFailed(err error) *StraceResult {
	return &StraceResult{Error: err}
}

func (strace *StraceResult) IsSameBug(repro *Result) bool {
	if strace == nil || strace.Report == nil || repro.Report == nil {
		return false
	}
	return strace.Report.Title == repro.Report.Title
}