From: Ingo Molnar From: David Mosberger The "No eXecute patch for x86" causes a serious exec() performance degradation on ia64 since it ends up incorrectly turning on the execute protection on all segments (since most ia64 binaries don't have a gnu_stack program-header). My change enforces the X bit for _all_ applications and gives the X bit to almost all mappings created by legacy applications: 005a1000-005b6000 r-xp 00000000 09:00 1786072 /lib/ld-2.3.3.so 005b6000-005b7000 r--p 00014000 09:00 1786072 /lib/ld-2.3.3.so 005b7000-005b8000 rwxp 00015000 09:00 1786072 /lib/ld-2.3.3.so 005be000-006d3000 r-xp 00000000 09:00 1786073 /lib/tls/libc-2.3.3.so 006d3000-006d5000 r--p 00115000 09:00 1786073 /lib/tls/libc-2.3.3.so 006d5000-006d7000 rwxp 00117000 09:00 1786073 /lib/tls/libc-2.3.3.so 006d7000-006d9000 rwxp 006d7000 00:00 0 00da2000-00da3000 r-xp 00da2000 00:00 0 01000000-01004000 r-xp 00000000 09:01 13356378 /home/mingo/cat-lowaddr 01004000-01005000 rwxp 00003000 09:01 13356378 /home/mingo/cat-lowaddr 08590000-085b1000 rwxp 08590000 00:00 0 f6e48000-f6e49000 r-xp 00e4b000 09:00 2439993 /usr/lib/locale/locale-archive f6e49000-f6e7b000 r-xp 00dc3000 09:00 2439993 /usr/lib/locale/locale-archive f6e7b000-f707b000 r-xp 00000000 09:00 2439993 /usr/lib/locale/locale-archive f707b000-f707c000 rwxp f707b000 00:00 0 fef8a000-ff000000 rwxp fef8a000 00:00 0 ffffd000-ffffe000 ---p 00000000 00:00 0 This way you get what you see. An X mapping is executable, a !X one isnt. No magic "this applications' mappings means this, that application's mappings mean that". This also streamlines the kernel side of any NX solution added to an arch where applications had executability expectations: you can just add the capability because the mappings done lie anymore and compatibility is done by following that old expectation for old binaries. No hackery with personalities, split decisions in the pte handling paths, etc. So as you can see in the above maps file, the change impacts the default mappings for the stack, heap and mmap()s. The only narrow exeception is that if legacy userspace asks for !PROT_EXEC via mprotect() explicitly and then expects executability _that_ will be denied (fortunately we havent met such a case yet) - but all the other cases will result in executable mappings, to preserve compatibility. E.g. there are only two non-executable mappings in the above layout, both were created by glibc via mprotect() and are fully expected to be non-executable. The process stack's executability itself is controlled via the value of PT_GNU_STACK - either X or !X. (subsequently any newly loaded shared library might also change the process' stack. So if you link against an older library without PT_GNU_STACK then the presumption will be the compatible one: to have an executable stack. This is not an issue in new distros, but might help with using third party libraries.) All of this is needed to have a smooth sailing into the NX world. Signed-off-by: Andrew Morton --- 25-akpm/fs/binfmt_elf.c | 6 ++++++ 1 files changed, 6 insertions(+) diff -puN fs/binfmt_elf.c~serious-performance-regression-due-to-nx-patch fs/binfmt_elf.c --- 25/fs/binfmt_elf.c~serious-performance-regression-due-to-nx-patch 2004-07-12 21:49:31.280325824 -0700 +++ 25-akpm/fs/binfmt_elf.c 2004-07-12 21:49:31.285325064 -0700 @@ -627,8 +627,14 @@ static int load_elf_binary(struct linux_ executable_stack = EXSTACK_DISABLE_X; break; } +#ifndef CONFIG_DEFAULT_NOEXEC + /* + * Legacy binaries (unless the arch defaults to noexec) have an + * expectation of executability - turn it on: + */ if (i == elf_ex.e_phnum) def_flags |= VM_EXEC | VM_MAYEXEC; +#endif /* Some simple consistency checks for the interpreter */ if (elf_interpreter) { _