diff --git a/arch/x86/include/asm/elf.h b/arch/x86/include/asm/elf.h index 5f962df..4cfc625 100644 --- a/arch/x86/include/asm/elf.h +++ b/arch/x86/include/asm/elf.h @@ -259,8 +259,8 @@ extern int force_personality32; * An executable for which elf_read_implies_exec() returns TRUE will * have the READ_IMPLIES_EXEC personality flag set automatically. */ -#define elf_read_implies_exec(ex, executable_stack) \ - (executable_stack != EXSTACK_DISABLE_X) +#define elf_read_implies_exec(ex, compat_mode) \ + (compat_mode == COMPAT_GNU_COMPAT) struct task_struct; diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c index 21ac5ee..1d9c4d8 100644 --- a/fs/binfmt_elf.c +++ b/fs/binfmt_elf.c @@ -572,6 +572,7 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs) unsigned long start_code, end_code, start_data, end_data; unsigned long reloc_func_desc __maybe_unused = 0; int executable_stack = EXSTACK_DEFAULT; + int compat_mode = COMPAT_DEFAULT; unsigned long def_flags = 0; struct { struct elfhdr elf_ex; @@ -694,6 +695,9 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs) executable_stack = EXSTACK_DISABLE_X; break; } + else if (elf_ppnt->p_type == PT_GNU_COMPAT) + if (elf_ppnt->p_flags & PF_X) + compat_mode = COMPAT_GNU_COMPAT; /* Some simple consistency checks for the interpreter */ if (elf_interpreter) { @@ -718,7 +722,7 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs) /* Do this immediately, since STACK_TOP as used in setup_arg_pages may depend on the personality. */ SET_PERSONALITY(loc->elf_ex); - if (elf_read_implies_exec(loc->elf_ex, executable_stack)) + if (elf_read_implies_exec(loc->elf_ex, compat_mode)) current->personality |= READ_IMPLIES_EXEC; if (!(current->personality & ADDR_NO_RANDOMIZE) && randomize_va_space) diff --git a/include/linux/binfmts.h b/include/linux/binfmts.h index fd88a39..1366919 100644 --- a/include/linux/binfmts.h +++ b/include/linux/binfmts.h @@ -123,6 +123,15 @@ extern int suid_dumpable; #define EXSTACK_DISABLE_X 1 /* Disable executable stacks */ #define EXSTACK_ENABLE_X 2 /* Enable executable stacks */ +/* Compatibility modes */ +#define COMPAT_DEFAULT 0 /* Default compatibility mode */ +/* The value of COMPAT_GNU_COMPAT is set to the same as the value of + * EXSTACK_ENABLE_X for architectures that still expect the value of + * the executable_stack variable (although not recommended) + * in elf_read_implies_exec(). + */ +#define COMPAT_GNU_COMPAT 2 /* GNU compatibility mode */ + extern int setup_arg_pages(struct linux_binprm * bprm, unsigned long stack_top, int executable_stack); diff --git a/include/linux/elf.h b/include/linux/elf.h index 31f0508..a336740 100644 --- a/include/linux/elf.h +++ b/include/linux/elf.h @@ -13,7 +13,7 @@ struct file; /* Executables for which elf_read_implies_exec() returns TRUE will have the READ_IMPLIES_EXEC personality flag set automatically. Override in asm/elf.h as needed. */ -# define elf_read_implies_exec(ex, have_pt_gnu_stack) 0 +# define elf_read_implies_exec(ex, compat_mode) 0 #endif /* 32-bit ELF base types. */ @@ -49,6 +49,7 @@ typedef __s64 Elf64_Sxword; #define PT_GNU_EH_FRAME 0x6474e550 #define PT_GNU_STACK (PT_LOOS + 0x474e551) +#define PT_GNU_COMPAT (PT_LOOS + 0x474e553) /* * Extended Numbering