Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Make Stack Pointer to a mmap returned pointer. (Linux, 32bit VM)

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)

like image 760
Edison Avatar asked May 13 '11 07:05

Edison


2 Answers

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,
    (this is architecture-dependent - so x86, ARM, PPC, MIPS, ... all have their own, and this is what contains the register set including the stackpointer).
like image 152
FrankH. Avatar answered Oct 14 '22 21:10

FrankH.


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.

like image 2
Edison Avatar answered Oct 14 '22 21:10

Edison