W^X and !W: atexit() in libc Introducing a case of minimum page permission use in libc void exit(int status) { struct atexit *p; int n; for (p = __atexit; p; p = p->next) for (n = p->ind; --n >= 0;) (*p->fns[n])(); if (__cleanup) (*__cleanup)(); _exit(status); } __atexit and __cleanup contain writeable function pointers! We modified atexit(3) to maintain function pointer storage which is kept non-writeable