From 6ef39602f449b25d12299bddb48d9d1b56c4cbca Mon Sep 17 00:00:00 2001 From: Dmitry Vyukov Date: Thu, 27 Jun 2024 08:05:05 +0200 Subject: pkg/runtest: test feature detection Fail some features in various ways for test OS, and check that features are detected properly. --- executor/common_test.h | 27 +++++++++++++++++++++++++++ executor/executor_test.h | 19 +++++++++++++++++++ pkg/runtest/executor_test.go | 4 ++-- pkg/runtest/run_test.go | 39 +++++++++++++++++++++++++++++++++++---- 4 files changed, 83 insertions(+), 6 deletions(-) diff --git a/executor/common_test.h b/executor/common_test.h index c5f7f5bca..d580ae2ff 100644 --- a/executor/common_test.h +++ b/executor/common_test.h @@ -129,6 +129,21 @@ static long syz_compare_zlib(volatile long data, volatile long size, volatile lo static void loop(); static int do_sandbox_none(void) { + // Test various ways how feature setup can fail. + // We don't care about these features for test OS, + // this is just to test the feature support detection code. +#if SYZ_EXECUTOR || SYZ_NET_INJECTION +#if SYZ_EXECUTOR + if (flag_net_injection) +#endif + fail("net injection is not supported"); +#endif +#if SYZ_EXECUTOR || SYZ_DEVLINK_PCI +#if SYZ_EXECUTOR + if (flag_devlink_pci) +#endif + exitf("devlink_pci is not supported"); +#endif loop(); return 0; } @@ -164,3 +179,15 @@ static long syz_inject_cover(volatile long a, volatile long b, volatile long c) } #endif #endif + +#if SYZ_EXECUTOR || SYZ_SYSCTL +static void setup_sysctl() +{ +} +#endif + +#if SYZ_EXECUTOR || (SYZ_CGROUPS && (SYZ_SANDBOX_NONE || SYZ_SANDBOX_SETUID || SYZ_SANDBOX_NAMESPACE || SYZ_SANDBOX_ANDROID)) +static void setup_cgroups() +{ +} +#endif diff --git a/executor/executor_test.h b/executor/executor_test.h index 0644e2d97..870dcb397 100644 --- a/executor/executor_test.h +++ b/executor/executor_test.h @@ -134,3 +134,22 @@ static long syz_inject_cover(volatile long a, volatile long b, volatile long c) memset(cov->data + size, 0xcd, std::min(100, cov->mmap_alloc_size - size)); return 0; } + +static const char* setup_fault() +{ + return nullptr; +} + +static const char* setup_leak() +{ + return "leak detection is not supported"; +} + +// Test various ways how feature setup can fail. +// We don't care about these features for test OS, +// this is just to test the feature support detection code. +#define SYZ_HAVE_FEATURES 1 +static feature_t features[] = { + {rpc::Feature::Fault, setup_fault}, + {rpc::Feature::Leak, setup_leak}, +}; diff --git a/pkg/runtest/executor_test.go b/pkg/runtest/executor_test.go index d6f9a8434..04d5b5969 100644 --- a/pkg/runtest/executor_test.go +++ b/pkg/runtest/executor_test.go @@ -61,7 +61,7 @@ func TestZlib(t *testing.T) { } executor := csource.BuildExecutor(t, target, "../..") source := queue.Plain() - startRpcserver(t, target, executor, source) + startRpcserver(t, target, executor, source, nil) r := rand.New(testutil.RandSource(t)) for i := 0; i < 10; i++ { data := testutil.RandMountImage(r) @@ -111,7 +111,7 @@ func TestExecutorCommonExt(t *testing.T) { t.Fatal(err) } source := queue.Plain() - startRpcserver(t, target, executor, source) + startRpcserver(t, target, executor, source, nil) req := &queue.Request{ Prog: p, ReturnError: true, diff --git a/pkg/runtest/run_test.go b/pkg/runtest/run_test.go index af613ed30..4de56f4e8 100644 --- a/pkg/runtest/run_test.go +++ b/pkg/runtest/run_test.go @@ -83,7 +83,34 @@ func test(t *testing.T, sysTarget *targets.Target) { Verbose: true, Debug: *flagDebug, } - startRpcserver(t, target, executor, ctx) + startRpcserver(t, target, executor, ctx, func(features flatrpc.Feature) { + // Features we expect to be enabled on the test OS. + // All sandboxes except for none are not implemented, coverage is not returned, + // and setup for few features is failing specifically to test feature detection. + want := flatrpc.FeatureCoverage | + flatrpc.FeatureExtraCoverage | + flatrpc.FeatureDelayKcovMmap | + flatrpc.FeatureSandboxNone | + flatrpc.FeatureFault | + flatrpc.FeatureNetDevices | + flatrpc.FeatureKCSAN | + flatrpc.FeatureNicVF | + flatrpc.FeatureUSBEmulation | + flatrpc.FeatureVhciInjection | + flatrpc.FeatureWifiEmulation | + flatrpc.FeatureLRWPANEmulation | + flatrpc.FeatureBinFmtMisc | + flatrpc.FeatureSwap + for feat, name := range flatrpc.EnumNamesFeature { + if features&feat != want&feat { + t.Errorf("expect featue %v to be %v, but it is %v", + name, want&feat != 0, features&feat != 0) + } + } + }) + if t.Failed() { + return + } if err := ctx.Run(); err != nil { t.Fatal(err) } @@ -277,7 +304,7 @@ func testCover(t *testing.T, target *prog.Target) { } executor := csource.BuildExecutor(t, target, "../../") source := queue.Plain() - startRpcserver(t, target, executor, source) + startRpcserver(t, target, executor, source, nil) for i, test := range tests { test := test t.Run(fmt.Sprint(i), func(t *testing.T) { @@ -352,14 +379,15 @@ func makeComps(comps ...Comparison) []byte { return w.Bytes() } -func startRpcserver(t *testing.T, target *prog.Target, executor string, source queue.Source) { +func startRpcserver(t *testing.T, target *prog.Target, executor string, source queue.Source, + machineChecked func(features flatrpc.Feature)) { ctx, done := context.WithCancel(context.Background()) cfg := &rpcserver.LocalConfig{ Config: rpcserver.Config{ Config: vminfo.Config{ Target: target, Debug: *flagDebug, - Features: flatrpc.FeatureSandboxNone, + Features: flatrpc.AllFeatures, Sandbox: flatrpc.ExecEnvSandboxNone, }, Procs: runtime.GOMAXPROCS(0), @@ -371,6 +399,9 @@ func startRpcserver(t *testing.T, target *prog.Target, executor string, source q GDB: *flagGDB, } cfg.MachineChecked = func(features flatrpc.Feature, syscalls map[*prog.Syscall]bool) queue.Source { + if machineChecked != nil { + machineChecked(features) + } cfg.Cover = true return source } -- cgit mrf-deployment