#define _GNU_SOURCE #include #include #include #include volatile unsigned long flags; volatile unsigned long flags_after; int *addr; void sigsegv(int sig, siginfo_t *info, ucontext_t *uc) { flags = uc->uc_mcontext.gregs[REG_EFL]; mprotect(addr, 4096, PROT_READ|PROT_WRITE); } int main() { struct sigaction sa = { .sa_handler = (void *)sigsegv, .sa_flags = SA_SIGINFO }; sigaction(SIGSEGV, &sa, NULL); /* fault in the page then protect it */ addr = mmap (NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANON, -1, 0); *addr = 0x1234; mprotect(addr, 4096, PROT_READ); asm("# set flags to all ones \n" "mov $-1, %%eax \n" "movq addr, %%rdi \n" "sahf \n" "sub %%eax, (%%rdi) \n" "pushf \n" "pop flags_after(%%rip) \n" : : : "eax", "edi", "memory"); /* OF can have any value before the SUB instruction. */ assert((flags & 0xff) == 0xd7 && (flags_after & 0x8ff) == 0x17); }