aboutsummaryrefslogtreecommitdiffstats
path: root/pkg/csource
diff options
context:
space:
mode:
authorAndrey Konovalov <andreyknvl@google.com>2019-02-05 16:19:34 +0100
committerAndrey Konovalov <andreyknvl@gmail.com>2019-03-05 14:30:10 +0100
commitdfd609eca1871f01757d6b04b19fc273c87c14e5 (patch)
treebd16e4561775f52e40f970a35a032f1f390171a9 /pkg/csource
parentc55829aef16e95df564cb23e700e5de8490229a0 (diff)
execprog, stress, prog2c: unify flags to enable additional features
This change makes all syz-execprog, syz-prog2c and syz-stress accept -enable and -disable flags to enable or disable additional features (tun, net_dev, net_reset, cgroups and binfmt_misc) instead of having a separate flag for each of them. The default (without any flags) behavior isn't changed: syz-execprog and syz-stress enabled all the features (provided the runtime supports them) and syz-prog2c disables all of them.
Diffstat (limited to 'pkg/csource')
-rw-r--r--pkg/csource/common.go5
-rw-r--r--pkg/csource/generated.go188
-rw-r--r--pkg/csource/options.go141
-rw-r--r--pkg/csource/options_test.go189
4 files changed, 355 insertions, 168 deletions
diff --git a/pkg/csource/common.go b/pkg/csource/common.go
index 9de387952..a39d714e0 100644
--- a/pkg/csource/common.go
+++ b/pkg/csource/common.go
@@ -82,8 +82,9 @@ func defineList(p, mmapProg *prog.Prog, opts Options) (defines []string) {
"SYZ_FAULT_INJECTION": opts.Fault,
"SYZ_TUN_ENABLE": opts.EnableTun,
"SYZ_ENABLE_CGROUPS": opts.EnableCgroups,
- "SYZ_ENABLE_NETDEV": opts.EnableNetdev,
- "SYZ_RESET_NET_NAMESPACE": opts.ResetNet,
+ "SYZ_ENABLE_NETDEV": opts.EnableNetDev,
+ "SYZ_RESET_NET_NAMESPACE": opts.EnableNetReset,
+ "SYZ_ENABLE_BINFMT_MISC": opts.EnableBinfmtMisc,
"SYZ_USE_TMP_DIR": opts.UseTmpDir,
"SYZ_HANDLE_SEGV": opts.HandleSegv,
"SYZ_REPRO": opts.Repro,
diff --git a/pkg/csource/generated.go b/pkg/csource/generated.go
index f58bf8e30..fbbd671bf 100644
--- a/pkg/csource/generated.go
+++ b/pkg/csource/generated.go
@@ -208,6 +208,7 @@ static int inject_fault(int nth)
return 0;
}
#endif
+
#if SYZ_EXECUTOR
static int fault_injected(int fail_fd)
{
@@ -1051,7 +1052,7 @@ static int event_timedwait(event_t* ev, uint64 timeout)
}
#endif
-#if SYZ_EXECUTOR || SYZ_FAULT_INJECTION || SYZ_ENABLE_CGROUPS || SYZ_SANDBOX_NONE || \
+#if SYZ_EXECUTOR || SYZ_REPEAT || SYZ_TUN_ENABLE || SYZ_FAULT_INJECTION || SYZ_SANDBOX_NONE || \
SYZ_SANDBOX_SETUID || SYZ_SANDBOX_NAMESPACE || SYZ_SANDBOX_ANDROID_UNTRUSTED_APP
#include <errno.h>
#include <fcntl.h>
@@ -3492,6 +3493,8 @@ static void reset_ebtables()
static void checkpoint_net_namespace(void)
{
#if SYZ_EXECUTOR
+ if (!flag_enable_net_reset)
+ return;
if (flag_sandbox == sandbox_setuid)
return;
#endif
@@ -3504,6 +3507,8 @@ static void checkpoint_net_namespace(void)
static void reset_net_namespace(void)
{
#if SYZ_EXECUTOR
+ if (!flag_enable_net_reset)
+ return;
if (flag_sandbox == sandbox_setuid)
return;
#endif
@@ -3514,7 +3519,7 @@ static void reset_net_namespace(void)
}
#endif
-#if SYZ_EXECUTOR || SYZ_ENABLE_CGROUPS
+#if SYZ_EXECUTOR || (SYZ_ENABLE_CGROUPS && (SYZ_SANDBOX_NONE || SYZ_SANDBOX_SETUID || SYZ_SANDBOX_NAMESPACE || SYZ_SANDBOX_ANDROID_UNTRUSTED_APP))
#include <fcntl.h>
#include <sys/mount.h>
#include <sys/stat.h>
@@ -3522,6 +3527,10 @@ static void reset_net_namespace(void)
static void setup_cgroups()
{
+#if SYZ_EXECUTOR
+ if (!flag_enable_cgroups)
+ return;
+#endif
if (mkdir("/syzcgroup", 0777)) {
debug("mkdir(/syzcgroup) failed: %d\n", errno);
}
@@ -3555,8 +3564,108 @@ static void setup_cgroups()
debug("chmod(/syzcgroup/net) failed: %d\n", errno);
}
}
+
+#if SYZ_EXECUTOR || SYZ_REPEAT
+static void setup_cgroups_loop()
+{
+#if SYZ_EXECUTOR
+ if (!flag_enable_cgroups)
+ return;
+#endif
+ int pid = getpid();
+ char file[128];
+ char cgroupdir[64];
+ snprintf(cgroupdir, sizeof(cgroupdir), "/syzcgroup/unified/syz%llu", procid);
+ if (mkdir(cgroupdir, 0777)) {
+ debug("mkdir(%s) failed: %d\n", cgroupdir, errno);
+ }
+ snprintf(file, sizeof(file), "%s/pids.max", cgroupdir);
+ write_file(file, "32");
+ snprintf(file, sizeof(file), "%s/memory.low", cgroupdir);
+ write_file(file, "%d", 298 << 20);
+ snprintf(file, sizeof(file), "%s/memory.high", cgroupdir);
+ write_file(file, "%d", 299 << 20);
+ snprintf(file, sizeof(file), "%s/memory.max", cgroupdir);
+ write_file(file, "%d", 300 << 20);
+ snprintf(file, sizeof(file), "%s/cgroup.procs", cgroupdir);
+ write_file(file, "%d", pid);
+ snprintf(cgroupdir, sizeof(cgroupdir), "/syzcgroup/cpu/syz%llu", procid);
+ if (mkdir(cgroupdir, 0777)) {
+ debug("mkdir(%s) failed: %d\n", cgroupdir, errno);
+ }
+ snprintf(file, sizeof(file), "%s/cgroup.procs", cgroupdir);
+ write_file(file, "%d", pid);
+ snprintf(cgroupdir, sizeof(cgroupdir), "/syzcgroup/net/syz%llu", procid);
+ if (mkdir(cgroupdir, 0777)) {
+ debug("mkdir(%s) failed: %d\n", cgroupdir, errno);
+ }
+ snprintf(file, sizeof(file), "%s/cgroup.procs", cgroupdir);
+ write_file(file, "%d", pid);
+}
+
+static void setup_cgroups_test()
+{
+#if SYZ_EXECUTOR
+ if (!flag_enable_cgroups)
+ return;
+#endif
+ char cgroupdir[64];
+ snprintf(cgroupdir, sizeof(cgroupdir), "/syzcgroup/unified/syz%llu", procid);
+ if (symlink(cgroupdir, "./cgroup")) {
+ debug("symlink(%s, ./cgroup) failed: %d\n", cgroupdir, errno);
+ }
+ snprintf(cgroupdir, sizeof(cgroupdir), "/syzcgroup/cpu/syz%llu", procid);
+ if (symlink(cgroupdir, "./cgroup.cpu")) {
+ debug("symlink(%s, ./cgroup.cpu) failed: %d\n", cgroupdir, errno);
+ }
+ snprintf(cgroupdir, sizeof(cgroupdir), "/syzcgroup/net/syz%llu", procid);
+ if (symlink(cgroupdir, "./cgroup.net")) {
+ debug("symlink(%s, ./cgroup.net) failed: %d\n", cgroupdir, errno);
+ }
+}
+#endif
+
+#if SYZ_EXECUTOR || SYZ_SANDBOX_NAMESPACE
+void initialize_cgroups()
+{
+#if SYZ_EXECUTOR
+ if (!flag_enable_cgroups)
+ return;
+#endif
+ if (mkdir("./syz-tmp/newroot/syzcgroup", 0700))
+ fail("mkdir failed");
+ if (mkdir("./syz-tmp/newroot/syzcgroup/unified", 0700))
+ fail("mkdir failed");
+ if (mkdir("./syz-tmp/newroot/syzcgroup/cpu", 0700))
+ fail("mkdir failed");
+ if (mkdir("./syz-tmp/newroot/syzcgroup/net", 0700))
+ fail("mkdir failed");
+ unsigned bind_mount_flags = MS_BIND | MS_REC | MS_PRIVATE;
+ if (mount("/syzcgroup/unified", "./syz-tmp/newroot/syzcgroup/unified", NULL, bind_mount_flags, NULL)) {
+ debug("mount(cgroup2, MS_BIND) failed: %d\n", errno);
+ }
+ if (mount("/syzcgroup/cpu", "./syz-tmp/newroot/syzcgroup/cpu", NULL, bind_mount_flags, NULL)) {
+ debug("mount(cgroup/cpu, MS_BIND) failed: %d\n", errno);
+ }
+ if (mount("/syzcgroup/net", "./syz-tmp/newroot/syzcgroup/net", NULL, bind_mount_flags, NULL)) {
+ debug("mount(cgroup/net, MS_BIND) failed: %d\n", errno);
+ }
+}
+#endif
+#endif
+
+#if SYZ_EXECUTOR || (SYZ_ENABLE_BINFMT_MISC && (SYZ_SANDBOX_NONE || SYZ_SANDBOX_SETUID || SYZ_SANDBOX_NAMESPACE || SYZ_SANDBOX_ANDROID_UNTRUSTED_APP))
+#include <fcntl.h>
+#include <sys/mount.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
static void setup_binfmt_misc()
{
+#if SYZ_EXECUTOR
+ if (!flag_enable_binfmt_misc)
+ return;
+#endif
if (mount(0, "/proc/sys/fs/binfmt_misc", "binfmt_misc", 0, 0)) {
debug("mount(binfmt_misc) failed: %d\n", errno);
}
@@ -3576,6 +3685,8 @@ static void setup_common()
}
#if SYZ_EXECUTOR || SYZ_ENABLE_CGROUPS
setup_cgroups();
+#endif
+#if SYZ_EXECUTOR || SYZ_ENABLE_BINFMT_MISC
setup_binfmt_misc();
#endif
}
@@ -3802,23 +3913,7 @@ static int namespace_sandbox_proc(void* arg)
if (mount("/sys", "./syz-tmp/newroot/sys", 0, bind_mount_flags, NULL))
fail("mount(sysfs) failed");
#if SYZ_EXECUTOR || SYZ_ENABLE_CGROUPS
- if (mkdir("./syz-tmp/newroot/syzcgroup", 0700))
- fail("mkdir failed");
- if (mkdir("./syz-tmp/newroot/syzcgroup/unified", 0700))
- fail("mkdir failed");
- if (mkdir("./syz-tmp/newroot/syzcgroup/cpu", 0700))
- fail("mkdir failed");
- if (mkdir("./syz-tmp/newroot/syzcgroup/net", 0700))
- fail("mkdir failed");
- if (mount("/syzcgroup/unified", "./syz-tmp/newroot/syzcgroup/unified", NULL, bind_mount_flags, NULL)) {
- debug("mount(cgroup2, MS_BIND) failed: %d\n", errno);
- }
- if (mount("/syzcgroup/cpu", "./syz-tmp/newroot/syzcgroup/cpu", NULL, bind_mount_flags, NULL)) {
- debug("mount(cgroup/cpu, MS_BIND) failed: %d\n", errno);
- }
- if (mount("/syzcgroup/net", "./syz-tmp/newroot/syzcgroup/net", NULL, bind_mount_flags, NULL)) {
- debug("mount(cgroup/net, MS_BIND) failed: %d\n", errno);
- }
+ initialize_cgroups();
#endif
if (mkdir("./syz-tmp/pivot", 0777))
fail("mkdir failed");
@@ -4090,12 +4185,15 @@ retry:
static int inject_fault(int nth)
{
+#if SYZ_EXECUTOR
+ if (!flag_enable_fault_injection)
+ return 0;
+#endif
int fd;
- char buf[16];
-
fd = open("/proc/thread-self/fail-nth", O_RDWR);
if (fd == -1)
exitf("failed to open /proc/thread-self/fail-nth");
+ char buf[16];
sprintf(buf, "%d", nth + 1);
if (write(fd, buf, strlen(buf)) != (ssize_t)strlen(buf))
exitf("failed to write /proc/thread-self/fail-nth");
@@ -4106,6 +4204,8 @@ static int inject_fault(int nth)
#if SYZ_EXECUTOR
static int fault_injected(int fail_fd)
{
+ if (!flag_enable_fault_injection)
+ return 0;
char buf[16];
int n = read(fail_fd, buf, sizeof(buf) - 1);
if (n <= 0)
@@ -4181,35 +4281,7 @@ static void kill_and_wait(int pid, int* status)
static void setup_loop()
{
#if SYZ_EXECUTOR || SYZ_ENABLE_CGROUPS
- int pid = getpid();
- char cgroupdir[64];
- char file[128];
- snprintf(cgroupdir, sizeof(cgroupdir), "/syzcgroup/unified/syz%llu", procid);
- if (mkdir(cgroupdir, 0777)) {
- debug("mkdir(%s) failed: %d\n", cgroupdir, errno);
- }
- snprintf(file, sizeof(file), "%s/pids.max", cgroupdir);
- write_file(file, "32");
- snprintf(file, sizeof(file), "%s/memory.low", cgroupdir);
- write_file(file, "%d", 298 << 20);
- snprintf(file, sizeof(file), "%s/memory.high", cgroupdir);
- write_file(file, "%d", 299 << 20);
- snprintf(file, sizeof(file), "%s/memory.max", cgroupdir);
- write_file(file, "%d", 300 << 20);
- snprintf(file, sizeof(file), "%s/cgroup.procs", cgroupdir);
- write_file(file, "%d", pid);
- snprintf(cgroupdir, sizeof(cgroupdir), "/syzcgroup/cpu/syz%llu", procid);
- if (mkdir(cgroupdir, 0777)) {
- debug("mkdir(%s) failed: %d\n", cgroupdir, errno);
- }
- snprintf(file, sizeof(file), "%s/cgroup.procs", cgroupdir);
- write_file(file, "%d", pid);
- snprintf(cgroupdir, sizeof(cgroupdir), "/syzcgroup/net/syz%llu", procid);
- if (mkdir(cgroupdir, 0777)) {
- debug("mkdir(%s) failed: %d\n", cgroupdir, errno);
- }
- snprintf(file, sizeof(file), "%s/cgroup.procs", cgroupdir);
- write_file(file, "%d", pid);
+ setup_cgroups_loop();
#endif
#if SYZ_EXECUTOR || SYZ_RESET_NET_NAMESPACE
checkpoint_net_namespace();
@@ -4245,21 +4317,9 @@ static void setup_test()
prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0);
setpgrp();
#if SYZ_EXECUTOR || SYZ_ENABLE_CGROUPS
- char cgroupdir[64];
- snprintf(cgroupdir, sizeof(cgroupdir), "/syzcgroup/unified/syz%llu", procid);
- if (symlink(cgroupdir, "./cgroup")) {
- debug("symlink(%s, ./cgroup) failed: %d\n", cgroupdir, errno);
- }
- snprintf(cgroupdir, sizeof(cgroupdir), "/syzcgroup/cpu/syz%llu", procid);
- if (symlink(cgroupdir, "./cgroup.cpu")) {
- debug("symlink(%s, ./cgroup.cpu) failed: %d\n", cgroupdir, errno);
- }
- snprintf(cgroupdir, sizeof(cgroupdir), "/syzcgroup/net/syz%llu", procid);
- if (symlink(cgroupdir, "./cgroup.net")) {
- debug("symlink(%s, ./cgroup.net) failed: %d\n", cgroupdir, errno);
- }
- write_file("/proc/self/oom_score_adj", "1000");
+ setup_cgroups_test();
#endif
+ write_file("/proc/self/oom_score_adj", "1000");
#if SYZ_EXECUTOR || SYZ_TUN_ENABLE
flush_tun();
#endif
diff --git a/pkg/csource/options.go b/pkg/csource/options.go
index 4a0cc9fbc..d82ff28bd 100644
--- a/pkg/csource/options.go
+++ b/pkg/csource/options.go
@@ -8,6 +8,8 @@ import (
"encoding/json"
"errors"
"fmt"
+ "sort"
+ "strings"
"github.com/google/syzkaller/pkg/mgrconfig"
)
@@ -27,12 +29,14 @@ type Options struct {
FaultNth int `json:"fault_nth,omitempty"`
// These options allow for a more fine-tuned control over the generated C code.
- EnableTun bool `json:"tun,omitempty"`
- UseTmpDir bool `json:"tmpdir,omitempty"`
- EnableCgroups bool `json:"cgroups,omitempty"`
- EnableNetdev bool `json:"netdev,omitempty"`
- ResetNet bool `json:"resetnet,omitempty"`
- HandleSegv bool `json:"segv,omitempty"`
+ EnableTun bool `json:"tun,omitempty"`
+ EnableNetDev bool `json:"netdev,omitempty"`
+ EnableNetReset bool `json:"resetnet,omitempty"`
+ EnableCgroups bool `json:"cgroups,omitempty"`
+ EnableBinfmtMisc bool `json:"binfmt_misc,omitempty"`
+
+ UseTmpDir bool `json:"tmpdir,omitempty"`
+ HandleSegv bool `json:"segv,omitempty"`
// Generate code for use with repro package to prints log messages,
// which allows to detect hangs.
@@ -58,8 +62,8 @@ func (opts Options) Check(OS string) error {
// This does not affect generated code.
return errors.New("Procs>1 without Repeat")
}
- if opts.ResetNet {
- return errors.New("ResetNet without Repeat")
+ if opts.EnableNetReset {
+ return errors.New("EnableNetReset without Repeat")
}
if opts.RepeatTimes > 1 {
return errors.New("RepeatTimes without Repeat")
@@ -69,11 +73,14 @@ func (opts Options) Check(OS string) error {
if opts.EnableTun {
return errors.New("EnableTun without sandbox")
}
+ if opts.EnableNetDev {
+ return errors.New("EnableNetDev without sandbox")
+ }
if opts.EnableCgroups {
return errors.New("EnableCgroups without sandbox")
}
- if opts.EnableNetdev {
- return errors.New("EnableNetdev without sandbox")
+ if opts.EnableBinfmtMisc {
+ return errors.New("EnableBinfmtMisc without sandbox")
}
}
if opts.Sandbox == sandboxNamespace && !opts.UseTmpDir {
@@ -82,12 +89,12 @@ func (opts Options) Check(OS string) error {
// which will fail if procs>1 and on second run of the program.
return errors.New("Sandbox=namespace without UseTmpDir")
}
+ if opts.EnableNetReset && (opts.Sandbox == "" || opts.Sandbox == sandboxSetuid) {
+ return errors.New("EnableNetReset without sandbox")
+ }
if opts.EnableCgroups && !opts.UseTmpDir {
return errors.New("EnableCgroups without UseTmpDir")
}
- if opts.ResetNet && (opts.Sandbox == "" || opts.Sandbox == sandboxSetuid) {
- return errors.New("ResetNet without sandbox")
- }
return opts.checkLinuxOnly(OS)
}
@@ -98,14 +105,17 @@ func (opts Options) checkLinuxOnly(OS string) error {
if opts.EnableTun && !(OS == "openbsd" || OS == "freebsd") {
return fmt.Errorf("EnableTun is not supported on %v", OS)
}
+ if opts.EnableNetDev {
+ return fmt.Errorf("EnableNetDev is not supported on %v", OS)
+ }
+ if opts.EnableNetReset {
+ return fmt.Errorf("EnableNetReset is not supported on %v", OS)
+ }
if opts.EnableCgroups {
return fmt.Errorf("EnableCgroups is not supported on %v", OS)
}
- if opts.EnableNetdev {
- return fmt.Errorf("EnableNetdev is not supported on %v", OS)
- }
- if opts.ResetNet {
- return fmt.Errorf("ResetNet is not supported on %v", OS)
+ if opts.EnableBinfmtMisc {
+ return fmt.Errorf("EnableBinfmtMisc is not supported on %v", OS)
}
if opts.Sandbox == sandboxNamespace ||
(opts.Sandbox == sandboxSetuid && !(OS == "openbsd" || OS == "freebsd")) ||
@@ -120,27 +130,29 @@ func (opts Options) checkLinuxOnly(OS string) error {
func DefaultOpts(cfg *mgrconfig.Config) Options {
opts := Options{
- Threaded: true,
- Collide: true,
- Repeat: true,
- Procs: cfg.Procs,
- Sandbox: cfg.Sandbox,
- EnableTun: true,
- EnableCgroups: true,
- EnableNetdev: true,
- ResetNet: true,
- UseTmpDir: true,
- HandleSegv: true,
- Repro: true,
+ Threaded: true,
+ Collide: true,
+ Repeat: true,
+ Procs: cfg.Procs,
+ Sandbox: cfg.Sandbox,
+ EnableTun: true,
+ EnableNetDev: true,
+ EnableNetReset: true,
+ EnableCgroups: true,
+ EnableBinfmtMisc: true,
+ UseTmpDir: true,
+ HandleSegv: true,
+ Repro: true,
}
if cfg.TargetOS != linux {
opts.EnableTun = false
+ opts.EnableNetDev = false
+ opts.EnableNetReset = false
opts.EnableCgroups = false
- opts.EnableNetdev = false
- opts.ResetNet = false
+ opts.EnableBinfmtMisc = false
}
if cfg.Sandbox == "" || cfg.Sandbox == "setuid" {
- opts.ResetNet = false
+ opts.EnableNetReset = false
}
if err := opts.Check(cfg.TargetOS); err != nil {
panic(fmt.Sprintf("DefaultOpts created bad opts: %v", err))
@@ -198,3 +210,66 @@ func DeserializeOptions(data []byte) (Options, error) {
}
return opts, err
}
+
+type Feature struct {
+ Description string
+ Enabled bool
+}
+
+type Features map[string]Feature
+
+func defaultFeatures(value bool) Features {
+ return map[string]Feature{
+ "tun": {"setup and use /dev/tun for packet injection", value},
+ "net_dev": {"setup more network devices for testing", value},
+ "net_reset": {"reset network namespace between programs", value},
+ "cgroups": {"setup cgroups for testing", value},
+ "binfmt_misc": {"setup binfmt_misc for testing", value},
+ }
+}
+
+func ParseFeaturesFlags(enable string, disable string, defaultValue bool) (Features, error) {
+ if enable == "none" && disable == "none" {
+ return defaultFeatures(defaultValue), nil
+ }
+ if enable != "none" && disable != "none" {
+ return nil, fmt.Errorf("can't use -enable and -disable flags at the same time")
+ }
+ if enable == "all" || disable == "" {
+ return defaultFeatures(true), nil
+ }
+ if disable == "all" || enable == "" {
+ return defaultFeatures(false), nil
+ }
+ var items []string
+ var features Features
+ if enable != "none" {
+ items = strings.Split(enable, ",")
+ features = defaultFeatures(false)
+ } else {
+ items = strings.Split(disable, ",")
+ features = defaultFeatures(true)
+ }
+ for _, item := range items {
+ if _, ok := features[item]; !ok {
+ return nil, fmt.Errorf("unknown feature specified: %s", item)
+ }
+ feature := features[item]
+ feature.Enabled = (enable != "none")
+ features[item] = feature
+ }
+ return features, nil
+}
+
+func PrintAvailableFeaturesFlags() {
+ fmt.Printf("Available features for -enable and -disable:\n")
+ features := defaultFeatures(false)
+ var names []string
+ for name := range features {
+ names = append(names, name)
+ }
+ sort.Strings(names)
+ for _, name := range names {
+ fmt.Printf(" %s - %s\n", name, features[name].Description)
+ }
+}
diff --git a/pkg/csource/options_test.go b/pkg/csource/options_test.go
index d8e8a217e..0240208e0 100644
--- a/pkg/csource/options_test.go
+++ b/pkg/csource/options_test.go
@@ -31,86 +31,91 @@ func TestParseOptionsCanned(t *testing.T) {
"fault":true,"fault_call":1,"fault_nth":2,"tun":true,"tmpdir":true,"cgroups":true,
"netdev":true,"resetnet":true,
"segv":true,"waitrepeat":true,"debug":true,"repro":true}`: {
- Threaded: true,
- Collide: true,
- Repeat: true,
- Procs: 10,
- Sandbox: "namespace",
- Fault: true,
- FaultCall: 1,
- FaultNth: 2,
- EnableTun: true,
- UseTmpDir: true,
- EnableCgroups: true,
- EnableNetdev: true,
- ResetNet: true,
- HandleSegv: true,
- Repro: true,
+ Threaded: true,
+ Collide: true,
+ Repeat: true,
+ Procs: 10,
+ Sandbox: "namespace",
+ Fault: true,
+ FaultCall: 1,
+ FaultNth: 2,
+ EnableTun: true,
+ EnableNetDev: true,
+ EnableNetReset: true,
+ EnableCgroups: true,
+ EnableBinfmtMisc: false,
+ UseTmpDir: true,
+ HandleSegv: true,
+ Repro: true,
},
`{"threaded":true,"collide":true,"repeat":true,"procs":10,"sandbox":"android_untrusted_app",
"fault":true,"fault_call":1,"fault_nth":2,"tun":true,"tmpdir":true,"cgroups":true,
"netdev":true,"resetnet":true,
"segv":true,"waitrepeat":true,"debug":true,"repro":true}`: {
- Threaded: true,
- Collide: true,
- Repeat: true,
- Procs: 10,
- Sandbox: "android_untrusted_app",
- Fault: true,
- FaultCall: 1,
- FaultNth: 2,
- EnableTun: true,
- UseTmpDir: true,
- EnableCgroups: true,
- EnableNetdev: true,
- ResetNet: true,
- HandleSegv: true,
- Repro: true,
+ Threaded: true,
+ Collide: true,
+ Repeat: true,
+ Procs: 10,
+ Sandbox: "android_untrusted_app",
+ Fault: true,
+ FaultCall: 1,
+ FaultNth: 2,
+ EnableTun: true,
+ EnableNetDev: true,
+ EnableNetReset: true,
+ EnableCgroups: true,
+ EnableBinfmtMisc: false,
+ UseTmpDir: true,
+ HandleSegv: true,
+ Repro: true,
},
"{Threaded:true Collide:true Repeat:true Procs:1 Sandbox:none Fault:false FaultCall:-1 FaultNth:0 EnableTun:true UseTmpDir:true HandleSegv:true WaitRepeat:true Debug:false Repro:false}": {
- Threaded: true,
- Collide: true,
- Repeat: true,
- Procs: 1,
- Sandbox: "none",
- Fault: false,
- FaultCall: -1,
- FaultNth: 0,
- EnableTun: true,
- UseTmpDir: true,
- EnableCgroups: false,
- HandleSegv: true,
- Repro: false,
+ Threaded: true,
+ Collide: true,
+ Repeat: true,
+ Procs: 1,
+ Sandbox: "none",
+ Fault: false,
+ FaultCall: -1,
+ FaultNth: 0,
+ EnableTun: true,
+ EnableCgroups: false,
+ EnableBinfmtMisc: false,
+ UseTmpDir: true,
+ HandleSegv: true,
+ Repro: false,
},
"{Threaded:true Collide:true Repeat:true Procs:1 Sandbox: Fault:false FaultCall:-1 FaultNth:0 EnableTun:true UseTmpDir:true HandleSegv:true WaitRepeat:true Debug:false Repro:false}": {
- Threaded: true,
- Collide: true,
- Repeat: true,
- Procs: 1,
- Sandbox: "",
- Fault: false,
- FaultCall: -1,
- FaultNth: 0,
- EnableTun: true,
- UseTmpDir: true,
- EnableCgroups: false,
- HandleSegv: true,
- Repro: false,
+ Threaded: true,
+ Collide: true,
+ Repeat: true,
+ Procs: 1,
+ Sandbox: "",
+ Fault: false,
+ FaultCall: -1,
+ FaultNth: 0,
+ EnableTun: true,
+ EnableCgroups: false,
+ EnableBinfmtMisc: false,
+ UseTmpDir: true,
+ HandleSegv: true,
+ Repro: false,
},
"{Threaded:false Collide:true Repeat:true Procs:1 Sandbox:namespace Fault:false FaultCall:-1 FaultNth:0 EnableTun:true UseTmpDir:true EnableCgroups:true HandleSegv:true WaitRepeat:true Debug:false Repro:false}": {
- Threaded: false,
- Collide: true,
- Repeat: true,
- Procs: 1,
- Sandbox: "namespace",
- Fault: false,
- FaultCall: -1,
- FaultNth: 0,
- EnableTun: true,
- UseTmpDir: true,
- EnableCgroups: true,
- HandleSegv: true,
- Repro: false,
+ Threaded: false,
+ Collide: true,
+ Repeat: true,
+ Procs: 1,
+ Sandbox: "namespace",
+ Fault: false,
+ FaultCall: -1,
+ FaultNth: 0,
+ EnableTun: true,
+ EnableCgroups: true,
+ EnableBinfmtMisc: false,
+ UseTmpDir: true,
+ HandleSegv: true,
+ Repro: false,
},
}
for data, want := range canned {
@@ -194,3 +199,49 @@ func enumerateField(OS string, opt Options, field int) []Options {
}
return checked
}
+
+func TestParseFeaturesFlags(t *testing.T) {
+ tests := []struct {
+ Enable string
+ Disable string
+ Default bool
+ Features map[string]bool
+ }{
+ {"none", "none", true, map[string]bool{
+ "tun": true, "net_dev": true, "net_reset": true, "cgroups": true, "binfmt_misc": true,
+ }},
+ {"none", "none", false, map[string]bool{
+ "tun": false, "net_dev": false, "net_reset": false, "cgroups": false, "binfmt_misc": false,
+ }},
+ {"all", "none", true, map[string]bool{
+ "tun": true, "net_dev": true, "net_reset": true, "cgroups": true, "binfmt_misc": true,
+ }},
+ {"", "none", true, map[string]bool{
+ "tun": false, "net_dev": false, "net_reset": false, "cgroups": false, "binfmt_misc": false,
+ }},
+ {"none", "all", true, map[string]bool{
+ "tun": false, "net_dev": false, "net_reset": false, "cgroups": false, "binfmt_misc": false,
+ }},
+ {"none", "", true, map[string]bool{
+ "tun": true, "net_dev": true, "net_reset": true, "cgroups": true, "binfmt_misc": true,
+ }},
+ {"tun,net_dev", "none", true, map[string]bool{
+ "tun": true, "net_dev": true, "net_reset": false, "cgroups": false, "binfmt_misc": false,
+ }},
+ {"none", "cgroups,net_dev", true, map[string]bool{
+ "tun": true, "net_dev": false, "net_reset": true, "cgroups": false, "binfmt_misc": true,
+ }},
+ }
+ for i, test := range tests {
+ features, err := ParseFeaturesFlags(test.Enable, test.Disable, test.Default)
+ if err != nil {
+ t.Fatalf("failed to parse features flags: %v", err)
+ }
+ for name, feature := range features {
+ if feature.Enabled != test.Features[name] {
+ t.Fatalf("test #%v: invalid value for feature flag %s: got %v, want %v",
+ i, name, feature.Enabled, test.Features[name])
+ }
+ }
+ }
+}