1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
|
// Copyright 2018 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
package host
import (
"time"
"github.com/google/syzkaller/pkg/csource"
"github.com/google/syzkaller/pkg/log"
"github.com/google/syzkaller/pkg/osutil"
"github.com/google/syzkaller/prog"
)
// DetectSupportedSyscalls returns list on supported and unsupported syscalls on the host.
// For unsupported syscalls it also returns reason as to why it is unsupported.
func DetectSupportedSyscalls(target *prog.Target, sandbox string) (
map[*prog.Syscall]bool, map[*prog.Syscall]string, error) {
log.Logf(1, "detecting supported syscalls")
supported := make(map[*prog.Syscall]bool)
unsupported := make(map[*prog.Syscall]string)
// Akaros does not have own host and parasitizes on some other OS.
if target.OS == "akaros" || target.OS == "test" {
for _, c := range target.Syscalls {
supported[c] = true
}
return supported, unsupported, nil
}
for _, c := range target.Syscalls {
ok, reason := false, ""
switch c.CallName {
case "syz_execute_func":
// syz_execute_func caused multiple problems:
// 1. First it lead to corpus exploision. The program used existing values in registers
// to pollute output area. We tried to zero registers (though, not reliably).
// 2. It lead to explosion again. The exact mechanics are unknown, here is one sample:
// syz_execute_func(&(0x7f0000000440)="f2af91930f0124eda133fa20430fbafce842f66188d0d4
// 430fc7f314c1ab5bf9e2f9660f3a0fae5e090000ba023c1fb63ac4817d73d74ec482310d46f44
// 9f216c863fa438036a91bdbae95aaaa420f383c02c401405c6bfd49d768d768f833fefbab6464
// 660f38323c8f26dbc1a1fe5ff6f6df0804f4c4efa59c0f01c4288ba6452e000054c4431d5cc100")
// 3. The code can also execute syscalls (and it is know to), but it's not subject to
// target.SanitizeCall. As the result it can do things that programs are not supposed to do.
// 4. Besides linux, corpus explosion also happens on freebsd and is clearly attributable
// to syz_execute_func based on corpus contents. Mechanics are also not known.
// It also did not cause finding of any new bugs (at least not that I know of).
// Let's disable it for now until we figure out how to resolve all these problems.
ok = false
reason = "always disabled for now"
default:
ok, reason = isSupported(c, target, sandbox)
}
if ok {
supported[c] = true
} else {
if reason == "" {
reason = "unknown"
}
unsupported[c] = reason
}
}
return supported, unsupported, nil
}
var testFallback = false
const (
FeatureCoverage = iota
FeatureComparisons
FeatureExtraCoverage
FeatureSandboxSetuid
FeatureSandboxNamespace
FeatureSandboxAndroidUntrustedApp
FeatureFaultInjection
FeatureLeakChecking
FeatureNetworkInjection
FeatureNetworkDevices
numFeatures
)
type Feature struct {
Name string
Enabled bool
Reason string
}
type Features [numFeatures]Feature
var checkFeature [numFeatures]func() string
func unconditionallyEnabled() string { return "" }
// Check detects features supported on the host.
// Empty string for a feature means the feature is supported,
// otherwise the string contains the reason why the feature is not supported.
func Check(target *prog.Target) (*Features, error) {
const unsupported = "support is not implemented in syzkaller"
res := &Features{
FeatureCoverage: {Name: "code coverage", Reason: unsupported},
FeatureComparisons: {Name: "comparison tracing", Reason: unsupported},
FeatureExtraCoverage: {Name: "extra coverage", Reason: unsupported},
FeatureSandboxSetuid: {Name: "setuid sandbox", Reason: unsupported},
FeatureSandboxNamespace: {Name: "namespace sandbox", Reason: unsupported},
FeatureSandboxAndroidUntrustedApp: {Name: "Android sandbox", Reason: unsupported},
FeatureFaultInjection: {Name: "fault injection", Reason: unsupported},
FeatureLeakChecking: {Name: "leak checking", Reason: unsupported},
FeatureNetworkInjection: {Name: "net packet injection", Reason: unsupported},
FeatureNetworkDevices: {Name: "net device setup", Reason: unsupported},
}
if target.OS == "akaros" || target.OS == "test" {
return res, nil
}
for n, check := range checkFeature {
if check == nil {
continue
}
if reason := check(); reason == "" {
res[n].Enabled = true
res[n].Reason = "enabled"
} else {
res[n].Reason = reason
}
}
return res, nil
}
// Setup enables and does any one-time setup for the requested features on the host.
// Note: this can be called multiple times and must be idempotent.
func Setup(target *prog.Target, features *Features, featureFlags csource.Features, executor string) error {
if target.OS == "akaros" {
return nil
}
args := []string{"setup"}
if features[FeatureLeakChecking].Enabled {
args = append(args, "leak")
}
if features[FeatureFaultInjection].Enabled {
args = append(args, "fault")
}
if target.OS == "linux" && featureFlags["binfmt_misc"].Enabled {
args = append(args, "binfmt_misc")
}
_, err := osutil.RunCmd(time.Minute, "", executor, args...)
return err
}
|