From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S933217AbcALAfu (ORCPT ); Mon, 11 Jan 2016 19:35:50 -0500 Received: from mail-ob0-f173.google.com ([209.85.214.173]:33085 "EHLO mail-ob0-f173.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S932510AbcALAft (ORCPT ); Mon, 11 Jan 2016 19:35:49 -0500 Date: Mon, 11 Jan 2016 17:35:47 -0700 From: "Jeff V. Merkey" To: torvalds@linux-foundation.org, LKML Cc: Thomas Gleixner , Andy Lutomirski , Ingo Molnar , "H. Peter Anvin" , X86 ML , Peter Zijlstra , Andy Lutomirski , Masami Hiramatsu , Steven Rostedt , Borislav Petkov , Jiri Olsa Subject: [GIT PULL v4.5] Fix INT1 recursion with unregistered breakpoints Message-ID: <20160112003547.GA3051@localhost.localdomain> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline User-Agent: Mutt/1.5.21 (2010-09-15) Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org The following changes since commit ee78027142ab39d4f3c0e1af71ed343e0ff2dafd: Merge pull request #12 from torvalds/master (2015-12-19 11:12:20 -0700) are available in the git repository at: https://github.com/jeffmerkey/linux.git fixes for you to fetch changes up to b5f894bf53e7c401cc5a88b8a8b13059a176a538: Fix INT1 Recursion with unregistered breakpoints (2015-12-19 20:33:59 -0700) ---------------------------------------------------------------- Jeff Merkey (1): Fix INT1 Recursion with unregistered breakpoints arch/x86/include/uapi/asm/debugreg.h | 1 + arch/x86/kernel/hw_breakpoint.c | 25 +++++++++++++++++++++++-- 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/arch/x86/include/uapi/asm/debugreg.h b/arch/x86/include/uapi/asm/debugreg.h index 3c0874d..78fc83c 100644 --- a/arch/x86/include/uapi/asm/debugreg.h +++ b/arch/x86/include/uapi/asm/debugreg.h @@ -38,6 +38,7 @@ #define DR_RW_EXECUTE (0x0) /* Settings for the access types to trap on */ #define DR_RW_WRITE (0x1) #define DR_RW_READ (0x3) +#define DR_RW_MASK (0x3) /* mask for breakpoint type field */ #define DR_LEN_1 (0x0) /* Settings for data length to trap on */ #define DR_LEN_2 (0x4) diff --git a/arch/x86/kernel/hw_breakpoint.c b/arch/x86/kernel/hw_breakpoint.c index 50a3fad..d199834 100644 --- a/arch/x86/kernel/hw_breakpoint.c +++ b/arch/x86/kernel/hw_breakpoint.c @@ -444,7 +444,7 @@ EXPORT_SYMBOL_GPL(hw_breakpoint_restore); static int hw_breakpoint_handler(struct die_args *args) { int i, cpu, rc = NOTIFY_STOP; - struct perf_event *bp; + struct perf_event *bp = NULL; unsigned long dr7, dr6; unsigned long *dr6_p; @@ -477,6 +477,14 @@ static int hw_breakpoint_handler(struct die_args *args) continue; /* + * Check if we got an execute breakpoint, if so + * set the resume flag to avoid int1 recursion. + */ + if (((dr7 >> ((i * DR_CONTROL_SIZE) + DR_CONTROL_SHIFT)) + & DR_RW_MASK) == DR_RW_EXECUTE) + args->regs->flags |= X86_EFLAGS_RF; + + /* * The counter may be concurrently released but that can only * occur from a call_rcu() path. We can then safely fetch * the breakpoint, use its callback, touch its counter @@ -503,7 +511,8 @@ static int hw_breakpoint_handler(struct die_args *args) /* * Set up resume flag to avoid breakpoint recursion when - * returning back to origin. + * returning back to origin. perf_bp_event may + * change the flags so check twice. */ if (bp->hw.info.type == X86_BREAKPOINT_EXECUTE) args->regs->flags |= X86_EFLAGS_RF; @@ -519,6 +528,18 @@ static int hw_breakpoint_handler(struct die_args *args) (dr6 & (~DR_TRAP_BITS))) rc = NOTIFY_DONE; + /* + * if we are about to signal to + * do_debug() to stop further processing + * and we have not ascertained the source + * of the breakpoint, log it as spurious. + */ + if (rc == NOTIFY_STOP && !bp) { + printk_ratelimited(KERN_INFO + "INFO: spurious INT1 exception dr6: 0x%lX dr7: 0x%lX\n", + dr6, dr7); + } + set_debugreg(dr7, 7); put_cpu();