Received: by 2002:a25:868d:0:0:0:0:0 with SMTP id z13csp2777589ybk; Tue, 12 May 2020 07:57:24 -0700 (PDT) X-Google-Smtp-Source: APiQypLNhynWS2PQyGGuAdcPuYjRMAxwhf27QHl3wWeyMKAAoWKIk6w8ppPvpBfl6PrNv9tuNiRF X-Received: by 2002:a50:9dcd:: with SMTP id l13mr18556837edk.126.1589295444468; Tue, 12 May 2020 07:57:24 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1589295444; cv=none; d=google.com; s=arc-20160816; b=X14+l1f0fyM6/XWiBmTzquvFcwYsaAaE3sWnjXkILkWnpwunHA6Br3jDSMLspE5EtX JGQ8fszPN2OuDJF+gSkSgtPnny6uVELpU16q3vJ1WTdVzUt48dPl0ghrcOXiuVxc3xtt 8zbrjzCrqqD32Eeb+zumXUoVkZ5BMVigdkwyhEyEH7eW4HhDebpHq1dPbX5v0MGWTG7l JYR9Zj9OW703hY4OpPFZjO9xYyi3Ilr594I7ii+jfeVbG0XYPkV73GVfL0WUy7C+WxUt lKgO4XNeYAuUG1w68dB0ba/nOD00AalmQBytJ7n9MsXsQR6gfALBDDKbaic/Ptvaknc+ USbA== 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 :references:in-reply-to:message-id:date:subject:cc:to:from :ironport-sdr:ironport-sdr; bh=wJD+rRi+TbdGNhxYu4QDbY+uX00Y1p5SYy9Anyeh7j0=; b=eNRVXhE14NpLRG80Ou3BMz5PZHoLVd4SPKjrpD4XLPFcDAX9lAEgFv9NGQqkXWC4mX K3wKCKmw/t+Q9c/9EG0O5g14rShhUPBQr9NcFR6AfFGGpuzhWtJuhSFzzBCUWPkyNNi6 47s+uKIEQ0W6PM36y9usAHBvluiGJqON1y1++QJxCIb3eyDUTw/R62LdcjbCAJQ5sap+ lKpOGjGvxzSVdW0tcXZaeSSZQTZBQRdSpipf/s57Fiha4lgufqNXIDocwLZba9l2sRyA /LZFe4UUXFLxj5v4Y3S2BbIOrIDgL+dYUo9SFb1ByJiiI8Z9yDc4ghxMG0Pwl6u7b6zN hJLA== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=intel.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id m4si8057276eje.107.2020.05.12.07.57.01; Tue, 12 May 2020 07:57:24 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=intel.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1730462AbgELOzU (ORCPT + 99 others); Tue, 12 May 2020 10:55:20 -0400 Received: from mga05.intel.com ([192.55.52.43]:29539 "EHLO mga05.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1730224AbgELOzO (ORCPT ); Tue, 12 May 2020 10:55:14 -0400 IronPort-SDR: lSFroILlIhLuDgLIdoVSgP9AhkcUv0qGWCYkSl4wKomJKJ3OtfPTcpn6B4X+6k1dVDCGs0qth1 u6drhhK8m+xw== X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga001.fm.intel.com ([10.253.24.23]) by fmsmga105.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 12 May 2020 07:55:09 -0700 IronPort-SDR: ZYlrBn6EeazaQRVZ09ptsgv+A1ZXJsJ8py4Hwfer0hjjS5z7lBNsWjQ5sqyJFW6X2ZxbcSaHzi zpjWTvPFSBqw== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.73,384,1583222400"; d="scan'208";a="371587832" Received: from yyu32-desk.sc.intel.com ([143.183.136.146]) by fmsmga001.fm.intel.com with ESMTP; 12 May 2020 07:55:09 -0700 From: Yu-cheng Yu To: linux-kernel@vger.kernel.org, x86@kernel.org, "H. Peter Anvin" , Thomas Gleixner , Ingo Molnar , Dave Hansen , Tony Luck , Andy Lutomirski , Borislav Petkov , Rik van Riel , "Ravi V. Shankar" , Sebastian Andrzej Siewior , Fenghua Yu , Peter Zijlstra Cc: Yu-cheng Yu Subject: [PATCH v4 09/10] x86/fpu/xstate: Preserve supervisor states for slow path of __fpu__restore_sig() Date: Tue, 12 May 2020 07:54:43 -0700 Message-Id: <20200512145444.15483-10-yu-cheng.yu@intel.com> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20200512145444.15483-1-yu-cheng.yu@intel.com> References: <20200512145444.15483-1-yu-cheng.yu@intel.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org The signal return code is responsible for taking an XSAVE buffer present in user memory and loading it into the hardware registers. This operation only affects user XSAVE state and never affects supervisor state. The fast path through this code simply points XRSTOR directly at the user buffer. However, since user memory is not guaranteed to be always mapped, this XRSTOR can fail. If it fails, the signal return code falls back to a slow path which can tolerate page faults. That slow path copies the xfeatures one by one out of the user buffer into the task's fpu state area. However, by being in a context where it can handle page faults, the code can also schedule. The lazy-fpu-load code would think it has an up-to-date fpstate and would fail to save the supervisor state when scheduling the task out. When scheduling back in, it would likely restore stale supervisor state. To fix that, preserve supervisor state before the slow path. Modify copy_user_to_fpregs_zeroing() so that if it fails, fpregs are not zeroed, and there is no need for fpregs_deactivate() and supervisor states are preserved. Move set_thread_flag(TIF_NEED_FPU_LOAD) to the slow path. Without doing this, the fast path also needs supervisor states to be saved first. Signed-off-by: Yu-cheng Yu --- arch/x86/kernel/fpu/signal.c | 53 +++++++++++++++++++----------------- 1 file changed, 28 insertions(+), 25 deletions(-) diff --git a/arch/x86/kernel/fpu/signal.c b/arch/x86/kernel/fpu/signal.c index 40583487883e..c0e07b548076 100644 --- a/arch/x86/kernel/fpu/signal.c +++ b/arch/x86/kernel/fpu/signal.c @@ -262,19 +262,23 @@ sanitize_restored_user_xstate(union fpregs_state *state, static int copy_user_to_fpregs_zeroing(void __user *buf, u64 xbv, int fx_only) { u64 init_bv; + int r; if (use_xsave()) { if (fx_only) { init_bv = xfeatures_mask_user() & ~XFEATURE_MASK_FPSSE; - copy_kernel_to_xregs(&init_fpstate.xsave, init_bv); - return copy_user_to_fxregs(buf); + r = copy_user_to_fxregs(buf); + if (!r) + copy_kernel_to_xregs(&init_fpstate.xsave, init_bv); + return r; } else { init_bv = xfeatures_mask_user() & ~xbv; - if (unlikely(init_bv)) + r = copy_user_to_xregs(buf, xbv); + if (!r && unlikely(init_bv)) copy_kernel_to_xregs(&init_fpstate.xsave, init_bv); - return copy_user_to_xregs(buf, xbv); + return r; } } else if (use_fxsr()) { return copy_user_to_fxregs(buf); @@ -327,28 +331,10 @@ static int __fpu__restore_sig(void __user *buf, void __user *buf_fx, int size) } } - /* - * The current state of the FPU registers does not matter. By setting - * TIF_NEED_FPU_LOAD unconditionally it is ensured that the our xstate - * is not modified on context switch and that the xstate is considered - * to be loaded again on return to userland (overriding last_cpu avoids - * the optimisation). - */ - set_thread_flag(TIF_NEED_FPU_LOAD); - __fpu_invalidate_fpregs_state(fpu); - if ((unsigned long)buf_fx % 64) fx_only = 1; - /* - * For 32-bit frames with fxstate, copy the fxstate so it can be - * reconstructed later. - */ - if (ia32_fxstate) { - ret = __copy_from_user(&env, buf, sizeof(env)); - if (ret) - goto err_out; - envp = &env; - } else { + + if (!ia32_fxstate) { /* * Attempt to restore the FPU registers directly from user * memory. For that to succeed, the user access cannot cause @@ -365,10 +351,27 @@ static int __fpu__restore_sig(void __user *buf, void __user *buf_fx, int size) fpregs_unlock(); return 0; } - fpregs_deactivate(fpu); fpregs_unlock(); + } else { + /* + * For 32-bit frames with fxstate, copy the fxstate so it can + * be reconstructed later. + */ + ret = __copy_from_user(&env, buf, sizeof(env)); + if (ret) + goto err_out; + envp = &env; } + /* + * The current state of the FPU registers does not matter. By setting + * TIF_NEED_FPU_LOAD unconditionally it is ensured that the our xstate + * is not modified on context switch and that the xstate is considered + * to be loaded again on return to userland (overriding last_cpu avoids + * the optimisation). + */ + set_thread_flag(TIF_NEED_FPU_LOAD); + __fpu_invalidate_fpregs_state(fpu); if (use_xsave() && !fx_only) { u64 init_bv = xfeatures_mask_user() & ~user_xfeatures; -- 2.21.0