diff options
| -rw-r--r-- | executor/common.h | 14 | ||||
| -rw-r--r-- | executor/common_linux.h | 12 | ||||
| -rw-r--r-- | executor/executor.cc | 6 | ||||
| -rw-r--r-- | pkg/csource/common.go | 1 | ||||
| -rw-r--r-- | pkg/csource/generated.go | 24 | ||||
| -rw-r--r-- | pkg/csource/options.go | 10 | ||||
| -rw-r--r-- | pkg/csource/options_test.go | 24 | ||||
| -rw-r--r-- | pkg/ipc/ipc.go | 1 | ||||
| -rw-r--r-- | pkg/repro/repro.go | 10 | ||||
| -rw-r--r-- | syz-fuzzer/fuzzer.go | 1 | ||||
| -rw-r--r-- | tools/syz-execprog/execprog.go | 3 | ||||
| -rw-r--r-- | tools/syz-prog2c/prog2c.go | 1 | ||||
| -rw-r--r-- | tools/syz-stress/stress.go | 3 |
13 files changed, 94 insertions, 16 deletions
diff --git a/executor/common.h b/executor/common.h index 5f33d3bf5..10e5b960b 100644 --- a/executor/common.h +++ b/executor/common.h @@ -483,6 +483,9 @@ again: } for (i = 0; i < 100 && __atomic_load_n(&running, __ATOMIC_RELAXED); i++) sleep_ms(1); +#if SYZ_HAVE_CLOSE_FDS + close_fds(); +#endif #if SYZ_COLLIDE if (!collide) { collide = 1; @@ -571,8 +574,8 @@ static void loop(void) close(kOutPipeFd); #endif execute_one(); -#if SYZ_HAVE_RESET_TEST - reset_test(); +#if SYZ_HAVE_CLOSE_FDS && !SYZ_THREADED + close_fds(); #endif doexit(0); #endif @@ -659,6 +662,9 @@ void loop(void) #endif { /*SYSCALLS*/ +#if SYZ_HAVE_CLOSE_FDS && !SYZ_THREADED && !SYZ_REPEAT + close_fds(); +#endif } #endif @@ -690,6 +696,10 @@ int main(void) use_temporary_dir(); #endif /*SANDBOX_FUNC*/ +#if SYZ_HAVE_CLOSE_FDS && !SYZ_THREADED && !SYZ_REPEAT && !SYZ_SANDBOX_NONE && \ + !SYZ_SANDBOX_SETUID && !SYZ_SANDBOX_NAMESPACE && !SYZ_SANDBOX_ANDROID_UNTRUSTED_APP + close_fds(); +#endif #if SYZ_PROCS } } diff --git a/executor/common_linux.h b/executor/common_linux.h index b84955577..0fd7a1582 100644 --- a/executor/common_linux.h +++ b/executor/common_linux.h @@ -2612,12 +2612,20 @@ static void setup_test() flush_tun(); #endif } +#endif -#define SYZ_HAVE_RESET_TEST 1 -static void reset_test() +#if SYZ_EXECUTOR || SYZ_ENABLE_CLOSE_FDS +#define SYZ_HAVE_CLOSE_FDS 1 +static void close_fds() { +#if SYZ_EXECUTOR + if (!flag_enable_close_fds) + return; +#endif // Keeping a 9p transport pipe open will hang the proccess dead, // so close all opened file descriptors. + // Also close all USB emulation descriptors to trigger exit from USB + // event loop to collect coverage. int fd; for (fd = 3; fd < 30; fd++) close(fd); diff --git a/executor/executor.cc b/executor/executor.cc index f1f6ba294..bbbb2da31 100644 --- a/executor/executor.cc +++ b/executor/executor.cc @@ -119,6 +119,7 @@ static bool flag_enable_net_dev; static bool flag_enable_net_reset; static bool flag_enable_cgroups; static bool flag_enable_binfmt_misc; +static bool flag_enable_close_fds; static bool flag_collect_cover; static bool flag_dedup_cover; @@ -454,6 +455,7 @@ void parse_env_flags(uint64 flags) flag_enable_net_reset = flags & (1 << 9); flag_enable_cgroups = flags & (1 << 10); flag_enable_binfmt_misc = flags & (1 << 11); + flag_enable_close_fds = flags & (1 << 12); } #if SYZ_EXECUTOR_USES_FORK_SERVER @@ -732,6 +734,10 @@ retry: } } +#if SYZ_HAVE_CLOSE_FDS + close_fds(); +#endif + if (flag_collide && !flag_inject_fault && !colliding && !collide) { debug("enabling collider\n"); collide = colliding = true; diff --git a/pkg/csource/common.go b/pkg/csource/common.go index 204256df2..d0c63402a 100644 --- a/pkg/csource/common.go +++ b/pkg/csource/common.go @@ -89,6 +89,7 @@ func defineList(p, mmapProg *prog.Prog, opts Options) (defines []string) { "SYZ_ENABLE_NETDEV": opts.EnableNetDev, "SYZ_RESET_NET_NAMESPACE": opts.EnableNetReset, "SYZ_ENABLE_BINFMT_MISC": opts.EnableBinfmtMisc, + "SYZ_ENABLE_CLOSE_FDS": opts.EnableCloseFds, "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 71a38106b..4bd86bcc2 100644 --- a/pkg/csource/generated.go +++ b/pkg/csource/generated.go @@ -4319,10 +4319,16 @@ static void setup_test() flush_tun(); #endif } +#endif -#define SYZ_HAVE_RESET_TEST 1 -static void reset_test() +#if SYZ_EXECUTOR || SYZ_ENABLE_CLOSE_FDS +#define SYZ_HAVE_CLOSE_FDS 1 +static void close_fds() { +#if SYZ_EXECUTOR + if (!flag_enable_close_fds) + return; +#endif int fd; for (fd = 3; fd < 30; fd++) close(fd); @@ -4614,6 +4620,9 @@ again: } for (i = 0; i < 100 && __atomic_load_n(&running, __ATOMIC_RELAXED); i++) sleep_ms(1); +#if SYZ_HAVE_CLOSE_FDS + close_fds(); +#endif #if SYZ_COLLIDE if (!collide) { collide = 1; @@ -4698,8 +4707,8 @@ static void loop(void) close(kOutPipeFd); #endif execute_one(); -#if SYZ_HAVE_RESET_TEST - reset_test(); +#if SYZ_HAVE_CLOSE_FDS && !SYZ_THREADED + close_fds(); #endif doexit(0); #endif @@ -4771,6 +4780,9 @@ void loop(void) #endif { /*SYSCALLS*/ +#if SYZ_HAVE_CLOSE_FDS && !SYZ_THREADED && !SYZ_REPEAT + close_fds(); +#endif } #endif #if GOOS_akaros && SYZ_REPEAT @@ -4800,6 +4812,10 @@ int main(void) use_temporary_dir(); #endif /*SANDBOX_FUNC*/ +#if SYZ_HAVE_CLOSE_FDS && !SYZ_THREADED && !SYZ_REPEAT && !SYZ_SANDBOX_NONE && \ + !SYZ_SANDBOX_SETUID && !SYZ_SANDBOX_NAMESPACE && !SYZ_SANDBOX_ANDROID_UNTRUSTED_APP + close_fds(); +#endif #if SYZ_PROCS } } diff --git a/pkg/csource/options.go b/pkg/csource/options.go index d5b396164..0a9539663 100644 --- a/pkg/csource/options.go +++ b/pkg/csource/options.go @@ -34,6 +34,7 @@ type Options struct { EnableNetReset bool `json:"resetnet,omitempty"` EnableCgroups bool `json:"cgroups,omitempty"` EnableBinfmtMisc bool `json:"binfmt_misc,omitempty"` + EnableCloseFds bool `json:"close_fds"` UseTmpDir bool `json:"tmpdir,omitempty"` HandleSegv bool `json:"segv,omitempty"` @@ -117,6 +118,9 @@ func (opts Options) checkLinuxOnly(OS string) error { if opts.EnableBinfmtMisc { return fmt.Errorf("EnableBinfmtMisc is not supported on %v", OS) } + if opts.EnableCloseFds { + return fmt.Errorf("EnableCloseFds is not supported on %v", OS) + } if opts.Sandbox == sandboxNamespace || (opts.Sandbox == sandboxSetuid && !(OS == openbsd || OS == freebsd)) || opts.Sandbox == sandboxAndroidUntrustedApp { @@ -140,6 +144,7 @@ func DefaultOpts(cfg *mgrconfig.Config) Options { EnableNetReset: true, EnableCgroups: true, EnableBinfmtMisc: true, + EnableCloseFds: true, UseTmpDir: true, HandleSegv: true, Repro: true, @@ -150,6 +155,7 @@ func DefaultOpts(cfg *mgrconfig.Config) Options { opts.EnableNetReset = false opts.EnableCgroups = false opts.EnableBinfmtMisc = false + opts.EnableCloseFds = false } if cfg.Sandbox == "" || cfg.Sandbox == "setuid" { opts.EnableNetReset = false @@ -170,6 +176,9 @@ func (opts Options) Serialize() []byte { func DeserializeOptions(data []byte) (Options, error) { var opts Options + // Before EnableCloseFds was added, close_fds() was always called, + // so default to true. + opts.EnableCloseFds = true if err := json.Unmarshal(data, &opts); err == nil { return opts, nil } @@ -225,6 +234,7 @@ func defaultFeatures(value bool) Features { "net_reset": {"reset network namespace between programs", value}, "cgroups": {"setup cgroups for testing", value}, "binfmt_misc": {"setup binfmt_misc for testing", value}, + "close_fds": {"close fds after each program", value}, } } diff --git a/pkg/csource/options_test.go b/pkg/csource/options_test.go index 0240208e0..13afa84d3 100644 --- a/pkg/csource/options_test.go +++ b/pkg/csource/options_test.go @@ -44,6 +44,7 @@ func TestParseOptionsCanned(t *testing.T) { EnableNetReset: true, EnableCgroups: true, EnableBinfmtMisc: false, + EnableCloseFds: true, UseTmpDir: true, HandleSegv: true, Repro: true, @@ -65,6 +66,7 @@ func TestParseOptionsCanned(t *testing.T) { EnableNetReset: true, EnableCgroups: true, EnableBinfmtMisc: false, + EnableCloseFds: true, UseTmpDir: true, HandleSegv: true, Repro: true, @@ -81,6 +83,7 @@ func TestParseOptionsCanned(t *testing.T) { EnableTun: true, EnableCgroups: false, EnableBinfmtMisc: false, + EnableCloseFds: true, UseTmpDir: true, HandleSegv: true, Repro: false, @@ -97,6 +100,7 @@ func TestParseOptionsCanned(t *testing.T) { EnableTun: true, EnableCgroups: false, EnableBinfmtMisc: false, + EnableCloseFds: true, UseTmpDir: true, HandleSegv: true, Repro: false, @@ -113,6 +117,7 @@ func TestParseOptionsCanned(t *testing.T) { EnableTun: true, EnableCgroups: true, EnableBinfmtMisc: false, + EnableCloseFds: true, UseTmpDir: true, HandleSegv: true, Repro: false, @@ -208,28 +213,31 @@ func TestParseFeaturesFlags(t *testing.T) { Features map[string]bool }{ {"none", "none", true, map[string]bool{ - "tun": true, "net_dev": true, "net_reset": true, "cgroups": true, "binfmt_misc": true, + "tun": true, "net_dev": true, "net_reset": true, "cgroups": true, "binfmt_misc": true, "close_fds": true, }}, {"none", "none", false, map[string]bool{ - "tun": false, "net_dev": false, "net_reset": false, "cgroups": false, "binfmt_misc": false, + "tun": false, "net_dev": false, "net_reset": false, "cgroups": false, "binfmt_misc": false, "close_fds": false, }}, {"all", "none", true, map[string]bool{ - "tun": true, "net_dev": true, "net_reset": true, "cgroups": true, "binfmt_misc": true, + "tun": true, "net_dev": true, "net_reset": true, "cgroups": true, "binfmt_misc": true, "close_fds": true, }}, {"", "none", true, map[string]bool{ - "tun": false, "net_dev": false, "net_reset": false, "cgroups": false, "binfmt_misc": false, + "tun": false, "net_dev": false, "net_reset": false, "cgroups": false, "binfmt_misc": false, "close_fds": false, }}, {"none", "all", true, map[string]bool{ - "tun": false, "net_dev": false, "net_reset": false, "cgroups": false, "binfmt_misc": false, + "tun": false, "net_dev": false, "net_reset": false, "cgroups": false, "binfmt_misc": false, "close_fds": false, }}, {"none", "", true, map[string]bool{ - "tun": true, "net_dev": true, "net_reset": true, "cgroups": true, "binfmt_misc": true, + "tun": true, "net_dev": true, "net_reset": true, "cgroups": true, "binfmt_misc": true, "close_fds": true, }}, {"tun,net_dev", "none", true, map[string]bool{ - "tun": true, "net_dev": true, "net_reset": false, "cgroups": false, "binfmt_misc": false, + "tun": true, "net_dev": true, "net_reset": false, "cgroups": false, "binfmt_misc": false, "close_fds": false, }}, {"none", "cgroups,net_dev", true, map[string]bool{ - "tun": true, "net_dev": false, "net_reset": true, "cgroups": false, "binfmt_misc": true, + "tun": true, "net_dev": false, "net_reset": true, "cgroups": false, "binfmt_misc": true, "close_fds": true, + }}, + {"close_fds", "none", true, map[string]bool{ + "tun": false, "net_dev": false, "net_reset": false, "cgroups": false, "binfmt_misc": false, "close_fds": true, }}, } for i, test := range tests { diff --git a/pkg/ipc/ipc.go b/pkg/ipc/ipc.go index f3bc029af..ab6c93a6f 100644 --- a/pkg/ipc/ipc.go +++ b/pkg/ipc/ipc.go @@ -38,6 +38,7 @@ const ( FlagEnableNetReset // reset network namespace between programs FlagEnableCgroups // setup cgroups for testing FlagEnableBinfmtMisc // setup binfmt_misc for testing + FlagEnableCloseFds // close fds after each program // 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 5db411617..af390162b 100644 --- a/pkg/repro/repro.go +++ b/pkg/repro/repro.go @@ -809,6 +809,7 @@ var cSimplifies = append(progSimplifies, []Simplify{ opts.EnableNetReset = false opts.EnableCgroups = false opts.EnableBinfmtMisc = false + opts.EnableCloseFds = false return true }, func(opts *csource.Options) bool { @@ -847,6 +848,15 @@ var cSimplifies = append(progSimplifies, []Simplify{ return true }, func(opts *csource.Options) bool { + // We don't want to remove close_fds() call when repeat is enabled, + // since that can lead to deadlocks, see executor/common_linux.h. + if !opts.EnableCloseFds || opts.Repeat { + return false + } + opts.EnableCloseFds = false + return true + }, + func(opts *csource.Options) bool { if !opts.UseTmpDir || opts.Sandbox == "namespace" || opts.EnableCgroups { return false } diff --git a/syz-fuzzer/fuzzer.go b/syz-fuzzer/fuzzer.go index d0ff1575b..b96938091 100644 --- a/syz-fuzzer/fuzzer.go +++ b/syz-fuzzer/fuzzer.go @@ -202,6 +202,7 @@ func main() { config.Flags |= ipc.FlagEnableNetReset config.Flags |= ipc.FlagEnableCgroups config.Flags |= ipc.FlagEnableBinfmtMisc + config.Flags |= ipc.FlagEnableCloseFds if *flagRunTest { runTest(target, manager, *flagName, config.Executor) diff --git a/tools/syz-execprog/execprog.go b/tools/syz-execprog/execprog.go index 07bae4567..b2902ba14 100644 --- a/tools/syz-execprog/execprog.go +++ b/tools/syz-execprog/execprog.go @@ -324,5 +324,8 @@ func createConfig(target *prog.Target, entries []*prog.LogEntry, if featuresFlags["binfmt_misc"].Enabled { config.Flags |= ipc.FlagEnableBinfmtMisc } + if featuresFlags["close_fds"].Enabled { + config.Flags |= ipc.FlagEnableCloseFds + } return config, execOpts } diff --git a/tools/syz-prog2c/prog2c.go b/tools/syz-prog2c/prog2c.go index d076ad2ee..86f703c3b 100644 --- a/tools/syz-prog2c/prog2c.go +++ b/tools/syz-prog2c/prog2c.go @@ -84,6 +84,7 @@ func main() { EnableNetReset: features["net_reset"].Enabled, EnableCgroups: features["cgroups"].Enabled, EnableBinfmtMisc: features["binfmt_misc"].Enabled, + EnableCloseFds: features["close_fds"].Enabled, UseTmpDir: *flagUseTmpDir, HandleSegv: *flagHandleSegv, Repro: false, diff --git a/tools/syz-stress/stress.go b/tools/syz-stress/stress.go index e287b4468..390a1fb4f 100644 --- a/tools/syz-stress/stress.go +++ b/tools/syz-stress/stress.go @@ -94,6 +94,9 @@ func main() { if featuresFlags["binfmt_misc"].Enabled { config.Flags |= ipc.FlagEnableBinfmtMisc } + if featuresFlags["close_fds"].Enabled { + config.Flags |= ipc.FlagEnableCloseFds + } gate = ipc.NewGate(2**flagProcs, nil) for pid := 0; pid < *flagProcs; pid++ { pid := pid |
