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