[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Message-ID: <alpine.DEB.2.20.1712082055390.2301@nanos>
Date: Fri, 8 Dec 2017 21:02:17 +0100 (CET)
From: Thomas Gleixner <tglx@...utronix.de>
To: Andy Lutomirski <luto@...nel.org>
cc: x86@...nel.org, LKML <linux-kernel@...r.kernel.org>,
Borislav Petkov <bp@...en8.de>,
Brian Gerst <brgerst@...il.com>,
David Laight <David.Laight@...lab.com>,
Kees Cook <keescook@...omium.org>,
Peter Zijlstra <peterz@...radead.org>,
Linus Torvalds <torvalds@...ux-foundation.org>
Subject: x86/ldt: Prevent ldt inheritance on exec
From: Thomas Gleixner <tglx@...utronix.de>
The LDT is inheritet independent of fork or exec, but that makes no sense
at all because exec is supposed to start the process clean.
The reason why this happens is that init_new_context_ldt() is called from
init_new_context() which obviously needs to be called for both fork() and
exec().
It would be surprising if anything relies on that behaviour, so it seems to
be safe to remove that misfeature.
Check whether current is in exec() and avoid the LDT clone if so.
Signed-off-by: Thomas Gleixner <tglx@...utronix.de>
---
arch/x86/kernel/ldt.c | 6 +++++-
tools/testing/selftests/x86/ldt_gdt.c | 9 +++------
2 files changed, 8 insertions(+), 7 deletions(-)
--- a/arch/x86/kernel/ldt.c
+++ b/arch/x86/kernel/ldt.c
@@ -135,7 +135,11 @@ int init_new_context_ldt(struct task_str
mutex_init(&mm->context.lock);
old_mm = current->mm;
- if (!old_mm) {
+ /*
+ * No action if current is a kernel thread or exec() is in
+ * progress.
+ */
+ if (!old_mm || current->in_execve) {
mm->context.ldt = NULL;
return 0;
}
--- a/tools/testing/selftests/x86/ldt_gdt.c
+++ b/tools/testing/selftests/x86/ldt_gdt.c
@@ -627,13 +627,10 @@ static void do_multicpu_tests(void)
static int finish_exec_test(void)
{
/*
- * In a sensible world, this would be check_invalid_segment(0, 1);
- * For better or for worse, though, the LDT is inherited across exec.
- * We can probably change this safely, but for now we test it.
+ * Older kernel versions did inherit the LDT on exec() which is
+ * wrong because exec() starts from a clean state.
*/
- check_valid_segment(0, 1,
- AR_DPL3 | AR_TYPE_XRCODE | AR_S | AR_P | AR_DB,
- 42, true);
+ check_invalid_segment(0, 1);
return nerrs ? 1 : 0;
}
Powered by blists - more mailing lists