Yonghong Yan
Yonghong Yan

Reputation: 11

change the stack on the fly of c program

I am writing the following code that will be able to change the stack of function call. but it always runs into segfault on printf. I debugged the code with assembly, the stack was successfully switched. it is the printf statement that created the segfault and not sure the reason. anybody has any clue what direction i should look into more?

Thanks.

char stack[4000000*4]; 

void foo(int ad) {
    int i = 100;
    int sum = i*i + ad;
    printf("stack changed to %X\n", stack);
}

/* in this example, foo (and its decendents) live on a new stack */
void change_stack(void *newstack) {
    void *ctx[5]; // Jump buffer for setjmp/longjmp.
    if (0 == __builtin_longjmp(ctx)) {
        ctx[2] = newstack; // switch stack  
        __builtin_longjmp(ctx, 1);/* here stack is switched */
    } else {
    /* now live on new stack, can we pass parameters now ? */
    int ad = 20;
    foo(ad);
    }
}

int main (int argc, char** argv)
{
  int i = 10;
  change_stack(stack);
  printf("return, %d\n", i);
  return 0;
}

Upvotes: 1

Views: 1695

Answers (2)

yhdang
yhdang

Reputation: 189

To anyone who still wants to play with the stack and also encountered SIGSEGV in printf, here is an important point:

You can find one of the subroutines of printf, __GI___tcgetattr under /path-to-glibc/sysdeps/unix/sysv/linux/tcgetattr.c. There is one instrution in it:

movdqa (%rsp),%xmm0

And according to this answer, it reads 16-byte align memory from source address. So you should keep the address of %rsp at least 16-byte address align when you switch the stack, otherwise you will get a SIGSEGV.

Upvotes: 1

Drew McGowen
Drew McGowen

Reputation: 11706

You switch stacks without copying the contents of the old one. When change_stack returns, the results are undefined (it may, for example, jump to address NULL, causing a segfault). Also, things like local variables will also be undefined.

Also, (assuming we're talking x86 here), the stack pointer is decremented on pushes. Since the new stack pointer you assigned is the base (i.e. lowest) address of your stack array, any push will decrease the pointer outside of this array, also possibly resulting in a segfault.

Upvotes: 2

Related Questions