| From dac853ae89043f1b7752875300faf614de43c74b Mon Sep 17 00:00:00 2001 |
| From: Mathias Krause <minipli@googlemail.com> |
| Date: Thu, 9 Jun 2011 20:05:18 +0200 |
| Subject: exec: delay address limit change until point of no return |
| |
| From: Mathias Krause <minipli@googlemail.com> |
| |
| commit dac853ae89043f1b7752875300faf614de43c74b upstream. |
| |
| Unconditionally changing the address limit to USER_DS and not restoring |
| it to its old value in the error path is wrong because it prevents us |
| using kernel memory on repeated calls to this function. This, in fact, |
| breaks the fallback of hard coded paths to the init program from being |
| ever successful if the first candidate fails to load. |
| |
| With this patch applied switching to USER_DS is delayed until the point |
| of no return is reached which makes it possible to have a multi-arch |
| rootfs with one arch specific init binary for each of the (hard coded) |
| probed paths. |
| |
| Since the address limit is already set to USER_DS when start_thread() |
| will be invoked, this redundancy can be safely removed. |
| |
| Signed-off-by: Mathias Krause <minipli@googlemail.com> |
| Cc: Al Viro <viro@zeniv.linux.org.uk> |
| Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> |
| |
| |
| --- |
| arch/x86/kernel/process_32.c | 1 - |
| arch/x86/kernel/process_64.c | 1 - |
| fs/exec.c | 5 +---- |
| 3 files changed, 1 insertion(+), 6 deletions(-) |
| |
| --- a/arch/x86/kernel/process_32.c |
| +++ b/arch/x86/kernel/process_32.c |
| @@ -298,7 +298,6 @@ start_thread(struct pt_regs *regs, unsig |
| { |
| set_user_gs(regs, 0); |
| regs->fs = 0; |
| - set_fs(USER_DS); |
| regs->ds = __USER_DS; |
| regs->es = __USER_DS; |
| regs->ss = __USER_DS; |
| --- a/arch/x86/kernel/process_64.c |
| +++ b/arch/x86/kernel/process_64.c |
| @@ -356,7 +356,6 @@ start_thread(struct pt_regs *regs, unsig |
| regs->cs = __USER_CS; |
| regs->ss = __USER_DS; |
| regs->flags = 0x200; |
| - set_fs(USER_DS); |
| /* |
| * Free the old FP and other extended state |
| */ |
| --- a/fs/exec.c |
| +++ b/fs/exec.c |
| @@ -1009,6 +1009,7 @@ int flush_old_exec(struct linux_binprm * |
| |
| bprm->mm = NULL; /* We're using it now */ |
| |
| + set_fs(USER_DS); |
| current->flags &= ~PF_RANDOMIZE; |
| flush_thread(); |
| current->personality &= ~bprm->per_clear; |
| @@ -1276,10 +1277,6 @@ int search_binary_handler(struct linux_b |
| if (retval) |
| return retval; |
| |
| - /* kernel module loader fixup */ |
| - /* so we don't try to load run modprobe in kernel space. */ |
| - set_fs(USER_DS); |
| - |
| retval = audit_bprm(bprm); |
| if (retval) |
| return retval; |