Commit a3cc2546 authored by Andi Kleen's avatar Andi Kleen Committed by Linus Torvalds

[PATCH] Force read implies exec for all 32bit processes in x86-64

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: default avatarAndi Kleen <ak@suse.de>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent f7581af4
...@@ -249,6 +249,8 @@ elf_core_copy_task_xfpregs(struct task_struct *t, elf_fpxregset_t *xfpu) ...@@ -249,6 +249,8 @@ elf_core_copy_task_xfpregs(struct task_struct *t, elf_fpxregset_t *xfpu)
#define elf_check_arch(x) \ #define elf_check_arch(x) \
((x)->e_machine == EM_386) ((x)->e_machine == EM_386)
extern int force_personality32;
#define ELF_EXEC_PAGESIZE PAGE_SIZE #define ELF_EXEC_PAGESIZE PAGE_SIZE
#define ELF_HWCAP (boot_cpu_data.x86_capability[0]) #define ELF_HWCAP (boot_cpu_data.x86_capability[0])
#define ELF_PLATFORM ("i686") #define ELF_PLATFORM ("i686")
...@@ -262,6 +264,8 @@ do { \ ...@@ -262,6 +264,8 @@ do { \
set_thread_flag(TIF_ABI_PENDING); \ set_thread_flag(TIF_ABI_PENDING); \
else \ else \
clear_thread_flag(TIF_ABI_PENDING); \ clear_thread_flag(TIF_ABI_PENDING); \
/* XXX This overwrites the user set personality */ \
current->personality |= force_personality32; \
} while (0) } while (0)
/* Override some function names */ /* Override some function names */
......
...@@ -577,6 +577,12 @@ void set_personality_64bit(void) ...@@ -577,6 +577,12 @@ void set_personality_64bit(void)
/* Make sure to be in 64bit mode */ /* Make sure to be in 64bit mode */
clear_thread_flag(TIF_IA32); 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) asmlinkage long sys_fork(struct pt_regs *regs)
......
...@@ -50,7 +50,7 @@ Control non executable mappings for 64bit processes. ...@@ -50,7 +50,7 @@ Control non executable mappings for 64bit processes.
on Enable(default) on Enable(default)
off Disable off Disable
*/ */
void __init nonx_setup(const char *str) int __init nonx_setup(char *str)
{ {
if (!strncmp(str, "on", 2)) { if (!strncmp(str, "on", 2)) {
__supported_pte_mask |= _PAGE_NX; __supported_pte_mask |= _PAGE_NX;
...@@ -58,8 +58,29 @@ void __init nonx_setup(const char *str) ...@@ -58,8 +58,29 @@ void __init nonx_setup(const char *str)
} else if (!strncmp(str, "off", 3)) { } else if (!strncmp(str, "off", 3)) {
do_not_nx = 1; do_not_nx = 1;
__supported_pte_mask &= ~_PAGE_NX; __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: * Great future plan:
......
...@@ -20,7 +20,7 @@ extern unsigned long __supported_pte_mask; ...@@ -20,7 +20,7 @@ extern unsigned long __supported_pte_mask;
#define swapper_pg_dir init_level4_pgt #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 paging_init(void);
extern void clear_kernel_mapping(unsigned long addr, unsigned long size); extern void clear_kernel_mapping(unsigned long addr, unsigned long size);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment