aboutsummaryrefslogtreecommitdiffstats
path: root/tools/syz-prog2c/prog2c.go
blob: f5402041d30ce4fe0028b7dcb5a4a642c9e1aa77 (plain)
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
// Copyright 2015 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 main

import (
	"flag"
	"fmt"
	"log"
	"os"
	"runtime"

	"github.com/google/syzkaller/pkg/csource"
	"github.com/google/syzkaller/pkg/kfuzztest"
	"github.com/google/syzkaller/prog"
	_ "github.com/google/syzkaller/sys"
)

var (
	flagOS         = flag.String("os", runtime.GOOS, "target os")
	flagArch       = flag.String("arch", runtime.GOARCH, "target arch")
	flagBuild      = flag.Bool("build", false, "also build the generated program")
	flagThreaded   = flag.Bool("threaded", false, "create threaded program")
	flagRepeat     = flag.Int("repeat", 1, "repeat program that many times (<=0 - infinitely)")
	flagProcs      = flag.Int("procs", 1, "number of parallel processes")
	flagSlowdown   = flag.Int("slowdown", 1, "execution slowdown caused by emulation/instrumentation")
	flagSandbox    = flag.String("sandbox", "", "sandbox to use (none, setuid, namespace, android)")
	flagSandboxArg = flag.Int("sandbox_arg", 0, "argument for executor to customize its behavior")
	flagProg       = flag.String("prog", "", "file with program to convert (required)")
	flagHandleSegv = flag.Bool("segv", false, "catch and ignore SIGSEGV")
	flagUseTmpDir  = flag.Bool("tmpdir", false, "create a temporary dir and execute inside it")
	flagTrace      = flag.Bool("trace", false, "trace syscall results")
	flagStrict     = flag.Bool("strict", false, "parse input program in strict mode")
	flagLeak       = flag.Bool("leak", false, "do leak checking")
	flagEnable     = flag.String("enable", "none", "enable only listed additional features")
	flagDisable    = flag.String("disable", "none", "enable all additional features except listed")
	flagVmlinux    = flag.String("vmlinux", "", "path to vmlinux binary (required for dynamically discovered calls")
)

func main() {
	flag.Usage = func() {
		flag.PrintDefaults()
		csource.PrintAvailableFeaturesFlags()
	}
	flag.Parse()
	if *flagProg == "" {
		flag.Usage()
		os.Exit(1)
	}
	features, err := csource.ParseFeaturesFlags(*flagEnable, *flagDisable, false)
	if err != nil {
		log.Fatalf("%v", err)
	}
	target, err := prog.GetTarget(*flagOS, *flagArch)
	if err != nil {
		fmt.Fprintf(os.Stderr, "%v\n", err)
		os.Exit(1)
	}
	if *flagVmlinux != "" {
		_, err = kfuzztest.ActivateKFuzzTargets(target, *flagVmlinux)
		if err != nil {
			fmt.Fprintf(os.Stderr, "%v\n", err)
			os.Exit(1)
		}
	}
	data, err := os.ReadFile(*flagProg)
	if err != nil {
		fmt.Fprintf(os.Stderr, "failed to read prog file: %v\n", err)
		os.Exit(1)
	}
	mode := prog.NonStrict
	if *flagStrict {
		mode = prog.Strict
	}
	p, err := target.Deserialize(data, mode)
	if err != nil {
		fmt.Fprintf(os.Stderr, "failed to deserialize the program: %v\n", err)
		os.Exit(1)
	}
	opts := csource.Options{
		Threaded:      *flagThreaded,
		Repeat:        *flagRepeat != 1,
		RepeatTimes:   *flagRepeat,
		Procs:         *flagProcs,
		Slowdown:      *flagSlowdown,
		Sandbox:       *flagSandbox,
		SandboxArg:    *flagSandboxArg,
		Leak:          *flagLeak,
		NetInjection:  features["tun"].Enabled,
		NetDevices:    features["net_dev"].Enabled,
		NetReset:      features["net_reset"].Enabled,
		Cgroups:       features["cgroups"].Enabled,
		BinfmtMisc:    features["binfmt_misc"].Enabled,
		CloseFDs:      features["close_fds"].Enabled,
		KCSAN:         features["kcsan"].Enabled,
		DevlinkPCI:    features["devlink_pci"].Enabled,
		NicVF:         features["nic_vf"].Enabled,
		USB:           features["usb"].Enabled,
		VhciInjection: features["vhci"].Enabled,
		Wifi:          features["wifi"].Enabled,
		IEEE802154:    features["ieee802154"].Enabled,
		Sysctl:        features["sysctl"].Enabled,
		Swap:          features["swap"].Enabled,
		UseTmpDir:     *flagUseTmpDir,
		HandleSegv:    *flagHandleSegv,
		Trace:         *flagTrace,
		CallComments:  true,
	}
	src, err := csource.Write(p, opts)
	if err != nil {
		fmt.Fprintf(os.Stderr, "failed to generate C source: %v\n", err)
		os.Exit(1)
	}
	if formatted, err := csource.Format(src); err != nil {
		fmt.Fprintf(os.Stderr, "%v\n", err)
	} else {
		src = formatted
	}
	os.Stdout.Write(src)
	if !*flagBuild {
		return
	}
	bin, err := csource.Build(target, src)
	if err != nil {
		fmt.Fprintf(os.Stderr, "failed to build C source: %v\n", err)
		os.Exit(1)
	}
	os.Remove(bin)
	fmt.Fprintf(os.Stderr, "binary build OK\n")
}