From: Andi Kleen This effectively enables executable stack and executable heap for all 32bit programs on x86-64, except if noexec32=on is specified. This does not support changing this with personality right now, this would need more intrusive changes. A 64bit process will always turn it off and a 32bit process turn it on. Also readd the noexec32=on option to turn this off and fix a minor bug in noexec=... (would be reported as unknown option) Signed-off-by: Andi Kleen Signed-off-by: Andrew Morton --- 25-akpm/arch/x86_64/ia32/ia32_binfmt.c | 4 ++++ 25-akpm/arch/x86_64/kernel/process.c | 6 ++++++ 25-akpm/arch/x86_64/kernel/setup64.c | 25 +++++++++++++++++++++++-- 25-akpm/include/asm-x86_64/pgtable.h | 2 +- 4 files changed, 34 insertions(+), 3 deletions(-) diff -puN arch/x86_64/ia32/ia32_binfmt.c~force-read-implies-exec-for-all-32bit-processes-in-x86-64 arch/x86_64/ia32/ia32_binfmt.c --- 25/arch/x86_64/ia32/ia32_binfmt.c~force-read-implies-exec-for-all-32bit-processes-in-x86-64 2005-02-08 01:02:15.000000000 -0800 +++ 25-akpm/arch/x86_64/ia32/ia32_binfmt.c 2005-02-08 01:02:15.000000000 -0800 @@ -249,6 +249,8 @@ elf_core_copy_task_xfpregs(struct task_s #define elf_check_arch(x) \ ((x)->e_machine == EM_386) +extern int force_personality32; + #define ELF_EXEC_PAGESIZE PAGE_SIZE #define ELF_HWCAP (boot_cpu_data.x86_capability[0]) #define ELF_PLATFORM ("i686") @@ -262,6 +264,8 @@ do { \ set_thread_flag(TIF_ABI_PENDING); \ else \ clear_thread_flag(TIF_ABI_PENDING); \ + /* XXX This overwrites the user set personality */ \ + current->personality |= force_personality32; \ } while (0) /* Override some function names */ diff -puN arch/x86_64/kernel/process.c~force-read-implies-exec-for-all-32bit-processes-in-x86-64 arch/x86_64/kernel/process.c --- 25/arch/x86_64/kernel/process.c~force-read-implies-exec-for-all-32bit-processes-in-x86-64 2005-02-08 01:02:15.000000000 -0800 +++ 25-akpm/arch/x86_64/kernel/process.c 2005-02-08 01:02:15.000000000 -0800 @@ -577,6 +577,12 @@ void set_personality_64bit(void) /* Make sure to be in 64bit mode */ clear_thread_flag(TIF_IA32); + + /* TBD: overwrites user setup. Should have two bits. + But 64bit processes have always behaved this way, + so it's not too bad. The main problem is just that + 32bit childs are affected again. */ + current->personality &= ~READ_IMPLIES_EXEC; } asmlinkage long sys_fork(struct pt_regs *regs) diff -puN arch/x86_64/kernel/setup64.c~force-read-implies-exec-for-all-32bit-processes-in-x86-64 arch/x86_64/kernel/setup64.c --- 25/arch/x86_64/kernel/setup64.c~force-read-implies-exec-for-all-32bit-processes-in-x86-64 2005-02-08 01:02:15.000000000 -0800 +++ 25-akpm/arch/x86_64/kernel/setup64.c 2005-02-08 01:02:15.000000000 -0800 @@ -50,7 +50,7 @@ Control non executable mappings for 64bi on Enable(default) off Disable */ -void __init nonx_setup(const char *str) +int __init nonx_setup(char *str) { if (!strncmp(str, "on", 2)) { __supported_pte_mask |= _PAGE_NX; @@ -58,8 +58,29 @@ void __init nonx_setup(const char *str) } else if (!strncmp(str, "off", 3)) { do_not_nx = 1; __supported_pte_mask &= ~_PAGE_NX; - } + } + return 0; } +__setup("noexec=", nonx_setup); /* parsed early actually */ + +int force_personality32 = READ_IMPLIES_EXEC; + +/* noexec32=on|off +Control non executable heap for 32bit processes. +To control the stack too use noexec=off + +on PROT_READ does not imply PROT_EXEC for 32bit processes +off PROT_READ implies PROT_EXEC (default) +*/ +static int __init nonx32_setup(char *str) +{ + if (!strcmp(str, "on")) + force_personality32 &= ~READ_IMPLIES_EXEC; + else if (!strcmp(str, "off")) + force_personality32 |= READ_IMPLIES_EXEC; + return 0; +} +__setup("noexec32=", nonx32_setup); /* * Great future plan: diff -puN include/asm-x86_64/pgtable.h~force-read-implies-exec-for-all-32bit-processes-in-x86-64 include/asm-x86_64/pgtable.h --- 25/include/asm-x86_64/pgtable.h~force-read-implies-exec-for-all-32bit-processes-in-x86-64 2005-02-08 01:02:15.000000000 -0800 +++ 25-akpm/include/asm-x86_64/pgtable.h 2005-02-08 01:02:15.000000000 -0800 @@ -20,7 +20,7 @@ extern unsigned long __supported_pte_mas #define swapper_pg_dir init_level4_pgt -extern void nonx_setup(const char *str); +extern int nonx_setup(char *str); extern void paging_init(void); extern void clear_kernel_mapping(unsigned long addr, unsigned long size); _