aboutsummaryrefslogtreecommitdiffstats
path: root/pkg
diff options
context:
space:
mode:
authorGrigory Bazilevich <g.bazilevich@ispras.ru>2025-09-29 00:33:58 +0300
committerGrigory Bazilevich <g.bazilevich@ispras.ru>2026-03-12 12:15:10 +0300
commitde2ea465e0fa9bd820feb6493445870ece9bacc5 (patch)
tree4abc7d0da515f6a75f005c923b805e50cbe2311f /pkg
parent2d88ab014d9ef9a6133ad5a5851bb4fd42959ad3 (diff)
syz-manager: always save crashes and repros locally
Save crashes and repros with corresponding kernel and syzkaller configs locally in syz-manager even when they are published to syz-dashboard, to be able to share the crashes with Linux Verification Center (linuxtesting.org). Signed-off-by: Grigory Bazilevich <g.bazilevich@ispras.ru> Signed-off-by: Sergey Zotov <svzotov@ispras.ru> Co-authored-by: Sergey Zotov <svzotov@ispras.ru>
Diffstat (limited to 'pkg')
-rw-r--r--pkg/manager/crash.go10
-rw-r--r--pkg/mgrconfig/load.go54
2 files changed, 64 insertions, 0 deletions
diff --git a/pkg/manager/crash.go b/pkg/manager/crash.go
index 6d0858837..cbc49580e 100644
--- a/pkg/manager/crash.go
+++ b/pkg/manager/crash.go
@@ -23,6 +23,7 @@ import (
type CrashStore struct {
Tag string
+ Ctag []byte
BaseDir string
MaxCrashLogs int
MaxReproLogs int
@@ -35,8 +36,14 @@ const straceFileName = "strace.log"
const MaxReproAttempts = 3
func NewCrashStore(cfg *mgrconfig.Config) *CrashStore {
+ ctag := "syzkaller-" + cfg.CtagSyzkaller
+ if cfg.CtagKernel != "" {
+ ctag = ctag + "\nlinux-" + cfg.CtagKernel
+ }
+
return &CrashStore{
Tag: cfg.Tag,
+ Ctag: []byte(ctag),
BaseDir: cfg.Workdir,
MaxCrashLogs: cfg.MaxCrashLogs,
MaxReproLogs: MaxReproAttempts,
@@ -91,6 +98,9 @@ func (cs *CrashStore) SaveCrash(crash *Crash) (bool, error) {
writeOrRemove("tag", []byte(cs.Tag))
writeOrRemove("report", report.MergeReportBytes(reps))
writeOrRemove("machineInfo", crash.MachineInfo)
+ writeOrRemove("time", []byte(time.Now().Format("01-02-2006 15:04:05")))
+ writeOrRemove("ctag", cs.Ctag)
+
if err := report.AddTitleStat(filepath.Join(dir, "title-stat"), reps); err != nil {
return false, fmt.Errorf("report.AddTitleStat: %w", err)
}
diff --git a/pkg/mgrconfig/load.go b/pkg/mgrconfig/load.go
index 38f0d0062..86064dc38 100644
--- a/pkg/mgrconfig/load.go
+++ b/pkg/mgrconfig/load.go
@@ -11,8 +11,10 @@ import (
"regexp"
"runtime"
"strings"
+ "time"
"github.com/google/syzkaller/pkg/config"
+ "github.com/google/syzkaller/pkg/hash"
"github.com/google/syzkaller/pkg/osutil"
"github.com/google/syzkaller/pkg/vminfo"
"github.com/google/syzkaller/prog"
@@ -38,6 +40,10 @@ type Derived struct {
NoMutateCalls map[int]bool // Set of IDs of syscalls which should not be mutated.
Timeouts targets.Timeouts
+ // Hashes of syzkaller and kernel configs for Linux Verification Center
+ CtagSyzkaller string
+ CtagKernel string
+
// Special debugging/development mode specified by VM type "none".
// In this mode syz-manager does not start any VMs, but instead a user is supposed
// to start syz-executor process in a VM manually.
@@ -54,6 +60,7 @@ func LoadData(data []byte) (*Config, error) {
if err := Complete(cfg); err != nil {
return nil, err
}
+ CompleteSyzCtagData(cfg, data)
return cfg, nil
}
@@ -65,6 +72,7 @@ func LoadFile(filename string) (*Config, error) {
if err := Complete(cfg); err != nil {
return nil, err
}
+ CompleteSyzCtagFile(cfg, filename)
return cfg, nil
}
@@ -90,6 +98,21 @@ func LoadPartialFile(filename string) (*Config, error) {
return cfg, nil
}
+func CompleteSyzCtagData(cfg *Config, data []byte) {
+ cfg.CtagSyzkaller = hash.String(data)
+ osutil.MkdirAll(filepath.Join(cfg.Workdir, "configs"))
+ osutil.WriteFile(filepath.Join(cfg.Workdir, "configs", "syzkaller-"+cfg.CtagSyzkaller+".cfg"), data)
+}
+
+func CompleteSyzCtagFile(cfg *Config, filename string) {
+ confdata, err := os.ReadFile(filename)
+ if err != nil {
+ cfg.CtagSyzkaller = time.Now().Format(time.RFC3339)
+ return
+ }
+ CompleteSyzCtagData(cfg, confdata)
+}
+
func DefaultValues() *Config {
return &Config{
SSHUser: "root",
@@ -174,6 +197,7 @@ func Complete(cfg *Config) error {
return err
}
cfg.CompleteKernelDirs()
+ cfg.completeKernelCtag()
if err := cfg.completeServices(); err != nil {
return nil
@@ -303,6 +327,36 @@ func (cfg *Config) KernelDirs() *KernelDirs {
}
}
+func (cfg *Config) completeKernelCtag() {
+ confhash, conffile := findKernelConfig(cfg)
+ if confhash != "" {
+ cfg.CtagKernel = confhash
+
+ confdata, _ := os.ReadFile(conffile)
+ osutil.MkdirAll(filepath.Join(cfg.Workdir, "configs"))
+ osutil.WriteFile(filepath.Join(cfg.Workdir, "configs", "linux-"+cfg.CtagKernel+".cfg"), confdata)
+ }
+}
+
+func findKernelConfig(cfg *Config) (string, string) {
+ configs := [3]string{cfg.KernelBuildSrc, cfg.KernelObj, cfg.KernelSrc}
+ for _, s := range configs {
+ if _, err := os.Stat(filepath.Join(s, ".config")); err == nil {
+ confdata, _ := os.ReadFile(filepath.Join(s, ".config"))
+ return hash.String(confdata), filepath.Join(s, ".config")
+ }
+ if _, err := os.Stat(filepath.Join(s, "kernel.config")); err == nil {
+ confdata, _ := os.ReadFile(filepath.Join(s, "kernel.config"))
+ return hash.String(confdata), filepath.Join(s, "kernel.config")
+ }
+ if _, err := os.Stat(filepath.Join(filepath.Dir(s), "kernel.config")); err == nil {
+ confdata, _ := os.ReadFile(filepath.Join(filepath.Dir(s), "kernel.config"))
+ return hash.String(confdata), filepath.Join(filepath.Dir(s), "kernel.config")
+ }
+ }
+ return "", ""
+}
+
func (cfg *Config) checkSSHParams() error {
if cfg.SSHKey == "" {
return nil