github.com/google/syzkaller@v0.0.0-20240517125934-c0f1611a36d6/pkg/instance/instance_test.go (about)

     1  // Copyright 2018 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 instance
     5  
     6  import (
     7  	"flag"
     8  	"os"
     9  	"runtime"
    10  	"strings"
    11  	"testing"
    12  
    13  	"github.com/google/syzkaller/pkg/tool"
    14  	"github.com/google/syzkaller/sys/targets"
    15  )
    16  
    17  func TestFuzzerCmd(t *testing.T) {
    18  	// IMPORTANT: if this test fails, do not fix it by changing flags here!
    19  	// Test how an old version of syz-fuzzer parses flags generated by the current FuzzerCmd.
    20  	// This actually happens in syz-ci when we test a patch for an old bug and use an old syz-fuzzer/execprog.
    21  	flags := flag.NewFlagSet("", flag.ContinueOnError)
    22  	flagName := flags.String("name", "", "unique name for manager")
    23  	flagArch := flags.String("arch", "", "target arch")
    24  	flagManager := flags.String("manager", "", "manager rpc address")
    25  	flagProcs := flags.Int("procs", 1, "number of parallel test processes")
    26  	flagLeak := flags.Bool("leak", false, "detect memory leaks")
    27  	flagOutput := flags.String("output", "stdout", "write programs to none/stdout/dmesg/file")
    28  	flagPprof := flags.String("pprof", "", "address to serve pprof profiles")
    29  	flagTest := flags.Bool("test", false, "enable image testing mode") // used by syz-ci
    30  	flagExecutor := flags.String("executor", "./syz-executor", "path to executor binary")
    31  	flagSignal := flags.Bool("cover", false, "collect feedback signals (coverage)")
    32  	flagSandbox := flags.String("sandbox", "none", "sandbox for fuzzing (none/setuid/namespace/android)")
    33  	flagDebug := flags.Bool("debug", false, "debug output from executor")
    34  	flagV := flags.Int("v", 0, "verbosity")
    35  	cmdLine := OldFuzzerCmd(os.Args[0], "/myexecutor", "myname", targets.Linux, targets.I386, "localhost:1234",
    36  		"namespace", 23, 3, true, true, false, 5)
    37  	args := strings.Split(cmdLine, " ")[1:]
    38  	if err := flags.Parse(args); err != nil {
    39  		t.Fatal(err)
    40  	}
    41  	if *flagName != "myname" {
    42  		t.Errorf("bad name: %q, want: %q", *flagName, "myname")
    43  	}
    44  	if *flagArch != targets.I386 {
    45  		t.Errorf("bad arch: %q, want: %q", *flagArch, targets.I386)
    46  	}
    47  	if *flagManager != "localhost:1234" {
    48  		t.Errorf("bad manager: %q, want: %q", *flagManager, "localhost:1234")
    49  	}
    50  	if *flagProcs != 3 {
    51  		t.Errorf("bad procs: %v, want: %v", *flagProcs, 3)
    52  	}
    53  	if *flagLeak {
    54  		t.Errorf("bad leak: %v, want: %v", *flagLeak, false)
    55  	}
    56  	if *flagOutput != "stdout" {
    57  		t.Errorf("bad output: %q, want: %q", *flagOutput, "stdout")
    58  	}
    59  	if *flagPprof != "" {
    60  		t.Errorf("bad pprof: %q, want: %q", *flagPprof, "")
    61  	}
    62  	if !*flagTest {
    63  		t.Errorf("bad test: %v, want: %v", *flagTest, true)
    64  	}
    65  	if *flagExecutor != "/myexecutor" {
    66  		t.Errorf("bad executor: %q, want: %q", *flagExecutor, "/myexecutor")
    67  	}
    68  	if *flagSandbox != "namespace" {
    69  		t.Errorf("bad sandbox: %q, want: %q", *flagSandbox, "namespace")
    70  	}
    71  	if !*flagSignal {
    72  		t.Errorf("bad signal: %v, want: %v", *flagSignal, true)
    73  	}
    74  	if *flagDebug {
    75  		t.Errorf("bad debug: %v, want: %v", *flagDebug, false)
    76  	}
    77  	if *flagV != 0 {
    78  		t.Errorf("bad verbosity: %v, want: %v", *flagV, 0)
    79  	}
    80  }
    81  
    82  func TestExecprogCmd(t *testing.T) {
    83  	// IMPORTANT: if this test fails, do not fix it by changing flags here!
    84  	// See comment in TestFuzzerCmd.
    85  	flags := flag.NewFlagSet("", flag.ContinueOnError)
    86  	flagOS := flags.String("os", runtime.GOOS, "target os")
    87  	flagArch := flags.String("arch", "", "target arch")
    88  	flagRepeat := flags.Int("repeat", 1, "repeat execution that many times (0 for infinite loop)")
    89  	flagProcs := flags.Int("procs", 1, "number of parallel processes to execute programs")
    90  	flagFaultCall := flags.Int("fault_call", -1, "inject fault into this call (0-based)")
    91  	flagFaultNth := flags.Int("fault_nth", 0, "inject fault on n-th operation (0-based)")
    92  	flagExecutor := flags.String("executor", "./syz-executor", "path to executor binary")
    93  	flagThreaded := flags.Bool("threaded", true, "use threaded mode in executor")
    94  	// In the older syzkaller versions `collide` flag defaulted to `true`, but in this
    95  	// test we can change it to false (new default), because syzkaller always explicitly
    96  	// sets this flag and never relies on the default value.
    97  	flagCollide := flags.Bool("collide", false, "collide syscalls to provoke data races")
    98  	flagSignal := flags.Bool("cover", false, "collect feedback signals (coverage)")
    99  	flagSandbox := flags.String("sandbox", "none", "sandbox for fuzzing (none/setuid/namespace/android)")
   100  	flagSlowdown := flags.Int("slowdown", 1, "")
   101  	cmdLine := ExecprogCmd(os.Args[0], "/myexecutor", targets.FreeBSD, targets.I386,
   102  		"namespace", 3, true, false, true, 7, 2, 3, true, 10, "myprog")
   103  	args := strings.Split(cmdLine, " ")[1:]
   104  	if err := tool.ParseFlags(flags, args); err != nil {
   105  		t.Fatal(err)
   106  	}
   107  	if len(flags.Args()) != 1 || flags.Arg(0) != "myprog" {
   108  		t.Errorf("bad args: %q, want: %q", flags.Args(), "myprog")
   109  	}
   110  	if *flagOS != runtime.GOOS {
   111  		t.Errorf("bad os: %q, want: %q", *flagOS, runtime.GOOS)
   112  	}
   113  	if *flagArch != targets.I386 {
   114  		t.Errorf("bad arch: %q, want: %q", *flagArch, targets.I386)
   115  	}
   116  	if *flagRepeat != 0 {
   117  		t.Errorf("bad repeat: %v, want: %v", *flagRepeat, 0)
   118  	}
   119  	if *flagProcs != 7 {
   120  		t.Errorf("bad procs: %v, want: %v", *flagProcs, 7)
   121  	}
   122  	if *flagFaultCall != 2 {
   123  		t.Errorf("bad procs: %v, want: %v", *flagFaultCall, 2)
   124  	}
   125  	if *flagFaultNth != 3 {
   126  		t.Errorf("bad procs: %v, want: %v", *flagFaultNth, 3)
   127  	}
   128  	if *flagExecutor != "/myexecutor" {
   129  		t.Errorf("bad executor: %q, want: %q", *flagExecutor, "/myexecutor")
   130  	}
   131  	if *flagSandbox != "namespace" {
   132  		t.Errorf("bad sandbox: %q, want: %q", *flagSandbox, "namespace")
   133  	}
   134  	if *flagSignal {
   135  		t.Errorf("bad signal: %v, want: %v", *flagSignal, false)
   136  	}
   137  	if *flagThreaded {
   138  		t.Errorf("bad threaded: %v, want: %v", *flagThreaded, false)
   139  	}
   140  	if !*flagCollide {
   141  		t.Errorf("bad collide: %v, want: %v", *flagCollide, true)
   142  	}
   143  	if *flagSlowdown != 10 {
   144  		t.Errorf("bad slowdown: %v, want: %v", *flagSlowdown, 10)
   145  	}
   146  }
   147  
   148  func TestRunnerCmd(t *testing.T) {
   149  	flags := flag.NewFlagSet("", flag.ContinueOnError)
   150  	flagFwdAddr := flags.String("addr", "", "verifier rpc address")
   151  	flagOS := flags.String("os", "", "target OS")
   152  	flagArch := flags.String("arch", "", "target architecture")
   153  	flagPool := flags.Int("pool", 0, "index of pool that started VM")
   154  	flagVM := flags.Int("vm", 0, "index of VM that started the Runner")
   155  	flagThreaded := flags.Bool("threaded", true, "use threaded mode in executor")
   156  	flagEnv := flags.Bool("new-env", true, "create a new environment for each program")
   157  
   158  	cmdLine := RunnerCmd(os.Args[0], "localhost:1234", targets.Linux, targets.AMD64, 0, 0, false, false)
   159  	args := strings.Split(cmdLine, " ")[1:]
   160  	if err := flags.Parse(args); err != nil {
   161  		t.Fatalf("error parsing flags: %v, want: nil", err)
   162  	}
   163  
   164  	if got, want := *flagFwdAddr, "localhost:1234"; got != want {
   165  		t.Errorf("bad addr: %q, want: %q", got, want)
   166  	}
   167  
   168  	if got, want := *flagOS, targets.Linux; got != want {
   169  		t.Errorf("bad os: %q, want %q", got, want)
   170  	}
   171  
   172  	if got, want := *flagArch, targets.AMD64; got != want {
   173  		t.Errorf("bad arch: %q, want: %q", got, want)
   174  	}
   175  
   176  	if got, want := *flagPool, 0; got != want {
   177  		t.Errorf("bad pool index: %d, want: %d", got, want)
   178  	}
   179  
   180  	if got, want := *flagVM, 0; got != want {
   181  		t.Errorf("bad vm index: %d, want: %d", got, want)
   182  	}
   183  
   184  	if got, want := *flagThreaded, false; got != want {
   185  		t.Errorf("bad threaded: %t, want: %t", got, want)
   186  	}
   187  
   188  	if got, want := *flagEnv, false; got != want {
   189  		t.Errorf("bad new-env: %t, want: %t", got, want)
   190  	}
   191  }