Page 1 of 1

Relocation and stack

Posted: Mon Oct 24, 2011 2:46 pm
by Jezze
I'm trying to do relocation (actually dynamic loading of modules) and it almost works.

What I've done is I implemented a syscall:

Code: Select all

call_add_module("test.ko")
The test.ko file is really small. This is the objdump of the entire program.

Code: Select all

00000000 <init>:
   0:   e9 fc ff ff ff          jmp    1 <init+0x1>
When entering the kernel stub for this syscall I read the content of test.ko and place it at a fixed position X in memory. Because it is an elf object file the .text section starts at offset 0x40 so what I do is that I change the value at address X + 0x40 + 0x01 to point to a place in memory where there exist a function called repfunc that I wish to link:

Code: Select all


// Relocated address
int reloc = (int)X + 0x40;

// Linking to repfunc
int *s = (int *)(reloc + 0x01);
*s += (int)repfunc - reloc;

// Running
void (*run)() = (void *)reloc;
run();

Now the interesting thing is that repfunc is actually called and if repfunc is empty it will succeed but as soon as repfunc in turn calls another function it will fail. This lead me to believe there is a problem with the stack but I have not had any problems with the stack for any other syscall so it might be the way I relocate. I've tried many combinations just to check I haven't done anything stupid but it refuses to work.

What have I missed?

Re: Relocation and stack

Posted: Mon Oct 24, 2011 3:36 pm
by Jezze
Ok I tried every offset I could think of and found one that worked but I don't understand why. In the repfunc I added a call to another function print(int, char*).

Code: Select all


repfunc()
{
    print(1, "Module loaded");
}

And if I changed this

Code: Select all

*s += (int)repfunc - reloc;
to

Code: Select all

*s += (int)repfunc - reloc - 0x06;
It worked perfectly. It makes no sense to me though.

Re: Relocation and stack

Posted: Mon Oct 24, 2011 5:45 pm
by Jezze
Ok, think I've figured it out. The correct offset was in fact 0x05

The value of *s is 0xffffffc before applying the relocation.

The difference is 4 and the offset is 1.

This gave me relocation address:

*s += (int)repfunc - reloc - 0x04 - 0x01;

Which seems to work well.

Sometimes it is just good to put a question out in order to help yourself =)