aboutsummaryrefslogtreecommitdiffstats
path: root/pkg/csource/generated.go
diff options
context:
space:
mode:
authorAleksandr Nogikh <nogikh@google.com>2022-01-19 17:38:24 +0000
committerAleksandr Nogikh <wp32pw@gmail.com>2022-01-21 11:28:49 +0100
commit214351e168def9426c79e1f65a93ddb112cee906 (patch)
tree7bd960ca4a7dd2cf5d720d7f3159385ba0eb3fc1 /pkg/csource/generated.go
parentab3d9f17d3b73b74f89b4ea3bd951e09ab4149a8 (diff)
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 <avagin@google.com>
Diffstat (limited to 'pkg/csource/generated.go')
-rw-r--r--pkg/csource/generated.go22
1 files changed, 21 insertions, 1 deletions
diff --git a/pkg/csource/generated.go b/pkg/csource/generated.go
index 16b128b42..04f6b6108 100644
--- a/pkg/csource/generated.go
+++ b/pkg/csource/generated.go
@@ -51,6 +51,10 @@ NORETURN void doexit(int status)
for (;;) {
}
}
+NORETURN void doexit_thread(int status)
+{
+ doexit(status);
+}
#endif
#if SYZ_EXECUTOR || SYZ_MULTI_PROC || SYZ_REPEAT && SYZ_CGROUPS || \
@@ -70,6 +74,7 @@ static unsigned long long procid;
#include <sys/syscall.h>
#endif
+static __thread int clone_ongoing;
static __thread int skip_segv;
static __thread jmp_buf segv_env;
@@ -83,6 +88,11 @@ static void recover(void)
static void segv_handler(int sig, siginfo_t* info, void* ctx)
{
+
+ if (__atomic_load_n(&clone_ongoing, __ATOMIC_RELAXED) != 0) {
+ doexit_thread(sig);
+ }
+
uintptr_t addr = (uintptr_t)info->si_addr;
const uintptr_t prog_start = 1 << 20;
const uintptr_t prog_end = 100 << 20;
@@ -10182,8 +10192,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;
+ }
usleep(USLEEP_FORKED_CHILD);
syscall(__NR_exit, 0);
while (1) {
@@ -10196,6 +10210,9 @@ static long syz_clone(volatile long flags, volatile long stack, volatile long st
volatile long ptid, volatile long ctid, volatile long tls)
{
long sp = (stack + stack_len) & ~15;
+#if SYZ_EXECUTOR || SYZ_HANDLE_SEGV
+ __atomic_store_n(&clone_ongoing, 1, __ATOMIC_RELAXED);
+#endif
long ret = (long)syscall(__NR_clone, flags & ~CLONE_VM, sp, ptid, ctid, tls);
return handle_clone_ret(ret);
}
@@ -10215,6 +10232,9 @@ static long syz_clone3(volatile long a0, volatile long a1)
memcpy(&clone_args, (void*)a0, copy_size);
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));
}