From 5bfde967dcbbfae884e343425da1fc069a9c4b86 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Fri, 16 Nov 2018 17:07:42 -0800 Subject: 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 Maintainer: Gabe Black --- src/base/fiber.cc | 39 ++++++++++++++++++++++++++++----------- src/base/fiber.hh | 4 +++- 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 #endif +#include +#include + #include +#include #include #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 -- cgit v1.2.3