github.com/google/syzkaller@v0.0.0-20251211124644-a066d2bc4b02/pkg/image/fsck_test.go (about) 1 // Copyright 2024 syzkaller project authors. All rights reserved. 2 // Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file. 3 4 package image_test 5 6 import ( 7 "fmt" 8 "io" 9 "os" 10 "path/filepath" 11 "strings" 12 "testing" 13 14 . "github.com/google/syzkaller/pkg/image" 15 "github.com/google/syzkaller/prog" 16 "github.com/google/syzkaller/sys/targets" 17 ) 18 19 // To get maximum test coverage here, install the following Debian packages: 20 // dosfstools e2fsprogs btrfs-progs util-linux f2fs-tools jfsutils util-linux 21 // dosfstools ocfs2-tools reiserfsprogs xfsprogs erofs-utils exfatprogs 22 // gfs2-utils. 23 24 const corruptedFs = "IAmACorruptedFs" 25 26 func TestFsck(t *testing.T) { 27 target, err := prog.GetTarget(targets.Linux, targets.AMD64) 28 if err != nil { 29 t.Fatal(err) 30 } 31 fsckChecker := FsckChecker{} 32 33 // Use the images generated by syz-imagegen as a collection of clean file systems. 34 cleanFsProgs, err := filepath.Glob(filepath.Join("..", "sys", "linux", "test", "syz_mount_image_*_0")) 35 if err != nil { 36 t.Fatalf("directory read failed: %v", err) 37 } 38 39 for _, file := range cleanFsProgs { 40 sourceProg, err := os.ReadFile(file) 41 if err != nil { 42 t.Fatal(err) 43 } 44 p, err := target.Deserialize(sourceProg, prog.NonStrict) 45 if err != nil { 46 t.Fatalf("failed to deserialize %s: %s", file, err) 47 } 48 p.ForEachAsset(func(name string, typ prog.AssetType, r io.Reader, c *prog.Call) { 49 if c.Meta.Attrs.Fsck == "" { 50 return 51 } 52 fsckCmd := c.Meta.Attrs.Fsck 53 // Tolerate missing fsck commands except during CI runs. 54 skip := !fsckChecker.Exists(fsckCmd) && os.Getenv("CI") == "" 55 56 fsName := strings.TrimPrefix(c.Meta.Name, "syz_mount_image$") 57 // Check that the file system in the image is detected as clean. 58 t.Run(fmt.Sprintf("clean %s", fsName), func(t *testing.T) { 59 if skip { 60 t.Skipf("%s not available", fsckCmd) 61 } 62 63 logs, isClean, err := Fsck(r, fsckCmd) 64 if err != nil { 65 t.Fatalf("failed to run fsck %s", err) 66 } 67 if !isClean { 68 t.Fatalf("%s should exit 0 on a clean file system %s", fsckCmd, string(logs)) 69 } 70 }) 71 72 // And use the same fsck command on a dummy fs to make sure that fails. 73 t.Run(fmt.Sprintf("corrupt %s", fsName), func(t *testing.T) { 74 if skip { 75 t.Skipf("%s not available", fsckCmd) 76 } 77 78 logs, isClean, err := Fsck(strings.NewReader(corruptedFs), fsckCmd) 79 if err != nil { 80 t.Fatalf("failed to run fsck %s", err) 81 } 82 if isClean { 83 t.Fatalf("%s shouldn't exit 0 on a corrupt file system %s", fsckCmd, string(logs)) 84 } 85 }) 86 }) 87 } 88 }