github.com/google/syzkaller@v0.0.0-20240517125934-c0f1611a36d6/pkg/vminfo/linux_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 vminfo 5 6 import ( 7 "bufio" 8 "bytes" 9 "fmt" 10 "os" 11 "runtime" 12 "strings" 13 "testing" 14 15 "github.com/google/go-cmp/cmp" 16 "github.com/google/syzkaller/pkg/flatrpc" 17 "github.com/google/syzkaller/sys/targets" 18 "github.com/stretchr/testify/assert" 19 ) 20 21 func TestLinuxSyscalls(t *testing.T) { 22 cfg := testConfig(t, targets.Linux, targets.AMD64) 23 checker := New(cfg) 24 filesystems := []string{ 25 // Without sysfs, the checks would also disable mount(). 26 "", "sysfs", "ext4", "binder", "", 27 } 28 files := []*flatrpc.FileInfo{ 29 { 30 Name: "/proc/version", 31 Exists: true, 32 Data: []byte("Linux version 6.8.0-dirty"), 33 }, 34 { 35 Name: "/proc/filesystems", 36 Exists: true, 37 Data: []byte(strings.Join(filesystems, "\nnodev\t")), 38 }, 39 } 40 stop := make(chan struct{}) 41 go createSuccessfulResults(checker, stop) 42 enabled, disabled, features, err := checker.Run(files, allFeatures()) 43 close(stop) 44 if err != nil { 45 t.Fatal(err) 46 } 47 expectDisabled := map[string]bool{ 48 "syz_kvm_setup_cpu$arm64": true, 49 "syz_kvm_setup_cpu$ppc64": true, 50 } 51 // All mount and syz_mount_image calls except for ext4 and binder will be disabled. 52 for call := range disabled { 53 name := call.Name 54 if name == "mount$binder" || name == "syz_mount_image$ext4" { 55 continue 56 } 57 if strings.HasPrefix(name, "syz_mount_image$") || strings.HasPrefix(name, "mount$") { 58 expectDisabled[name] = true 59 } 60 } 61 for call, reason := range disabled { 62 if expectDisabled[call.Name] { 63 continue 64 } 65 t.Errorf("disabled call %v: %v", call.Name, reason) 66 } 67 for _, id := range cfg.Syscalls { 68 call := cfg.Target.Syscalls[id] 69 if enabled[call] && disabled[call] != "" { 70 t.Fatalf("%s is both enabled and disabled", call.Name) 71 } 72 expected := !expectDisabled[call.Name] 73 got := enabled[call] 74 if expected != got { 75 t.Errorf("%s: expected %t, got %t", call.Name, expected, got) 76 } 77 } 78 expectEnabled := len(cfg.Syscalls) - len(expectDisabled) 79 if len(enabled) != expectEnabled { 80 t.Errorf("enabled only %v calls out of %v", len(enabled), expectEnabled) 81 } 82 if len(features) != len(flatrpc.EnumNamesFeature) { 83 t.Errorf("enabled only %v features out of %v", len(features), len(flatrpc.EnumNamesFeature)) 84 } 85 for feat, info := range features { 86 if !info.Enabled { 87 t.Errorf("feature %v is not enabled: %v", flatrpc.EnumNamesFeature[feat], info.Reason) 88 } 89 } 90 } 91 92 func TestReadKVMInfo(t *testing.T) { 93 if runtime.GOOS != "linux" { 94 t.Skip("not linux") 95 } 96 _, files := hostChecker(t) 97 fs := createVirtualFilesystem(files) 98 buf := new(bytes.Buffer) 99 if _, err := linuxReadKVMInfo(fs, buf); err != nil { 100 t.Fatal(err) 101 } 102 for s := bufio.NewScanner(buf); s.Scan(); { 103 line := s.Text() 104 if line == "" { 105 continue 106 } 107 splitted := strings.Split(line, ":") 108 if len(splitted) != 2 { 109 t.Fatalf("the format of line \"%s\" is not correct", line) 110 } 111 key := strings.TrimSpace(splitted[0]) 112 if key == "" { 113 t.Fatalf("empty key") 114 } 115 if key[0] != '/' { 116 continue 117 } 118 119 if !strings.HasPrefix(key, "/sys/module/kvm") { 120 t.Fatalf("the directory does not match /sys/module/kvm*") 121 } 122 } 123 } 124 125 func TestCannedCPUInfoLinux(t *testing.T) { 126 tests := cpuInfoTests 127 if runtime.GOOS == "linux" { 128 data, err := os.ReadFile("/proc/cpuinfo") 129 if err != nil { 130 t.Fatal(err) 131 } 132 tests = append(tests, cannedTest{ 133 arch: runtime.GOARCH, 134 data: string(data), 135 }) 136 } 137 for i, test := range tests { 138 t.Run(fmt.Sprint(i), func(t *testing.T) { 139 files := createVirtualFilesystem([]*flatrpc.FileInfo{{ 140 Name: "/proc/cpuinfo", 141 Exists: true, 142 Data: []byte(test.data), 143 }}) 144 buf := new(bytes.Buffer) 145 if _, err := linuxReadCPUInfo(files, buf); err != nil { 146 t.Fatal(err) 147 } 148 if test.want != "" { 149 if diff := cmp.Diff(buf.String(), test.want); diff != "" { 150 t.Fatal(diff) 151 } 152 return 153 } 154 checkCPUInfo(t, buf.Bytes(), test.arch) 155 }) 156 } 157 } 158 159 func checkCPUInfo(t *testing.T, data []byte, arch string) { 160 keys := make(map[string]bool) 161 s := bufio.NewScanner(bytes.NewReader(data)) 162 s.Buffer(nil, 1<<20) 163 for s.Scan() { 164 splitted := strings.Split(s.Text(), ":") 165 if len(splitted) != 2 { 166 t.Fatalf("the format of line %q is not correct", s.Text()) 167 } 168 key := strings.TrimSpace(splitted[0]) 169 keys[key] = true 170 } 171 assert.Nil(t, s.Err(), "scanner failed reading the CpuInfo: %v", s.Err()) 172 173 importantKeys := map[string][]string{ 174 targets.PPC64LE: {"cpu", "revision", "platform", "model", "machine"}, 175 targets.AMD64: {"vendor_id", "model", "flags"}, 176 targets.S390x: {"vendor_id", "processor 0", "features"}, 177 targets.I386: {"vendor_id", "model", "flags"}, 178 targets.ARM64: {"CPU implementer", "CPU part", "Features"}, 179 targets.ARM: {"CPU implementer", "CPU part", "Features"}, 180 targets.MIPS64LE: {"system type", "cpu model", "ASEs implemented"}, 181 targets.RiscV64: {"processor", "isa", "mmu"}, 182 } 183 archKeys := importantKeys[arch] 184 if len(archKeys) == 0 { 185 t.Fatalf("unknown arch %v", arch) 186 } 187 for _, name := range archKeys { 188 if !keys[name] { 189 t.Fatalf("key %q not found", name) 190 } 191 } 192 } 193 194 type cannedTest struct { 195 arch string 196 data string 197 want string 198 } 199 200 // nolint:lll 201 var cpuInfoTests = []cannedTest{ 202 { 203 arch: targets.PPC64LE, 204 data: ` 205 processor : 0 206 cpu : POWER8 (architected), altivec supported 207 clock : 3425.000000MHz 208 revision : 2.1 (pvr 004b 0201) 209 210 processor : 1 211 cpu : POWER8 (architected), altivec supported 212 clock : 3425.000000MHz 213 revision : 2.1 (pvr 004b 0201) 214 215 processor : 2 216 cpu : POWER8 (architected), altivec supported 217 clock : 3425.000000MHz 218 revision : 2.1 (pvr 004b 0201) 219 220 processor : 3 221 cpu : POWER8 (architected), altivec supported 222 clock : 3425.000000MHz 223 revision : 2.1 (pvr 004b 0201) 224 225 timebase : 512000000 226 platform : pSeries 227 model : IBM pSeries (emulated by qemu) 228 machine : CHRP IBM pSeries (emulated by qemu) 229 MMU : Hash 230 `, 231 }, 232 { 233 arch: targets.PPC64LE, 234 data: ` 235 processor : 0 236 cpu : POWER8 (architected), altivec supported 237 clock : 3425.000000MHz 238 revision : 2.1 (pvr 004b 0201) 239 240 <insert 62 more processors here> 241 242 processor : 63 243 cpu : POWER8 (architected), altivec supported 244 clock : 3425.000000MHz 245 revision : 2.1 (pvr 004b 0201) 246 247 timebase : 512000000 248 platform : pSeries 249 model : IBM,8247-22L 250 machine : CHRP IBM,8247-22L 251 MMU : Hash 252 `, 253 }, 254 { 255 arch: targets.PPC64LE, 256 data: ` 257 processor : 0 258 cpu : POWER8E, altivec supported 259 clock : 3358.000000MHz 260 revision : 2.1 (pvr 004b 0201) 261 262 processor : 8 263 cpu : POWER8E, altivec supported 264 clock : 3358.000000MHz 265 revision : 2.1 (pvr 004b 0201) 266 267 processor : 16 268 cpu : POWER8E, altivec supported 269 clock : 3358.000000MHz 270 revision : 2.1 (pvr 004b 0201) 271 272 processor : 24 273 cpu : POWER8E, altivec supported 274 clock : 3358.000000MHz 275 revision : 2.1 (pvr 004b 0201) 276 277 processor : 32 278 cpu : POWER8E, altivec supported 279 clock : 3358.000000MHz 280 revision : 2.1 (pvr 004b 0201) 281 282 processor : 40 283 cpu : POWER8E, altivec supported 284 clock : 3358.000000MHz 285 revision : 2.1 (pvr 004b 0201) 286 287 timebase : 512000000 288 platform : PowerNV 289 model : 8286-41A 290 machine : PowerNV 8286-41A 291 firmware : OPAL 292 MMU : Hash 293 `, 294 }, 295 { 296 arch: targets.AMD64, 297 data: ` 298 processor : 0 299 vendor_id : GenuineIntel 300 cpu family : 6 301 model : 142 302 model name : Intel(R) Core(TM) i7-8650U CPU @ 1.90GHz 303 stepping : 10 304 microcode : 0xd6 305 cpu MHz : 2015.517 306 cache size : 8192 KB 307 physical id : 0 308 siblings : 8 309 core id : 0 310 cpu cores : 4 311 apicid : 0 312 initial apicid : 0 313 fpu : yes 314 fpu_exception : yes 315 cpuid level : 22 316 wp : yes 317 flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc art arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc cpuid aperfmperf pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 sdbg fma cx16 xtpr pdcm pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm abm 3dnowprefetch cpuid_fault epb invpcid_single pti ssbd ibrs ibpb stibp tpr_shadow vnmi flexpriority ept vpid ept_ad fsgsbase tsc_adjust bmi1 hle avx2 smep bmi2 erms invpcid rtm mpx rdseed adx smap clflushopt intel_pt xsaveopt xsavec xgetbv1 xsaves dtherm ida arat pln pts hwp hwp_notify hwp_act_window hwp_epp md_clear flush_l1d 318 vmx flags : vnmi preemption_timer invvpid ept_x_only ept_ad ept_1gb flexpriority tsc_offset vtpr mtf vapic ept vpid unrestricted_guest ple shadow_vmcs pml ept_mode_based_exec 319 bugs : cpu_meltdown spectre_v1 spectre_v2 spec_store_bypass l1tf mds swapgs taa itlb_multihit srbds 320 bogomips : 4199.88 321 clflush size : 64 322 cache_alignment : 64 323 address sizes : 39 bits physical, 48 bits virtual 324 power management: 325 326 processor : 1 327 vendor_id : GenuineIntel 328 cpu family : 6 329 model : 142 330 model name : Intel(R) Core(TM) i7-8650U CPU @ 1.90GHz 331 stepping : 10 332 microcode : 0xd6 333 cpu MHz : 1384.935 334 cache size : 8192 KB 335 physical id : 0 336 siblings : 8 337 core id : 1 338 cpu cores : 4 339 apicid : 2 340 initial apicid : 2 341 fpu : yes 342 fpu_exception : yes 343 cpuid level : 22 344 wp : yes 345 flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc art arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc cpuid aperfmperf pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 sdbg fma cx16 xtpr pdcm pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm abm 3dnowprefetch cpuid_fault epb invpcid_single pti ssbd ibrs ibpb stibp tpr_shadow vnmi flexpriority ept vpid ept_ad fsgsbase tsc_adjust bmi1 hle avx2 smep bmi2 erms invpcid rtm mpx rdseed adx smap clflushopt intel_pt xsaveopt xsavec xgetbv1 xsaves dtherm ida arat pln pts hwp hwp_notify hwp_act_window hwp_epp md_clear flush_l1d 346 vmx flags : vnmi preemption_timer invvpid ept_x_only ept_ad ept_1gb flexpriority tsc_offset vtpr mtf vapic ept vpid unrestricted_guest ple shadow_vmcs pml ept_mode_based_exec 347 bugs : cpu_meltdown spectre_v1 spectre_v2 spec_store_bypass l1tf mds swapgs taa itlb_multihit srbds 348 bogomips : 4199.88 349 clflush size : 64 350 cache_alignment : 64 351 address sizes : 39 bits physical, 48 bits virtual 352 power management: 353 `, 354 }, 355 { 356 arch: targets.AMD64, 357 data: ` 358 processor : 0 359 vendor_id : GenuineIntel 360 cpu family : 6 361 model : 85 362 model name : Intel(R) Xeon(R) CPU @ 2.00GHz 363 stepping : 3 364 microcode : 0x1 365 cpu MHz : 2000.166 366 cache size : 56320 KB 367 physical id : 0 368 siblings : 64 369 core id : 0 370 cpu cores : 32 371 apicid : 0 372 initial apicid : 0 373 fpu : yes 374 fpu_exception : yes 375 cpuid level : 13 376 wp : yes 377 flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ss ht syscall nx pdpe1gb rdtscp lm constant_tsc rep_good nopl xtopology nonstop_tsc cpuid tsc_known_freq pni pclmulqdq ssse3 fma cx16 pcid sse4_1 sse4_2 x2apic movbe popcnt aes xsave avx f16c rdrand hypervisor lahf_lm abm 3dnowprefetch invpcid_single pti fsgsbase tsc_adjust bmi1 hle avx2 smep bmi2 erms invpcid rtm mpx avx512f avx512dq rdseed adx smap clflushopt clwb avx512cd avx512bw avx512vl xsaveopt xsavec xgetbv1 xsaves 378 bugs : cpu_meltdown spectre_v1 spectre_v2 spec_store_bypass l1tf mds swapgs 379 bogomips : 4000.33 380 clflush size : 64 381 cache_alignment : 64 382 address sizes : 46 bits physical, 48 bits virtual 383 power management: 384 385 processor : 1 386 vendor_id : GenuineIntel 387 cpu family : 6 388 model : 85 389 model name : Intel(R) Xeon(R) CPU @ 2.00GHz 390 stepping : 3 391 microcode : 0x1 392 cpu MHz : 2000.166 393 cache size : 56320 KB 394 physical id : 0 395 siblings : 64 396 core id : 1 397 cpu cores : 32 398 apicid : 2 399 initial apicid : 2 400 fpu : yes 401 fpu_exception : yes 402 cpuid level : 13 403 wp : yes 404 flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ss ht syscall nx pdpe1gb rdtscp lm constant_tsc rep_good nopl xtopology nonstop_tsc cpuid tsc_known_freq pni pclmulqdq ssse3 fma cx16 pcid sse4_1 sse4_2 x2apic movbe popcnt aes xsave avx f16c rdrand hypervisor lahf_lm abm 3dnowprefetch invpcid_single pti fsgsbase tsc_adjust bmi1 hle avx2 smep bmi2 erms invpcid rtm mpx avx512f avx512dq rdseed adx smap clflushopt clwb avx512cd avx512bw avx512vl xsaveopt xsavec xgetbv1 xsaves 405 bugs : cpu_meltdown spectre_v1 spectre_v2 spec_store_bypass l1tf mds swapgs 406 bogomips : 4000.33 407 clflush size : 64 408 cache_alignment : 64 409 address sizes : 46 bits physical, 48 bits virtual 410 power management: 411 `, 412 }, 413 { 414 data: `A: a 415 B: b 416 417 C: c1 418 D: d 419 C: c1 420 D: d 421 C: c2 422 D: d 423 `, 424 want: `A : a 425 B : b 426 C : c1, c1, c2 427 D : d 428 `, 429 }, 430 }