From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754088AbbCPMHz (ORCPT ); Mon, 16 Mar 2015 08:07:55 -0400 Received: from terminus.zytor.com ([198.137.202.10]:35943 "EHLO terminus.zytor.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753062AbbCPMHv (ORCPT ); Mon, 16 Mar 2015 08:07:51 -0400 Date: Mon, 16 Mar 2015 05:07:11 -0700 From: tip-bot for Oleg Nesterov Message-ID: Cc: priikone@iki.fi, fenghua.yu@intel.com, bp@suse.de, stable@vger.kernel.org, tglx@linutronix.de, bp@alien8.de, dave.hansen@intel.com, sbsiddha@gmail.com, torvalds@linux-foundation.org, linux-kernel@vger.kernel.org, luto@amacapital.net, hpa@zytor.com, oleg@redhat.com, quentin.casasnovas@oracle.com, mingo@kernel.org, riel@redhat.com Reply-To: hpa@zytor.com, oleg@redhat.com, quentin.casasnovas@oracle.com, mingo@kernel.org, riel@redhat.com, bp@suse.de, stable@vger.kernel.org, tglx@linutronix.de, priikone@iki.fi, fenghua.yu@intel.com, dave.hansen@intel.com, bp@alien8.de, sbsiddha@gmail.com, torvalds@linux-foundation.org, luto@amacapital.net, linux-kernel@vger.kernel.org In-Reply-To: <20150307153844.GB25954@redhat.com> References: <20150307153844.GB25954@redhat.com> To: linux-tip-commits@vger.kernel.org Subject: [tip:x86/urgent] x86/fpu: Avoid math_state_restore() without used_math() in __restore_xstate_sig() Git-Commit-ID: a7c80ebcac3068b1c3cb27d538d29558c30010c8 X-Mailer: tip-git-log-daemon Robot-ID: Robot-Unsubscribe: Contact to get blacklisted from these emails MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Content-Type: text/plain; charset=UTF-8 Content-Disposition: inline Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Commit-ID: a7c80ebcac3068b1c3cb27d538d29558c30010c8 Gitweb: http://git.kernel.org/tip/a7c80ebcac3068b1c3cb27d538d29558c30010c8 Author: Oleg Nesterov AuthorDate: Fri, 13 Mar 2015 09:53:09 +0100 Committer: Ingo Molnar CommitDate: Fri, 13 Mar 2015 12:44:28 +0100 x86/fpu: Avoid math_state_restore() without used_math() in __restore_xstate_sig() math_state_restore() assumes it is called with irqs disabled, but this is not true if the caller is __restore_xstate_sig(). This means that if ia32_fxstate == T and __copy_from_user() fails, __restore_xstate_sig() returns with irqs disabled too. This triggers: BUG: sleeping function called from invalid context at kernel/locking/rwsem.c:41 dump_stack ___might_sleep ? _raw_spin_unlock_irqrestore __might_sleep down_read ? _raw_spin_unlock_irqrestore print_vma_addr signal_fault sys32_rt_sigreturn Change __restore_xstate_sig() to call set_used_math() unconditionally. This avoids enabling and disabling interrupts in math_state_restore(). If copy_from_user() fails, we can simply do fpu_finit() by hand. [ Note: this is only the first step. math_state_restore() should not check used_math(), it should set this flag. While init_fpu() should simply die. ] Signed-off-by: Oleg Nesterov Signed-off-by: Borislav Petkov Cc: Cc: Andy Lutomirski Cc: Borislav Petkov Cc: Dave Hansen Cc: Fenghua Yu Cc: H. Peter Anvin Cc: Linus Torvalds Cc: Pekka Riikonen Cc: Quentin Casasnovas Cc: Rik van Riel Cc: Suresh Siddha Cc: Thomas Gleixner Link: http://lkml.kernel.org/r/20150307153844.GB25954@redhat.com Signed-off-by: Ingo Molnar --- arch/x86/kernel/xsave.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/arch/x86/kernel/xsave.c b/arch/x86/kernel/xsave.c index 34f66e5..cdc6cf9 100644 --- a/arch/x86/kernel/xsave.c +++ b/arch/x86/kernel/xsave.c @@ -379,7 +379,7 @@ int __restore_xstate_sig(void __user *buf, void __user *buf_fx, int size) * thread's fpu state, reconstruct fxstate from the fsave * header. Sanitize the copied state etc. */ - struct xsave_struct *xsave = &tsk->thread.fpu.state->xsave; + struct fpu *fpu = &tsk->thread.fpu; struct user_i387_ia32_struct env; int err = 0; @@ -393,14 +393,15 @@ int __restore_xstate_sig(void __user *buf, void __user *buf_fx, int size) */ drop_fpu(tsk); - if (__copy_from_user(xsave, buf_fx, state_size) || + if (__copy_from_user(&fpu->state->xsave, buf_fx, state_size) || __copy_from_user(&env, buf, sizeof(env))) { + fpu_finit(fpu); err = -1; } else { sanitize_restored_xstate(tsk, &env, xstate_bv, fx_only); - set_used_math(); } + set_used_math(); if (use_eager_fpu()) { preempt_disable(); math_state_restore();