From 9e8eaa75a18a5cf8102e862be692c0781759e51b Mon Sep 17 00:00:00 2001 From: Kris Alder Date: Mon, 7 Mar 2022 23:00:21 +0000 Subject: pkg/host: only try enabled syscalls when starting syz-fuzzer When syz-fuzzer starts, it tries all syscalls to filter out any that are not supported. This process should include only the syscalls that are enabled using the 'enable_syscalls' and 'disable_syscalls' fields in syz-manager's config. This is useful for fuzzing Cuttlefish devices, for example, where the 'vhost_vsock' syscall needs to be excluded from fuzzing and from this test. --- pkg/host/host_test.go | 6 +++++- pkg/host/syscalls.go | 5 ++++- pkg/host/syscalls_linux_test.go | 16 ++++++++++------ pkg/runtest/run_test.go | 6 +++++- syz-fuzzer/testing.go | 3 ++- syz-runner/runner.go | 6 +++++- tools/syz-stress/stress.go | 23 ++++++++--------------- 7 files changed, 39 insertions(+), 26 deletions(-) diff --git a/pkg/host/host_test.go b/pkg/host/host_test.go index dc8565920..6e9770744 100644 --- a/pkg/host/host_test.go +++ b/pkg/host/host_test.go @@ -23,8 +23,12 @@ func TestDetectSupportedSyscalls(t *testing.T) { if err != nil { t.Fatal(err) } + enabled := make(map[*prog.Syscall]bool) + for _, c := range target.Syscalls { + enabled[c] = true + } // Dump for manual inspection. - supp, disabled, err := DetectSupportedSyscalls(target, "none") + supp, disabled, err := DetectSupportedSyscalls(target, "none", enabled) if err != nil { t.Fatal(err) } diff --git a/pkg/host/syscalls.go b/pkg/host/syscalls.go index c6424bfe4..fd8acc4d1 100644 --- a/pkg/host/syscalls.go +++ b/pkg/host/syscalls.go @@ -10,7 +10,7 @@ import ( // DetectSupportedSyscalls returns list on supported and unsupported syscalls on the host. // For unsupported syscalls it also returns reason as to why it is unsupported. -func DetectSupportedSyscalls(target *prog.Target, sandbox string) ( +func DetectSupportedSyscalls(target *prog.Target, sandbox string, enabled map[*prog.Syscall]bool) ( map[*prog.Syscall]bool, map[*prog.Syscall]string, error) { log.Logf(1, "detecting supported syscalls") supported := make(map[*prog.Syscall]bool) @@ -32,6 +32,9 @@ func DetectSupportedSyscalls(target *prog.Target, sandbox string) ( case c.Attrs.Disabled: ok = false reason = disabledAttribute + case !enabled[c]: + ok = false + reason = "not in set of enabled calls" case c.CallName == "syz_execute_func": // syz_execute_func caused multiple problems: // 1. First it lead to corpus explosion. The program used existing values in registers diff --git a/pkg/host/syscalls_linux_test.go b/pkg/host/syscalls_linux_test.go index 5fc87377c..97f11c25f 100644 --- a/pkg/host/syscalls_linux_test.go +++ b/pkg/host/syscalls_linux_test.go @@ -22,10 +22,6 @@ func TestSupportedSyscalls(t *testing.T) { if err != nil { t.Fatal(err) } - supp, _, err := DetectSupportedSyscalls(target, "none") - if err != nil { - t.Skipf("skipping: %v", err) - } // These are safe to execute with invalid arguments. safe := []string{ "memfd_create", @@ -37,18 +33,26 @@ func TestSupportedSyscalls(t *testing.T) { "write", "stat", } + enabled := make(map[*prog.Syscall]bool) for _, name := range safe { c := target.SyscallMap[name] if c == nil { t.Fatalf("can't find syscall '%v'", name) } + enabled[c] = true + } + supp, _, err := DetectSupportedSyscalls(target, "none", enabled) + if err != nil { + t.Skipf("skipping: %v", err) + } + for c := range enabled { a := ^uintptr(0) - 4097 // hopefully invalid _, _, err := syscall.Syscall6(uintptr(c.NR), a, a, a, a, a, a) if err == 0 { - t.Fatalf("%v did not fail", name) + t.Fatalf("%v did not fail", c.Name) } if ok := err != syscall.ENOSYS; ok != supp[c] { - t.Fatalf("syscall %v: perse=%v kallsyms=%v", name, ok, supp[c]) + t.Fatalf("syscall %v: perse=%v kallsyms=%v", c.Name, ok, supp[c]) } } } diff --git a/pkg/runtest/run_test.go b/pkg/runtest/run_test.go index adafedab2..bc71a9f08 100644 --- a/pkg/runtest/run_test.go +++ b/pkg/runtest/run_test.go @@ -58,7 +58,11 @@ func test(t *testing.T, sysTarget *targets.Target) { if err != nil { t.Fatalf("failed to detect host features: %v", err) } - calls, _, err := host.DetectSupportedSyscalls(target, "none") + enabled := make(map[*prog.Syscall]bool) + for _, c := range target.Syscalls { + enabled[c] = true + } + calls, _, err := host.DetectSupportedSyscalls(target, "none", enabled) if err != nil { t.Fatalf("failed to detect supported syscalls: %v", err) } diff --git a/syz-fuzzer/testing.go b/syz-fuzzer/testing.go index 6274c3174..a754a6afd 100644 --- a/syz-fuzzer/testing.go +++ b/syz-fuzzer/testing.go @@ -294,7 +294,8 @@ func buildCallList(target *prog.Target, enabledCalls []int, sandbox string) ( calls[c] = true } } - _, unsupported, err := host.DetectSupportedSyscalls(target, sandbox) + + _, unsupported, err := host.DetectSupportedSyscalls(target, sandbox, calls) if err != nil { return nil, nil, fmt.Errorf("failed to detect host supported syscalls: %v", err) } diff --git a/syz-runner/runner.go b/syz-runner/runner.go index 9317055d4..a8965bbc3 100644 --- a/syz-runner/runner.go +++ b/syz-runner/runner.go @@ -70,8 +70,12 @@ func main() { log.Fatalf("failed to connect to verifier: %v", err) } + enabled := make(map[*prog.Syscall]bool) + for _, c := range target.Syscalls { + enabled[c] = true + } if r.CheckUnsupportedCalls { - _, unsupported, err := host.DetectSupportedSyscalls(target, ipc.FlagsToSandbox(config.Flags)) + _, unsupported, err := host.DetectSupportedSyscalls(target, ipc.FlagsToSandbox(config.Flags), enabled) if err != nil { log.Fatalf("failed to get unsupported system calls: %v", err) } diff --git a/tools/syz-stress/stress.go b/tools/syz-stress/stress.go index 2122774b6..0b12fc65b 100644 --- a/tools/syz-stress/stress.go +++ b/tools/syz-stress/stress.go @@ -186,30 +186,23 @@ func buildCallList(target *prog.Target, enabled []string) map[*prog.Syscall]bool } return calls } - calls, disabled, err := host.DetectSupportedSyscalls(target, "none") - if err != nil { - log.Fatalf("failed to detect host supported syscalls: %v", err) - } + + enabledSyscalls := make(map[*prog.Syscall]bool) if len(enabled) != 0 { syscallsIDs, err := mgrconfig.ParseEnabledSyscalls(target, enabled, nil) if err != nil { log.Fatalf("failed to parse enabled syscalls: %v", err) } - enabledSyscalls := make(map[*prog.Syscall]bool) for _, id := range syscallsIDs { enabledSyscalls[target.Syscalls[id]] = true } - for c := range calls { - if !enabledSyscalls[c] { - delete(calls, c) - } - } - for c := range disabled { - if !enabledSyscalls[c] { - delete(disabled, c) - } - } } + + calls, disabled, err := host.DetectSupportedSyscalls(target, "none", enabledSyscalls) + if err != nil { + log.Fatalf("failed to detect host supported syscalls: %v", err) + } + for c, reason := range disabled { log.Logf(0, "unsupported syscall: %v: %v", c.Name, reason) } -- cgit mrf-deployment