From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S934556AbcBQMRS (ORCPT ); Wed, 17 Feb 2016 07:17:18 -0500 Received: from terminus.zytor.com ([198.137.202.10]:56218 "EHLO terminus.zytor.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S933355AbcBQMRM (ORCPT ); Wed, 17 Feb 2016 07:17:12 -0500 Date: Wed, 17 Feb 2016 04:15:59 -0800 From: tip-bot for Andy Lutomirski Message-ID: Cc: bp@alien8.de, brgerst@gmail.com, luto@amacapital.net, torvalds@linux-foundation.org, dvlasenk@redhat.com, viro@zeniv.linux.org.uk, mingo@kernel.org, peterz@infradead.org, linux-kernel@vger.kernel.org, robert@ocallahan.org, tglx@linutronix.de, hpa@zytor.com, shuahkh@osg.samsung.com, luto@kernel.org Reply-To: shuahkh@osg.samsung.com, luto@kernel.org, hpa@zytor.com, tglx@linutronix.de, linux-kernel@vger.kernel.org, robert@ocallahan.org, peterz@infradead.org, viro@zeniv.linux.org.uk, mingo@kernel.org, dvlasenk@redhat.com, torvalds@linux-foundation.org, luto@amacapital.net, brgerst@gmail.com, bp@alien8.de In-Reply-To: References: To: linux-tip-commits@vger.kernel.org Subject: [tip:x86/asm] x86/entry/compat: Keep TS_COMPAT set during signal delivery Git-Commit-ID: 4e79e182b419172e35936a47f098509092d69817 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: 4e79e182b419172e35936a47f098509092d69817 Gitweb: http://git.kernel.org/tip/4e79e182b419172e35936a47f098509092d69817 Author: Andy Lutomirski AuthorDate: Wed, 10 Feb 2016 14:15:27 -0800 Committer: Ingo Molnar CommitDate: Wed, 17 Feb 2016 09:51:06 +0100 x86/entry/compat: Keep TS_COMPAT set during signal delivery Signal delivery needs to know the sign of an interrupted syscall's return value in order to detect -ERESTART variants. Normally this works independently of bitness because syscalls internally return long. Under ptrace, however, this can break, and syscall_get_error is supposed to sign-extend regs->ax if needed. We were clearing TS_COMPAT too early, though, and this prevented sign extension, which subtly broke syscall restart under ptrace. Reported-by: Robert O'Callahan Signed-off-by: Andy Lutomirski Cc: Al Viro Cc: Andy Lutomirski Cc: Borislav Petkov Cc: Brian Gerst Cc: Denys Vlasenko Cc: H. Peter Anvin Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Shuah Khan Cc: Thomas Gleixner Cc: stable@vger.kernel.org # 4.3.x- Fixes: c5c46f59e4e7 ("x86/entry: Add new, comprehensible entry and exit handlers written in C") Link: http://lkml.kernel.org/r/cbce3cf545522f64eb37f5478cb59746230db3b5.1455142412.git.luto@kernel.org Signed-off-by: Ingo Molnar --- arch/x86/entry/common.c | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/arch/x86/entry/common.c b/arch/x86/entry/common.c index c6ab2eb..1a000f5 100644 --- a/arch/x86/entry/common.c +++ b/arch/x86/entry/common.c @@ -269,6 +269,7 @@ static void exit_to_usermode_loop(struct pt_regs *regs, u32 cached_flags) /* Called with IRQs disabled. */ __visible inline void prepare_exit_to_usermode(struct pt_regs *regs) { + struct thread_info *ti = pt_regs_to_thread_info(regs); u32 cached_flags; if (IS_ENABLED(CONFIG_PROVE_LOCKING) && WARN_ON(!irqs_disabled())) @@ -276,12 +277,22 @@ __visible inline void prepare_exit_to_usermode(struct pt_regs *regs) lockdep_sys_exit(); - cached_flags = - READ_ONCE(pt_regs_to_thread_info(regs)->flags); + cached_flags = READ_ONCE(ti->flags); if (unlikely(cached_flags & EXIT_TO_USERMODE_LOOP_FLAGS)) exit_to_usermode_loop(regs, cached_flags); +#ifdef CONFIG_COMPAT + /* + * Compat syscalls set TS_COMPAT. Make sure we clear it before + * returning to user mode. We need to clear it *after* signal + * handling, because syscall restart has a fixup for compat + * syscalls. The fixup is exercised by the ptrace_syscall_32 + * selftest. + */ + ti->status &= ~TS_COMPAT; +#endif + user_enter(); } @@ -333,14 +344,6 @@ __visible inline void syscall_return_slowpath(struct pt_regs *regs) if (unlikely(cached_flags & SYSCALL_EXIT_WORK_FLAGS)) syscall_slow_exit_work(regs, cached_flags); -#ifdef CONFIG_COMPAT - /* - * Compat syscalls set TS_COMPAT. Make sure we clear it before - * returning to user mode. - */ - ti->status &= ~TS_COMPAT; -#endif - local_irq_disable(); prepare_exit_to_usermode(regs); }