This is the mail archive of the java-discuss@sourceware.cygnus.com mailing list for the Java project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Re: stack overflow


> 
> I'm sure it can be implemented portably.  I don't know about
> portably *and* efficiently.  I also don't know (remember) anything
> about the Gcc implementation, and how general/robust it is.
> 

In case anybody is interested, here's my test program for the sparc.
It tests whether we can recover from a segfault taken on an alternate
stack.

It works if the SIGSEGV is caused by a null pointer access.
It doesn't work if the SIGSEGV is caused by a stack overflow, however.
Maybe I'm doing something wrong here.

I should say that I've worked with a system 5 years ago for which
userland stack expansion did work.  This system ran only on 
SunOS 4.1.x, however.

A similar test to the one I show below fails on Linux RH 6.0 as well.  
Linux versions such as RH5.2 don't even support sigaltstack.
I tried both the case where the thread stack in question is the main 
thread stack or a stack I allocated (either on the data segment or
in anonymously mmapped memory --- same result.)

I'm wondering whether this approach is really portable?  For instance, 
under linux-threads, you don't have the option to specify alternate stack 
locations and sizes when creating a thread.  POSIX 1b guarantees mprotect 
to only work on mmapped() pages.  Is it portable to assume that you can 
mmap your own native, kernel-provided thread?  I don't know.

I would really like to learn just how you do this.
You said something about the gcc implementation: do you have any pointers?
Is this part of any of the runtime libraries accompanying gcc?

	- Godmar


/* stack1sparc.c
   compile with gcc -o stack1sparc stack1sparc.c

   Sparc/Solaris only.

   run with 
   "./stack1sparc"      for stack overflow test
   "./stack1sparc -np"  for sigsegv test.
 */
#include <setjmp.h>
#include <signal.h>
#include <stdio.h>
#include <fcntl.h>
#include <assert.h>
#include <sys/mman.h>

jmp_buf env;
jmp_buf env2;
void *guard;
void *thread_stack;
char alternate_stack[64*4096];


void handler(int sig)
{
        int rc;
        printf("handler stack %p\n", &rc);
        mprotect(guard, 4096, PROT_READ|PROT_WRITE);
        longjmp(env, 1);
}

void overflow(int i) { 
        int r;
        if (i % 8 == 0) {
            printf("%p ", &r); 
        }
        if (i % 64 == 0) {
            printf("\n"); 
        }
        overflow(i+1); 
}

static int what;

void
new_thread()
{
        int rc;
        printf("current sp at %p\n", &rc);
        if (what) {
                /* demonstrate that a normal SEGFAULT works */
                *(int*)0 = 42;
        } else {
                overflow(1);
        }
}

main(int ac, char *av[])
{
        stack_t ss;
        int rc;
        setbuf(stdout, 0);

        what = ac > 1 && !strcmp(av[1], "-np");

        guard = thread_stack = mmap(0, 16*4096, PROT_READ|PROT_WRITE, MAP_PRIVATE, 
                open("/dev/zero", O_RDWR)
                , 0);
        if ((int)guard == -1) 
                perror("mmap"), exit(0);

        rc = mprotect(guard, 4096, PROT_NONE);
        if (rc != 0)
                perror("mprotect"), exit(0);

        ss.ss_sp = &alternate_stack[(sizeof alternate_stack)/2];
        ss.ss_size = (sizeof alternate_stack)/2;
        ss.ss_flags = 0;
        printf("alternate at %p, size is %d\n", ss.ss_sp, ss.ss_size);
        rc = sigaltstack(&ss, (stack_t*)0 /* old stack_t */);
        if (rc != 0)
                perror("sigaltstack"), exit(0);

        printf("guarding from %p-%p mystack is %p\n", guard, guard+4096, &rc);

        signal(SIGSEGV, (void(*)(int))handler);
        if (setjmp(env)) {
                printf("okay, caught stackoverflow\n");
        } else {
                if (setjmp(env2)) {
                        new_thread();
                } else {
                        /* fix up stack pointer */
                        ((void**)&env2)[1] = thread_stack + 8*4096;
                        longjmp(env2, 1);
                } 
        }
}


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]