github.com/google/syzkaller@v0.0.0-20251211124644-a066d2bc4b02/pkg/build/gvisor.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 build 5 6 import ( 7 "fmt" 8 "path/filepath" 9 "strings" 10 "time" 11 12 "github.com/google/syzkaller/pkg/log" 13 "github.com/google/syzkaller/pkg/osutil" 14 "github.com/google/syzkaller/sys/targets" 15 ) 16 17 type gvisor struct{} 18 19 func (gvisor gvisor) build(params Params) (ImageDetails, error) { 20 if params.Compiler == "" { 21 params.Compiler = "bazel" 22 } 23 24 // Bring down bazel daemon right away. We don't need it running and consuming memory. 25 defer osutil.RunCmd(10*time.Minute, params.KernelDir, params.Compiler, "shutdown") 26 27 config, err := parseGVisorConfig(params.Config) 28 if err != nil { 29 return ImageDetails{}, fmt.Errorf("cannot parse gVisor configuration: %w", err) 30 } 31 bazelOpts := "--verbose_failures" 32 33 target := "//runsc:runsc" 34 if config.Coverage { 35 if config.Race { 36 target = "//runsc:runsc_race_coverage" 37 } else { 38 target = "//runsc:runsc_coverage" 39 } 40 } else if config.Race { 41 bazelOpts += " --config=race " 42 target = "//runsc:runsc-race" 43 } 44 45 outBinary := filepath.Join(params.OutputDir, "image") 46 cmd := osutil.Command("make", "copy", 47 "DOCKER_BUILD=0", 48 fmt.Sprintf("BAZEL_OPTIONS=%s", bazelOpts), 49 fmt.Sprintf("TARGETS=%s", target), 50 fmt.Sprintf("DESTINATION=%s", outBinary), 51 ) 52 cmd.Dir = params.KernelDir 53 54 log.Logf(0, "bazel copy: %v", cmd.Env) 55 if _, err := osutil.Run(60*time.Minute, cmd); err != nil { 56 return ImageDetails{}, err 57 } 58 59 sysTarget := targets.Get(params.TargetOS, params.TargetArch) 60 return ImageDetails{}, osutil.CopyFile(outBinary, filepath.Join(params.OutputDir, "obj", sysTarget.KernelObject)) 61 } 62 63 func (gvisor) clean(params Params) error { 64 // Let's assume that bazel always properly handles build without cleaning (until proven otherwise). 65 return nil 66 } 67 68 // Known gVisor configuration flags. 69 const ( 70 gvisorFlagCover = "-cover" 71 gvisorFlagRace = "-race" 72 ) 73 74 // gvisorConfig is a gVisor configuration. 75 type gvisorConfig struct { 76 // Coverage represents whether code coverage is enabled. 77 Coverage bool 78 79 // Race represents whether race condition detection is enabled. 80 Race bool 81 } 82 83 // parseGVisorConfig parses a set of flags into a `gvisorConfig`. 84 func parseGVisorConfig(config []byte) (gvisorConfig, error) { 85 var cfg gvisorConfig 86 for _, flag := range strings.Fields(string(config)) { 87 switch flag { 88 case gvisorFlagCover: 89 cfg.Coverage = true 90 case gvisorFlagRace: 91 cfg.Race = true 92 default: 93 return cfg, fmt.Errorf("unknown gVisor configuration flag: %q", flag) 94 } 95 } 96 return cfg, nil 97 }