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)
{
/* catch control-c */
lx_sigaction(LX_SIGINT, sigint_handler);
lx_sigaction(LX_SIGINT, sigint_handler, false);
/* catch SIGCHLD */
lx_sigaction(LX_SIGCHLD, sigchld_handler);
lx_sigaction(LX_SIGCHLD, sigchld_handler, false);
/* create resource directory under /tmp */
lx_mkdir(resource_path(), S_IRWXU);

View File

@ -17,6 +17,7 @@
/* base-internal includes */
#include <base/internal/native_thread.h>
#include <base/internal/stack.h>
/* Linux syscall bindings */
#include <linux_syscalls.h>
@ -26,17 +27,22 @@ using namespace Genode;
static void empty_signal_handler(int) { }
static char signal_stack[0x2000] __attribute__((aligned(0x1000)));
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
* 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

View File

@ -78,17 +78,18 @@ void exception_signal_handler(int signum)
* We reset the signal handler to SIG_DFL and trigger exception again,
* i.e., terminate the process.
*/
lx_sigaction(signum, nullptr);
lx_sigaction(signum, nullptr, false);
return;
}
void lx_exception_signal_handlers()
{
lx_sigaction(LX_SIGILL, exception_signal_handler);
lx_sigaction(LX_SIGBUS, exception_signal_handler);
lx_sigaction(LX_SIGFPE, exception_signal_handler);
lx_sigaction(LX_SIGSEGV, exception_signal_handler);
/* use alternate stack in fatal-signal handlers */
lx_sigaction(LX_SIGILL, exception_signal_handler, true);
lx_sigaction(LX_SIGBUS, exception_signal_handler, true);
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 char signal_stack[0x2000] __attribute__((aligned(0x1000)));
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 retried after a signal gets received.
*/
lx_sigaction(LX_SIGUSR1, empty_signal_handler);
Thread * const thread = Thread::myself();
lx_sigaction(LX_SIGUSR1, empty_signal_handler, false);
/* inform core about the new thread and process ID of the new thread */
Linux_native_cpu_client native_cpu(thread->_cpu_session->native_cpu());
@ -141,7 +143,7 @@ void Thread::start()
*/
static bool threadlib_initialized = false;
if (!threadlib_initialized) {
lx_sigaction(LX_SIGCANCEL, thread_exit_signal_handler);
lx_sigaction(LX_SIGCANCEL, thread_exit_signal_handler, false);
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
* transparently retried after a signal gets received.
*/
lx_sigaction(LX_SIGUSR1, empty_signal_handler);
lx_sigaction(LX_SIGUSR1, empty_signal_handler, false);
}
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
* 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)
*/
lx_sigaction(LX_SIGCHLD, (void (*)(int))1);
lx_sigaction(LX_SIGCHLD, (void (*)(int))1, false);
/* assign 'Native_thread::Meta_data' pointer to TLS entry */
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
*/
inline int lx_sigaction(int signum, void (*handler)(int))
inline int lx_sigaction(int signum, void (*handler)(int), bool altstack)
{
struct kernel_sigaction act;
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.
*/
enum { SA_RESTORER = 0x04000000 };
act.flags = SA_RESTORER | SA_ONSTACK;
act.flags = SA_RESTORER;
act.restorer = lx_restore_rt;
#else
act.flags = SA_ONSTACK;
act.flags = 0;
act.restorer = 0;
#endif
/* use alternate signal stack if requested */
act.flags |= altstack ? SA_ONSTACK : 0;
lx_sigemptyset(&act.mask);
return lx_syscall(SYS_rt_sigaction, signum, &act, 0UL, _NSIG/8);