github.com/google/syzkaller@v0.0.0-20240517125934-c0f1611a36d6/tools/syz-imagegen/imagegen.go (about) 1 // Copyright 2018 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 // As we use syscall package: 5 //go:build linux 6 7 // syz-imagegen generates sys/linux/test/syz_mount_image_* test files. 8 // It requires the following packages to be installed: 9 // 10 // f2fs-tools xfsprogs reiserfsprogs gfs2-utils ocfs2-tools genromfs erofs-utils makefs udftools 11 // mtd-utils nilfs-tools squashfs-tools genisoimage jfsutils exfat-utils ntfs-3g hfsprogs 12 // bcachefs-tools. 13 package main 14 15 import ( 16 "bufio" 17 "bytes" 18 "encoding/binary" 19 "errors" 20 "flag" 21 "fmt" 22 "hash/crc32" 23 "os" 24 "os/exec" 25 "path/filepath" 26 "runtime" 27 "strings" 28 "syscall" 29 "time" 30 "unsafe" 31 32 "github.com/google/syzkaller/pkg/image" 33 "github.com/google/syzkaller/pkg/osutil" 34 "github.com/google/syzkaller/pkg/tool" 35 "github.com/google/syzkaller/prog" 36 _ "github.com/google/syzkaller/sys" 37 "github.com/google/syzkaller/sys/targets" 38 ) 39 40 // FileSystem represents one file system. 41 // Each FileSystem produces multiple images, see MkfsFlagCombinations and Image type. 42 type FileSystem struct { 43 // Name of the file system. Needs to match syz_mount_image$NAME name. 44 Name string 45 // Imagegen autodetects size for images starting from MinSize and then repeatedly doubling it if mkfs fails. 46 MinSize int 47 // Don't populate this image with files (can't mount read-write). 48 ReadOnly bool 49 // These flags are always appended to mkfs as is. 50 MkfsFlags []string 51 // Generate images for all possible permutations of these flag combinations. 52 MkfsFlagCombinations [][]string 53 // Custom mkfs invocation, if nil then mkfs.name is invoked in a standard way. 54 Mkfs func(img *Image) error 55 } 56 57 // nolint:lll 58 var fileSystems = []FileSystem{ 59 { 60 Name: "f2fs", 61 MinSize: 64 << 20, 62 MkfsFlags: []string{"-e cold"}, 63 MkfsFlagCombinations: [][]string{ 64 {"-a 0", "-a 1"}, 65 {"-s 1", "-s 2"}, 66 { 67 "", 68 "-O encrypt", 69 "-O extra_attr", 70 "-O extra_attr -O flexible_inline_xattr -O inode_checksum -O inode_crtime -O project_quota", 71 }, 72 }, 73 }, 74 { 75 Name: "btrfs", 76 MinSize: 16 << 20, 77 MkfsFlagCombinations: [][]string{ 78 {"", "-M"}, 79 {"", "-K"}, 80 {"--csum crc32c", "--csum xxhash", "--csum sha256", "--csum blake2"}, 81 {"--nodesize 4096 -O mixed-bg", "-O extref", "-O raid56", "-O no-holes", "-O raid1c34"}, 82 }, 83 }, 84 { 85 Name: "vfat", 86 MinSize: 64 << 10, 87 MkfsFlags: []string{"-n", "SYZKALLER"}, 88 MkfsFlagCombinations: [][]string{ 89 {"", "-a -I"}, 90 {"", "-h 3 -f 4"}, 91 {"-s 1", "-s 8", "-s 64"}, 92 { 93 "-F 12 -r 64 -S 512", 94 "-F 12 -r 64 -S 2048 -A", 95 "-F 16 -r 112 -S 512", 96 "-F 32 -r 768 -S 512", 97 "-F 32 -r 768 -S 2048 -A", 98 }, 99 }, 100 }, 101 { 102 Name: "msdos", 103 MinSize: 64 << 10, 104 MkfsFlags: []string{"-n", "SYZKALLER"}, 105 MkfsFlagCombinations: [][]string{ 106 {"", "-a -I"}, 107 {"", "-h 3 -f 4"}, 108 {"-s 1", "-s 8", "-s 64"}, 109 { 110 "-F 12 -r 64 -S 512", 111 "-F 12 -r 64 -S 2048 -A", 112 "-F 16 -r 112 -S 512", 113 "-F 32 -r 768 -S 512", 114 "-F 32 -r 768 -S 2048 -A", 115 }, 116 }, 117 }, 118 { 119 Name: "exfat", 120 MinSize: 128 << 10, 121 MkfsFlags: []string{"-i", "0x12341234"}, 122 MkfsFlagCombinations: [][]string{ 123 {"", "-p 3"}, 124 }, 125 }, 126 { 127 Name: "bfs", 128 MinSize: 4 << 10, 129 ReadOnly: true, // creating files fails with ENOPERM 130 MkfsFlags: []string{"-V", "syzkal", "-F", "syzkal"}, 131 MkfsFlagCombinations: [][]string{ 132 {"-N 48", "-N 127", "-N 512"}, 133 }, 134 }, 135 { 136 Name: "xfs", 137 MinSize: 16 << 20, 138 MkfsFlags: []string{"-l", "internal", "--unsupported"}, 139 MkfsFlagCombinations: [][]string{ 140 // Most XFS options are inter-dependent and total number of combinations is huge, 141 // so we enumerate some combinations that don't produce errors. 142 { 143 "-b size=512 -i size=256 -d agcount=2 -m crc=0 -m finobt=0 -m rmapbt=0 -m reflink=0 -i sparse=0 -i maxpct=25 -i attr=1 -i projid32bit=0 -l lazy-count=0", 144 "-b size=2k -i size=1024 -d agcount=2 -m crc=0 -m finobt=0 -m rmapbt=0 -m reflink=0 -i sparse=0 -i maxpct=5 -i attr=1 -i projid32bit=0 -l lazy-count=1", 145 "-b size=4k -i size=2048 -d agcount=4 -m crc=0 -m finobt=0 -m rmapbt=0 -m reflink=0 -i sparse=0 -i maxpct=90 -i attr=2 -i projid32bit=1 -l lazy-count=0", 146 "-b size=1k -i size=512 -d agcount=2 -m crc=1 -m finobt=0 -m rmapbt=0 -m reflink=0 -i sparse=0 -i maxpct=20 -i attr=2 -i projid32bit=1 -l lazy-count=1", 147 "-b size=2k -i size=1024 -d agcount=4 -m crc=1 -m finobt=1 -m rmapbt=1 -m reflink=1 -i sparse=0 -i maxpct=3 -i attr=2 -i projid32bit=1 -l lazy-count=1", 148 "-b size=4k -i size=2048 -d agcount=1 -m crc=1 -m finobt=0 -m rmapbt=1 -m reflink=0 -i sparse=0 -i maxpct=100 -i attr=2 -i projid32bit=1 -l lazy-count=1", 149 "-b size=1k -i size=512 -d agcount=2 -m crc=1 -m finobt=0 -m rmapbt=0 -m reflink=0 -i sparse=1 -i maxpct=99 -i attr=2 -i projid32bit=1 -l lazy-count=1", 150 "-b size=2k -i size=1024 -d agcount=1 -m crc=1 -m finobt=1 -m rmapbt=1 -m reflink=1 -i sparse=1 -i maxpct=50 -i attr=2 -i projid32bit=1 -l lazy-count=1", 151 "-b size=4k -i size=1024 -d agcount=1 -m crc=1 -m finobt=1 -m rmapbt=0 -m reflink=1 -i sparse=1 -i maxpct=10 -i attr=2 -i projid32bit=1 -l lazy-count=1", 152 }, 153 {"-l sunit=16", "-l sunit=64", "-l sunit=128", "-l su=8k"}, 154 }, 155 }, 156 { 157 Name: "minix", 158 MinSize: 16 << 10, 159 MkfsFlagCombinations: [][]string{ 160 { 161 "-1 -n 14", 162 "-1 -n 30", 163 "-2 -n 14", 164 "-2 -n 30", 165 "-3 -n 60", 166 }, 167 {"-i 16", "-i 64", "-i 1024"}, 168 }, 169 }, 170 { 171 Name: "reiserfs", 172 MinSize: 4 << 20, 173 ReadOnly: true, // mounting this crashes my host kernel 174 MkfsFlags: []string{"-f", "-f", "-l", "syzkaller"}, 175 MkfsFlagCombinations: [][]string{ 176 {"-b 4096", "-b 8192"}, 177 {"-h r5", "-h rupasov", "-h tea"}, 178 {"--format 3.5", "--format 3.6 -u 12312312-1233-1233-1231-123413412412"}, 179 { 180 "-s 513", 181 "-s 8193 -t 128", 182 "-s 8193 -t 1024", 183 "-s 15749 -t 128", 184 "-s 15749 -t 1024", 185 }, 186 }, 187 }, 188 { 189 Name: "jfs", 190 MinSize: 16 << 20, 191 MkfsFlags: []string{"-q"}, 192 MkfsFlagCombinations: [][]string{ 193 {"", "-s 1M"}, 194 {"", "-O"}, 195 }, 196 }, 197 { 198 Name: "ntfs", 199 MinSize: 1 << 20, 200 MkfsFlags: []string{"-f", "-F", "-L", "syzkaller"}, 201 MkfsFlagCombinations: [][]string{ 202 { 203 "-s 256 -c 2048", 204 "-s 512 -c 1024", 205 "-s 512 -c 4096", 206 "-s 1024 -c 4096", 207 "-s 1024 -c 65536", 208 "-s 2048 -c 2048", 209 "-s 2048 -c 4096", 210 "-s 4096 -c 4096", 211 "-s 4096 -c 131072", 212 }, 213 {"", "-I"}, 214 }, 215 }, 216 { 217 Name: "ntfs3", 218 MinSize: 1 << 20, 219 MkfsFlags: []string{"-f", "-F", "-L", "syzkaller"}, 220 MkfsFlagCombinations: [][]string{ 221 { 222 "-s 512 -c 1024", 223 "-s 512 -c 4096", 224 "-s 1024 -c 4096", 225 "-s 1024 -c 65536", 226 "-s 2048 -c 2048", 227 "-s 2048 -c 4096", 228 "-s 4096 -c 4096", 229 "-s 4096 -c 131072", 230 }, 231 {"", "-I"}, 232 }, 233 Mkfs: func(img *Image) error { 234 _, err := runCmd("mkfs.ntfs", append(img.flags, img.disk)...) 235 return err 236 }, 237 }, 238 { 239 Name: "ext4", 240 MinSize: 64 << 10, 241 MkfsFlags: []string{"-L", "syzkaller", "-U", "clear", "-E", "test_fs"}, 242 MkfsFlagCombinations: [][]string{ 243 {"-t ext2", "-t ext3", "-t ext4"}, 244 // Total number of combinations is too large and there are lots of dependencies between flags, 245 // so we create just few permutations generated with fair dice rolls. 246 // TODO: We also need to give some combination of -E encoding=utf8/utf8-12.1 and -E encoding_flags=strict, 247 // but mounting such fs on my host fails with "Filesystem with casefold feature cannot be mounted without CONFIG_UNICODE". 248 { 249 "-b 1024 -I 128 -E lazy_itable_init=0 -E num_backup_sb=0 -E packed_meta_blocks=0 -O ^64bit -O extents -O ^bigalloc -O ^dir_index -O dir_nlink -O ea_inode -O ^encrypt -O ext_attr -O extra_isize -O flex_bg -O ^huge_file -O ^inline_data -O large_dir -O ^metadata_csum -O meta_bg -O mmp -O quota -O ^resize_inode -O ^sparse_super -O ^uninit_bg -O ^verity -j -J size=1024", 250 "-b 1024 -I 256 -E lazy_itable_init=0 -E num_backup_sb=1 -E packed_meta_blocks=1 -O 64bit -O extents -O bigalloc -O ^dir_index -O ^dir_nlink -O ^ea_inode -O ^encrypt -O ext_attr -O ^extra_isize -O flex_bg -O ^huge_file -O ^inline_data -O large_dir -O ^metadata_csum -O meta_bg -O ^mmp -O quota -O ^resize_inode -O ^sparse_super -O uninit_bg -O ^verity", 251 "-b 1024 -I 1024 -E lazy_itable_init=0 -E num_backup_sb=1 -E packed_meta_blocks=1 -O 64bit -O extents -O bigalloc -O ^dir_index -O ^dir_nlink -O ^ea_inode -O encrypt -O ext_attr -O ^extra_isize -O flex_bg -O ^huge_file -O inline_data -O large_dir -O ^metadata_csum -O meta_bg -O ^mmp -O quota -O ^resize_inode -O ^sparse_super -O uninit_bg -O ^verity -j -J size=1024", 252 "-b 1024 -I 128 -E lazy_itable_init=1 -E num_backup_sb=0 -E packed_meta_blocks=1 -O 64bit -O extents -O bigalloc -O ^dir_index -O dir_nlink -O ea_inode -O ^encrypt -O ext_attr -O ^extra_isize -O ^flex_bg -O huge_file -O ^inline_data -O ^large_dir -O ^metadata_csum -O ^meta_bg -O mmp -O ^quota -O resize_inode -O sparse_super -O ^uninit_bg -O ^verity", 253 "-b 1024 -I 256 -E lazy_itable_init=1 -E num_backup_sb=0 -E packed_meta_blocks=1 -O 64bit -O extents -O bigalloc -O ^dir_index -O dir_nlink -O ea_inode -O ^encrypt -O ext_attr -O ^extra_isize -O ^flex_bg -O huge_file -O inline_data -O ^large_dir -O ^metadata_csum -O ^meta_bg -O mmp -O ^quota -O resize_inode -O sparse_super -O ^uninit_bg -O ^verity", 254 "-b 1024 -I 256 -E lazy_itable_init=1 -E num_backup_sb=1 -E packed_meta_blocks=0 -O ^64bit -O ^extents -O ^bigalloc -O dir_index -O ^dir_nlink -O ea_inode -O encrypt -O ^ext_attr -O ^extra_isize -O ^flex_bg -O huge_file -O inline_data -O ^large_dir -O ^metadata_csum -O ^meta_bg -O ^mmp -O ^quota -O ^resize_inode -O sparse_super2 -O uninit_bg -O ^verity -j -J size=1024", 255 "-b 1024 -I 512 -E lazy_itable_init=1 -E num_backup_sb=1 -E packed_meta_blocks=0 -O ^64bit -O ^extents -O ^bigalloc -O dir_index -O ^dir_nlink -O ea_inode -O encrypt -O ^ext_attr -O ^extra_isize -O ^flex_bg -O huge_file -O inline_data -O ^large_dir -O ^metadata_csum -O ^meta_bg -O ^mmp -O ^quota -O ^resize_inode -O sparse_super2 -O uninit_bg -O ^verity", 256 "-b 2048 -I 128 -E lazy_itable_init=0 -E num_backup_sb=0 -E packed_meta_blocks=0 -O ^64bit -O extents -O ^bigalloc -O ^dir_index -O dir_nlink -O ea_inode -O ^encrypt -O ext_attr -O extra_isize -O flex_bg -O ^huge_file -O ^inline_data -O large_dir -O ^metadata_csum -O meta_bg -O mmp -O quota -O ^resize_inode -O ^sparse_super -O ^uninit_bg -O ^verity", 257 "-b 2048 -I 256 -E lazy_itable_init=0 -E num_backup_sb=1 -E packed_meta_blocks=1 -O 64bit -O extents -O bigalloc -O ^dir_index -O ^dir_nlink -O ^ea_inode -O encrypt -O ext_attr -O ^extra_isize -O flex_bg -O ^huge_file -O ^inline_data -O large_dir -O ^metadata_csum -O meta_bg -O ^mmp -O quota -O ^resize_inode -O ^sparse_super -O uninit_bg -O ^verity -j -J size=1024", 258 "-b 2048 -I 1024 -E lazy_itable_init=0 -E num_backup_sb=1 -E packed_meta_blocks=1 -O 64bit -O extents -O bigalloc -O ^dir_index -O ^dir_nlink -O ^ea_inode -O encrypt -O ext_attr -O ^extra_isize -O flex_bg -O ^huge_file -O inline_data -O large_dir -O ^metadata_csum -O meta_bg -O ^mmp -O quota -O ^resize_inode -O ^sparse_super -O uninit_bg -O ^verity", 259 "-b 2048 -I 128 -E lazy_itable_init=1 -E num_backup_sb=0 -E packed_meta_blocks=1 -O 64bit -O extents -O bigalloc -O ^dir_index -O dir_nlink -O ea_inode -O ^encrypt -O ext_attr -O ^extra_isize -O ^flex_bg -O huge_file -O ^inline_data -O ^large_dir -O ^metadata_csum -O ^meta_bg -O mmp -O ^quota -O resize_inode -O sparse_super -O ^uninit_bg -O ^verity", 260 "-b 2048 -I 256 -E lazy_itable_init=1 -E num_backup_sb=0 -E packed_meta_blocks=1 -O 64bit -O extents -O bigalloc -O ^dir_index -O dir_nlink -O ea_inode -O ^encrypt -O ext_attr -O ^extra_isize -O ^flex_bg -O huge_file -O inline_data -O ^large_dir -O ^metadata_csum -O ^meta_bg -O mmp -O ^quota -O resize_inode -O sparse_super -O ^uninit_bg -O ^verity -j -J size=1024", 261 "-b 2048 -I 256 -E lazy_itable_init=1 -E num_backup_sb=1 -E packed_meta_blocks=0 -O ^64bit -O ^extents -O ^bigalloc -O dir_index -O ^dir_nlink -O ea_inode -O encrypt -O ^ext_attr -O ^extra_isize -O ^flex_bg -O huge_file -O inline_data -O ^large_dir -O ^metadata_csum -O ^meta_bg -O ^mmp -O ^quota -O ^resize_inode -O sparse_super2 -O uninit_bg -O ^verity", 262 "-b 2048 -I 512 -E lazy_itable_init=1 -E num_backup_sb=1 -E packed_meta_blocks=0 -O ^64bit -O ^extents -O ^bigalloc -O dir_index -O ^dir_nlink -O ea_inode -O ^encrypt -O ^ext_attr -O ^extra_isize -O ^flex_bg -O huge_file -O inline_data -O ^large_dir -O ^metadata_csum -O ^meta_bg -O ^mmp -O ^quota -O ^resize_inode -O sparse_super2 -O uninit_bg -O ^verity", 263 "-b 4096 -I 128 -E lazy_itable_init=0 -E num_backup_sb=0 -E packed_meta_blocks=0 -O ^64bit -O extents -O ^bigalloc -O ^dir_index -O dir_nlink -O ea_inode -O ^encrypt -O ext_attr -O extra_isize -O flex_bg -O ^huge_file -O ^inline_data -O large_dir -O ^metadata_csum -O meta_bg -O mmp -O quota -O ^resize_inode -O ^sparse_super -O ^uninit_bg -O ^verity -j -J size=1024", 264 "-b 4096 -I 256 -E lazy_itable_init=0 -E num_backup_sb=1 -E packed_meta_blocks=1 -O 64bit -O extents -O bigalloc -O ^dir_index -O ^dir_nlink -O ^ea_inode -O encrypt -O ext_attr -O ^extra_isize -O flex_bg -O ^huge_file -O ^inline_data -O large_dir -O ^metadata_csum -O meta_bg -O ^mmp -O quota -O ^resize_inode -O ^sparse_super -O uninit_bg -O verity", 265 "-b 4096 -I 1024 -E lazy_itable_init=0 -E num_backup_sb=1 -E packed_meta_blocks=1 -O 64bit -O extents -O bigalloc -O ^dir_index -O ^dir_nlink -O ^ea_inode -O ^encrypt -O ext_attr -O ^extra_isize -O flex_bg -O ^huge_file -O inline_data -O large_dir -O ^metadata_csum -O meta_bg -O ^mmp -O quota -O ^resize_inode -O ^sparse_super -O uninit_bg -O ^verity", 266 "-b 4096 -I 128 -E lazy_itable_init=1 -E num_backup_sb=0 -E packed_meta_blocks=1 -O 64bit -O extents -O bigalloc -O ^dir_index -O dir_nlink -O ea_inode -O ^encrypt -O ext_attr -O ^extra_isize -O ^flex_bg -O huge_file -O ^inline_data -O ^large_dir -O ^metadata_csum -O ^meta_bg -O mmp -O ^quota -O resize_inode -O sparse_super -O ^uninit_bg -O verity -j -J size=1024", 267 "-b 4096 -I 256 -E lazy_itable_init=1 -E num_backup_sb=0 -E packed_meta_blocks=1 -O 64bit -O extents -O bigalloc -O ^dir_index -O dir_nlink -O ea_inode -O ^encrypt -O ext_attr -O ^extra_isize -O ^flex_bg -O huge_file -O inline_data -O ^large_dir -O ^metadata_csum -O ^meta_bg -O mmp -O ^quota -O resize_inode -O sparse_super -O ^uninit_bg -O ^verity", 268 "-b 4096 -I 256 -E lazy_itable_init=1 -E num_backup_sb=1 -E packed_meta_blocks=0 -O ^64bit -O ^extents -O ^bigalloc -O dir_index -O ^dir_nlink -O ea_inode -O ^encrypt -O ^ext_attr -O ^extra_isize -O ^flex_bg -O huge_file -O inline_data -O ^large_dir -O ^metadata_csum -O ^meta_bg -O ^mmp -O ^quota -O ^resize_inode -O sparse_super2 -O uninit_bg -O verity -j -J size=1024", 269 "-b 4096 -I 512 -E lazy_itable_init=1 -E num_backup_sb=1 -E packed_meta_blocks=0 -O ^64bit -O ^extents -O ^bigalloc -O dir_index -O ^dir_nlink -O ea_inode -O encrypt -O ^ext_attr -O ^extra_isize -O ^flex_bg -O huge_file -O inline_data -O ^large_dir -O ^metadata_csum -O ^meta_bg -O ^mmp -O ^quota -O ^resize_inode -O sparse_super2 -O uninit_bg -O ^verity", 270 }, 271 }, 272 }, 273 { 274 Name: "gfs2", 275 MinSize: 16 << 20, 276 ReadOnly: true, // mounting this crashes my host kernel 277 MkfsFlags: []string{"-O", "-t", "syz:syz"}, 278 MkfsFlagCombinations: [][]string{ 279 { 280 // Lots of combinations lead to huge images that don't fit into 4MB encodingexec buffer. 281 "-b 1024 -o sunit=1024 -o swidth=1024 -c 1M -j 1 -J 8 -o align=0 -p lock_dlm", 282 "-b 1024 -o sunit=1024 -o swidth=1024 -c 1M -j 1 -J 8 -o align=1 -p lock_nolock", 283 "-b 1024 -o sunit=1024 -o swidth=1024 -c 4M -j 1 -J 8 -o align=0 -p lock_dlm", 284 "-b 1024 -o sunit=1024 -o swidth=1024 -c 4M -j 1 -J 8 -o align=1 -p lock_nolock", 285 "-b 1024 -o sunit=4096 -o swidth=8192 -c 1M -j 1 -J 8 -o align=0 -p lock_dlm", 286 "-b 1024 -o sunit=4096 -o swidth=8192 -c 1M -j 1 -J 8 -o align=1 -p lock_nolock", 287 "-b 1024 -o sunit=4096 -o swidth=8192 -c 4M -j 1 -J 8 -o align=0 -p lock_dlm", 288 "-b 1024 -o sunit=4096 -o swidth=8192 -c 4M -j 1 -J 8 -o align=1 -p lock_nolock", 289 "-b 2048 -o sunit=2048 -o swidth=4096 -c 1M -j 1 -J 8 -o align=0 -p lock_dlm", 290 "-b 2048 -o sunit=2048 -o swidth=4096 -c 1M -j 1 -J 8 -o align=1 -p lock_nolock", 291 "-b 2048 -o sunit=2048 -o swidth=4096 -c 4M -j 1 -J 8 -o align=0 -p lock_dlm", 292 "-b 2048 -o sunit=2048 -o swidth=4096 -c 4M -j 1 -J 8 -o align=1 -p lock_nolock", 293 "-b 2048 -o sunit=4096 -o swidth=4096 -c 1M -j 1 -J 8 -o align=0 -p lock_dlm", 294 "-b 2048 -o sunit=4096 -o swidth=4096 -c 1M -j 1 -J 8 -o align=1 -p lock_nolock", 295 "-b 2048 -o sunit=4096 -o swidth=4096 -c 4M -j 1 -J 8 -o align=0 -p lock_dlm", 296 "-b 2048 -o sunit=4096 -o swidth=4096 -c 4M -j 1 -J 8 -o align=1 -p lock_nolock", 297 "-b 4096 -o sunit=4096 -o swidth=4096 -c 1M -j 1 -J 8 -o align=0 -p lock_dlm", 298 "-b 4096 -o sunit=4096 -o swidth=4096 -c 1M -j 1 -J 8 -o align=1 -p lock_nolock", 299 "-b 4096 -o sunit=4096 -o swidth=4096 -c 1M -j 2 -J 16 -o align=0 -p lock_dlm", 300 "-b 4096 -o sunit=4096 -o swidth=4096 -c 1M -j 2 -J 16 -o align=1 -p lock_nolock", 301 "-b 4096 -o sunit=4096 -o swidth=4096 -c 4M -j 1 -J 8 -o align=0 -p lock_dlm", 302 "-b 4096 -o sunit=4096 -o swidth=4096 -c 4M -j 1 -J 8 -o align=1 -p lock_nolock", 303 "-b 4096 -o sunit=4096 -o swidth=4096 -c 4M -j 2 -J 16 -o align=0 -p lock_dlm", 304 "-b 4096 -o sunit=4096 -o swidth=4096 -c 4M -j 2 -J 16 -o align=1 -p lock_nolock", 305 "-b 4096 -o sunit=8192 -o swidth=16384 -c 1M -j 1 -J 8 -o align=0 -p lock_dlm", 306 "-b 4096 -o sunit=8192 -o swidth=16384 -c 1M -j 1 -J 8 -o align=1 -p lock_nolock", 307 "-b 4096 -o sunit=8192 -o swidth=16384 -c 1M -j 2 -J 16 -o align=0 -p lock_dlm", 308 "-b 4096 -o sunit=8192 -o swidth=16384 -c 1M -j 2 -J 16 -o align=1 -p lock_nolock", 309 "-b 4096 -o sunit=8192 -o swidth=16384 -c 4M -j 1 -J 8 -o align=0 -p lock_dlm", 310 "-b 4096 -o sunit=8192 -o swidth=16384 -c 4M -j 1 -J 8 -o align=1 -p lock_nolock", 311 "-b 4096 -o sunit=8192 -o swidth=16384 -c 4M -j 2 -J 16 -o align=0 -p lock_dlm", 312 "-b 4096 -o sunit=8192 -o swidth=16384 -c 4M -j 2 -J 16 -o align=1 -p lock_nolock", 313 }, 314 }, 315 }, 316 { 317 Name: "ocfs2", 318 MinSize: 8 << 20, 319 ReadOnly: true, // mounting this crashes my host kernel 320 MkfsFlagCombinations: [][]string{ 321 {"-b 512", "-b 4096"}, 322 {"-C 4K", "-C 16K", "-C 1M"}, 323 {"-J block32", "-J block64"}, 324 {"-T mail -N 1 -M local", "-T datafiles -N 2 -M local", "-T vmstore -N 2 -M cluster"}, 325 {"", "--fs-features backup-super,sparse,unwritten,inline-data,extended-slotmap,metaecc,refcount,xattr,usrquota,grpquota,indexed-dirs,discontig-bg"}, 326 }, 327 }, 328 { 329 Name: "cramfs", 330 MinSize: 1 << 10, 331 // The file system is read-only and requires a root directory at creation time. 332 ReadOnly: true, 333 MkfsFlags: []string{}, 334 MkfsFlagCombinations: [][]string{ 335 {"-b 4096", "-b 8192"}, 336 {"-N big", "-N little"}, 337 }, 338 Mkfs: func(img *Image) error { 339 _, err := runCmd("mkfs.cramfs", append(img.flags, img.templateDir, img.disk)...) 340 return err 341 }, 342 }, 343 { 344 Name: "romfs", 345 MinSize: 1 << 10, 346 // The file system is read-only and requires a root directory at creation time. 347 ReadOnly: true, 348 MkfsFlagCombinations: [][]string{ 349 {"-a 16", "-a 256"}, 350 }, 351 Mkfs: func(img *Image) error { 352 _, err := runCmd("genromfs", append(img.flags, "-f", img.disk, "-d", img.templateDir)...) 353 return err 354 }, 355 }, 356 { 357 Name: "erofs", 358 MinSize: 1 << 10, 359 // The file system is read-only and requires a root directory at creation time. 360 ReadOnly: true, 361 MkfsFlags: []string{"-T1000"}, 362 MkfsFlagCombinations: [][]string{ 363 {"-z lz4", "-z lz4hc,1", "-z lz4hc,9"}, 364 {"-x 1", "-x 2"}, 365 {"", "-E legacy-compress"}, 366 }, 367 Mkfs: func(img *Image) error { 368 _, err := runCmd("mkfs.erofs", append(img.flags, img.disk, img.templateDir)...) 369 return err 370 }, 371 }, 372 { 373 Name: "efs", 374 MinSize: 1 << 10, 375 // The file system is read-only and requires a root directory at creation time. 376 ReadOnly: true, 377 MkfsFlags: []string{"-M", "65536"}, 378 MkfsFlagCombinations: [][]string{ 379 { 380 "-t ffs -B big -S 128 -o bsize=4k,version=1,optimization=space", 381 "-t ffs -B big -S 512 -o bsize=8k,version=1,optimization=time", 382 "-t ffs -B big -S 2048 -o bsize=8k,version=1,optimization=space", 383 "-t ffs -B little -S 128 -o bsize=4k,version=1,optimization=time", 384 "-t ffs -B little -S 512 -o bsize=4k,version=1,optimization=space", 385 "-t ffs -B little -S 2048 -o bsize=8k,version=1,optimization=time", 386 "-t ffs -B big -S 128 -o bsize=4k,version=2,optimization=space", 387 "-t ffs -B big -S 512 -o bsize=8k,version=2,optimization=time", 388 "-t ffs -B big -S 2048 -o bsize=8k,version=2,optimization=space", 389 "-t ffs -B little -S 128 -o bsize=4k,version=2,optimization=time", 390 "-t ffs -B little -S 512 -o bsize=4k,version=2,optimization=space", 391 "-t ffs -B little -S 2048 -o bsize=8k,version=2,optimization=time", 392 "-t cd9660", 393 "-t cd9660 -o rockridge", 394 }, 395 }, 396 Mkfs: func(img *Image) error { 397 _, err := runCmd("makefs", append(img.flags, img.disk, img.templateDir)...) 398 return err 399 }, 400 }, 401 { 402 Name: "udf", 403 MinSize: 64 << 10, 404 MkfsFlags: []string{"-u", "1234567812345678"}, 405 MkfsFlagCombinations: [][]string{ 406 {"-b 512", "-b 1024", "-b 4096"}, 407 { 408 "-m hd -r 1.01", 409 "-m hd -r 1.01 --ad=short", 410 "-m hd -r 1.50 --ad=long", 411 "-m hd -r 2.01", 412 "-m hd -r 2.01 --space=unallocbitmap", 413 "-m mo -r 1.01", 414 "-m mo -r 1.01 --ad=long", 415 "-m mo -r 1.50 --space=unalloctable", 416 "-m mo -r 1.50 --space=unallocbitmap", 417 "-m mo -r 2.01 --noefe --ad=short", 418 "-m cdrw -r 1.50", 419 "-m cdrw -r 1.50 --space=unalloctable --ad=long", 420 "-m cdrw -r 2.01", 421 "-m dvdrw -r 1.50 --space=unallocbitmap --ad=short", 422 "-m dvdrw -r 2.01 --sparspace=512 --space=unalloctable --noefe", 423 "-m dvdrw -r 2.01 --sparspace=512", 424 "-m dvdram -r 1.50 --ad=long", 425 "-m dvdram -r 2.01 ", 426 "-m dvdram -r 2.01 --space=unallocbitmap --ad=long", 427 }, 428 }, 429 }, 430 { 431 Name: "jffs2", 432 MinSize: 1 << 10, 433 ReadOnly: true, 434 MkfsFlags: []string{"--squash", "--faketime", "--with-xattr"}, 435 MkfsFlagCombinations: [][]string{ 436 {"--pagesize 4096", "--pagesize 8192"}, 437 {"--little-endian", "--big-endian"}, 438 {"--compression-mode=none", "--compression-mode=size"}, 439 }, 440 Mkfs: func(img *Image) error { 441 _, err := runCmd("mkfs.jffs2", append(img.flags, "-o", img.disk, "--root", img.templateDir)...) 442 return err 443 }, 444 }, 445 { 446 Name: "nilfs2", 447 MinSize: 1 << 20, 448 MkfsFlagCombinations: [][]string{ 449 {"-b 1024", "-b 2048", "-b 4096"}, 450 {"-B 16", "-B 64", "-B 512"}, 451 {"-O none", "-O block_count"}, 452 }, 453 }, 454 { 455 Name: "squashfs", 456 MinSize: 1 << 10, 457 ReadOnly: true, 458 MkfsFlagCombinations: [][]string{ 459 {"-comp gzip -b 4k", "-comp lzo -b 16k", "-comp xz -b 1M"}, 460 {"", "-noI -noX", "-noI -noD -noF -noX"}, 461 {"-no-fragments", "-always-use-fragments -nopad"}, 462 }, 463 Mkfs: func(img *Image) error { 464 os.Remove(img.disk) 465 _, err := runCmd("mksquashfs", append([]string{img.templateDir, img.disk}, img.flags...)...) 466 return err 467 }, 468 }, 469 { 470 Name: "iso9660", 471 MinSize: 1 << 10, 472 ReadOnly: true, 473 MkfsFlags: []string{"-abstract", "file1", "-biblio", "file2", "-copyright", "file3", "-publisher", "syzkaller"}, 474 MkfsFlagCombinations: [][]string{ 475 {"", "-J", "-J -udf"}, 476 {"-pad", "-no-pad"}, 477 {"", "-hfs", "-apple -r"}, 478 }, 479 Mkfs: func(img *Image) error { 480 _, err := runCmd("genisoimage", append(img.flags, "-o", img.disk, img.templateDir)...) 481 return err 482 }, 483 }, 484 { 485 Name: "hfs", 486 MinSize: 16 << 10, 487 MkfsFlagCombinations: [][]string{ 488 {"", "-P"}, 489 {"", "-c a=1024,b=512,c=128,d=256"}, 490 }, 491 }, 492 { 493 Name: "hfsplus", 494 MinSize: 512 << 10, 495 MkfsFlagCombinations: [][]string{ 496 {"", "-P"}, 497 {"", "-s"}, 498 {"-b 512", "-b 1024", "-b 2048"}, 499 }, 500 }, 501 { 502 Name: "bcachefs", 503 MinSize: 512 << 10, 504 MkfsFlagCombinations: [][]string{ 505 {"", "--encrypted --no_passphrase"}, 506 {"", "--compression=lz4"}, 507 {"", "--data_checksum=none --metadata_checksum=none"}, 508 }, 509 }, 510 { 511 Name: parttable, 512 MinSize: 1 << 20, 513 ReadOnly: true, 514 MkfsFlagCombinations: [][]string{{ 515 // You can test/explore these commands with: 516 // $ rm -f disk && touch disk && fallocate -l 16M disk && fdisk disk 517 "g n 1 34 47 n 2 48 96 n 3 97 2013 t 1 uefi t 2 linux t 3 swap w", 518 "g n 1 100 200 n 2 50 80 n 3 1000 1900 M a c r x n 1 syzkaller A 1 r w", 519 "g n 3 200 300 n 7 400 500 n 2 600 700 x l 700 r w", 520 "G n 1 16065 16265 w", 521 "G n 16 20000 30000 i w", 522 "o n p 1 2048 4096 n p 3 4097 4100 n e 2 4110 4200 a 1 t 2 a5 t 3 uefi b y x 1 e r w", 523 "o n p 1 2048 3071 n e 3 3072 32767 n 6200 7999 n 10240 20000 w", 524 "s c 1 a 2 w", 525 }}, 526 Mkfs: func(img *Image) error { 527 cmd := exec.Command("fdisk", "--noauto-pt", "--color=always", img.disk) 528 cmd.Stdin = strings.NewReader(strings.Join(img.flags, "\n")) 529 output, err := osutil.Run(10*time.Minute, cmd) 530 if err != nil { 531 return err 532 } 533 // It's hard to understand if any of the commands fail, 534 // fdisk does not exit with an error and print assorted error messages. 535 // So instead we run it with --color=always and grep for red color marker 536 // in the output (ESC[31m). 537 if bytes.Contains(output, []byte{0x1b, 0x5b, 0x33, 0x31, 0x6d}) { 538 return errors.New(string(output)) 539 } 540 return err 541 }, 542 }, 543 } 544 545 const ( 546 syzMountImage = "syz_mount_image" 547 syzReadPartTable = "syz_read_part_table" 548 parttable = "parttable" 549 ) 550 551 func (fs FileSystem) filePrefix() string { 552 if fs.Name == parttable { 553 return syzReadPartTable 554 } 555 return syzMountImage + "_" + fs.Name 556 } 557 558 // Image represents one image we generate for a file system. 559 type Image struct { 560 target *prog.Target 561 fs FileSystem 562 flags []string // mkfs flags 563 index int // index within the file system 564 size int // image size (autodetected starting from fs.MinSize) 565 hash uint32 // crc32 hash of the resulting image to detect duplicates 566 disk string // disk image file name 567 templateDir string // name of a directory with contents for the file system (shared across all images) 568 done chan error 569 } 570 571 func (img *Image) String() string { 572 size := fmt.Sprintf("%vKB", img.size>>10) 573 if img.size >= 1<<20 { 574 size = fmt.Sprintf("%vMB", img.size>>20) 575 } 576 return fmt.Sprintf("#%02v: mkfs.%v[%5v] %v", img.index, img.fs.Name, size, img.flags) 577 } 578 579 var errShutdown = errors.New("shutdown") 580 581 func main() { 582 var ( 583 flagList = flag.Bool("list", false, "list supported file systems and exit") 584 flagVerbose = flag.Bool("v", false, "print successfully created images") 585 flagDebug = flag.Bool("debug", false, "print lots of debugging output") 586 flagPopulate = flag.String("populate", "", "populate the specified image with files (for internal use)") 587 flagKeepImage = flag.Bool("keep", false, "save disk images as .img files") 588 flagFS = flag.String("fs", "", "comma-separated list of filesystems to generate, all if empty") 589 ) 590 flag.Parse() 591 if *flagDebug { 592 *flagVerbose = true 593 } 594 if *flagPopulate != "" { 595 if err := populate(*flagPopulate, *flagFS); err != nil { 596 tool.Fail(err) 597 } 598 return 599 } 600 target, err := prog.GetTarget(targets.Linux, targets.AMD64) 601 if err != nil { 602 tool.Fail(err) 603 } 604 addEmptyImages(target) 605 images, err := generateImages(target, *flagFS, *flagList) 606 if err != nil { 607 tool.Fail(err) 608 } 609 if *flagList { 610 return 611 } 612 // Create a single template dir for file systems that need the root dir at creation time. 613 templateDir, err := os.MkdirTemp("", "syz-imagegen") 614 if err != nil { 615 tool.Fail(err) 616 } 617 defer os.RemoveAll(templateDir) 618 if err := populateDir(templateDir); err != nil { 619 tool.Fail(err) 620 } 621 shutdown := make(chan struct{}) 622 osutil.HandleInterrupts(shutdown) 623 procs := runtime.NumCPU() 624 requests := make(chan *Image, procs) 625 go func() { 626 for _, img := range images { 627 img.templateDir = templateDir 628 requests <- img 629 } 630 close(requests) 631 }() 632 for p := 0; p < procs; p++ { 633 go func() { 634 for img := range requests { 635 select { 636 case <-shutdown: 637 img.done <- errShutdown 638 default: 639 img.done <- img.generate() 640 } 641 } 642 }() 643 } 644 printResults(images, shutdown, *flagKeepImage, *flagVerbose) 645 } 646 647 func addEmptyImages(target *prog.Target) { 648 // Since syz_mount_image calls are no_generate we need to add at least some 649 // empty seeds for all the filesystems. 650 have := make(map[string]bool) 651 for _, fs := range fileSystems { 652 have[fs.Name] = true 653 } 654 for _, call := range target.Syscalls { 655 if call.CallName != syzMountImage { 656 continue 657 } 658 name := strings.TrimPrefix(call.Name, syzMountImage+"$") 659 if have[name] { 660 continue 661 } 662 fileSystems = append(fileSystems, FileSystem{ 663 Name: name, 664 MinSize: 64 << 10, 665 ReadOnly: true, 666 MkfsFlags: []string{"fake image"}, 667 Mkfs: func(img *Image) error { 668 // Fill the image with unique 4-byte values. 669 // This allows hints mutation to easily guess magic numbers and checksums. 670 f, err := os.Create(img.disk) 671 if err != nil { 672 return err 673 } 674 defer f.Close() 675 buf := bufio.NewWriter(f) 676 defer buf.Flush() 677 for i := uint32(0); i < uint32(img.size/int(unsafe.Sizeof(i))); i++ { 678 if err := binary.Write(buf, binary.LittleEndian, i+0x7b3184b5); err != nil { 679 return err 680 } 681 } 682 return nil 683 }, 684 }) 685 } 686 } 687 688 func printResults(images []*Image, shutdown chan struct{}, keepImage, verbose bool) { 689 good, failed := 0, 0 690 hashes := make(map[uint32][]*Image) 691 for _, img := range images { 692 err := <-img.done 693 if img.disk != "" && !keepImage { 694 os.Remove(img.disk) 695 } 696 select { 697 case <-shutdown: 698 err = errShutdown 699 default: 700 } 701 if err == errShutdown { 702 continue 703 } 704 res := "ok" 705 if err != nil { 706 res = fmt.Sprintf("failed:\n\t%v", err) 707 } 708 if verbose || err != nil { 709 fmt.Printf("%v: %v\n", img, res) 710 } 711 if err != nil { 712 failed++ 713 continue 714 } 715 hashes[img.hash] = append(hashes[img.hash], img) 716 good++ 717 } 718 fmt.Printf("generated images: %v/%v\n", good, len(images)) 719 for _, img := range images { 720 group := hashes[img.hash] 721 if len(group) <= 1 { 722 continue 723 } 724 delete(hashes, img.hash) 725 fmt.Printf("equal images:\n") 726 for _, img := range group { 727 fmt.Printf("\tmkfs.%v %v\n", img.fs.Name, img.flags) 728 } 729 } 730 if failed != 0 { 731 os.Exit(1) 732 } 733 } 734 735 func generateImages(target *prog.Target, flagFS string, list bool) ([]*Image, error) { 736 var images []*Image 737 for _, fs := range fileSystems { 738 if flagFS != "" && !strings.Contains(","+flagFS+",", ","+fs.Name+",") { 739 continue 740 } 741 index := 0 742 enumerateFlags(target, &images, &index, fs, fs.MkfsFlags, 0) 743 if list { 744 fmt.Printf("%v [%v images]\n", fs.Name, index) 745 continue 746 } 747 files, err := filepath.Glob(filepath.Join("sys", targets.Linux, "test", fs.filePrefix()+"_*")) 748 if err != nil { 749 return nil, fmt.Errorf("error reading output dir: %w", err) 750 } 751 for _, file := range files { 752 if err := os.Remove(file); err != nil { 753 return nil, fmt.Errorf("error removing output file: %w", err) 754 } 755 } 756 } 757 return images, nil 758 } 759 760 func enumerateFlags(target *prog.Target, images *[]*Image, index *int, fs FileSystem, flags []string, flagsIndex int) { 761 if flagsIndex == len(fs.MkfsFlagCombinations) { 762 *images = append(*images, &Image{ 763 target: target, 764 fs: fs, 765 flags: append([]string{}, flags...), 766 index: *index, 767 done: make(chan error, 1), 768 }) 769 *index++ 770 return 771 } 772 for _, flag := range fs.MkfsFlagCombinations[flagsIndex] { 773 flags1 := flags 774 for _, f := range strings.Split(flag, " ") { 775 if f != "" { 776 flags1 = append(flags1, f) 777 } 778 } 779 enumerateFlags(target, images, index, fs, flags1, flagsIndex+1) 780 } 781 } 782 783 func (img *Image) generate() error { 784 var err error 785 for img.size = img.fs.MinSize; img.size <= 128<<20; img.size *= 2 { 786 if err = img.generateSize(); err == nil { 787 return nil 788 } 789 } 790 return err 791 } 792 793 func (img *Image) generateSize() error { 794 outFile := filepath.Join("sys", targets.Linux, "test", 795 fmt.Sprintf("%v_%v", img.fs.filePrefix(), img.index)) 796 img.disk = outFile + ".img" 797 f, err := os.Create(img.disk) 798 if err != nil { 799 return err 800 } 801 f.Close() 802 if err := os.Truncate(img.disk, int64(img.size)); err != nil { 803 return err 804 } 805 if img.fs.Mkfs == nil { 806 if _, err := runCmd("mkfs."+img.fs.Name, append(img.flags, img.disk)...); err != nil { 807 return err 808 } 809 } else { 810 if err := img.fs.Mkfs(img); err != nil { 811 return err 812 } 813 } 814 if !img.fs.ReadOnly { 815 // This does not work with runCmd -- sudo does not show password prompt on console. 816 cmd := exec.Command("sudo", os.Args[0], "-populate", img.disk, "-fs", img.fs.Name) 817 if out, err := cmd.CombinedOutput(); err != nil { 818 return fmt.Errorf("image population failed: %w\n%s", err, out) 819 } 820 } 821 data, err := os.ReadFile(img.disk) 822 if err != nil { 823 return err 824 } 825 img.hash = crc32.ChecksumIEEE(data) 826 827 // Write out image *with* change of directory. 828 out, err := writeImage(img, data) 829 if err != nil { 830 return fmt.Errorf("failed to write image: %w", err) 831 } 832 833 p, err := img.target.Deserialize(out, prog.Strict) 834 if err != nil { 835 return fmt.Errorf("failed to deserialize resulting program: %w", err) 836 } 837 if _, err := p.SerializeForExec(); err != nil { 838 return fmt.Errorf("failed to serialize for execution: %w", err) 839 } 840 841 return osutil.WriteFile(outFile, out) 842 } 843 844 // Runs under sudo in a subprocess. 845 func populate(disk, fs string) error { 846 output, err := runCmd("losetup", "-f", "--show", "-P", disk) 847 if err != nil { 848 return err 849 } 850 loop := strings.TrimSpace(string(output)) 851 defer runCmd("losetup", "-d", loop) 852 853 dir, err := os.MkdirTemp("", "syz-imagegen") 854 if err != nil { 855 return err 856 } 857 defer os.RemoveAll(dir) 858 if _, err := runCmd("mount", "-t", fs, loop, dir); err != nil { 859 return fmt.Errorf("%w\n%s", err, output) 860 } 861 defer runCmd("umount", dir) 862 return populateDir(dir) 863 } 864 865 func populateDir(dir string) error { 866 zeros := func(size int) []byte { 867 return make([]byte, size) 868 } 869 nonzeros := func(size int) []byte { 870 const fill = "syzkaller" 871 return bytes.Repeat([]byte(fill), size/len(fill)+1)[:size] 872 } 873 if err := os.Mkdir(filepath.Join(dir, "file0"), 0777); err != nil { 874 return err 875 } 876 if err := os.WriteFile(filepath.Join(dir, "file0", "file0"), nonzeros(1050), 0777); err != nil { 877 return err 878 } 879 os.Symlink(filepath.Join(dir, "file0", "file0"), filepath.Join(dir, "file0", "file1")) 880 if err := os.WriteFile(filepath.Join(dir, "file1"), nonzeros(10), 0777); err != nil { 881 return err 882 } 883 // Note: some errors are not checked because some file systems don't have support for links/attrs. 884 // TODO: does it make sense to create other attribute types (system./trusted./security./btrfs.)? 885 syscall.Setxattr(filepath.Join(dir, "file1"), "user.xattr1", []byte("xattr1"), 0) 886 syscall.Setxattr(filepath.Join(dir, "file1"), "user.xattr2", []byte("xattr2"), 0) 887 if err := os.WriteFile(filepath.Join(dir, "file2"), zeros(9000), 0777); err != nil { 888 return err 889 } 890 os.Link(filepath.Join(dir, "file2"), filepath.Join(dir, "file3")) 891 // f2fs considers .cold extension specially. 892 if err := os.WriteFile(filepath.Join(dir, "file.cold"), nonzeros(100), 0777); err != nil { 893 return err 894 } 895 return nil 896 } 897 898 func runCmd(cmd string, args ...string) ([]byte, error) { 899 return osutil.RunCmd(10*time.Minute, "", cmd, args...) 900 } 901 902 func writeImage(img *Image, data []byte) ([]byte, error) { 903 buf := new(bytes.Buffer) 904 fmt.Fprintf(buf, "# Code generated by tools/syz-imagegen. DO NOT EDIT.\n") 905 fmt.Fprintf(buf, "# requires: manual\n\n") 906 fmt.Fprintf(buf, "# %v\n\n", img) 907 compressedData := image.Compress(data) 908 b64Data := image.EncodeB64(compressedData) 909 if img.fs.Name == parttable { 910 fmt.Fprintf(buf, `%s(AUTO, &AUTO="$`, syzReadPartTable) 911 } else { 912 fmt.Fprintf(buf, `%s$%v(&AUTO='%v\x00', &AUTO='./file0\x00', 0x0, &AUTO, 0x1, AUTO, &AUTO="$`, 913 syzMountImage, img.fs.Name, img.fs.Name) 914 } 915 buf.Write(b64Data) 916 fmt.Fprintf(buf, "\")\n") 917 918 return buf.Bytes(), nil 919 }