Received: by 2002:a25:7ec1:0:0:0:0:0 with SMTP id z184csp6003142ybc; Wed, 27 Nov 2019 13:13:24 -0800 (PST) X-Google-Smtp-Source: APXvYqw2+Dho6B6dr08Iv8zsNUr2jHTGlpKv8uANnbtRIcn43iP8d/RpeLYbQOlqCBsMU1b1GsVG X-Received: by 2002:a05:6402:2051:: with SMTP id bc17mr1960718edb.28.1574889204656; Wed, 27 Nov 2019 13:13:24 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1574889204; cv=none; d=google.com; s=arc-20160816; b=YZEwZOfl0QqS0UfjgWxxqsFONKTYKbIzJE5UxZXTA+YLZribP9owg8UWYu0kih9hH9 OUJd24a/S/1vc0pWqb9+1orGmbexTnJ1ACOXmj1iYu5o2zU1XblpmYA8b5ZrJhCynVL9 qGTZ1swpy/vw38RDsAN28izbJSOHH64Z2jtlp20JkoduoeSgJetvsZm0mxkeb9jE2zLE VWqDXbR+ih36FsFhKvhbMSPuu2ms/T5AEYtCFXTMutZzT/bQ7qkZWtRmS9yAsKfGxNMJ 2Mrt+OPwam0fJZVOBXSt1acLVbZ04n2XoSdsIKeeXW3nuVPSYaF878j2ix/AFo5eq6Pj tKCg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding:mime-version :user-agent:references:in-reply-to:message-id:date:subject:cc:to :from:dkim-signature; bh=DkveuzLgYir9rsgu5MCBDBWxnMwBHkDx98OfHg4ppF0=; b=ggvvrW41RvQwLHIaUbOiPhBjX0mEYx314IXVKI3yXP2g3Qi38juoQXFbEF19PxWmTP bCW2MvAMcki6PO3WaAb7/mgQG5J4LrWhVNNvtD3tTJQKl/G8/iiig5U01vy2jD1CPZDa 1DVP5hgsT/mlImKznKMQNdQLgStRsyrSsJKZDDAlVQL3dW+Wb7lUiVUbmIitrhuqWfWN IUxo4pLY38MMqtMsRT1omUyHAYl/Wmwl/kgNabMcm9AHbjKsHBKS1sNIIuKZOTrq8KfX ExYBVUjnydsOoCnu8+slKjFP/hRTRz1zucwH53VNAV09YUedC5BT6+BneCt2ys+lcitN wDGQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b=yIxgaU4M; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id i12si10476665edr.198.2019.11.27.13.13.00; Wed, 27 Nov 2019 13:13:24 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b=yIxgaU4M; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727344AbfK0VKr (ORCPT + 99 others); Wed, 27 Nov 2019 16:10:47 -0500 Received: from mail.kernel.org ([198.145.29.99]:38108 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1732659AbfK0VKl (ORCPT ); Wed, 27 Nov 2019 16:10:41 -0500 Received: from localhost (83-86-89-107.cable.dynamic.v4.ziggo.nl [83.86.89.107]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id AF0822154A; Wed, 27 Nov 2019 21:10:39 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1574889040; bh=w+m6KjUIoZY/8hFdgusd84msZw06EQ08t3XBUtOWqvI=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=yIxgaU4MJ8qY1rbO+61gNURVEpwZwOowGhjLfwoHvYVCjg2jdRTKiNup62DolLaCD Y3ctweMRNAJ3Fh+7cMamnllaRW5cTCSvo/ZcOTg/qZ5ZxmgXaTotNcsfI7qHRuz6vN 8TuU2/81N2k+nNrPXsIVflZq33/iAAtqI5hznTqc= From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, "Peter Zijlstra (Intel)" , Andy Lutomirski , stable@kernel.org Subject: [PATCH 5.3 61/95] x86/entry/32: Fix NMI vs ESPFIX Date: Wed, 27 Nov 2019 21:32:18 +0100 Message-Id: <20191127202927.340839341@linuxfoundation.org> X-Mailer: git-send-email 2.24.0 In-Reply-To: <20191127202845.651587549@linuxfoundation.org> References: <20191127202845.651587549@linuxfoundation.org> User-Agent: quilt/0.66 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Peter Zijlstra commit 895429076512e9d1cf5428181076299c90713159 upstream. When the NMI lands on an ESPFIX_SS, we are on the entry stack and must swizzle, otherwise we'll run do_nmi() on the entry stack, which is BAD. Also, similar to the normal exception path, we need to correct the ESPFIX magic before leaving the entry stack, otherwise pt_regs will present a non-flat stack pointer. Tested by running sigreturn_32 concurrent with perf-record. Fixes: e5862d0515ad ("x86/entry/32: Leave the kernel via trampoline stack") Signed-off-by: Peter Zijlstra (Intel) Acked-by: Andy Lutomirski Cc: stable@kernel.org Signed-off-by: Greg Kroah-Hartman --- arch/x86/entry/entry_32.S | 53 +++++++++++++++++++++++++++++++++++----------- 1 file changed, 41 insertions(+), 12 deletions(-) --- a/arch/x86/entry/entry_32.S +++ b/arch/x86/entry/entry_32.S @@ -205,6 +205,7 @@ #define CS_FROM_ENTRY_STACK (1 << 31) #define CS_FROM_USER_CR3 (1 << 30) #define CS_FROM_KERNEL (1 << 29) +#define CS_FROM_ESPFIX (1 << 28) .macro FIXUP_FRAME /* @@ -342,8 +343,8 @@ .endif .endm -.macro SAVE_ALL_NMI cr3_reg:req - SAVE_ALL +.macro SAVE_ALL_NMI cr3_reg:req unwind_espfix=0 + SAVE_ALL unwind_espfix=\unwind_espfix BUG_IF_WRONG_CR3 @@ -1526,6 +1527,10 @@ ENTRY(nmi) ASM_CLAC #ifdef CONFIG_X86_ESPFIX32 + /* + * ESPFIX_SS is only ever set on the return to user path + * after we've switched to the entry stack. + */ pushl %eax movl %ss, %eax cmpw $__ESPFIX_SS, %ax @@ -1561,6 +1566,11 @@ ENTRY(nmi) movl %ebx, %esp .Lnmi_return: +#ifdef CONFIG_X86_ESPFIX32 + testl $CS_FROM_ESPFIX, PT_CS(%esp) + jnz .Lnmi_from_espfix +#endif + CHECK_AND_APPLY_ESPFIX RESTORE_ALL_NMI cr3_reg=%edi pop=4 jmp .Lirq_return @@ -1568,23 +1578,42 @@ ENTRY(nmi) #ifdef CONFIG_X86_ESPFIX32 .Lnmi_espfix_stack: /* - * create the pointer to lss back + * Create the pointer to LSS back */ pushl %ss pushl %esp addl $4, (%esp) - /* copy the iret frame of 12 bytes */ - .rept 3 - pushl 16(%esp) - .endr - pushl %eax - SAVE_ALL_NMI cr3_reg=%edi + + /* Copy the (short) IRET frame */ + pushl 4*4(%esp) # flags + pushl 4*4(%esp) # cs + pushl 4*4(%esp) # ip + + pushl %eax # orig_ax + + SAVE_ALL_NMI cr3_reg=%edi unwind_espfix=1 ENCODE_FRAME_POINTER - FIXUP_ESPFIX_STACK # %eax == %esp + + /* clear CS_FROM_KERNEL, set CS_FROM_ESPFIX */ + xorl $(CS_FROM_ESPFIX | CS_FROM_KERNEL), PT_CS(%esp) + xorl %edx, %edx # zero error code - call do_nmi + movl %esp, %eax # pt_regs pointer + jmp .Lnmi_from_sysenter_stack + +.Lnmi_from_espfix: RESTORE_ALL_NMI cr3_reg=%edi - lss 12+4(%esp), %esp # back to espfix stack + /* + * Because we cleared CS_FROM_KERNEL, IRET_FRAME 'forgot' to + * fix up the gap and long frame: + * + * 3 - original frame (exception) + * 2 - ESPFIX block (above) + * 6 - gap (FIXUP_FRAME) + * 5 - long frame (FIXUP_FRAME) + * 1 - orig_ax + */ + lss (1+5+6)*4(%esp), %esp # back to espfix stack jmp .Lirq_return #endif END(nmi)