github.com/google/syzkaller@v0.0.0-20240517125934-c0f1611a36d6/syz-runner/runner.go (about)

     1  // Copyright 2021 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  package main
     4  
     5  import (
     6  	"flag"
     7  	"log"
     8  	"runtime"
     9  
    10  	"github.com/google/syzkaller/pkg/ipc"
    11  	"github.com/google/syzkaller/pkg/ipc/ipcconfig"
    12  	"github.com/google/syzkaller/pkg/rpctype"
    13  	"github.com/google/syzkaller/prog"
    14  )
    15  
    16  // Runner is responsible of running programs sent by the host via RPC and
    17  // reporting the execution results back to the host.
    18  type Runner struct {
    19  	vrf      *rpctype.RPCClient
    20  	target   *prog.Target
    21  	opts     *ipc.ExecOpts
    22  	config   *ipc.Config
    23  	pool, vm int
    24  	newEnv   bool
    25  }
    26  
    27  func main() {
    28  	flagPool := flag.Int("pool", 0, "index of pool it corresponds to")
    29  	flagVM := flag.Int("vm", 0, "index of VM that started the Runner")
    30  	flagAddr := flag.String("addr", "", "verifier rpc address")
    31  	flagOS := flag.String("os", runtime.GOOS, "target OS")
    32  	flagArch := flag.String("arch", runtime.GOARCH, "target arch")
    33  	flagEnv := flag.Bool("new-env", true, "create a new environment for each program")
    34  	flag.Parse()
    35  
    36  	target, err := prog.GetTarget(*flagOS, *flagArch)
    37  	if err != nil {
    38  		log.Fatalf("failed to configure target: %v", err)
    39  	}
    40  
    41  	config, opts, err := ipcconfig.Default(target)
    42  	if err != nil {
    43  		log.Fatalf("failed to create default ipc config: %v", err)
    44  	}
    45  
    46  	vrf, err := rpctype.NewRPCClient(*flagAddr)
    47  	if err != nil {
    48  		log.Fatalf("failed to connect to verifier : %v", err)
    49  	}
    50  
    51  	rn := &Runner{
    52  		vrf:    vrf,
    53  		target: target,
    54  		opts:   opts,
    55  		config: config,
    56  		pool:   *flagPool,
    57  		vm:     *flagVM,
    58  		newEnv: *flagEnv,
    59  	}
    60  
    61  	a := &rpctype.RunnerConnectArgs{
    62  		Pool: rn.pool,
    63  		VM:   rn.vm,
    64  	}
    65  	r := &rpctype.RunnerConnectRes{}
    66  	if err := vrf.Call("Verifier.Connect", a, r); err != nil {
    67  		log.Fatalf("failed to connect to verifier: %v", err)
    68  	}
    69  
    70  	enabled := make(map[*prog.Syscall]bool)
    71  	for _, c := range target.Syscalls {
    72  		enabled[c] = true
    73  	}
    74  	if r.CheckUnsupportedCalls {
    75  		a := &rpctype.UpdateUnsupportedArgs{Pool: rn.pool, UnsupportedCalls: nil}
    76  		if err := vrf.Call("Verifier.UpdateUnsupported", a, nil); err != nil {
    77  			log.Fatalf("failed to send unsupported system calls: %v", err)
    78  		}
    79  	}
    80  
    81  	res := &rpctype.NextExchangeRes{}
    82  	if err := rn.vrf.Call("Verifier.NextExchange", &rpctype.NextExchangeArgs{Pool: rn.pool, VM: rn.vm}, res); err != nil {
    83  		log.Fatalf("failed to get initial program: %v", err)
    84  	}
    85  
    86  	rn.Run(res.Prog, res.ID)
    87  }
    88  
    89  // Run is responsible for requesting new programs from the verifier, executing them and then sending back the Result.
    90  // TODO: Implement functionality to execute several programs at once and send back a slice of results.
    91  func (rn *Runner) Run(firstProg []byte, taskID int64) {
    92  	p, id := firstProg, taskID
    93  
    94  	env, err := ipc.MakeEnv(rn.config, 0)
    95  	if err != nil {
    96  		log.Fatalf("failed to create initial execution environment: %v", err)
    97  	}
    98  
    99  	for {
   100  		prog, err := rn.target.Deserialize(p, prog.NonStrict)
   101  		if err != nil {
   102  			log.Fatalf("failed to deserialise new program: %v", err)
   103  		}
   104  
   105  		log.Printf("executing program") // watchdog for monitor
   106  		_, info, hanged, err := env.Exec(rn.opts, prog)
   107  		if err != nil {
   108  			log.Fatalf("failed to execute the program: %v", err)
   109  		}
   110  
   111  		a := &rpctype.NextExchangeArgs{
   112  			Pool:       rn.pool,
   113  			VM:         rn.vm,
   114  			Hanged:     hanged,
   115  			Info:       *info,
   116  			ExecTaskID: id,
   117  		}
   118  
   119  		r := &rpctype.NextExchangeRes{}
   120  		if err := rn.vrf.Call("Verifier.NextExchange", a, r); err != nil {
   121  			log.Fatalf("failed to make exchange with verifier: %v", err)
   122  		}
   123  		p, id = r.Prog, r.ID
   124  
   125  		if !rn.newEnv {
   126  			continue
   127  		}
   128  
   129  		err = env.Close()
   130  		if err != nil {
   131  			log.Fatalf("failed to close the execution environment: %v", err)
   132  		}
   133  
   134  		env, err = ipc.MakeEnv(rn.config, 0)
   135  		if err != nil {
   136  			log.Fatalf("failed to create new execution environment: %v", err)
   137  		}
   138  	}
   139  }