arraysmemorysegmentation-faultarmv6opcodes

SIGSEGV at executing machine code from array on ARMv6


I'm trying to execute machine code stored in array on first Raspberry Pi under ArchLinux. I've done it under x86, but I can't get what I'm doing wrong under ARMv6. The problem is that it doesn't matter what code is in the array, it will always crash after executing first instruction. Code is compiled with Thumb interworking disabled under gcc 5.2.0.

This is the code I've used for testing:

#include <stdio.h>

char shellcode[] = {
 0x04, 0xb0, 0x2d, 0xe5, // push {r11}
 0x00, 0xb0, 0x8d, 0xe2, // add r11, sp, #0
 0x00, 0x00, 0xa0, 0xe1, // nop
 0x00, 0x00, 0xa0, 0xe1, // nop
 0x00, 0x00, 0xa0, 0xe1, // nop
 0x00, 0xd0, 0x4b, 0xe2, // sub sp, r11, #0
 0x04, 0xb0, 0x9d, 0xe4, // pop {r11}
 0x1e, 0xff, 0x2f, 0xe1  // bx lr
};

void shellcode2() {
 asm("mov r0, r0");
 asm("mov r0, r0");
}

typedef void (*entry_t)();

int main() {
 entry_t entry = (entry_t)(shellcode);
 entry();

 return 0;
}

Machine code was taken from the shellcode2 function disassembly, I don't know if it is proper way to do this but the problem is that even if first instruction in shellcode is a nop - it'll crash.

Program received signal SIGSEGV, Segmentation fault.
0x00020704 in shellcode ()
(gdb) disas /r
Dump of assembler code for function shellcode:
=> 0x00020704 <+0>:     04 b0 2d e5     push    {r11}           ; (str r11, [sp, #-4]!)
   0x00020708 <+4>:     00 b0 8d e2     add     r11, sp, #0
   0x0002070c <+8>:     00 00 a0 e1     nop                     ; (mov r0, r0)
   0x00020710 <+12>:    00 00 a0 e1     nop                     ; (mov r0, r0)
   0x00020714 <+16>:    00 00 a0 e1     nop                     ; (mov r0, r0)
   0x00020718 <+20>:    00 d0 4b e2     sub     sp, r11, #0
   0x0002071c <+24>:    04 b0 9d e4     pop     {r11}           ; (ldr r11, [sp], #4)
   0x00020720 <+28>:    1e ff 2f e1     bx      lr
End of assembler dump.

Am I missing something or just doing it plain wrong on ARMv6? If anybody can point me in the proper direction I would be grateful.

Thanks in advance.


Solution

  • Putting the comment in an answer so future users can find it.

    ARMv6 supports 'Execute Never' regions, which can be used to prevent pages that contain data from being executed as code.

    This is done as a security measure, since it protects against a variety of hack approaches. But it can be an issue for programs trying to do self-modifying code (which is effectively what OP is trying to do).

    Check out the ARMv6 docs for details.