summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGabe Black <gabeblack@google.com>2018-11-16 17:07:42 -0800
committerGabe Black <gabeblack@google.com>2018-11-18 10:44:26 +0000
commit5bfde967dcbbfae884e343425da1fc069a9c4b86 (patch)
tree74238175235f5286797fe41edff55666974dde6b
parent040fabe2bd1d3e34dc2855b2b443af503b967c6b (diff)
downloadgem5-5bfde967dcbbfae884e343425da1fc069a9c4b86.tar.xz
base: Set up a guard page for fiber stacks.
This will help detect stack overflow for fibers. Change-Id: Iff2b102120ec351709e495291d6bead597f8d10c Reviewed-on: https://gem5-review.googlesource.com/c/14395 Reviewed-by: Daniel Carvalho <odanrc@yahoo.com.br> Maintainer: Gabe Black <gabeblack@google.com>
-rw-r--r--src/base/fiber.cc39
-rw-r--r--src/base/fiber.hh4
2 files changed, 31 insertions, 12 deletions
diff --git a/src/base/fiber.cc b/src/base/fiber.cc
index eac1d9394..af63216da 100644
--- a/src/base/fiber.cc
+++ b/src/base/fiber.cc
@@ -33,7 +33,11 @@
#include <valgrind/valgrind.h>
#endif
+#include <sys/mman.h>
+#include <unistd.h>
+
#include <cerrno>
+#include <cstdio>
#include <cstring>
#include "base/logging.hh"
@@ -71,28 +75,41 @@ Fiber::entryTrampoline()
startingFiber->start();
}
-Fiber::Fiber(size_t stack_size) :
- link(primaryFiber()),
- stack(stack_size ? new uint8_t[stack_size] : nullptr),
- stackSize(stack_size), started(false), _finished(false)
+Fiber::Fiber(size_t stack_size) : Fiber(primaryFiber(), stack_size)
+{}
+
+Fiber::Fiber(Fiber *link, size_t stack_size) :
+ link(link), stack(nullptr), stackSize(stack_size), guardPage(nullptr),
+ guardPageSize(sysconf(_SC_PAGE_SIZE)), started(false), _finished(false)
{
+ if (stack_size) {
+ guardPage = mmap(nullptr, guardPageSize + stack_size,
+ PROT_READ | PROT_WRITE,
+ MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
+ if (guardPage == (void *)MAP_FAILED) {
+ perror("mmap");
+ fatal("Could not mmap %d byte fiber stack.\n", stack_size);
+ }
+ stack = (void *)((uint8_t *)guardPage + guardPageSize);
+ if (mprotect(guardPage, guardPageSize, PROT_NONE)) {
+ perror("mprotect");
+ fatal("Could not forbid access to fiber stack guard page.");
+ }
+ }
#if HAVE_VALGRIND
- valgrindStackId = VALGRIND_STACK_REGISTER(stack, stack + stack_size);
+ valgrindStackId = VALGRIND_STACK_REGISTER(
+ stack, (uint8_t *)stack + stack_size);
#endif
}
-Fiber::Fiber(Fiber *link, size_t stack_size) :
- link(link), stack(stack_size ? new uint8_t[stack_size] : nullptr),
- stackSize(stack_size), started(false), _finished(false)
-{}
-
Fiber::~Fiber()
{
panic_if(stack && _currentFiber == this, "Fiber stack is in use.");
#if HAVE_VALGRIND
VALGRIND_STACK_DEREGISTER(valgrindStackId);
#endif
- delete [] stack;
+ if (guardPage)
+ munmap(guardPage, guardPageSize + stackSize);
}
void
diff --git a/src/base/fiber.hh b/src/base/fiber.hh
index 3d82075f0..4d95e032b 100644
--- a/src/base/fiber.hh
+++ b/src/base/fiber.hh
@@ -106,8 +106,10 @@ class Fiber
Fiber *link;
// The stack for this context, or a nullptr if allocated elsewhere.
- uint8_t *stack;
+ void *stack;
size_t stackSize;
+ void *guardPage;
+ size_t guardPageSize;
#if HAVE_VALGRIND
unsigned valgrindStackId;
#endif