From 55e0929fab461fee7733a18f8b543f9a5d6b9f6f Mon Sep 17 00:00:00 2001 From: Aleksandr Nogikh Date: Thu, 6 Feb 2025 15:06:26 +0100 Subject: all: enable run_fsck by default Check for the existence of fsck binaries and report their absence only once. --- pkg/image/fsck.go | 26 ++++++++++++++++++++++++++ pkg/image/fsck_test.go | 9 ++------- pkg/mgrconfig/config.go | 1 + pkg/mgrconfig/load.go | 1 + syz-manager/manager.go | 6 ++++-- 5 files changed, 34 insertions(+), 9 deletions(-) diff --git a/pkg/image/fsck.go b/pkg/image/fsck.go index e749871f9..fbaeca9c4 100644 --- a/pkg/image/fsck.go +++ b/pkg/image/fsck.go @@ -11,7 +11,9 @@ import ( "os/exec" "strconv" "strings" + "sync" + "github.com/google/syzkaller/pkg/log" "github.com/google/syzkaller/pkg/osutil" ) @@ -59,3 +61,27 @@ func Fsck(r io.Reader, fsckCmd string) ([]byte, bool, error) { prefix := fsckCmd + " exited with status code " + strconv.Itoa(exitCode) + "\n" return append([]byte(prefix), output...), exitCode == 0, nil } + +type FsckChecker struct { + mu sync.Mutex + exists map[string]bool +} + +func (fc *FsckChecker) Exists(cmd string) bool { + fc.mu.Lock() + defer fc.mu.Unlock() + bin := strings.Fields(cmd)[0] + if ret, ok := fc.exists[bin]; ok { + return ret + } + if fc.exists == nil { + fc.exists = map[string]bool{} + } + _, err := exec.LookPath(bin) + found := err == nil + if !found { + log.Logf(0, "%s not found, images won't be checked", bin) + } + fc.exists[bin] = found + return found +} diff --git a/pkg/image/fsck_test.go b/pkg/image/fsck_test.go index aae102ec7..e901e089f 100644 --- a/pkg/image/fsck_test.go +++ b/pkg/image/fsck_test.go @@ -7,7 +7,6 @@ import ( "fmt" "io" "os" - "os/exec" "path/filepath" "strings" "testing" @@ -24,16 +23,12 @@ import ( const corruptedFs = "IAmACorruptedFs" -func fsckAvailable(cmd string) bool { - _, err := exec.LookPath(strings.Fields(cmd)[0]) - return err == nil -} - func TestFsck(t *testing.T) { target, err := prog.GetTarget(targets.Linux, targets.AMD64) if err != nil { t.Fatal(err) } + fsckChecker := FsckChecker{} // Use the images generated by syz-imagegen as a collection of clean file systems. cleanFsProgs, err := filepath.Glob(filepath.Join("..", "sys", "linux", "test", "syz_mount_image_*_0")) @@ -56,7 +51,7 @@ func TestFsck(t *testing.T) { } fsckCmd := c.Meta.Attrs.Fsck // Tolerate missing fsck commands except during CI runs. - skip := !fsckAvailable(fsckCmd) && os.Getenv("CI") == "" + skip := !fsckChecker.Exists(fsckCmd) && os.Getenv("CI") == "" fsName := strings.TrimPrefix(c.Meta.Name, "syz_mount_image$") // Check that the file system in the image is detected as clean. diff --git a/pkg/mgrconfig/config.go b/pkg/mgrconfig/config.go index a02c00c67..42730eef4 100644 --- a/pkg/mgrconfig/config.go +++ b/pkg/mgrconfig/config.go @@ -206,6 +206,7 @@ type Config struct { // Note: you may need to install 3rd-party dependencies for this to work. // fsck commands that can be run by syz-manager are specified in mount // syscall descriptions - typically in sys/linux/filesystem.txt. + // Enabled by default. RunFsck bool `json:"run_fsck"` // Type of virtual machine to use, e.g. "qemu", "gce", "android", "isolated", etc. diff --git a/pkg/mgrconfig/load.go b/pkg/mgrconfig/load.go index 0624dae00..81ff2871a 100644 --- a/pkg/mgrconfig/load.go +++ b/pkg/mgrconfig/load.go @@ -94,6 +94,7 @@ func defaultValues() *Config { MaxCrashLogs: 100, Procs: 6, PreserveCorpus: true, + RunFsck: true, Experimental: Experimental{ RemoteCover: true, CoverEdges: true, diff --git a/syz-manager/manager.go b/syz-manager/manager.go index fdb4929d7..b0354ea61 100644 --- a/syz-manager/manager.go +++ b/syz-manager/manager.go @@ -106,6 +106,7 @@ type Manager struct { benchFile *os.File assetStorage *asset.Storage + fsckChecker image.FsckChecker reproLoop *manager.ReproLoop @@ -944,10 +945,11 @@ func (mgr *Manager) uploadReproAssets(repro *repro.Result) []dashapi.NewAsset { return } // Report file systems that fail fsck with a separate tag. - if mgr.cfg.RunFsck && dashTyp == dashapi.MountInRepro && c.Meta.Attrs.Fsck != "" { + if mgr.cfg.RunFsck && dashTyp == dashapi.MountInRepro && + c.Meta.Attrs.Fsck != "" && mgr.fsckChecker.Exists(c.Meta.Attrs.Fsck) { logs, isClean, err := image.Fsck(r2, c.Meta.Attrs.Fsck) if err != nil { - log.Logf(1, "fsck of the asset %v failed: %v", name, err) + log.Errorf("fsck of the asset %v failed: %v", name, err) } else { asset.FsckLog = logs asset.FsIsClean = isClean -- cgit mrf-deployment