I'm trying to move my stack pointer to a mmap-ed region to simulate a context switch, but somehow the code below always give a segmentation error:
C:
struct savectx {
void *regs[JB_SIZE];
};
struct savectx* initctx=(struct savectx*)malloc(sizeof(savectx));
void *newsp;
if ((newsp=mmap(0,STACK_SIZE,PROT_READ|PROT_WRITE,
MAP_PRIVATE|MAP_ANONYMOUS,0,0))==MAP_FAILED){
perror("mmap failed");
}
initctx->regs[4]=newsp;
restorectx(initctx,0);
x86:
restorectx:
movl 4(%esp),%ecx /*Move jump buffer addr to ecx */
movl 8(%esp),%eax /*Longjmp return value */
movl (JB_SP*4)(%ecx),%esp /*JB_SP is defined to be 4,*/
The program fails on the last line of the assembly.
For malloc I know that I might have to add 0x000f0000 to the pointer, but what about mmap? Or how do we make the stack adjust to the mmapp-ed location. (man page for mmap: http://linux.die.net/man/3/mmap, compiled with GCC on ubuntu)
Linux (or UN*X in general) already has functions to perform this sort of context substitution:
setcontext()
makecontext()
If you use those, you can substitute the entire initial register set (including the stackpointer) by setting up a suitable ucontext_t
/ struct sigcontext
(the uc_mcontext
member of ucontext_t
). Calling setcontext()
then becomes kind-of an extended longjmp()
.
A usage example can be found in the Wikipedia article on setcontext()
.
For the Linux definition of ucontext_t
, see:
ucontext_t
: Linux sourcecode,
struct sigcontext
: Linux sourcecode, x86 architecture definition,So the problem was actually that mmap grows at the opposite direction of the stack (which, sadly, I forgot). So to assign the pointer, I just had to assign (mmaped_stack+stack_size) instead of just the pointer.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With