From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752925AbcAPVU1 (ORCPT ); Sat, 16 Jan 2016 16:20:27 -0500 Received: from terminus.zytor.com ([198.137.202.10]:56662 "EHLO terminus.zytor.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752794AbcAPVUX (ORCPT ); Sat, 16 Jan 2016 16:20:23 -0500 Date: Sat, 16 Jan 2016 13:19:19 -0800 From: tip-bot for Thomas Gleixner Message-ID: Cc: bp@alien8.de, joe.lawrence@stratus.com, mingo@kernel.org, hpa@zytor.com, jmmahler@gmail.com, jiang.liu@linux.intel.com, tglx@linutronix.de, linux@roeck-us.net, linux-kernel@vger.kernel.org Reply-To: linux@roeck-us.net, linux-kernel@vger.kernel.org, joe.lawrence@stratus.com, bp@alien8.de, mingo@kernel.org, hpa@zytor.com, jmmahler@gmail.com, jiang.liu@linux.intel.com, tglx@linutronix.de In-Reply-To: <20151231160106.892412198@linutronix.de> References: <20151231160106.892412198@linutronix.de> To: linux-tip-commits@vger.kernel.org Subject: [tip:x86/urgent] x86/irq: Clear move_in_progress before sending cleanup IPI Git-Commit-ID: c1684f5035b60e9f98566493e869496fb5de1d89 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: c1684f5035b60e9f98566493e869496fb5de1d89 Gitweb: http://git.kernel.org/tip/c1684f5035b60e9f98566493e869496fb5de1d89 Author: Thomas Gleixner AuthorDate: Thu, 31 Dec 2015 16:30:51 +0000 Committer: Thomas Gleixner CommitDate: Fri, 15 Jan 2016 13:44:01 +0100 x86/irq: Clear move_in_progress before sending cleanup IPI send_cleanup_vector() fiddles with the old_domain mask unprotected because it relies on the protection by the move_in_progress flag. But this is fatal, as the flag is reset after the IPI has been sent. So a cpu which receives the IPI can still see the flag set and therefor ignores the cleanup request. If no other cleanup request happens then the vector stays stale on that cpu and in case of an irq removal the vector still persists. That can lead to use after free when the next cleanup IPI happens. Protect the code with vector_lock and clear move_in_progress before sending the IPI. This does not plug the race which Joe reported because: CPU0 CPU1 CPU2 lock_vector() data->move_in_progress=0 sendIPI() unlock_vector() set_affinity() assign_irq_vector() lock_vector() handle_IPI move_in_progress = 1 lock_vector() unlock_vector() move_in_progress == 1 The full fix comes with a later patch. Reported-and-tested-by: Joe Lawrence Signed-off-by: Thomas Gleixner Tested-by: Borislav Petkov Cc: Jiang Liu Cc: Jeremiah Mahler Cc: andy.shevchenko@gmail.com Cc: Guenter Roeck Cc: stable@vger.kernel.org #4.3+ Link: http://lkml.kernel.org/r/20151231160106.892412198@linutronix.de Signed-off-by: Thomas Gleixner --- arch/x86/kernel/apic/vector.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/arch/x86/kernel/apic/vector.c b/arch/x86/kernel/apic/vector.c index 68d18b3..ed62f9c 100644 --- a/arch/x86/kernel/apic/vector.c +++ b/arch/x86/kernel/apic/vector.c @@ -532,6 +532,8 @@ static void __send_cleanup_vector(struct apic_chip_data *data) { cpumask_var_t cleanup_mask; + raw_spin_lock(&vector_lock); + data->move_in_progress = 0; if (unlikely(!alloc_cpumask_var(&cleanup_mask, GFP_ATOMIC))) { unsigned int i; @@ -543,7 +545,7 @@ static void __send_cleanup_vector(struct apic_chip_data *data) apic->send_IPI_mask(cleanup_mask, IRQ_MOVE_CLEANUP_VECTOR); free_cpumask_var(cleanup_mask); } - data->move_in_progress = 0; + raw_spin_unlock(&vector_lock); } void send_cleanup_vector(struct irq_cfg *cfg)