mirror of
https://github.com/HeyPuter/gex.git
synced 2026-11-13 20:12:43 -10:00
The page's executable test for instruction fetch asked a + 4 <= end, from the AArch64 build, and fetch asks it of every byte: on x86 the last three bytes of every executable mapping were not code, so an instruction ending there decoded short and the process died as an illegal instruction (status 132). Unity's own Mono hit it in its JIT code: a jmp rel32 at a 64 KiB chunk's +0xfffa (Muck, dm10: 'illegal instruction 0x005611e9 at pc=0x3a204ffa'). The native host asks a + INST_ALIGN. tests/x86-programs/exec-tail.c: code whose last byte is a mapping's last byte, tails of 1 to 8 bytes; on the page tier before the fix: illegal instruction at +0xffb, status 132; after: as natively. tgkill-futex's ack counter is atomic (natively the handlers raced and printed 11). Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]> Claude-Session: https://claude.ai/code/session_1896c5b302a54696aaa92c5f4047f20b
35 lines
1.2 KiB
C
35 lines
1.2 KiB
C
// Code that ends in the last bytes of an executable mapping: a JIT's chunk
|
|
// (Mono's) can end with a 5-byte jmp in its final bytes. Each case puts
|
|
// `mov eax, imm32; ret` so that the ret is the mapping's last byte, then
|
|
// shorter tails down to a lone `ret`.
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <sys/mman.h>
|
|
int main(void) {
|
|
long sum = 0;
|
|
for (int tail = 1; tail <= 8; tail++) {
|
|
unsigned char *p = mmap(0, 4096, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
|
|
if (p == MAP_FAILED) return 1;
|
|
memset(p, 0xcc, 4096);
|
|
unsigned char *f;
|
|
if (tail >= 6) {
|
|
f = p + 4096 - 6;
|
|
unsigned char code[6] = {0xb8, (unsigned char)(40 + tail), 0, 0, 0, 0xc3};
|
|
memcpy(f, code, 6);
|
|
} else {
|
|
// a short jmp back from the tail to a body earlier in the page, then the tail is a jmp rel32 ending at the last byte
|
|
f = p + 4096 - 5;
|
|
unsigned char *body = p + 64;
|
|
unsigned char code[6] = {0xb8, (unsigned char)(40 + tail), 0, 0, 0, 0xc3};
|
|
memcpy(body, code, 6);
|
|
int rel = (int)(body - (f + 5));
|
|
f[0] = 0xe9; memcpy(f + 1, &rel, 4);
|
|
}
|
|
int (*fn)(void) = (int (*)(void))f;
|
|
sum += fn();
|
|
munmap(p, 4096);
|
|
}
|
|
printf("exec-tail sum %ld\n", sum);
|
|
return 0;
|
|
}
|