linux: place alternate signal stack in stack area

The alternate stack must use the stack area as, e.g., Thread::myself()
depends on this property. Hybrid components do not depend on this
property and, therefore, use a static stack buffer.

Fixes #1935
This commit is contained in:
Christian Helmuth 2016-06-22 16:14:18 +02:00
parent d8c34237bf
commit d7ddc83fa9
6 changed files with 36 additions and 23 deletions

View File

@ -90,10 +90,10 @@ Platform::Platform()
: _core_mem_alloc(nullptr) : _core_mem_alloc(nullptr)
{ {
/* catch control-c */ /* catch control-c */
lx_sigaction(LX_SIGINT, sigint_handler); lx_sigaction(LX_SIGINT, sigint_handler, false);
/* catch SIGCHLD */ /* catch SIGCHLD */
lx_sigaction(LX_SIGCHLD, sigchld_handler); lx_sigaction(LX_SIGCHLD, sigchld_handler, false);
/* create resource directory under /tmp */ /* create resource directory under /tmp */
lx_mkdir(resource_path(), S_IRWXU); lx_mkdir(resource_path(), S_IRWXU);

View File

@ -17,6 +17,7 @@
/* base-internal includes */ /* base-internal includes */
#include <base/internal/native_thread.h> #include <base/internal/native_thread.h>
#include <base/internal/stack.h>
/* Linux syscall bindings */ /* Linux syscall bindings */
#include <linux_syscalls.h> #include <linux_syscalls.h>
@ -26,17 +27,22 @@ using namespace Genode;
static void empty_signal_handler(int) { } static void empty_signal_handler(int) { }
static char signal_stack[0x2000] __attribute__((aligned(0x1000)));
void Thread::_thread_start() void Thread::_thread_start()
{ {
lx_sigaltstack(signal_stack, sizeof(signal_stack)); Thread * const thread = Thread::myself();
/* use primary stack as alternate stack for fatal signals (exceptions) */
void *stack_base = (void *)thread->_stack->base();
size_t stack_size = thread->_stack->top() - thread->_stack->base();
lx_sigaltstack(stack_base, stack_size);
/* /*
* Set signal handler such that canceled system calls get not transparently * Set signal handler such that canceled system calls get not transparently
* retried after a signal gets received. * retried after a signal gets received.
*/ */
lx_sigaction(LX_SIGUSR1, empty_signal_handler); lx_sigaction(LX_SIGUSR1, empty_signal_handler, false);
/* /*
* Deliver SIGCHLD signals to no thread other than the main thread. Core's * Deliver SIGCHLD signals to no thread other than the main thread. Core's

View File

@ -78,17 +78,18 @@ void exception_signal_handler(int signum)
* We reset the signal handler to SIG_DFL and trigger exception again, * We reset the signal handler to SIG_DFL and trigger exception again,
* i.e., terminate the process. * i.e., terminate the process.
*/ */
lx_sigaction(signum, nullptr); lx_sigaction(signum, nullptr, false);
return; return;
} }
void lx_exception_signal_handlers() void lx_exception_signal_handlers()
{ {
lx_sigaction(LX_SIGILL, exception_signal_handler); /* use alternate stack in fatal-signal handlers */
lx_sigaction(LX_SIGBUS, exception_signal_handler); lx_sigaction(LX_SIGILL, exception_signal_handler, true);
lx_sigaction(LX_SIGFPE, exception_signal_handler); lx_sigaction(LX_SIGBUS, exception_signal_handler, true);
lx_sigaction(LX_SIGSEGV, exception_signal_handler); lx_sigaction(LX_SIGFPE, exception_signal_handler, true);
lx_sigaction(LX_SIGSEGV, exception_signal_handler, true);
} }

View File

@ -46,19 +46,21 @@ static Lock &startup_lock()
static void thread_exit_signal_handler(int) { lx_exit(0); } static void thread_exit_signal_handler(int) { lx_exit(0); }
static char signal_stack[0x2000] __attribute__((aligned(0x1000)));
void Thread::_thread_start() void Thread::_thread_start()
{ {
lx_sigaltstack(signal_stack, sizeof(signal_stack)); Thread * const thread = Thread::myself();
/* use primary stack as alternate stack for fatal signals (exceptions) */
void *stack_base = (void *)thread->_stack->base();
size_t stack_size = thread->_stack->top() - thread->_stack->base();
lx_sigaltstack(stack_base, stack_size);
/* /*
* Set signal handler such that canceled system calls get not * Set signal handler such that canceled system calls get not
* transparently retried after a signal gets received. * transparently retried after a signal gets received.
*/ */
lx_sigaction(LX_SIGUSR1, empty_signal_handler); lx_sigaction(LX_SIGUSR1, empty_signal_handler, false);
Thread * const thread = Thread::myself();
/* inform core about the new thread and process ID of the new thread */ /* inform core about the new thread and process ID of the new thread */
Linux_native_cpu_client native_cpu(thread->_cpu_session->native_cpu()); Linux_native_cpu_client native_cpu(thread->_cpu_session->native_cpu());
@ -141,7 +143,7 @@ void Thread::start()
*/ */
static bool threadlib_initialized = false; static bool threadlib_initialized = false;
if (!threadlib_initialized) { if (!threadlib_initialized) {
lx_sigaction(LX_SIGCANCEL, thread_exit_signal_handler); lx_sigaction(LX_SIGCANCEL, thread_exit_signal_handler, false);
threadlib_initialized = true; threadlib_initialized = true;
} }

View File

@ -71,7 +71,7 @@ __attribute__((constructor(101))) void lx_hybrid_init()
* Set signal handler such that canceled system calls get not * Set signal handler such that canceled system calls get not
* transparently retried after a signal gets received. * transparently retried after a signal gets received.
*/ */
lx_sigaction(LX_SIGUSR1, empty_signal_handler); lx_sigaction(LX_SIGUSR1, empty_signal_handler, false);
} }
namespace Genode { namespace Genode {
@ -345,12 +345,12 @@ static void adopt_thread(Native_thread::Meta_data *meta_data)
* Set signal handler such that canceled system calls get not * Set signal handler such that canceled system calls get not
* transparently retried after a signal gets received. * transparently retried after a signal gets received.
*/ */
lx_sigaction(LX_SIGUSR1, empty_signal_handler); lx_sigaction(LX_SIGUSR1, empty_signal_handler, false);
/* /*
* Prevent children from becoming zombies. (SIG_IGN = 1) * Prevent children from becoming zombies. (SIG_IGN = 1)
*/ */
lx_sigaction(LX_SIGCHLD, (void (*)(int))1); lx_sigaction(LX_SIGCHLD, (void (*)(int))1, false);
/* assign 'Native_thread::Meta_data' pointer to TLS entry */ /* assign 'Native_thread::Meta_data' pointer to TLS entry */
pthread_setspecific(tls_key(), meta_data); pthread_setspecific(tls_key(), meta_data);

View File

@ -245,7 +245,7 @@ extern "C" void lx_restore_rt (void);
/** /**
* Simplified binding for sigaction system call * Simplified binding for sigaction system call
*/ */
inline int lx_sigaction(int signum, void (*handler)(int)) inline int lx_sigaction(int signum, void (*handler)(int), bool altstack)
{ {
struct kernel_sigaction act; struct kernel_sigaction act;
act.handler = handler; act.handler = handler;
@ -258,12 +258,16 @@ inline int lx_sigaction(int signum, void (*handler)(int))
* when leaving the signal handler and it should call the rt_sigreturn syscall. * when leaving the signal handler and it should call the rt_sigreturn syscall.
*/ */
enum { SA_RESTORER = 0x04000000 }; enum { SA_RESTORER = 0x04000000 };
act.flags = SA_RESTORER | SA_ONSTACK; act.flags = SA_RESTORER;
act.restorer = lx_restore_rt; act.restorer = lx_restore_rt;
#else #else
act.flags = SA_ONSTACK; act.flags = 0;
act.restorer = 0; act.restorer = 0;
#endif #endif
/* use alternate signal stack if requested */
act.flags |= altstack ? SA_ONSTACK : 0;
lx_sigemptyset(&act.mask); lx_sigemptyset(&act.mask);
return lx_syscall(SYS_rt_sigaction, signum, &act, 0UL, _NSIG/8); return lx_syscall(SYS_rt_sigaction, signum, &act, 0UL, _NSIG/8);