* Patches queued for 2.6.32.8:
- FDPIC: Respect PT_GNU_STACK exec protection markings when creating NOMMU stack - Split 'flush_old_exec' into two functions (CVE-2010-0307) svn path=/dists/trunk/linux-2.6/; revision=15102
This commit is contained in:
parent
ec0059d2e1
commit
42ee301828
|
@ -11,6 +11,10 @@ linux-2.6 (2.6.32-7) UNRELEASED; urgency=low
|
|||
[ dann frazier ]
|
||||
* Disable FUNCTION_TRACER due to performance/build issues.
|
||||
(Closes: #568025)
|
||||
* Patches queued for 2.6.32.8:
|
||||
- FDPIC: Respect PT_GNU_STACK exec protection markings when creating
|
||||
NOMMU stack
|
||||
- Split 'flush_old_exec' into two functions (CVE-2010-0307)
|
||||
|
||||
-- maximilian attems <maks@debian.org> Mon, 01 Feb 2010 17:16:31 +0100
|
||||
|
||||
|
|
|
@ -0,0 +1,105 @@
|
|||
From 04e4f2b18c8de1389d1e00fef0f42a8099910daf Mon Sep 17 00:00:00 2001
|
||||
From: Mike Frysinger <vapier@gentoo.org>
|
||||
Date: Wed, 6 Jan 2010 17:23:17 +0000
|
||||
Subject: FDPIC: Respect PT_GNU_STACK exec protection markings when creating NOMMU stack
|
||||
|
||||
From: Mike Frysinger <vapier@gentoo.org>
|
||||
|
||||
commit 04e4f2b18c8de1389d1e00fef0f42a8099910daf upstream.
|
||||
|
||||
The current code will load the stack size and protection markings, but
|
||||
then only use the markings in the MMU code path. The NOMMU code path
|
||||
always passes PROT_EXEC to the mmap() call. While this doesn't matter
|
||||
to most people whilst the code is running, it will cause a pointless
|
||||
icache flush when starting every FDPIC application. Typically this
|
||||
icache flush will be of a region on the order of 128KB in size, or may
|
||||
be the entire icache, depending on the facilities available on the CPU.
|
||||
|
||||
In the case where the arch default behaviour seems to be desired
|
||||
(EXSTACK_DEFAULT), we probe VM_STACK_FLAGS for VM_EXEC to determine
|
||||
whether we should be setting PROT_EXEC or not.
|
||||
|
||||
For arches that support an MPU (Memory Protection Unit - an MMU without
|
||||
the virtual mapping capability), setting PROT_EXEC or not will make an
|
||||
important difference.
|
||||
|
||||
It should be noted that this change also affects the executability of
|
||||
the brk region, since ELF-FDPIC has that share with the stack. However,
|
||||
this is probably irrelevant as NOMMU programs aren't likely to use the
|
||||
brk region, preferring instead allocation via mmap().
|
||||
|
||||
Signed-off-by: Mike Frysinger <vapier@gentoo.org>
|
||||
Signed-off-by: David Howells <dhowells@redhat.com>
|
||||
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
|
||||
|
||||
---
|
||||
arch/blackfin/include/asm/page.h | 5 +++++
|
||||
arch/frv/include/asm/page.h | 2 --
|
||||
fs/binfmt_elf_fdpic.c | 13 +++++++++++--
|
||||
3 files changed, 16 insertions(+), 4 deletions(-)
|
||||
|
||||
--- a/arch/blackfin/include/asm/page.h
|
||||
+++ b/arch/blackfin/include/asm/page.h
|
||||
@@ -10,4 +10,9 @@
|
||||
#include <asm-generic/page.h>
|
||||
#define MAP_NR(addr) (((unsigned long)(addr)-PAGE_OFFSET) >> PAGE_SHIFT)
|
||||
|
||||
+#define VM_DATA_DEFAULT_FLAGS \
|
||||
+ (VM_READ | VM_WRITE | \
|
||||
+ ((current->personality & READ_IMPLIES_EXEC) ? VM_EXEC : 0 ) | \
|
||||
+ VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
|
||||
+
|
||||
#endif
|
||||
--- a/arch/frv/include/asm/page.h
|
||||
+++ b/arch/frv/include/asm/page.h
|
||||
@@ -63,12 +63,10 @@ extern unsigned long max_pfn;
|
||||
#define virt_addr_valid(kaddr) pfn_valid(__pa(kaddr) >> PAGE_SHIFT)
|
||||
|
||||
|
||||
-#ifdef CONFIG_MMU
|
||||
#define VM_DATA_DEFAULT_FLAGS \
|
||||
(VM_READ | VM_WRITE | \
|
||||
((current->personality & READ_IMPLIES_EXEC) ? VM_EXEC : 0 ) | \
|
||||
VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
|
||||
-#endif
|
||||
|
||||
#endif /* __ASSEMBLY__ */
|
||||
|
||||
--- a/fs/binfmt_elf_fdpic.c
|
||||
+++ b/fs/binfmt_elf_fdpic.c
|
||||
@@ -171,6 +171,9 @@ static int load_elf_fdpic_binary(struct
|
||||
#ifdef ELF_FDPIC_PLAT_INIT
|
||||
unsigned long dynaddr;
|
||||
#endif
|
||||
+#ifndef CONFIG_MMU
|
||||
+ unsigned long stack_prot;
|
||||
+#endif
|
||||
struct file *interpreter = NULL; /* to shut gcc up */
|
||||
char *interpreter_name = NULL;
|
||||
int executable_stack;
|
||||
@@ -316,6 +319,8 @@ static int load_elf_fdpic_binary(struct
|
||||
* defunct, deceased, etc. after this point we have to exit via
|
||||
* error_kill */
|
||||
set_personality(PER_LINUX_FDPIC);
|
||||
+ if (elf_read_implies_exec(&exec_params.hdr, executable_stack))
|
||||
+ current->personality |= READ_IMPLIES_EXEC;
|
||||
set_binfmt(&elf_fdpic_format);
|
||||
|
||||
current->mm->start_code = 0;
|
||||
@@ -377,9 +382,13 @@ static int load_elf_fdpic_binary(struct
|
||||
if (stack_size < PAGE_SIZE * 2)
|
||||
stack_size = PAGE_SIZE * 2;
|
||||
|
||||
+ stack_prot = PROT_READ | PROT_WRITE;
|
||||
+ if (executable_stack == EXSTACK_ENABLE_X ||
|
||||
+ (executable_stack == EXSTACK_DEFAULT && VM_STACK_FLAGS & VM_EXEC))
|
||||
+ stack_prot |= PROT_EXEC;
|
||||
+
|
||||
down_write(¤t->mm->mmap_sem);
|
||||
- current->mm->start_brk = do_mmap(NULL, 0, stack_size,
|
||||
- PROT_READ | PROT_WRITE | PROT_EXEC,
|
||||
+ current->mm->start_brk = do_mmap(NULL, 0, stack_size, stack_prot,
|
||||
MAP_PRIVATE | MAP_ANONYMOUS | MAP_GROWSDOWN,
|
||||
0);
|
||||
|
|
@ -0,0 +1,245 @@
|
|||
From 221af7f87b97431e3ee21ce4b0e77d5411cf1549 Mon Sep 17 00:00:00 2001
|
||||
From: Linus Torvalds <torvalds@linux-foundation.org>
|
||||
Date: Thu, 28 Jan 2010 22:14:42 -0800
|
||||
Subject: Split 'flush_old_exec' into two functions
|
||||
|
||||
From: Linus Torvalds <torvalds@linux-foundation.org>
|
||||
|
||||
commit 221af7f87b97431e3ee21ce4b0e77d5411cf1549 upstream.
|
||||
|
||||
'flush_old_exec()' is the point of no return when doing an execve(), and
|
||||
it is pretty badly misnamed. It doesn't just flush the old executable
|
||||
environment, it also starts up the new one.
|
||||
|
||||
Which is very inconvenient for things like setting up the new
|
||||
personality, because we want the new personality to affect the starting
|
||||
of the new environment, but at the same time we do _not_ want the new
|
||||
personality to take effect if flushing the old one fails.
|
||||
|
||||
As a result, the x86-64 '32-bit' personality is actually done using this
|
||||
insane "I'm going to change the ABI, but I haven't done it yet" bit
|
||||
(TIF_ABI_PENDING), with SET_PERSONALITY() not actually setting the
|
||||
personality, but just the "pending" bit, so that "flush_thread()" can do
|
||||
the actual personality magic.
|
||||
|
||||
This patch in no way changes any of that insanity, but it does split the
|
||||
'flush_old_exec()' function up into a preparatory part that can fail
|
||||
(still called flush_old_exec()), and a new part that will actually set
|
||||
up the new exec environment (setup_new_exec()). All callers are changed
|
||||
to trivially comply with the new world order.
|
||||
|
||||
Signed-off-by: H. Peter Anvin <hpa@zytor.com>
|
||||
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
|
||||
|
||||
---
|
||||
arch/sh/kernel/process_64.c | 2 +-
|
||||
arch/x86/ia32/ia32_aout.c | 10 ++++++----
|
||||
fs/binfmt_aout.c | 1 +
|
||||
fs/binfmt_elf.c | 27 ++-------------------------
|
||||
fs/binfmt_elf_fdpic.c | 3 +++
|
||||
fs/binfmt_flat.c | 1 +
|
||||
fs/binfmt_som.c | 1 +
|
||||
fs/exec.c | 26 ++++++++++++++++----------
|
||||
include/linux/binfmts.h | 1 +
|
||||
include/linux/sched.h | 2 +-
|
||||
10 files changed, 33 insertions(+), 41 deletions(-)
|
||||
|
||||
--- a/arch/sh/kernel/process_64.c
|
||||
+++ b/arch/sh/kernel/process_64.c
|
||||
@@ -367,7 +367,7 @@ void exit_thread(void)
|
||||
void flush_thread(void)
|
||||
{
|
||||
|
||||
- /* Called by fs/exec.c (flush_old_exec) to remove traces of a
|
||||
+ /* Called by fs/exec.c (setup_new_exec) to remove traces of a
|
||||
* previously running executable. */
|
||||
#ifdef CONFIG_SH_FPU
|
||||
if (last_task_used_math == current) {
|
||||
--- a/arch/x86/ia32/ia32_aout.c
|
||||
+++ b/arch/x86/ia32/ia32_aout.c
|
||||
@@ -308,15 +308,17 @@ static int load_aout_binary(struct linux
|
||||
if (retval)
|
||||
return retval;
|
||||
|
||||
- regs->cs = __USER32_CS;
|
||||
- regs->r8 = regs->r9 = regs->r10 = regs->r11 = regs->r12 =
|
||||
- regs->r13 = regs->r14 = regs->r15 = 0;
|
||||
-
|
||||
/* OK, This is the point of no return */
|
||||
set_personality(PER_LINUX);
|
||||
set_thread_flag(TIF_IA32);
|
||||
clear_thread_flag(TIF_ABI_PENDING);
|
||||
|
||||
+ setup_new_exec(bprm);
|
||||
+
|
||||
+ regs->cs = __USER32_CS;
|
||||
+ regs->r8 = regs->r9 = regs->r10 = regs->r11 = regs->r12 =
|
||||
+ regs->r13 = regs->r14 = regs->r15 = 0;
|
||||
+
|
||||
current->mm->end_code = ex.a_text +
|
||||
(current->mm->start_code = N_TXTADDR(ex));
|
||||
current->mm->end_data = ex.a_data +
|
||||
--- a/fs/binfmt_aout.c
|
||||
+++ b/fs/binfmt_aout.c
|
||||
@@ -263,6 +263,7 @@ static int load_aout_binary(struct linux
|
||||
#else
|
||||
set_personality(PER_LINUX);
|
||||
#endif
|
||||
+ setup_new_exec(bprm);
|
||||
|
||||
current->mm->end_code = ex.a_text +
|
||||
(current->mm->start_code = N_TXTADDR(ex));
|
||||
--- a/fs/binfmt_elf.c
|
||||
+++ b/fs/binfmt_elf.c
|
||||
@@ -662,27 +662,6 @@ static int load_elf_binary(struct linux_
|
||||
if (elf_interpreter[elf_ppnt->p_filesz - 1] != '\0')
|
||||
goto out_free_interp;
|
||||
|
||||
- /*
|
||||
- * The early SET_PERSONALITY here is so that the lookup
|
||||
- * for the interpreter happens in the namespace of the
|
||||
- * to-be-execed image. SET_PERSONALITY can select an
|
||||
- * alternate root.
|
||||
- *
|
||||
- * However, SET_PERSONALITY is NOT allowed to switch
|
||||
- * this task into the new images's memory mapping
|
||||
- * policy - that is, TASK_SIZE must still evaluate to
|
||||
- * that which is appropriate to the execing application.
|
||||
- * This is because exit_mmap() needs to have TASK_SIZE
|
||||
- * evaluate to the size of the old image.
|
||||
- *
|
||||
- * So if (say) a 64-bit application is execing a 32-bit
|
||||
- * application it is the architecture's responsibility
|
||||
- * to defer changing the value of TASK_SIZE until the
|
||||
- * switch really is going to happen - do this in
|
||||
- * flush_thread(). - akpm
|
||||
- */
|
||||
- SET_PERSONALITY(loc->elf_ex);
|
||||
-
|
||||
interpreter = open_exec(elf_interpreter);
|
||||
retval = PTR_ERR(interpreter);
|
||||
if (IS_ERR(interpreter))
|
||||
@@ -730,9 +709,6 @@ static int load_elf_binary(struct linux_
|
||||
/* Verify the interpreter has a valid arch */
|
||||
if (!elf_check_arch(&loc->interp_elf_ex))
|
||||
goto out_free_dentry;
|
||||
- } else {
|
||||
- /* Executables without an interpreter also need a personality */
|
||||
- SET_PERSONALITY(loc->elf_ex);
|
||||
}
|
||||
|
||||
/* Flush all traces of the currently running executable */
|
||||
@@ -752,7 +728,8 @@ static int load_elf_binary(struct linux_
|
||||
|
||||
if (!(current->personality & ADDR_NO_RANDOMIZE) && randomize_va_space)
|
||||
current->flags |= PF_RANDOMIZE;
|
||||
- arch_pick_mmap_layout(current->mm);
|
||||
+
|
||||
+ setup_new_exec(bprm);
|
||||
|
||||
/* Do this so that we can load the interpreter, if need be. We will
|
||||
change some of these later */
|
||||
--- a/fs/binfmt_elf_fdpic.c
|
||||
+++ b/fs/binfmt_elf_fdpic.c
|
||||
@@ -321,6 +321,9 @@ static int load_elf_fdpic_binary(struct
|
||||
set_personality(PER_LINUX_FDPIC);
|
||||
if (elf_read_implies_exec(&exec_params.hdr, executable_stack))
|
||||
current->personality |= READ_IMPLIES_EXEC;
|
||||
+
|
||||
+ setup_new_exec(bprm);
|
||||
+
|
||||
set_binfmt(&elf_fdpic_format);
|
||||
|
||||
current->mm->start_code = 0;
|
||||
--- a/fs/binfmt_flat.c
|
||||
+++ b/fs/binfmt_flat.c
|
||||
@@ -519,6 +519,7 @@ static int load_flat_file(struct linux_b
|
||||
|
||||
/* OK, This is the point of no return */
|
||||
set_personality(PER_LINUX_32BIT);
|
||||
+ setup_new_exec(bprm);
|
||||
}
|
||||
|
||||
/*
|
||||
--- a/fs/binfmt_som.c
|
||||
+++ b/fs/binfmt_som.c
|
||||
@@ -227,6 +227,7 @@ load_som_binary(struct linux_binprm * bp
|
||||
/* OK, This is the point of no return */
|
||||
current->flags &= ~PF_FORKNOEXEC;
|
||||
current->personality = PER_HPUX;
|
||||
+ setup_new_exec(bprm);
|
||||
|
||||
/* Set the task size for HP-UX processes such that
|
||||
* the gateway page is outside the address space.
|
||||
--- a/fs/exec.c
|
||||
+++ b/fs/exec.c
|
||||
@@ -931,9 +931,7 @@ void set_task_comm(struct task_struct *t
|
||||
|
||||
int flush_old_exec(struct linux_binprm * bprm)
|
||||
{
|
||||
- char * name;
|
||||
- int i, ch, retval;
|
||||
- char tcomm[sizeof(current->comm)];
|
||||
+ int retval;
|
||||
|
||||
/*
|
||||
* Make sure we have a private signal table and that
|
||||
@@ -953,6 +951,20 @@ int flush_old_exec(struct linux_binprm *
|
||||
goto out;
|
||||
|
||||
bprm->mm = NULL; /* We're using it now */
|
||||
+ return 0;
|
||||
+
|
||||
+out:
|
||||
+ return retval;
|
||||
+}
|
||||
+EXPORT_SYMBOL(flush_old_exec);
|
||||
+
|
||||
+void setup_new_exec(struct linux_binprm * bprm)
|
||||
+{
|
||||
+ int i, ch;
|
||||
+ char * name;
|
||||
+ char tcomm[sizeof(current->comm)];
|
||||
+
|
||||
+ arch_pick_mmap_layout(current->mm);
|
||||
|
||||
/* This is the point of no return */
|
||||
current->sas_ss_sp = current->sas_ss_size = 0;
|
||||
@@ -1009,14 +1021,8 @@ int flush_old_exec(struct linux_binprm *
|
||||
|
||||
flush_signal_handlers(current, 0);
|
||||
flush_old_files(current->files);
|
||||
-
|
||||
- return 0;
|
||||
-
|
||||
-out:
|
||||
- return retval;
|
||||
}
|
||||
-
|
||||
-EXPORT_SYMBOL(flush_old_exec);
|
||||
+EXPORT_SYMBOL(setup_new_exec);
|
||||
|
||||
/*
|
||||
* Prepare credentials and lock ->cred_guard_mutex.
|
||||
--- a/include/linux/binfmts.h
|
||||
+++ b/include/linux/binfmts.h
|
||||
@@ -101,6 +101,7 @@ extern int prepare_binprm(struct linux_b
|
||||
extern int __must_check remove_arg_zero(struct linux_binprm *);
|
||||
extern int search_binary_handler(struct linux_binprm *,struct pt_regs *);
|
||||
extern int flush_old_exec(struct linux_binprm * bprm);
|
||||
+extern void setup_new_exec(struct linux_binprm * bprm);
|
||||
|
||||
extern int suid_dumpable;
|
||||
#define SUID_DUMP_DISABLE 0 /* No setuid dumping */
|
||||
--- a/include/linux/sched.h
|
||||
+++ b/include/linux/sched.h
|
||||
@@ -1354,7 +1354,7 @@ struct task_struct {
|
||||
char comm[TASK_COMM_LEN]; /* executable name excluding path
|
||||
- access with [gs]et_task_comm (which lock
|
||||
it with task_lock())
|
||||
- - initialized normally by flush_old_exec */
|
||||
+ - initialized normally by setup_new_exec */
|
||||
/* file system info */
|
||||
int link_count, total_link_count;
|
||||
#ifdef CONFIG_SYSVIPC
|
|
@ -1 +1,3 @@
|
|||
+ bugfix/all/clocksource-events-Fix-fallout-of-generic-code-changes.patch
|
||||
+ bugfix/all/fdpic-respect-pt_gnu_stack-exec-protection-markings-when-creating-nommu-stack.patch
|
||||
+ bugfix/all/split-flush_old_exec-into-two-functions.patch
|
||||
|
|
Loading…
Reference in New Issue