I found a couple of interesting integer underflows leading to memcpy()
wild copies in a TLV parser process of some random IoT firmware. It is 32-bit ARMv7.
I'm able to emulate the userspace process using qemu and debug it, I can confirm the wild copy by inspecting register state before the memcpy()
and memory state after it, but when I let it run, it won't crash. No page fault, no overwritten PC, it just exits.
I tried to come up with some C code that resembles what my code in the field does:
#include <string.h>
#include <stdlib.h>
void parse_stuff(char*);
int main(int argc, char** argv) {
char buffer[128];
char c;
while (1) {
parse_stuff(buffer);
c = getc(stdin);
if (c == 'e')
return 0;
}
}
void parse_stuff(char* buf){
char* heap = malloc(0x1000);
for(int i=0;i<0x1000;i++)
heap[i] = 0x41;
memcpy(buf, heap, 0xffffffff);
}
If I compile this and run it in qemu, it won't crash.
There is a tight loop and the parser routine is called from that, so I'm guessing if the parse_stuff stack frame is a leaf, then a stack bof could only happen when the caller is the one trying to restore the PC to its caller (entry / libc_start_main
, whatever), but I'm still puzzled by this, because on x86-64, this easily crashes so somehow the ARM binary or maybe the QEMU environment does not trigger that page violation that I'm expecting to happen due to the wild memcpy()
, even if there is no PC control due to the cyclometric situation this way.
Has any of you run into something like this?
#include <stdio.h>
is missing and a cast of themalloc()
return value). What compiler do you use (also exact version)? What compiler and linker options? Also, are you certain that this is the exact code you are observing and that this isn't perchance some sort of implementation where the 0xffffffff for the length happens to mean -1 and some "magic" happens (such as looking for a terminating character as with strings)? godbolt.org/z/Machnnr8Y