Raspberry PI hang instruction

August 31, 2015 in Code Snippets, Programming, Raspberry PI, Security by admin

raspberry-NASSource from here

While writing my own assembler for ARM, I realized that an instruction fuzzer can spot some funky results on real CPUs. Undefined behaviour is a known topic for some ancient CPUs like z80, where many undefined instructions have been analyzed and exploited in order to achieve some performance tricks for the demoscene.

But undefined behaviour on modern SOCs and CPUs is not really a known topic for several reasons. First one is that there are several manufacturers and models for every single architecture, and in addition, the microcode is not documented and distributed in encrypted form, so understand what an instruction really does is hard.

This is also a problem for compilers and handwritten assembly optimizations which tend to require several fall-back implementations depending on the CPU model because the same instruction performs different on different chips.

As long as ARM is a fixed-length instruction length (except for Thumb2, which is quite easy to handle), it makes fuzzing those instructions easier than say x86. By understanding how instructions are composed you can quickly reduce the amount of instructions to fuzz.

And this is how I found 4 bytes that hang the RPI CPU; this undefined instruction doesn’t requires special privileges, so any user can execute it and brick the board. Requiring a hardware reset to bring it back to life.

A tiny ELF can be cooked with rabin2:

$ rabin2 -a arm -b32 -C elf:fedeffe7 killrpi

Radare2 allows us to quickly check that instruction with different disassemblers.

$ for a in arm arm.gnu arm.winedbg ; do rasm2 -a $a -b 32 -d fedeffe7 ; done 
    trap ; 
    <UNDEFINED> 0xe7ffdefe 
    ldrbt sp,

This doesn’t seems to show us anything useful, so let’s go deeper with the documentation:

So we can now decompose the bits of that instruction in order to understand what it is supposed to be doing:

BYTES: E7 FF DE FE 

E    7     F    F  D  E F    E 
1110 011 1 1111 [imm12] 1111 [imm4] 

So, acording to this documentation, that instruction is decoded as UDF, which is a variety of instructions that are undefined by definition and are used by debuggers to set breakpoints.

But, why only that specific construction hangs the board? Digging a bit in Google looks like this sequence is used by the Angel Debugger, which is a hardware debugger that is attached to the board using the JTAG connector and that specific core seems to enforce that exception to wait for reply.

The only way to bring it back to live is by unplugging and plugging back the power.

This bug only affects all the models of the first Raspberry PI. The RPI2 is not affected, as well as other ARM devices (phones and tablets) I tried… but maybe, other instructions provoke similar behavior 🙂

Follow the original link for more information.