1 #define _GNU_SOURCE 2 #include <sys/mman.h> 3 #include <signal.h> 4 #include <stdio.h> 5 #include <assert.h> 6 7 volatile unsigned long flags; 8 volatile unsigned long flags_after; 9 int *addr; 10 11 void sigsegv(int sig, siginfo_t *info, ucontext_t *uc) 12 { 13 flags = uc->uc_mcontext.gregs[REG_EFL]; 14 mprotect(addr, 4096, PROT_READ|PROT_WRITE); 15 } 16 17 int main() 18 { 19 struct sigaction sa = { .sa_handler = (void *)sigsegv, .sa_flags = SA_SIGINFO }; 20 sigaction(SIGSEGV, &sa, NULL); 21 22 /* fault in the page then protect it */ 23 addr = mmap (NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANON, -1, 0); 24 *addr = 0x1234; 25 mprotect(addr, 4096, PROT_READ); 26 27 asm("# set flags to all ones \n" 28 "mov $-1, %%eax \n" 29 "movq addr, %%rdi \n" 30 "sahf \n" 31 "sub %%eax, (%%rdi) \n" 32 "pushf \n" 33 "pop flags_after(%%rip) \n" : : : "eax", "edi", "memory"); 34 35 /* OF can have any value before the SUB instruction. */ 36 assert((flags & 0xff) == 0xd7 && (flags_after & 0x8ff) == 0x17); 37 } 38