From 214351e168def9426c79e1f65a93ddb112cee906 Mon Sep 17 00:00:00 2001 From: Aleksandr Nogikh Date: Wed, 19 Jan 2022 17:38:24 +0000 Subject: executor: fail on SEGV during clone() As was found out in #2921, fork bombs are still possible in Linux-based instances. One of the possible reasons is described below. An invalid stack can be passed to the clone() call, thus causing it to stumble on an invalid memory access right during returning from the clone() call. This is in turn catched by the NONFAILING() macro and the control actually jumps over it and eventually both the child and the parent continue executing the same code. Prevent it by handling SIGSEGV and SIGBUS differently during the clone process. Co-authored-by: Andrei Vagin --- executor/common_linux.h | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) (limited to 'executor/common_linux.h') diff --git a/executor/common_linux.h b/executor/common_linux.h index 520c13506..88c129f85 100644 --- a/executor/common_linux.h +++ b/executor/common_linux.h @@ -5226,8 +5226,12 @@ static long syz_80211_join_ibss(volatile long a0, volatile long a1, volatile lon static long handle_clone_ret(long ret) { - if (ret != 0) + if (ret != 0) { +#if SYZ_EXECUTOR || SYZ_HANDLE_SEGV + __atomic_store_n(&clone_ongoing, 0, __ATOMIC_RELAXED); +#endif return ret; + } // Exit if we're in the child process - not all kernels provide the proper means // to prevent fork-bombs. // But first sleep for some time. This will hopefully foster IPC fuzzing. @@ -5247,6 +5251,9 @@ static long syz_clone(volatile long flags, volatile long stack, volatile long st { // ABI requires 16-byte stack alignment. long sp = (stack + stack_len) & ~15; +#if SYZ_EXECUTOR || SYZ_HANDLE_SEGV + __atomic_store_n(&clone_ongoing, 1, __ATOMIC_RELAXED); +#endif // Clear the CLONE_VM flag. Otherwise it'll very likely corrupt syz-executor. long ret = (long)syscall(__NR_clone, flags & ~CLONE_VM, sp, ptid, ctid, tls); return handle_clone_ret(ret); @@ -5270,6 +5277,9 @@ static long syz_clone3(volatile long a0, volatile long a1) // As in syz_clone, clear the CLONE_VM flag. Flags are in the first 8-byte integer field. uint64* flags = (uint64*)&clone_args; *flags &= ~CLONE_VM; +#if SYZ_EXECUTOR || SYZ_HANDLE_SEGV + __atomic_store_n(&clone_ongoing, 1, __ATOMIC_RELAXED); +#endif return handle_clone_ret((long)syscall(__NR_clone3, &clone_args, copy_size)); } -- cgit mrf-deployment