From e503f048b0f40379900055c31da154292d105791 Mon Sep 17 00:00:00 2001 From: Dmitry Vyukov Date: Tue, 21 May 2019 11:47:51 +0200 Subject: docs: don't duplicate manager config parameters Currently we have them duplicated in docs/configuration.md and the actual source in pkg/mgrconfig/config.go. Documentation is missing in one place or another, some is outdated, some is phrased slightly differently. Move all docs to pkg/mgrconfig/config.go and reference it from docs/configuration.md instead. --- docs/configuration.md | 47 +------ pkg/mgrconfig/config.go | 99 ++++++++++++++ pkg/mgrconfig/load.go | 236 +++++++++++++++++++++++++++++++++ pkg/mgrconfig/mgrconfig.go | 315 --------------------------------------------- vm/qemu/qemu.go | 16 ++- 5 files changed, 349 insertions(+), 364 deletions(-) create mode 100644 pkg/mgrconfig/config.go create mode 100644 pkg/mgrconfig/load.go delete mode 100644 pkg/mgrconfig/mgrconfig.go diff --git a/docs/configuration.md b/docs/configuration.md index bb793a153..7e4dbc302 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -1,45 +1,6 @@ # Configuration -The operation of the syzkaller `syz-manager` process is governed by a configuration file, passed at -invocation time with the `-config` option. This configuration can be based on the -[example](/pkg/mgrconfig/testdata/qemu.cfg); the file is in JSON format with the -following keys in its top-level object: - - - `http`: URL that will display information about the running `syz-manager` process. - - `email_addrs`: Optional list of email addresses to receive notifications when bugs are encountered for the first time. - Mailx is the only supported mailer. Please set it up prior to using this function. - - `workdir`: Location of a working directory for the `syz-manager` process. Outputs here include: - - `/crashes/*`: crash output files (see [Crash Reports](#crash-reports)) - - `/corpus.db`: corpus with interesting programs - - `/instance-x`: per VM instance temporary files - - `syzkaller`: Location of the `syzkaller` checkout, `syz-manager` will look - for binaries in `bin` subdir (does not have to be `syzkaller` checkout as - long as it preserves `bin` dir structure) - - `kernel_obj`: Directory with object files (e.g. `vmlinux` for linux) - (used for report symbolization and coverage reports, optional). - - `procs`: Number of parallel test processes in each VM (4 or 8 would be a reasonable number). - - `image`: Location of the disk image file for the QEMU instance; a copy of this file is passed as the - `-hda` option to `qemu-system-x86_64`. - - `sshkey`: Location (on the host machine) of a root SSH identity to use for communicating with - the virtual machine. - - `sandbox` : Sandboxing mode, the following modes are supported: - - "none": don't do anything special (has false positives, e.g. due to killing init), default - - "setuid": impersonate into user nobody (65534) - - "namespace": use namespaces to drop privileges - (requires a kernel built with `CONFIG_NAMESPACES`, `CONFIG_UTS_NS`, - `CONFIG_USER_NS`, `CONFIG_PID_NS` and `CONFIG_NET_NS`) - - `enable_syscalls`: List of syscalls to test (optional). - - `disable_syscalls`: List of system calls that should be treated as disabled (optional). - - `suppressions`: List of regexps for known bugs. - - `type`: Type of virtual machine to use, e.g. `qemu` or `adb`. - - `vm`: object with VM-type-specific parameters; for example, for `qemu` type paramters include: - - `count`: Number of VMs to run in parallel. - - `kernel`: Location of the `bzImage` file for the kernel to be tested; - this is passed as the `-kernel` option to `qemu-system-x86_64`. - - `cmdline`: Additional command line options for the booting kernel, for example `root=/dev/sda1`. - - `cpu`: Number of CPUs to simulate in the VM (*not currently used*). - - `mem`: Amount of memory (in MiB) for the VM; this is passed as the `-m` option to `qemu-system-x86_64`. - -See also: - - [config.go](/pkg/mgrconfig/mgrconfig.go) for all config parameters; - - [qemu.go](/vm/qemu/qemu.go) for all vm parameters. +The operation of the syzkaller `syz-manager` process is governed by a +configuration file, passed at invocation time with the `-config` option. +This configuration can be based on the [example](/pkg/mgrconfig/testdata/qemu.cfg); +the file is in JSON format and contains the the [following parameters](/pkg/mgrconfig/config.go). diff --git a/pkg/mgrconfig/config.go b/pkg/mgrconfig/config.go new file mode 100644 index 000000000..48609d5c4 --- /dev/null +++ b/pkg/mgrconfig/config.go @@ -0,0 +1,99 @@ +// 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 mgrconfig + +import "encoding/json" + +type Config struct { + // Instance name (used for identification and as GCE instance prefix). + Name string `json:"name"` + // Target OS/arch, e.g. "linux/arm64" or "linux/amd64/386" (amd64 OS with 386 test process). + Target string `json:"target"` + // URL that will display information about the running syz-manager process (e.g. "localhost:50000"). + HTTP string `json:"http"` + // TCP address to serve RPC for fuzzer processes (optional). + RPC string `json:"rpc,omitempty"` + // Location of a working directory for the syz-manager process. Outputs here include: + // - /crashes/*: crash output files + // - /corpus.db: corpus with interesting programs + // - /instance-x: per VM instance temporary files + Workdir string `json:"workdir"` + // Directory with kernel object files (e.g. `vmlinux` for linux) + // (used for report symbolization and coverage reports, optional). + KernelObj string `json:"kernel_obj"` + // Kernel source directory (if not set defaults to KernelObj). + KernelSrc string `json:"kernel_src,omitempty"` + // Arbitrary optional tag that is saved along with crash reports (e.g. branch/commit). + Tag string `json:"tag,omitempty"` + // Location of the disk image file. + Image string `json:"image,omitempty"` + // Location (on the host machine) of a root SSH identity to use for communicating with + // the virtual machine (may be empty for some VM types). + SSHKey string `json:"sshkey,omitempty"` + // SSH user ("root" by default). + SSHUser string `json:"ssh_user,omitempty"` + + HubClient string `json:"hub_client,omitempty"` + HubAddr string `json:"hub_addr,omitempty"` + HubKey string `json:"hub_key,omitempty"` + + // List of email addresses to receive notifications when bugs are encountered for the first time (optional). + // Mailx is the only supported mailer. Please set it up prior to using this function. + EmailAddrs []string `json:"email_addrs,omitempty"` + + DashboardClient string `json:"dashboard_client,omitempty"` + DashboardAddr string `json:"dashboard_addr,omitempty"` + DashboardKey string `json:"dashboard_key,omitempty"` + + // Location of the syzkaller checkout, syz-manager will look + // for binaries in bin subdir (does not have to be syzkaller checkout as + // long as it preserves `bin` dir structure) + Syzkaller string `json:"syzkaller"` + + // Number of parallel test processes inside of each VM. + // 1 by default, 4 or 8 would be reasonable numbers too. + Procs int `json:"procs"` + + // Type of sandbox to use during fuzzing: + // "none": don't do anything special beyond resource sandboxing, default + // "setuid": impersonate into user nobody (65534). Supported only for some OSes. + // "namespace": create a new namespace for fuzzer using CLONE_NEWNS/CLONE_NEWNET/CLONE_NEWPID/etc, + // requires building kernel with CONFIG_NAMESPACES, CONFIG_UTS_NS, CONFIG_USER_NS, + // CONFIG_PID_NS and CONFIG_NET_NS. Supported only for some OSes. + // "android_untrusted_app": (Android) Emulate permissions of an untrusted app. + Sandbox string `json:"sandbox"` + + // Use KCOV coverage (default: true). + Cover bool `json:"cover"` + // Reproduce, localize and minimize crashers (default: true). + Reproduce bool `json:"reproduce"` + + // List of syscalls to test (optional). + EnabledSyscalls []string `json:"enable_syscalls,omitempty"` + // List of system calls that should be treated as disabled (optional). + DisabledSyscalls []string `json:"disable_syscalls,omitempty"` + // List of regexps for known bugs. + // Don't save reports matching these regexps, but reboot VM after them, + // matched against whole report output. + Suppressions []string `json:"suppressions,omitempty"` + // Completely ignore reports matching these regexps (don't save nor reboot), + // must match the first line of crash message. + Ignores []string `json:"ignores,omitempty"` + + // Type of virtual machine to use, e.g. "qemu", "gce", "android", "isolated", etc. + Type string `json:"type"` + // VM-type-specific parameters. + // Parameters for concrete types are in Config type in vm/TYPE/TYPE.go, e.g. vm/qemu/qemu.go. + VM json.RawMessage `json:"vm"` + + // Implementation details beyond this point. + // Parsed Target: + TargetOS string `json:"-"` + TargetArch string `json:"-"` + TargetVMArch string `json:"-"` + // Syzkaller binaries that we are going to use: + SyzFuzzerBin string `json:"-"` + SyzExecprogBin string `json:"-"` + SyzExecutorBin string `json:"-"` +} diff --git a/pkg/mgrconfig/load.go b/pkg/mgrconfig/load.go new file mode 100644 index 000000000..1fdcc0155 --- /dev/null +++ b/pkg/mgrconfig/load.go @@ -0,0 +1,236 @@ +// 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 mgrconfig + +import ( + "fmt" + "os" + "path/filepath" + "strings" + + "github.com/google/syzkaller/pkg/config" + "github.com/google/syzkaller/pkg/osutil" + "github.com/google/syzkaller/prog" + _ "github.com/google/syzkaller/sys" // most mgrconfig users want targets too + "github.com/google/syzkaller/sys/targets" +) + +func LoadData(data []byte) (*Config, error) { + cfg, err := LoadPartialData(data) + if err != nil { + return nil, err + } + if err := Complete(cfg); err != nil { + return nil, err + } + return cfg, nil +} + +func LoadFile(filename string) (*Config, error) { + cfg, err := LoadPartialFile(filename) + if err != nil { + return nil, err + } + if err := Complete(cfg); err != nil { + return nil, err + } + return cfg, nil +} + +func LoadPartialData(data []byte) (*Config, error) { + cfg := defaultValues() + if err := config.LoadData(data, cfg); err != nil { + return nil, err + } + return loadPartial(cfg) +} + +func LoadPartialFile(filename string) (*Config, error) { + cfg := defaultValues() + if err := config.LoadFile(filename, cfg); err != nil { + return nil, err + } + return loadPartial(cfg) +} + +func defaultValues() *Config { + return &Config{ + SSHUser: "root", + Cover: true, + Reproduce: true, + Sandbox: "none", + RPC: ":0", + Procs: 1, + } +} + +func loadPartial(cfg *Config) (*Config, error) { + var err error + cfg.TargetOS, cfg.TargetVMArch, cfg.TargetArch, err = splitTarget(cfg.Target) + if err != nil { + return nil, err + } + return cfg, nil +} + +func Complete(cfg *Config) error { + if cfg.TargetOS == "" || cfg.TargetVMArch == "" || cfg.TargetArch == "" { + return fmt.Errorf("target parameters are not filled in") + } + if cfg.Workdir == "" { + return fmt.Errorf("config param workdir is empty") + } + cfg.Workdir = osutil.Abs(cfg.Workdir) + if cfg.Syzkaller == "" { + return fmt.Errorf("config param syzkaller is empty") + } + if err := completeBinaries(cfg); err != nil { + return err + } + if cfg.HTTP == "" { + return fmt.Errorf("config param http is empty") + } + if cfg.Type == "" { + return fmt.Errorf("config param type is empty") + } + if cfg.Procs < 1 || cfg.Procs > 32 { + return fmt.Errorf("bad config param procs: '%v', want [1, 32]", cfg.Procs) + } + switch cfg.Sandbox { + case "none", "setuid", "namespace", "android_untrusted_app": + default: + return fmt.Errorf("config param sandbox must contain one of none/setuid/namespace/android_untrusted_app") + } + if err := checkSSHParams(cfg); err != nil { + return err + } + + cfg.KernelObj = osutil.Abs(cfg.KernelObj) + if cfg.KernelSrc == "" { + cfg.KernelSrc = cfg.KernelObj // assume in-tree build by default + } + cfg.KernelSrc = osutil.Abs(cfg.KernelSrc) + if cfg.HubClient != "" && (cfg.Name == "" || cfg.HubAddr == "" || cfg.HubKey == "") { + return fmt.Errorf("hub_client is set, but name/hub_addr/hub_key is empty") + } + if cfg.DashboardClient != "" && (cfg.Name == "" || + cfg.DashboardAddr == "" || + cfg.DashboardKey == "") { + return fmt.Errorf("dashboard_client is set, but name/dashboard_addr/dashboard_key is empty") + } + + return nil +} + +func checkSSHParams(cfg *Config) error { + if cfg.SSHUser == "" { + return fmt.Errorf("bad config syzkaller param: ssh user is empty") + } + if cfg.SSHKey == "" { + return nil + } + info, err := os.Stat(cfg.SSHKey) + if err != nil { + return err + } + if info.Mode()&0077 != 0 { + return fmt.Errorf("sshkey %v is unprotected, ssh will reject it, do chmod 0600", cfg.SSHKey) + } + return nil +} + +func completeBinaries(cfg *Config) error { + sysTarget := targets.Get(cfg.TargetOS, cfg.TargetArch) + if sysTarget == nil { + return fmt.Errorf("unsupported OS/arch: %v/%v", cfg.TargetOS, cfg.TargetArch) + } + cfg.Syzkaller = osutil.Abs(cfg.Syzkaller) + exe := sysTarget.ExeExtension + targetBin := func(name, arch string) string { + return filepath.Join(cfg.Syzkaller, "bin", cfg.TargetOS+"_"+arch, name+exe) + } + cfg.SyzFuzzerBin = targetBin("syz-fuzzer", cfg.TargetVMArch) + cfg.SyzExecprogBin = targetBin("syz-execprog", cfg.TargetVMArch) + cfg.SyzExecutorBin = targetBin("syz-executor", cfg.TargetArch) + if !osutil.IsExist(cfg.SyzFuzzerBin) { + return fmt.Errorf("bad config syzkaller param: can't find %v", cfg.SyzFuzzerBin) + } + if !osutil.IsExist(cfg.SyzExecprogBin) { + return fmt.Errorf("bad config syzkaller param: can't find %v", cfg.SyzExecprogBin) + } + if !osutil.IsExist(cfg.SyzExecutorBin) { + return fmt.Errorf("bad config syzkaller param: can't find %v", cfg.SyzExecutorBin) + } + return nil +} + +func splitTarget(target string) (string, string, string, error) { + if target == "" { + return "", "", "", fmt.Errorf("target is empty") + } + targetParts := strings.Split(target, "/") + if len(targetParts) != 2 && len(targetParts) != 3 { + return "", "", "", fmt.Errorf("bad config param target") + } + os := targetParts[0] + vmarch := targetParts[1] + arch := targetParts[1] + if len(targetParts) == 3 { + arch = targetParts[2] + } + return os, vmarch, arch, nil +} + +func ParseEnabledSyscalls(target *prog.Target, enabled, disabled []string) ([]int, error) { + syscalls := make(map[int]bool) + if len(enabled) != 0 { + for _, c := range enabled { + n := 0 + for _, call := range target.Syscalls { + if matchSyscall(call.Name, c) { + syscalls[call.ID] = true + n++ + } + } + if n == 0 { + return nil, fmt.Errorf("unknown enabled syscall: %v", c) + } + } + } else { + for _, call := range target.Syscalls { + syscalls[call.ID] = true + } + } + for _, c := range disabled { + n := 0 + for _, call := range target.Syscalls { + if matchSyscall(call.Name, c) { + delete(syscalls, call.ID) + n++ + } + } + if n == 0 { + return nil, fmt.Errorf("unknown disabled syscall: %v", c) + } + } + if len(syscalls) == 0 { + return nil, fmt.Errorf("all syscalls are disabled by disable_syscalls in config") + } + var arr []int + for id := range syscalls { + arr = append(arr, id) + } + return arr, nil +} + +func matchSyscall(name, pattern string) bool { + if pattern == name || strings.HasPrefix(name, pattern+"$") { + return true + } + if len(pattern) > 1 && pattern[len(pattern)-1] == '*' && + strings.HasPrefix(name, pattern[:len(pattern)-1]) { + return true + } + return false +} diff --git a/pkg/mgrconfig/mgrconfig.go b/pkg/mgrconfig/mgrconfig.go deleted file mode 100644 index e4c9efc0b..000000000 --- a/pkg/mgrconfig/mgrconfig.go +++ /dev/null @@ -1,315 +0,0 @@ -// 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 mgrconfig - -import ( - "encoding/json" - "fmt" - "os" - "path/filepath" - "strings" - - "github.com/google/syzkaller/pkg/config" - "github.com/google/syzkaller/pkg/osutil" - "github.com/google/syzkaller/prog" - _ "github.com/google/syzkaller/sys" // most mgrconfig users want targets too - "github.com/google/syzkaller/sys/targets" -) - -type Config struct { - // Instance name (used for identification and as GCE instance prefix). - Name string `json:"name"` - // Target OS/arch, e.g. "linux/arm64" or "linux/amd64/386" (amd64 OS with 386 test process). - Target string `json:"target"` - // TCP address to serve HTTP stats page (e.g. "localhost:50000"). - HTTP string `json:"http"` - // TCP address to serve RPC for fuzzer processes (optional). - RPC string `json:"rpc,omitempty"` - Workdir string `json:"workdir"` - // Directory with kernel object files. - KernelObj string `json:"kernel_obj"` - // Kernel source directory (if not set defaults to KernelObj). - KernelSrc string `json:"kernel_src,omitempty"` - // Arbitrary optional tag that is saved along with crash reports (e.g. branch/commit). - Tag string `json:"tag,omitempty"` - // Linux image for VMs. - Image string `json:"image,omitempty"` - // SSH key for the image (may be empty for some VM types). - SSHKey string `json:"sshkey,omitempty"` - // SSH user ("root" by default). - SSHUser string `json:"ssh_user,omitempty"` - - HubClient string `json:"hub_client,omitempty"` - HubAddr string `json:"hub_addr,omitempty"` - HubKey string `json:"hub_key,omitempty"` - - // syz-manager will send crash emails to this list of emails using mailx (optional). - EmailAddrs []string `json:"email_addrs,omitempty"` - - DashboardClient string `json:"dashboard_client,omitempty"` - DashboardAddr string `json:"dashboard_addr,omitempty"` - DashboardKey string `json:"dashboard_key,omitempty"` - - // Path to syzkaller checkout (syz-manager will look for binaries in bin subdir). - Syzkaller string `json:"syzkaller"` - // Number of parallel processes inside of every VM. - Procs int `json:"procs"` - - // Type of sandbox to use during fuzzing: - // "none": don't do anything special (has false positives, e.g. due to killing init), default - // "setuid": impersonate into user nobody (65534) - // "namespace": create a new namespace for fuzzer using CLONE_NEWNS/CLONE_NEWNET/CLONE_NEWPID/etc, - // requires building kernel with CONFIG_NAMESPACES, CONFIG_UTS_NS, CONFIG_USER_NS, - // CONFIG_PID_NS and CONFIG_NET_NS. - // "android_untrusted_app": (Android) Emulate permissions of an untrusted app - Sandbox string `json:"sandbox"` - - // Use KCOV coverage (default: true). - Cover bool `json:"cover"` - // Reproduce, localize and minimize crashers (default: true). - Reproduce bool `json:"reproduce"` - - EnabledSyscalls []string `json:"enable_syscalls,omitempty"` - DisabledSyscalls []string `json:"disable_syscalls,omitempty"` - // Don't save reports matching these regexps, but reboot VM after them, - // matched against whole report output. - Suppressions []string `json:"suppressions,omitempty"` - // Completely ignore reports matching these regexps (don't save nor reboot), - // must match the first line of crash message. - Ignores []string `json:"ignores,omitempty"` - - // VM type (qemu, gce, android, isolated, etc). - Type string `json:"type"` - // VM-type-specific config. - VM json.RawMessage `json:"vm"` - - // Implementation details beyond this point. - // Parsed Target: - TargetOS string `json:"-"` - TargetArch string `json:"-"` - TargetVMArch string `json:"-"` - // Syzkaller binaries that we are going to use: - SyzFuzzerBin string `json:"-"` - SyzExecprogBin string `json:"-"` - SyzExecutorBin string `json:"-"` -} - -func LoadData(data []byte) (*Config, error) { - cfg, err := LoadPartialData(data) - if err != nil { - return nil, err - } - if err := Complete(cfg); err != nil { - return nil, err - } - return cfg, nil -} - -func LoadFile(filename string) (*Config, error) { - cfg, err := LoadPartialFile(filename) - if err != nil { - return nil, err - } - if err := Complete(cfg); err != nil { - return nil, err - } - return cfg, nil -} - -func LoadPartialData(data []byte) (*Config, error) { - cfg := defaultValues() - if err := config.LoadData(data, cfg); err != nil { - return nil, err - } - return loadPartial(cfg) -} - -func LoadPartialFile(filename string) (*Config, error) { - cfg := defaultValues() - if err := config.LoadFile(filename, cfg); err != nil { - return nil, err - } - return loadPartial(cfg) -} - -func defaultValues() *Config { - return &Config{ - SSHUser: "root", - Cover: true, - Reproduce: true, - Sandbox: "none", - RPC: ":0", - Procs: 1, - } -} - -func loadPartial(cfg *Config) (*Config, error) { - var err error - cfg.TargetOS, cfg.TargetVMArch, cfg.TargetArch, err = splitTarget(cfg.Target) - if err != nil { - return nil, err - } - return cfg, nil -} - -func Complete(cfg *Config) error { - if cfg.TargetOS == "" || cfg.TargetVMArch == "" || cfg.TargetArch == "" { - return fmt.Errorf("target parameters are not filled in") - } - if cfg.Workdir == "" { - return fmt.Errorf("config param workdir is empty") - } - cfg.Workdir = osutil.Abs(cfg.Workdir) - if cfg.Syzkaller == "" { - return fmt.Errorf("config param syzkaller is empty") - } - if err := completeBinaries(cfg); err != nil { - return err - } - if cfg.HTTP == "" { - return fmt.Errorf("config param http is empty") - } - if cfg.Type == "" { - return fmt.Errorf("config param type is empty") - } - if cfg.Procs < 1 || cfg.Procs > 32 { - return fmt.Errorf("bad config param procs: '%v', want [1, 32]", cfg.Procs) - } - switch cfg.Sandbox { - case "none", "setuid", "namespace", "android_untrusted_app": - default: - return fmt.Errorf("config param sandbox must contain one of none/setuid/namespace/android_untrusted_app") - } - if err := checkSSHParams(cfg); err != nil { - return err - } - - cfg.KernelObj = osutil.Abs(cfg.KernelObj) - if cfg.KernelSrc == "" { - cfg.KernelSrc = cfg.KernelObj // assume in-tree build by default - } - cfg.KernelSrc = osutil.Abs(cfg.KernelSrc) - if cfg.HubClient != "" && (cfg.Name == "" || cfg.HubAddr == "" || cfg.HubKey == "") { - return fmt.Errorf("hub_client is set, but name/hub_addr/hub_key is empty") - } - if cfg.DashboardClient != "" && (cfg.Name == "" || - cfg.DashboardAddr == "" || - cfg.DashboardKey == "") { - return fmt.Errorf("dashboard_client is set, but name/dashboard_addr/dashboard_key is empty") - } - - return nil -} - -func checkSSHParams(cfg *Config) error { - if cfg.SSHUser == "" { - return fmt.Errorf("bad config syzkaller param: ssh user is empty") - } - if cfg.SSHKey == "" { - return nil - } - info, err := os.Stat(cfg.SSHKey) - if err != nil { - return err - } - if info.Mode()&0077 != 0 { - return fmt.Errorf("sshkey %v is unprotected, ssh will reject it, do chmod 0600", cfg.SSHKey) - } - return nil -} - -func completeBinaries(cfg *Config) error { - sysTarget := targets.Get(cfg.TargetOS, cfg.TargetArch) - if sysTarget == nil { - return fmt.Errorf("unsupported OS/arch: %v/%v", cfg.TargetOS, cfg.TargetArch) - } - cfg.Syzkaller = osutil.Abs(cfg.Syzkaller) - exe := sysTarget.ExeExtension - targetBin := func(name, arch string) string { - return filepath.Join(cfg.Syzkaller, "bin", cfg.TargetOS+"_"+arch, name+exe) - } - cfg.SyzFuzzerBin = targetBin("syz-fuzzer", cfg.TargetVMArch) - cfg.SyzExecprogBin = targetBin("syz-execprog", cfg.TargetVMArch) - cfg.SyzExecutorBin = targetBin("syz-executor", cfg.TargetArch) - if !osutil.IsExist(cfg.SyzFuzzerBin) { - return fmt.Errorf("bad config syzkaller param: can't find %v", cfg.SyzFuzzerBin) - } - if !osutil.IsExist(cfg.SyzExecprogBin) { - return fmt.Errorf("bad config syzkaller param: can't find %v", cfg.SyzExecprogBin) - } - if !osutil.IsExist(cfg.SyzExecutorBin) { - return fmt.Errorf("bad config syzkaller param: can't find %v", cfg.SyzExecutorBin) - } - return nil -} - -func splitTarget(target string) (string, string, string, error) { - if target == "" { - return "", "", "", fmt.Errorf("target is empty") - } - targetParts := strings.Split(target, "/") - if len(targetParts) != 2 && len(targetParts) != 3 { - return "", "", "", fmt.Errorf("bad config param target") - } - os := targetParts[0] - vmarch := targetParts[1] - arch := targetParts[1] - if len(targetParts) == 3 { - arch = targetParts[2] - } - return os, vmarch, arch, nil -} - -func ParseEnabledSyscalls(target *prog.Target, enabled, disabled []string) ([]int, error) { - syscalls := make(map[int]bool) - if len(enabled) != 0 { - for _, c := range enabled { - n := 0 - for _, call := range target.Syscalls { - if matchSyscall(call.Name, c) { - syscalls[call.ID] = true - n++ - } - } - if n == 0 { - return nil, fmt.Errorf("unknown enabled syscall: %v", c) - } - } - } else { - for _, call := range target.Syscalls { - syscalls[call.ID] = true - } - } - for _, c := range disabled { - n := 0 - for _, call := range target.Syscalls { - if matchSyscall(call.Name, c) { - delete(syscalls, call.ID) - n++ - } - } - if n == 0 { - return nil, fmt.Errorf("unknown disabled syscall: %v", c) - } - } - if len(syscalls) == 0 { - return nil, fmt.Errorf("all syscalls are disabled by disable_syscalls in config") - } - var arr []int - for id := range syscalls { - arr = append(arr, id) - } - return arr, nil -} - -func matchSyscall(name, pattern string) bool { - if pattern == name || strings.HasPrefix(name, pattern+"$") { - return true - } - if len(pattern) > 1 && pattern[len(pattern)-1] == '*' && - strings.HasPrefix(name, pattern[:len(pattern)-1]) { - return true - } - return false -} diff --git a/vm/qemu/qemu.go b/vm/qemu/qemu.go index f3332e57e..6609a61a5 100644 --- a/vm/qemu/qemu.go +++ b/vm/qemu/qemu.go @@ -28,15 +28,19 @@ func init() { } type Config struct { - Count int `json:"count"` // number of VMs to use - Qemu string `json:"qemu"` // qemu binary name (qemu-system-arch by default) - QemuArgs string `json:"qemu_args"` // additional command line arguments for qemu binary - Kernel string `json:"kernel"` // kernel for injected boot (e.g. arch/x86/boot/bzImage) - Cmdline string `json:"cmdline"` // kernel command line (can only be specified with kernel) + Count int `json:"count"` // number of VMs to run in parallel + Qemu string `json:"qemu"` // qemu binary name (qemu-system-arch by default) + QemuArgs string `json:"qemu_args"` // additional command line arguments for qemu binary + // Location of the kernel for injected boot (e.g. arch/x86/boot/bzImage, optional). + // This is passed to qemu as the -kernel option. + Kernel string `json:"kernel"` + // Additional command line options for the booting kernel, for example `root=/dev/sda1`. + // Can only be specified with kernel. + Cmdline string `json:"cmdline"` Initrd string `json:"initrd"` // linux initial ramdisk. (optional) ImageDevice string `json:"image_device"` // qemu image device (hda by default) CPU int `json:"cpu"` // number of VM CPUs - Mem int `json:"mem"` // amount of VM memory in MBs + Mem int `json:"mem"` // amount of VM memory in MiB Snapshot bool `json:"snapshot"` // For building kernels without -snapshot (for pkg/build) } -- cgit mrf-deployment