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
sigsegv(int sig,siginfo_t * info,ucontext_t * uc)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
main()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