github.com/google/syzkaller@v0.0.0-20240517125934-c0f1611a36d6/pkg/host/features.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 host 5 6 import ( 7 "bytes" 8 "fmt" 9 "strings" 10 "time" 11 12 "github.com/google/syzkaller/pkg/csource" 13 "github.com/google/syzkaller/pkg/flatrpc" 14 "github.com/google/syzkaller/pkg/ipc" 15 "github.com/google/syzkaller/pkg/log" 16 "github.com/google/syzkaller/pkg/osutil" 17 "github.com/google/syzkaller/prog" 18 "github.com/google/syzkaller/sys/targets" 19 ) 20 21 // SetupFeatures enables and does any one-time setup for the requested features on the host. 22 // Note: this can be called multiple times and must be idempotent. 23 func SetupFeatures(target *prog.Target, executor string, mask flatrpc.Feature, flags csource.Features) ( 24 []*flatrpc.FeatureInfo, error) { 25 if noHostChecks(target) { 26 return nil, nil 27 } 28 var results []*flatrpc.FeatureInfo 29 resultC := make(chan *flatrpc.FeatureInfo) 30 for feat := range flatrpc.EnumNamesFeature { 31 feat := feat 32 if mask&feat == 0 { 33 continue 34 } 35 opt := ipc.FlatRPCFeaturesToCSource[feat] 36 if opt != "" && flags != nil && !flags["binfmt_misc"].Enabled { 37 continue 38 } 39 results = append(results, nil) 40 go setupFeature(executor, feat, resultC) 41 } 42 // Feature 0 setups common things that are not part of any feature. 43 setupFeature(executor, 0, nil) 44 for i := range results { 45 results[i] = <-resultC 46 } 47 return results, nil 48 } 49 50 func setupFeature(executor string, feat flatrpc.Feature, resultC chan *flatrpc.FeatureInfo) { 51 args := strings.Split(executor, " ") 52 executor = args[0] 53 args = append(args[1:], "setup", fmt.Sprint(uint64(feat))) 54 output, err := osutil.RunCmd(3*time.Minute, "", executor, args...) 55 log.Logf(1, "executor %v\n%s", args, bytes.ReplaceAll(output, []byte("SYZFAIL:"), nil)) 56 outputStr := string(output) 57 if err == nil { 58 outputStr = "" 59 } else if outputStr == "" { 60 outputStr = err.Error() 61 } 62 needSetup := true 63 if strings.Contains(outputStr, "feature setup is not needed") { 64 needSetup = false 65 outputStr = "" 66 } 67 if resultC != nil { 68 resultC <- &flatrpc.FeatureInfo{ 69 Id: feat, 70 NeedSetup: needSetup, 71 Reason: outputStr, 72 } 73 } 74 } 75 76 func noHostChecks(target *prog.Target) bool { 77 // HostFuzzer targets can't run Go binaries on the targets, 78 // so we actually run on the host on another OS. The same for targets.TestOS OS. 79 return targets.Get(target.OS, target.Arch).HostFuzzer || target.OS == targets.TestOS 80 }