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  }