I found the error.
I forgot to flush the data cache after doing the writing the
executable code to the data segment.
This can be done using the following function:

static void cacheFlush(void* code, size_t size)
{
        asm volatile (
                "push    {r7}\n"
                "mov     r0, %0\n"
                "mov     r1, %1\n"
                "mov     r7, #0xf0000\n"
                "add     r7, r7, #0x2\n"
                "mov     r2, #0x0\n"
                "svc     0x0\n"
                "pop     {r7}\n"
                :
                : "r" (code), "r" (reinterpret_cast<char*>(code) + size)
                : "r0", "r1", "r2");
}

Now it works :-).



On 28 Jun., 11:12, "[email protected]"
<[email protected]> wrote:
> I wrote a simple data execution prevention (DEP) test to check if my
> DEP patch for Android is working and to also check the PaX patch.
> This worked pretty fine, but my test program crashes with a SIGSEGV in
> 50% of the test runs. In the other cases the tests work perfectly.
> I don't know why my test does not always succeed. I already tried to
> clear the instruction cache. But this did not help either.
> I tried the same on the x86. There it does always work perfectly. But
> it also has a common instruction and data cache. Maybe that has to do
> with the problem.
>
> Any ideas?
>
> @Google: I think Android should have enabled DEP and ASLR in the
> kernel by default, just like iOS :-). This is only a minimal patch
> (you do not need the complete PaX patch)
>
> Here is my test code:
>
> DepTest.cpp:
> #include <stdlib.h>
> #include <stdio.h>
> #include <unistd.h>
> #include <sys/mman.h>
>
> extern "C" uint32_t jmpToCode(uint32_t address);
>
> int main()
> {
>         void* data = new uint32_t[4096];
>
>         uint32_t* code = (uint32_t*) data;
>         // arm-eabi-objdump -d Test
> //      code[0] = 0xef9f0002; // endless loop
>         code[0] = 0xe320f000; // nop
>         code[1] = 0xe320f000; // nop
>         code[2] = 0xe320f000; // nop
>         code[3] = 0xe320f000; // nop
>         code[4] = 0xe320f000; // nop
>         code[5] = 0xe320f000; // nop
>         code[6] = 0xe320f000; // nop
>         code[7] = 0xe1a0f00e; // jump back to calling function -> mov pc, lr
>
>         printf("DEP-Test (1): 0x%X: 0x%X\n", code, code[0]);
>         uint32_t rc = jmpToCode((uint32_t)code);
>         printf("DEP-Test (2): 0x%X 0x%X: 0x%X\n", rc, code, code[0]);
>
>         return 0;
>
> }
>
> Utils.S:
> .text
>
> # The first 4 args are passed via r0 to r3
> # The return code is always in r0
> # pc points to the next instruction to be fetched, not to the
> instructing that will be executed next
> # - in ARM state, the pc always points to the address of the
> instruction plus 8 bytes
> # - in Thumb state, the pc is the instruction address plus 4 bytes
>
> .code 32
> .align 4
> .global jmpToCode
> jmpToCode:
>         push    {ip, lr}
>         mov             lr, pc          @ lr points to the "mov r0, ..." 
> command
>         mov     pc, r0
>         mov             r0, r0
>         pop     {ip, pc}

-- 
unsubscribe: [email protected]
website: http://groups.google.com/group/android-porting

Reply via email to