// 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" "io/ioutil" "os" "runtime" "github.com/google/syzkaller/pkg/csource" "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") flagCollide = flag.Bool("collide", false, "create collide program") flagRepeat = flag.Int("repeat", 1, "repeat program that many times (<=0 - infinitely)") flagProcs = flag.Int("procs", 1, "number of parallel processes") flagSandbox = flag.String("sandbox", "", "sandbox to use (none, setuid, namespace)") flagProg = flag.String("prog", "", "file with program to convert (required)") flagFaultCall = flag.Int("fault_call", -1, "inject fault into this call (0-based)") flagFaultNth = flag.Int("fault_nth", 0, "inject fault on n-th operation (0-based)") flagEnableTun = flag.Bool("tun", false, "set up TUN/TAP interface") flagUseTmpDir = flag.Bool("tmpdir", false, "create a temporary dir and execute inside it") flagCgroups = flag.Bool("cgroups", false, "enable cgroups support") flagNetdev = flag.Bool("netdev", false, "setup various net devices") flagResetNet = flag.Bool("resetnet", false, "reset net namespace after each test") flagHandleSegv = flag.Bool("segv", false, "catch and ignore SIGSEGV") flagTrace = flag.Bool("trace", false, "trace syscall results") ) func main() { flag.Parse() if *flagProg == "" { flag.PrintDefaults() os.Exit(1) } target, err := prog.GetTarget(*flagOS, *flagArch) if err != nil { fmt.Fprintf(os.Stderr, "%v", err) os.Exit(1) } data, err := ioutil.ReadFile(*flagProg) if err != nil { fmt.Fprintf(os.Stderr, "failed to read prog file: %v\n", err) os.Exit(1) } p, err := target.Deserialize(data) if err != nil { fmt.Fprintf(os.Stderr, "failed to deserialize the program: %v\n", err) os.Exit(1) } opts := csource.Options{ Threaded: *flagThreaded, Collide: *flagCollide, Repeat: *flagRepeat != 1, RepeatTimes: *flagRepeat, Procs: *flagProcs, Sandbox: *flagSandbox, Fault: *flagFaultCall >= 0, FaultCall: *flagFaultCall, FaultNth: *flagFaultNth, EnableTun: *flagEnableTun, UseTmpDir: *flagUseTmpDir, EnableCgroups: *flagCgroups, EnableNetdev: *flagNetdev, ResetNet: *flagResetNet, HandleSegv: *flagHandleSegv, Repro: false, Trace: *flagTrace, } 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") }