[Xenomai] rt task & stack overflow

Johann Obermayr johann.obermayr at sigmatek.at
Wed Apr 20 12:09:15 CEST 2016


Am 19.04.2016 um 21:30 schrieb Gilles Chanteperdrix:
> On Tue, Apr 19, 2016 at 09:10:52PM +0200, Gilles Chanteperdrix wrote:
>> On Tue, Apr 19, 2016 at 12:21:48AM +0200, Johann Obermayr wrote:
>>> Hello,
>>>
>>> is there a way to handle a stack overflow with a xenomai  rt_task ?
>>>
>>> this example work for a standard linux
>> This example does not handle stack overflows. It handles the SIGSEGV
>> signal, which may happen in case of stack overflow or for many other
>> reasons. In order to handle properly a stack overflow, you would
>> have to:
>> - use the SA_SIGINFO flag and setup an sa_sigaction handler instead
>> of sa_handler with additional arguments
>> - in the handler, use the additional arguments to extract the fault
>> address and architecture specific stack pointer and check that the
>> fault address is "near" the stack pointer (and in fact it may not be
>> at all)
>> - or walk /proc/self/maps to find the mapping where the fault
>> address is and check if it is "near" a thread stack.
>> - or check that the fault program counter is an operation involving
>> a store or read relative to the stack pointer.
>>
>> But I do not think there is a reliable way to detect stack
>> overflows. It is even possible to overflow the stack so much that
>> the code appears to work by writing to another thread stack (if the
>> overflow length is larger than the glibc guard size).
>>
>>> #define _XOPEN_SOURCE 700
>>> #include <stdio.h>
>>> #include <signal.h>
>>> #include <unistd.h>
>>> void handler(int sig)
>>> {
>>>       printf("stack overflow: %d\n", sig);
>>>       _exit(1);
>>> }
>> Also, using printf in a signal handler is bad. printf is not async
>> signal safe.
> And on my platform at least, SIGSTKSZ is something like 8192 or
> 16384 which may be too small for a printf, so printf could cause a
> stack overflow (depending on the length of the printed string).
>
Hello,

Thanks you for answer.

i have refactoring the example.
Here is the source
-------------------------------------------------- begin source
#define __USE_BSD

#include <stdio.h>
#include <malloc.h>
#include <memory.h>
#include <signal.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/mman.h> //mloockall

#ifdef USE_XENOMAI
#include <native/task.h>
#endif

#define SIGSTACKSIZE    32*1024

void dohandler(const char *name, int sig, siginfo_t *info, void *ptr)
{
     char buf[256];

     int len = sprintf(buf, "%s: signal_handler: %d\n", name, sig);
     write(STDOUT_FILENO, buf, len) ;
     _exit(1);
}

void signal_handler_linux(int sig, siginfo_t *info, void *ptr)
{
     dohandler("linux", sig, info, ptr);
}

void signal_handler_xeno(int sig, siginfo_t *info, void *ptr)
{
     dohandler("xeno", sig, info, ptr);
}


unsigned infinite_recursion(unsigned x) {
     char buf[4*128*1024];

     memset(buf, 0, sizeof(buf));
     return infinite_recursion(x)+1;
}

void help()
{
     printf("program <options>\n");
     printf("  --help              this help\n");
     printf("  --sigstack          use the sigalstack function to set a 
own signal stack\n");
     _exit(1);
}

int main(int argc, char *argv[])
{
#ifdef USE_XENOMAI
     RT_TASK mainTask;
     int rval;
#endif

     static char stack[SIGSTACKSIZE];
     stack_t ss = {
         .ss_size = SIGSTACKSIZE,
         .ss_sp = stack,
     .ss_flags = SS_ONSTACK,
     };
     struct sigaction sa = {
         .sa_sigaction = signal_handler_linux,
         .sa_flags = SA_SIGINFO,
     };
     int i;
     int use_sigstack = 0;

     mlockall(MCL_CURRENT|MCL_FUTURE);

     for(i = 1; i < argc; i++) {
         if (strcmp(argv[i], "--help") == 0) help();
         if (strcmp(argv[i], "--sigstack") == 0) use_sigstack = 1;
     }

     if (use_sigstack) {
         sa.sa_flags |= SA_ONSTACK;
         sigaltstack(&ss, 0);
     }

     sigfillset(&sa.sa_mask);
     sigaction(SIGSEGV, &sa, 0);

#ifdef USE_XENOMAI
     rval = rt_task_shadow(&mainTask, "MainRecursion", 5, 0);
     if (rval)
         printf("rt_task_shadow return:%d\n", rval);
     rval = rt_sigaction(SIGSEGV, signal_handler_xeno);
     if (rval)
         printf("rt_sigaction return:%d\n", rval);

#endif
     infinite_recursion(0);
}
--------------------------------------------- end source

i create to example first without xenomai, second with xenomai.

root at sigmatek-arm-mp:~# ./signaltest01arm
Segmentation fault

root at sigmatek-arm-mp:~# ./signaltest01arm --sigstack
linux: signal_handler: 11

root at sigmatek-arm-mp:~# ./signaltest01armx
Segmentation fault

root at sigmatek-arm-mp:~# ./signaltest01armx --sigstack
Segmentation fault

root at sigmatek-arm-mp:~#

for a standard linux thread the function sigaltstack will work correct.
But not with xenomai (rt_task_shadow)

we use kernel 3.0.53 & xenomai 2.6.2.1.

regards
   Johann





More information about the Xenomai mailing list