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 4package host 5 6import ( 7 "github.com/google/syzkaller/prog" 8) 9 10// DetectSupportedSyscalls returns list on supported and unsupported syscalls on the host. 11// For unsupported syscalls it also returns reason as to why it is unsupported. 12func DetectSupportedSyscalls(target *prog.Target, sandbox string) ( 13 map[*prog.Syscall]bool, map[*prog.Syscall]string, error) { 14 supported := make(map[*prog.Syscall]bool) 15 unsupported := make(map[*prog.Syscall]string) 16 // Akaros does not have own host and parasitizes on some other OS. 17 if target.OS == "akaros" || target.OS == "test" { 18 for _, c := range target.Syscalls { 19 supported[c] = true 20 } 21 return supported, unsupported, nil 22 } 23 for _, c := range target.Syscalls { 24 ok, reason := isSupported(c, sandbox) 25 if ok { 26 supported[c] = true 27 } else { 28 if reason == "" { 29 reason = "unknown" 30 } 31 unsupported[c] = reason 32 } 33 } 34 return supported, unsupported, nil 35} 36 37var testFallback = false 38 39const ( 40 FeatureCoverage = iota 41 FeatureComparisons 42 FeatureSandboxSetuid 43 FeatureSandboxNamespace 44 FeatureFaultInjection 45 FeatureLeakChecking 46 FeatureNetworkInjection 47 FeatureNetworkDevices 48 numFeatures 49) 50 51type Feature struct { 52 Name string 53 Enabled bool 54 Reason string 55} 56 57type Features [numFeatures]Feature 58 59var checkFeature [numFeatures]func() string 60var setupFeature [numFeatures]func() error 61var callbFeature [numFeatures]func() 62 63func unconditionallyEnabled() string { return "" } 64 65// Check detects features supported on the host. 66// Empty string for a feature means the feature is supported, 67// otherwise the string contains the reason why the feature is not supported. 68func Check(target *prog.Target) (*Features, error) { 69 const unsupported = "support is not implemented in syzkaller" 70 res := &Features{ 71 FeatureCoverage: {Name: "code coverage", Reason: unsupported}, 72 FeatureComparisons: {Name: "comparison tracing", Reason: unsupported}, 73 FeatureSandboxSetuid: {Name: "setuid sandbox", Reason: unsupported}, 74 FeatureSandboxNamespace: {Name: "namespace sandbox", Reason: unsupported}, 75 FeatureFaultInjection: {Name: "fault injection", Reason: unsupported}, 76 FeatureLeakChecking: {Name: "leak checking", Reason: unsupported}, 77 FeatureNetworkInjection: {Name: "net packed injection", Reason: unsupported}, 78 FeatureNetworkDevices: {Name: "net device setup", Reason: unsupported}, 79 } 80 if target.OS == "akaros" || target.OS == "test" { 81 return res, nil 82 } 83 for n, check := range checkFeature { 84 if check == nil { 85 continue 86 } 87 if reason := check(); reason == "" { 88 res[n].Enabled = true 89 res[n].Reason = "enabled" 90 } else { 91 res[n].Reason = reason 92 } 93 } 94 return res, nil 95} 96 97// Setup enables and does any one-time setup for the requested features on the host. 98// Note: this can be called multiple times and must be idempotent. 99func Setup(target *prog.Target, features *Features) (func(), error) { 100 if target.OS == "akaros" || target.OS == "test" { 101 return nil, nil 102 } 103 var callback func() 104 for n, setup := range setupFeature { 105 if setup == nil || !features[n].Enabled { 106 continue 107 } 108 if err := setup(); err != nil { 109 return nil, err 110 } 111 cb := callbFeature[n] 112 if cb != nil { 113 prev := callback 114 callback = func() { 115 cb() 116 if prev != nil { 117 prev() 118 } 119 } 120 121 } 122 } 123 return callback, nil 124} 125