2017-12-15 10:25:19 +00:00
|
|
|
// Copyright 2017 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.
|
|
|
|
|
2018-07-27 08:17:52 +00:00
|
|
|
//go:generate go run gen.go
|
2018-07-20 18:26:05 +00:00
|
|
|
|
2017-12-15 10:25:19 +00:00
|
|
|
package csource
|
|
|
|
|
|
|
|
import (
|
|
|
|
"bytes"
|
|
|
|
"fmt"
|
2019-05-18 15:54:03 +00:00
|
|
|
"regexp"
|
2019-03-07 19:36:03 +00:00
|
|
|
"runtime"
|
2018-08-02 14:50:09 +00:00
|
|
|
"sort"
|
2017-12-15 10:25:19 +00:00
|
|
|
"strings"
|
|
|
|
|
|
|
|
"github.com/google/syzkaller/pkg/osutil"
|
|
|
|
"github.com/google/syzkaller/prog"
|
|
|
|
"github.com/google/syzkaller/sys/targets"
|
|
|
|
)
|
|
|
|
|
2018-07-20 18:26:05 +00:00
|
|
|
const (
|
2019-03-07 01:32:44 +00:00
|
|
|
linux = "linux"
|
|
|
|
freebsd = "freebsd"
|
|
|
|
openbsd = "openbsd"
|
2019-08-21 14:13:43 +00:00
|
|
|
netbsd = "netbsd"
|
2018-07-20 18:26:05 +00:00
|
|
|
|
2019-11-14 17:56:34 +00:00
|
|
|
sandboxNone = "none"
|
|
|
|
sandboxSetuid = "setuid"
|
|
|
|
sandboxNamespace = "namespace"
|
|
|
|
sandboxAndroid = "android"
|
2018-07-20 18:26:05 +00:00
|
|
|
)
|
|
|
|
|
2018-07-26 15:47:27 +00:00
|
|
|
func createCommonHeader(p, mmapProg *prog.Prog, replacements map[string]string, opts Options) ([]byte, error) {
|
2018-08-02 14:50:09 +00:00
|
|
|
defines := defineList(p, mmapProg, opts)
|
2018-11-17 18:32:19 +00:00
|
|
|
sysTarget := targets.Get(p.Target.OS, p.Target.Arch)
|
|
|
|
cmd := osutil.Command(sysTarget.CPP, "-nostdinc", "-undef", "-fdirectives-only", "-dDI", "-E", "-P", "-")
|
2017-12-15 10:25:19 +00:00
|
|
|
for _, def := range defines {
|
|
|
|
cmd.Args = append(cmd.Args, "-D"+def)
|
|
|
|
}
|
|
|
|
cmd.Stdin = strings.NewReader(commonHeader)
|
|
|
|
stderr := new(bytes.Buffer)
|
|
|
|
stdout := new(bytes.Buffer)
|
|
|
|
cmd.Stderr = stderr
|
|
|
|
cmd.Stdout = stdout
|
2020-08-14 12:07:37 +00:00
|
|
|
// Note: we ignore error because we pass -nostdinc so there are lots of errors of the form:
|
|
|
|
// error: no include path in which to search for stdlib.h
|
|
|
|
// This is exactly what we want: we don't want these to be included into the C reproducer.
|
|
|
|
// But the downside is that we can miss some real errors, e.g.:
|
|
|
|
// error: missing binary operator before token "SYZ_SANDBOX_ANDROID"
|
|
|
|
// 3776 | #if not SYZ_SANDBOX_ANDROID
|
|
|
|
// Potentially we could analyze errors manually and ignore only the expected ones.
|
2017-12-15 10:25:19 +00:00
|
|
|
if err := cmd.Run(); len(stdout.Bytes()) == 0 {
|
2020-08-14 12:07:37 +00:00
|
|
|
return nil, fmt.Errorf("cpp failed: %v %v: %v\n%v\n%v", cmd.Path, cmd.Args, err, stdout.String(), stderr.String())
|
2017-12-15 10:25:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
src, err := removeSystemDefines(stdout.Bytes(), defines)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2017-12-27 09:56:12 +00:00
|
|
|
|
2018-07-26 15:47:27 +00:00
|
|
|
for from, to := range replacements {
|
2020-08-04 12:14:40 +00:00
|
|
|
src = bytes.Replace(src, []byte("/*{{{"+from+"}}}*/"), []byte(to), -1)
|
2018-07-26 15:47:27 +00:00
|
|
|
}
|
|
|
|
|
2017-12-27 09:56:12 +00:00
|
|
|
for from, to := range map[string]string{
|
|
|
|
"uint64": "uint64_t",
|
|
|
|
"uint32": "uint32_t",
|
|
|
|
"uint16": "uint16_t",
|
|
|
|
"uint8": "uint8_t",
|
|
|
|
} {
|
|
|
|
src = bytes.Replace(src, []byte(from), []byte(to), -1)
|
|
|
|
}
|
2019-05-18 15:54:03 +00:00
|
|
|
src = regexp.MustCompile("#define SYZ_HAVE_.*").ReplaceAll(src, nil)
|
2017-12-27 09:56:12 +00:00
|
|
|
|
2017-12-15 10:25:19 +00:00
|
|
|
return src, nil
|
|
|
|
}
|
|
|
|
|
2018-08-02 14:50:09 +00:00
|
|
|
func defineList(p, mmapProg *prog.Prog, opts Options) (defines []string) {
|
2019-11-14 17:36:26 +00:00
|
|
|
for def, ok := range commonDefines(p, opts) {
|
|
|
|
if ok {
|
|
|
|
defines = append(defines, def)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
for _, c := range p.Calls {
|
|
|
|
defines = append(defines, "__NR_"+c.Meta.CallName)
|
|
|
|
}
|
|
|
|
for _, c := range mmapProg.Calls {
|
|
|
|
defines = append(defines, "__NR_"+c.Meta.CallName)
|
|
|
|
}
|
|
|
|
sort.Strings(defines)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
func commonDefines(p *prog.Prog, opts Options) map[string]bool {
|
2018-08-02 14:50:09 +00:00
|
|
|
sysTarget := targets.Get(p.Target.OS, p.Target.Arch)
|
2018-02-18 13:16:07 +00:00
|
|
|
bitmasks, csums := prog.RequiredFeatures(p)
|
2019-11-14 17:36:26 +00:00
|
|
|
return map[string]bool{
|
2019-11-14 17:44:30 +00:00
|
|
|
"GOOS_" + p.Target.OS: true,
|
|
|
|
"GOARCH_" + p.Target.Arch: true,
|
|
|
|
"HOSTGOOS_" + runtime.GOOS: true,
|
|
|
|
"SYZ_USE_BITMASKS": bitmasks,
|
|
|
|
"SYZ_USE_CHECKSUMS": csums,
|
|
|
|
"SYZ_SANDBOX_NONE": opts.Sandbox == sandboxNone,
|
|
|
|
"SYZ_SANDBOX_SETUID": opts.Sandbox == sandboxSetuid,
|
|
|
|
"SYZ_SANDBOX_NAMESPACE": opts.Sandbox == sandboxNamespace,
|
2019-11-14 17:56:34 +00:00
|
|
|
"SYZ_SANDBOX_ANDROID": opts.Sandbox == sandboxAndroid,
|
2019-11-14 17:44:30 +00:00
|
|
|
"SYZ_THREADED": opts.Threaded,
|
|
|
|
"SYZ_COLLIDE": opts.Collide,
|
|
|
|
"SYZ_REPEAT": opts.Repeat,
|
|
|
|
"SYZ_REPEAT_TIMES": opts.RepeatTimes > 1,
|
|
|
|
"SYZ_MULTI_PROC": opts.Procs > 1,
|
|
|
|
"SYZ_FAULT": opts.Fault,
|
|
|
|
"SYZ_LEAK": opts.Leak,
|
2019-11-15 09:23:23 +00:00
|
|
|
"SYZ_NET_INJECTION": opts.NetInjection,
|
|
|
|
"SYZ_NET_DEVICES": opts.NetDevices,
|
|
|
|
"SYZ_NET_RESET": opts.NetReset,
|
|
|
|
"SYZ_CGROUPS": opts.Cgroups,
|
|
|
|
"SYZ_BINFMT_MISC": opts.BinfmtMisc,
|
|
|
|
"SYZ_CLOSE_FDS": opts.CloseFDs,
|
|
|
|
"SYZ_KCSAN": opts.KCSAN,
|
|
|
|
"SYZ_DEVLINK_PCI": opts.DevlinkPCI,
|
2020-04-01 17:37:07 +00:00
|
|
|
"SYZ_USB": opts.USB,
|
2020-07-30 09:33:48 +00:00
|
|
|
"SYZ_VHCI_INJECTION": opts.VhciInjection,
|
2019-11-14 17:44:30 +00:00
|
|
|
"SYZ_USE_TMP_DIR": opts.UseTmpDir,
|
|
|
|
"SYZ_HANDLE_SEGV": opts.HandleSegv,
|
|
|
|
"SYZ_REPRO": opts.Repro,
|
|
|
|
"SYZ_TRACE": opts.Trace,
|
2020-09-08 05:25:27 +00:00
|
|
|
"SYZ_WIFI": opts.Wifi,
|
2019-11-14 17:44:30 +00:00
|
|
|
"SYZ_EXECUTOR_USES_SHMEM": sysTarget.ExecutorUsesShmem,
|
|
|
|
"SYZ_EXECUTOR_USES_FORK_SERVER": sysTarget.ExecutorUsesForkServer,
|
2018-08-02 14:50:09 +00:00
|
|
|
}
|
2017-12-15 10:25:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func removeSystemDefines(src []byte, defines []string) ([]byte, error) {
|
2018-07-26 15:47:27 +00:00
|
|
|
remove := map[string]string{
|
|
|
|
"__STDC__": "1",
|
|
|
|
"__STDC_HOSTED__": "1",
|
|
|
|
"__STDC_UTF_16__": "1",
|
|
|
|
"__STDC_UTF_32__": "1",
|
|
|
|
}
|
|
|
|
for _, def := range defines {
|
|
|
|
eq := strings.IndexByte(def, '=')
|
|
|
|
if eq == -1 {
|
|
|
|
remove[def] = "1"
|
|
|
|
} else {
|
|
|
|
remove[def[:eq]] = def[eq+1:]
|
|
|
|
}
|
|
|
|
}
|
|
|
|
for def, val := range remove {
|
|
|
|
src = bytes.Replace(src, []byte("#define "+def+" "+val+"\n"), nil, -1)
|
2017-12-15 10:25:19 +00:00
|
|
|
}
|
|
|
|
// strip: #define __STDC_VERSION__ 201112L
|
|
|
|
for _, def := range []string{"__STDC_VERSION__"} {
|
|
|
|
pos := bytes.Index(src, []byte("#define "+def))
|
|
|
|
if pos == -1 {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
end := bytes.IndexByte(src[pos:], '\n')
|
|
|
|
if end == -1 {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
src = bytes.Replace(src, src[pos:end+1], nil, -1)
|
|
|
|
}
|
|
|
|
return src, nil
|
|
|
|
}
|