Reputation: 11
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
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
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