From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752708AbdLHUCe (ORCPT ); Fri, 8 Dec 2017 15:02:34 -0500 Received: from Galois.linutronix.de ([146.0.238.70]:57596 "EHLO Galois.linutronix.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1750980AbdLHUCU (ORCPT ); Fri, 8 Dec 2017 15:02:20 -0500 Date: Fri, 8 Dec 2017 21:02:17 +0100 (CET) From: Thomas Gleixner To: Andy Lutomirski cc: x86@kernel.org, LKML , Borislav Petkov , Brian Gerst , David Laight , Kees Cook , Peter Zijlstra , Linus Torvalds Subject: x86/ldt: Prevent ldt inheritance on exec Message-ID: User-Agent: Alpine 2.20 (DEB 67 2015-01-07) MIME-Version: 1.0 Content-Type: text/plain; charset=US-ASCII X-Linutronix-Spam-Score: -1.0 X-Linutronix-Spam-Level: - X-Linutronix-Spam-Status: No , -1.0 points, 5.0 required, ALL_TRUSTED=-1,SHORTCIRCUIT=-0.0001 Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Thomas Gleixner 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 --- 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; }