
From: Andi Kleen <ak@suse.de>

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 <ak@suse.de>
Signed-off-by: Andrew Morton <akpm@osdl.org>
---

 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);
 
_
