aboutsummaryrefslogtreecommitdiffstats
path: root/pkg
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
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')
-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
-rw-r--r--pkg/ipc/ipc.go9
-rw-r--r--pkg/repro/repro.go26
-rw-r--r--pkg/repro/repro_test.go24
-rw-r--r--pkg/runtest/run.go4
8 files changed, 393 insertions, 193 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])
+ }
+ }
+ }
+}
diff --git a/pkg/ipc/ipc.go b/pkg/ipc/ipc.go
index b2d4c9d63..e1e22445e 100644
--- a/pkg/ipc/ipc.go
+++ b/pkg/ipc/ipc.go
@@ -31,10 +31,13 @@ const (
FlagSandboxSetuid // impersonate nobody user
FlagSandboxNamespace // use namespaces for sandboxing
FlagSandboxAndroidUntrustedApp // use Android sandboxing for the untrusted_app domain
- FlagEnableTun // initialize and use tun in executor
- FlagEnableNetDev // setup a bunch of various network devices for testing
- FlagEnableFault // enable fault injection support
FlagExtraCover // collect extra coverage
+ FlagEnableFault // enable fault injection support
+ FlagEnableTun // setup and use /dev/tun for packet injection
+ FlagEnableNetDev // setup more network devices for testing
+ FlagEnableNetReset // reset network namespace between programs
+ FlagEnableCgroups // setup cgroups for testing
+ FlagEnableBinfmtMisc // setup binfmt_misc for testing
// Executor does not know about these:
FlagUseShmem // use shared memory instead of pipes for communication
FlagUseForkServer // use extended protocol with handshake
diff --git a/pkg/repro/repro.go b/pkg/repro/repro.go
index ab91e545a..2c6a0e6ed 100644
--- a/pkg/repro/repro.go
+++ b/pkg/repro/repro.go
@@ -777,7 +777,7 @@ var progSimplifies = []Simplify{
}
opts.Repeat = false
opts.EnableCgroups = false
- opts.ResetNet = false
+ opts.EnableNetReset = false
opts.Procs = 1
return true
},
@@ -804,9 +804,10 @@ var cSimplifies = append(progSimplifies, []Simplify{
}
opts.Sandbox = ""
opts.EnableTun = false
+ opts.EnableNetDev = false
+ opts.EnableNetReset = false
opts.EnableCgroups = false
- opts.EnableNetdev = false
- opts.ResetNet = false
+ opts.EnableBinfmtMisc = false
return true
},
func(opts *csource.Options) bool {
@@ -817,24 +818,31 @@ var cSimplifies = append(progSimplifies, []Simplify{
return true
},
func(opts *csource.Options) bool {
- if !opts.EnableCgroups {
+ if !opts.EnableNetDev {
return false
}
- opts.EnableCgroups = false
+ opts.EnableNetDev = false
return true
},
func(opts *csource.Options) bool {
- if !opts.EnableNetdev {
+ if !opts.EnableNetReset {
return false
}
- opts.EnableNetdev = false
+ opts.EnableNetReset = false
+ return true
+ },
+ func(opts *csource.Options) bool {
+ if !opts.EnableCgroups {
+ return false
+ }
+ opts.EnableCgroups = false
return true
},
func(opts *csource.Options) bool {
- if !opts.ResetNet {
+ if !opts.EnableBinfmtMisc {
return false
}
- opts.ResetNet = false
+ opts.EnableBinfmtMisc = false
return true
},
func(opts *csource.Options) bool {
diff --git a/pkg/repro/repro_test.go b/pkg/repro/repro_test.go
index 349b412fc..c417b7416 100644
--- a/pkg/repro/repro_test.go
+++ b/pkg/repro/repro_test.go
@@ -73,18 +73,18 @@ func TestBisect(t *testing.T) {
func TestSimplifies(t *testing.T) {
opts := csource.Options{
- Threaded: true,
- Collide: true,
- Repeat: true,
- Procs: 10,
- Sandbox: "namespace",
- EnableTun: true,
- EnableCgroups: true,
- EnableNetdev: true,
- ResetNet: true,
- UseTmpDir: true,
- HandleSegv: true,
- Repro: true,
+ Threaded: true,
+ Collide: true,
+ Repeat: true,
+ Procs: 10,
+ Sandbox: "namespace",
+ EnableTun: true,
+ EnableNetDev: true,
+ EnableNetReset: true,
+ EnableCgroups: true,
+ UseTmpDir: true,
+ HandleSegv: true,
+ Repro: true,
}
var check func(opts csource.Options, i int)
check = func(opts csource.Options, i int) {
diff --git a/pkg/runtest/run.go b/pkg/runtest/run.go
index 0af03158e..13195dc36 100644
--- a/pkg/runtest/run.go
+++ b/pkg/runtest/run.go
@@ -349,6 +349,8 @@ func (ctx *Context) createSyzTest(p *prog.Prog, sandbox string, threaded, cov bo
if ctx.Features[host.FeatureNetworkDevices].Enabled {
cfg.Flags |= ipc.FlagEnableNetDev
}
+ cfg.Flags |= ipc.FlagEnableNetReset
+ cfg.Flags |= ipc.FlagEnableCgroups
req := &RunRequest{
P: p,
Cfg: cfg,
@@ -376,7 +378,7 @@ func (ctx *Context) createCTest(p *prog.Prog, sandbox string, threaded bool, tim
opts.EnableTun = true
}
if ctx.Features[host.FeatureNetworkDevices].Enabled {
- opts.EnableNetdev = true
+ opts.EnableNetDev = true
}
}
src, err := csource.Write(p, opts)