Under 4.1.5 x86-64 kernel, PT_GNU_STACK interferes with mprotect. With PT_GNU_STACK, __mprotect (newp->start, newp->len, PROT_READ|PROT_WRITE) changes the pages to PROT_READ|PROT_WRITE|PROT_EXEC: [hjl@gnu-6 pr18801]$ cat foo.c int zoo_1 (void) { return 0; } void *selector (void) { return (void *)&zoo_1; } int zoo(void) __attribute__ ((ifunc ("selector"))); int main(void) { return zoo (); } [hjl@gnu-6 pr18801]$ gcc -O2 foo.c -mcmodel=large -pie [hjl@gnu-6 pr18801]$ ./a.out Segmentation fault # <--- This is expected. [hjl@gnu-6 pr18801]$ gcc -O2 foo.c -mcmodel=large -pie -Wl,-z,execstack [hjl@gnu-6 pr18801]$ ./a.out # <--- This should segfault. [hjl@gnu-6 pr18801]$ Before mprotect: 555555554000-555555555000 r-xp 00000000 08:11 24735096 .. After mprotect: 555555554000-555555555000 rwxp 00000000 08:11 24735096 ^ It should be off. IA32 is OK: [hjl@gnu-6 pr18801]$ gcc -O2 foo.c -m32 -pie [hjl@gnu-6 pr18801]$ ./a.out Segmentation fault [hjl@gnu-6 pr18801]$ gcc -O2 foo.c -m32 -pie -Wl,-z,execstack [hjl@gnu-6 pr18801]$ ./a.out Segmentation fault [hjl@gnu-6 pr18801]$