Received: by 2002:ad5:474a:0:0:0:0:0 with SMTP id i10csp1738375imu; Wed, 28 Nov 2018 14:22:41 -0800 (PST) X-Google-Smtp-Source: AJdET5el1rz4flgld12brBefJYbwa7xStvkQh7W+nzBoTu4GOe8I0xl6Go8F2uBiXP5TLAuOsuhI X-Received: by 2002:a62:4587:: with SMTP id n7mr38915165pfi.118.1543443760980; Wed, 28 Nov 2018 14:22:40 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1543443760; cv=none; d=google.com; s=arc-20160816; b=oLxQeoobj9y4vamg82lFuQgqjqXEEFZ2WssX2B3EsJTAHYzszg1yvqTgBMjIq3yCE5 szUL02ncbrdMDK6zRbjJ2MAgVk327mOimUhj4TzTsrdBs6xr4l28Ei5/ad/O/VMB+UwL Ytp2p4m712msi+XsvwwooXZxzXmgFPhNr7ukSuRXzS31z7zO46d1bbH5Im7Em+ScRGTR jpg0m1//vug7J/LZ0oSP8uudwW2iY7R7tTqcLTWY1czMPOSekEGZy5NgPF/mTcovPiSS y+/JlLXQRNFPdpS3v0HQwM3OVCZtHAG90fdXKTQyJoIhEVvzI5/d3BXKNfDG1RjKKN0C ZCng== 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; bh=XTWkcEosOsIMTlZGCbIST7Ob5aRzug8FVeJ2LxD1ykY=; b=FSn2X2gcSSfgLNgYpIyooBv8lyMFTIVS7a3IRFH4A53zd1UbGoTDFdeh1KFM/aprsM 0IKqcPShYlzcan2T4jyxIqwShb4nQGOZ37jOC9I4r5PztHFADfYBjuoIvff1swFFtKgO I300aOfoKWeGFadULvVFvaGzfa9RoqB+ybe47xq/0siiCCxsawnZ9PcZuh1THYhrnuGg chQ0fHQ4PgUUaCLxlre6rXV0O/fGpO2wiwjvMG4xey5fz1I9js2hWuFO2+U63/Aqi1qC 7gTY7kgRbr6B16caRp67lQYpS0u9V5HBcd5QLbtFUV0B64+Nq97biR0DC4c7O9XlU3C7 RyOA== ARC-Authentication-Results: i=1; mx.google.com; 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 e4si9760pgl.570.2018.11.28.14.22.25; Wed, 28 Nov 2018 14:22:40 -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; 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 S1727450AbeK2JYr (ORCPT + 99 others); Thu, 29 Nov 2018 04:24:47 -0500 Received: from Galois.linutronix.de ([146.0.238.70]:33254 "EHLO Galois.linutronix.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726528AbeK2JYq (ORCPT ); Thu, 29 Nov 2018 04:24:46 -0500 Received: from localhost ([127.0.0.1] helo=bazinga.breakpoint.cc) by Galois.linutronix.de with esmtp (Exim 4.80) (envelope-from ) id 1gS8D4-0001GX-IY; Wed, 28 Nov 2018 23:21:31 +0100 From: Sebastian Andrzej Siewior To: linux-kernel@vger.kernel.org Cc: x86@kernel.org, Andy Lutomirski , Paolo Bonzini , =?UTF-8?q?Radim=20Kr=C4=8Dm=C3=A1=C5=99?= , kvm@vger.kernel.org, "Jason A. Donenfeld" , Rik van Riel , Dave Hansen , Sebastian Andrzej Siewior Subject: [PATCH 28/29] x86/fpu: Merge the two code paths in __fpu__restore_sig() Date: Wed, 28 Nov 2018 23:20:34 +0100 Message-Id: <20181128222035.2996-29-bigeasy@linutronix.de> X-Mailer: git-send-email 2.20.0.rc1 In-Reply-To: <20181128222035.2996-1-bigeasy@linutronix.de> References: <20181128222035.2996-1-bigeasy@linutronix.de> 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 ia32_fxstate case (32bit with fxsr) and the other (64bit, 32bit without fxsr) restore both from kernel memory and sanitize the content. The !ia32_fxstate version restores missing xstates from "init state" while the ia32_fxstate doesn't and skips it. Merge the two code paths and keep the !ia32_fxstate version. Copy only the user_i387_ia32_struct data structure in the ia32_fxstate. Signed-off-by: Sebastian Andrzej Siewior --- arch/x86/kernel/fpu/signal.c | 162 ++++++++++++++--------------------- 1 file changed, 65 insertions(+), 97 deletions(-) diff --git a/arch/x86/kernel/fpu/signal.c b/arch/x86/kernel/fpu/signal.c index 339a8c113517e..fb16d0da71bca 100644 --- a/arch/x86/kernel/fpu/signal.c +++ b/arch/x86/kernel/fpu/signal.c @@ -228,6 +228,11 @@ static int __fpu__restore_sig(void __user *buf, void __user *buf_fx, int size) struct task_struct *tsk = current; struct fpu *fpu = &tsk->thread.fpu; int state_size = fpu_kernel_xstate_size; + union fpregs_state *state; + void *tmp; + struct user_i387_ia32_struct env; + struct user_i387_ia32_struct *envp = NULL; + int ret = 0; u64 xfeatures = 0; int fx_only = 0; @@ -264,106 +269,69 @@ static int __fpu__restore_sig(void __user *buf, void __user *buf_fx, int size) } } + tmp = kzalloc(sizeof(*state) + fpu_kernel_xstate_size + 64, GFP_KERNEL); + if (!tmp) + return -ENOMEM; + state = PTR_ALIGN(tmp, 64); + + 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) { - /* - * For 32-bit frames with fxstate, copy the user state to the - * thread's fpu state, reconstruct fxstate from the fsave - * header. Validate and sanitize the copied state. - */ - union fpregs_state *state; - void *tmp; - struct user_i387_ia32_struct env; - int err = 0; - - tmp = kzalloc(sizeof(*state) + fpu_kernel_xstate_size + 64, GFP_KERNEL); - if (!tmp) - return -ENOMEM; - state = PTR_ALIGN(tmp, 64); - - if (using_compacted_format()) { - err = copy_user_to_xstate(&state->xsave, buf_fx); - } else { - err = __copy_from_user(&state->xsave, buf_fx, state_size); - - if (!err && state_size > offsetof(struct xregs_state, header)) - err = validate_xstate_header(&state->xsave.header); - } - - if (err || __copy_from_user(&env, buf, sizeof(env))) { - err = -1; - } else { - sanitize_restored_xstate(state, &env, - xfeatures, fx_only); - copy_kernel_to_fpregs(state); - } - - kfree(tmp); - return err; - } else { - union fpregs_state *state; - void *tmp; - int ret; - - tmp = kzalloc(sizeof(*state) + fpu_kernel_xstate_size + 64, GFP_KERNEL); - if (!tmp) - return -ENOMEM; - state = PTR_ALIGN(tmp, 64); - - /* - * For 64-bit frames and 32-bit fsave frames, restore the user - * state to the registers directly (with exceptions handled). - */ - if ((unsigned long)buf_fx % 64) - fx_only = 1; - - if (use_xsave() && !fx_only) { - u64 init_bv = xfeatures_mask & ~xfeatures; - - if (using_compacted_format()) { - ret = copy_user_to_xstate(&state->xsave, buf_fx); - } else { - ret = __copy_from_user(&state->xsave, buf_fx, state_size); - - if (!ret && state_size > offsetof(struct xregs_state, header)) - ret = validate_xstate_header(&state->xsave.header); - } - if (ret) - goto err_out; - sanitize_restored_xstate(state, NULL, xfeatures, - fx_only); - - if (unlikely(init_bv)) - copy_kernel_to_xregs(&init_fpstate.xsave, init_bv); - ret = copy_users_to_xregs(&state->xsave, xfeatures); - - } else if (use_fxsr()) { - ret = __copy_from_user(&state->fxsave, buf_fx, state_size); - if (ret) - goto err_out; - - if (use_xsave()) { - u64 init_bv = xfeatures_mask & ~XFEATURE_MASK_FPSSE; - copy_kernel_to_xregs(&init_fpstate.xsave, init_bv); - } - state->fxsave.mxcsr &= mxcsr_feature_mask; - - ret = copy_users_to_fxregs(&state->fxsave); - } else { - ret = __copy_from_user(&state->fsave, buf_fx, state_size); - if (ret) - goto err_out; - ret = copy_users_to_fregs(buf_fx); - } - -err_out: - kfree(tmp); - if (ret) { - fpu__clear(fpu); - return -1; - } + ret = __copy_from_user(&env, buf, sizeof(env)); + if (ret) + goto err_out; + envp = &env; } - return 0; + if (use_xsave() && !fx_only) { + u64 init_bv = xfeatures_mask & ~xfeatures; + + if (using_compacted_format()) { + ret = copy_user_to_xstate(&state->xsave, buf_fx); + } else { + ret = __copy_from_user(&state->xsave, buf_fx, state_size); + + if (!ret && state_size > offsetof(struct xregs_state, header)) + ret = validate_xstate_header(&state->xsave.header); + } + if (ret) + goto err_out; + + sanitize_restored_xstate(state, envp, xfeatures, fx_only); + + if (unlikely(init_bv)) + copy_kernel_to_xregs(&init_fpstate.xsave, init_bv); + ret = copy_users_to_xregs(&state->xsave, xfeatures); + + } else if (use_fxsr()) { + ret = __copy_from_user(&state->fxsave, buf_fx, state_size); + if (ret) + goto err_out; + + sanitize_restored_xstate(state, envp, xfeatures, fx_only); + if (use_xsave()) { + u64 init_bv = xfeatures_mask & ~XFEATURE_MASK_FPSSE; + copy_kernel_to_xregs(&init_fpstate.xsave, init_bv); + } + + ret = copy_users_to_fxregs(&state->fxsave); + } else { + ret = __copy_from_user(&state->fsave, buf_fx, state_size); + if (ret) + goto err_out; + ret = copy_users_to_fregs(buf_fx); + } + +err_out: + kfree(tmp); + if (ret) + fpu__clear(fpu); + return ret; } static inline int xstate_sigframe_size(void) -- 2.20.0.rc1