aboutsummaryrefslogtreecommitdiffstats
path: root/pkg/vminfo
diff options
context:
space:
mode:
authorDmitry Vyukov <dvyukov@google.com>2024-05-07 17:20:52 +0200
committerDmitry Vyukov <dvyukov@google.com>2024-05-07 15:42:03 +0000
commit560bf7dcd4369d4633568a2b9912c71bb9928322 (patch)
treed697bdacd688822382025b21387f47f047759702 /pkg/vminfo
parentfc7348e9d52ba26a91ae1fcf1d602bbf84bbdcd2 (diff)
pkg/vminfo: deduplicate syscall test programs
Properly dedup syscall tests. This reduces number of test programs for linux from 4349 to 641.
Diffstat (limited to 'pkg/vminfo')
-rw-r--r--pkg/vminfo/linux_syscalls.go14
-rw-r--r--pkg/vminfo/linux_test.go24
-rw-r--r--pkg/vminfo/vminfo_test.go49
3 files changed, 70 insertions, 17 deletions
diff --git a/pkg/vminfo/linux_syscalls.go b/pkg/vminfo/linux_syscalls.go
index a11eb06b4..529fed3bd 100644
--- a/pkg/vminfo/linux_syscalls.go
+++ b/pkg/vminfo/linux_syscalls.go
@@ -20,7 +20,19 @@ func (linux) syscallCheck(ctx *checkContext, call *prog.Syscall) string {
check := linuxSyscallChecks[call.CallName]
if check == nil {
check = func(ctx *checkContext, call *prog.Syscall) string {
- return ctx.supportedSyscalls([]string{call.Name})
+ // Execute plain syscall (rather than a variation with $) to make test program
+ // deduplication effective. However, if the plain syscall does not exist take
+ // the first variant for this syscall, this still allows to dedup all variants.
+ // This works b/c in syscall test we only check for ENOSYS result.
+ name := call.CallName
+ if ctx.target.SyscallMap[name] == nil {
+ for _, call1 := range ctx.target.Syscalls {
+ if name == call1.CallName {
+ name = call1.Name
+ }
+ }
+ }
+ return ctx.supportedSyscalls([]string{name})
}
}
if reason := check(ctx, call); reason != "" {
diff --git a/pkg/vminfo/linux_test.go b/pkg/vminfo/linux_test.go
index 702167606..be157b858 100644
--- a/pkg/vminfo/linux_test.go
+++ b/pkg/vminfo/linux_test.go
@@ -14,8 +14,6 @@ import (
"github.com/google/go-cmp/cmp"
"github.com/google/syzkaller/pkg/flatrpc"
- "github.com/google/syzkaller/pkg/ipc"
- "github.com/google/syzkaller/pkg/rpctype"
"github.com/google/syzkaller/sys/targets"
"github.com/stretchr/testify/assert"
)
@@ -24,6 +22,13 @@ func TestLinuxSyscalls(t *testing.T) {
cfg := testConfig(t, targets.Linux, targets.AMD64)
checker := New(cfg)
_, checkProgs := checker.StartCheck()
+ t.Logf("got %v test programs", len(checkProgs))
+ if len(checkProgs) > 1000 {
+ // This is just a sanity check that we don't do something stupid accidentally.
+ // If it grows above the limit intentionally, the limit can be increased.
+ // Currently we have 641 (when we failed to properly dedup syscall tests, it was 4349).
+ t.Fatal("too many test programs")
+ }
filesystems := []string{
"", "9p", "esdfs", "incremental-fs", "cgroup", "cgroup2",
"pvfs2", "nfs", "nfs4", "fuse", "fuseblk", "afs", "pipefs",
@@ -47,20 +52,7 @@ func TestLinuxSyscalls(t *testing.T) {
Data: []byte(strings.Join(filesystems, "\nnodev\t")),
},
}
- var results []rpctype.ExecutionResult
- for _, req := range checkProgs {
- p, err := cfg.Target.DeserializeExec(req.ProgData, nil)
- if err != nil {
- t.Fatal(err)
- }
- res := rpctype.ExecutionResult{
- ID: req.ID,
- Info: ipc.ProgInfo{
- Calls: make([]ipc.CallInfo, len(p.Calls)),
- },
- }
- results = append(results, res)
- }
+ results := createSuccessfulResults(t, cfg.Target, checkProgs)
enabled, disabled, err := checker.FinishCheck(files, results)
if err != nil {
t.Fatal(err)
diff --git a/pkg/vminfo/vminfo_test.go b/pkg/vminfo/vminfo_test.go
index 7e7781a73..de41b48fe 100644
--- a/pkg/vminfo/vminfo_test.go
+++ b/pkg/vminfo/vminfo_test.go
@@ -12,6 +12,7 @@ import (
"github.com/google/syzkaller/pkg/host"
"github.com/google/syzkaller/pkg/ipc"
"github.com/google/syzkaller/pkg/mgrconfig"
+ "github.com/google/syzkaller/pkg/rpctype"
"github.com/google/syzkaller/prog"
"github.com/google/syzkaller/sys/targets"
)
@@ -42,6 +43,54 @@ func TestHostMachineInfo(t *testing.T) {
}
}
+func TestSyscalls(t *testing.T) {
+ t.Parallel()
+ for _, arches := range targets.List {
+ for _, target := range arches {
+ target := target
+ if target.OS == targets.Linux {
+ continue // linux has own TestLinuxSyscalls test
+ }
+ t.Run(target.OS+"/"+target.Arch, func(t *testing.T) {
+ t.Parallel()
+ cfg := testConfig(t, target.OS, target.Arch)
+ checker := New(cfg)
+ _, checkProgs := checker.StartCheck()
+ results := createSuccessfulResults(t, cfg.Target, checkProgs)
+ enabled, disabled, err := checker.FinishCheck(nil, results)
+ if err != nil {
+ t.Fatal(err)
+ }
+ for call, reason := range disabled {
+ t.Errorf("disabled call %v: %v", call.Name, reason)
+ }
+ if len(enabled) != len(cfg.Syscalls) {
+ t.Errorf("enabled only %v calls out of %v", len(enabled), len(cfg.Syscalls))
+ }
+ })
+ }
+ }
+}
+
+func createSuccessfulResults(t *testing.T, target *prog.Target,
+ progs []rpctype.ExecutionRequest) []rpctype.ExecutionResult {
+ var results []rpctype.ExecutionResult
+ for _, req := range progs {
+ p, err := target.DeserializeExec(req.ProgData, nil)
+ if err != nil {
+ t.Fatal(err)
+ }
+ res := rpctype.ExecutionResult{
+ ID: req.ID,
+ Info: ipc.ProgInfo{
+ Calls: make([]ipc.CallInfo, len(p.Calls)),
+ },
+ }
+ results = append(results, res)
+ }
+ return results
+}
+
func hostChecker(t *testing.T) (*Checker, []flatrpc.FileInfo) {
cfg := testConfig(t, runtime.GOOS, runtime.GOARCH)
checker := New(cfg)