github.com/google/syzkaller@v0.0.0-20251211124644-a066d2bc4b02/vm/proxyapp/init.go (about) 1 // Copyright 2022 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 proxyapp 5 6 import ( 7 "context" 8 "encoding/json" 9 "errors" 10 "fmt" 11 "io" 12 "net/url" 13 "os" 14 "time" 15 16 "github.com/google/syzkaller/pkg/config" 17 "github.com/google/syzkaller/pkg/osutil" 18 "github.com/google/syzkaller/vm/vmimpl" 19 ) 20 21 func makeDefaultParams() *proxyAppParams { 22 return &proxyAppParams{ 23 CommandRunner: osutilCommandContext, 24 InitRetryDelay: 10 * time.Second, 25 LogOutput: os.Stdout, 26 } 27 } 28 29 func init() { 30 vmimpl.Register("proxyapp", vmimpl.Type{ 31 Ctor: func(env *vmimpl.Env) (vmimpl.Pool, error) { 32 return ctor(makeDefaultParams(), env) 33 }, 34 }) 35 } 36 37 // Package configuration VARs are mostly needed for tests. 38 type proxyAppParams struct { 39 CommandRunner func(context.Context, string, ...string) subProcessCmd 40 InitRetryDelay time.Duration 41 LogOutput io.Writer 42 } 43 44 func osutilCommandContext(ctx context.Context, bin string, args ...string) subProcessCmd { 45 return osutil.CommandContext(ctx, bin, args...) 46 } 47 48 type subProcessCmd interface { 49 StdinPipe() (io.WriteCloser, error) 50 StdoutPipe() (io.ReadCloser, error) 51 StderrPipe() (io.ReadCloser, error) 52 Start() error 53 Wait() error 54 } 55 56 // Config is valid if at least cmd or rpc_server_uri specified. 57 type Config struct { 58 // cmd is the optional command needed to initialize plugin. 59 // By default we'll connect to its std[in, out, err]. 60 Command string `json:"cmd"` 61 // rpc_server_uri is used to specify plugin endpoint address. 62 // if not specified, we'll connect to the plugin by std[in, out, err]. 63 RPCServerURI string `json:"rpc_server_uri"` 64 // security can be one of "none", "tls" (for server TLS) and "mtls" for mutal 65 // TLS. 66 Security string `json:"security"` 67 // server_tls_cert points a TLS certificate used to authenticate the server. 68 // If not provided, the default system certificate pool will be used. 69 ServerTLSCert string `json:"server_tls_cert"` 70 // transfer_file_content will send the file content as a byte array in 71 // addition to the filename. 72 TransferFileContent bool `json:"transfer_file_content"` 73 // config is an optional remote plugin config 74 ProxyAppConfig json.RawMessage `json:"config"` 75 } 76 77 func parseConfig(conf []byte) (*Config, error) { 78 vmCfg := new(Config) 79 if err := config.LoadData(conf, vmCfg); err != nil { 80 return nil, fmt.Errorf("failed to parseConfig(): %w", err) 81 } 82 83 if vmCfg.RPCServerURI == "" && vmCfg.Command == "" { 84 return nil, errors.New("failed to parseConfig(): neither 'cmd' nor 'rpc_server_uri' specified for plugin") 85 } 86 87 if vmCfg.RPCServerURI != "" && URIParseErr(vmCfg.RPCServerURI) != nil { 88 return nil, fmt.Errorf("failed to parseConfig(): %w", URIParseErr(vmCfg.RPCServerURI)) 89 } 90 91 return vmCfg, nil 92 } 93 94 func URIParseErr(uri string) error { 95 dest, err := url.Parse("http://" + uri) 96 if err != nil || dest.Port() == "" || dest.Host != uri { 97 return fmt.Errorf("bad uri (%v), host:port were expected", uri) 98 } 99 return nil 100 }