Commit 97417cb9 authored by Lai Jiangshan's avatar Lai Jiangshan Committed by Thomas Gleixner

x86/hw_breakpoint: Prevent data breakpoints on direct GDT

A data breakpoint on the GDT can be fatal and must be avoided.  The GDT in
the CPU entry area is already protected, but not the direct GDT.

Add the necessary protection.
Signed-off-by: default avatarLai Jiangshan <laijs@linux.alibaba.com>
Signed-off-by: default avatarPeter Zijlstra (Intel) <peterz@infradead.org>
Signed-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
Link: https://lkml.kernel.org/r/20200526014221.2119-3-laijs@linux.alibaba.com
Link: https://lkml.kernel.org/r/20200529213320.840953950@infradead.org

parent d390e6de
...@@ -32,6 +32,7 @@ ...@@ -32,6 +32,7 @@
#include <asm/processor.h> #include <asm/processor.h>
#include <asm/debugreg.h> #include <asm/debugreg.h>
#include <asm/user.h> #include <asm/user.h>
#include <asm/desc.h>
/* Per cpu debug control register value */ /* Per cpu debug control register value */
DEFINE_PER_CPU(unsigned long, cpu_dr7); DEFINE_PER_CPU(unsigned long, cpu_dr7);
...@@ -237,13 +238,26 @@ static inline bool within_area(unsigned long addr, unsigned long end, ...@@ -237,13 +238,26 @@ static inline bool within_area(unsigned long addr, unsigned long end,
} }
/* /*
* Checks whether the range from addr to end, inclusive, overlaps the CPU * Checks whether the range from addr to end, inclusive, overlaps the fixed
* entry area range. * mapped CPU entry area range or other ranges used for CPU entry.
*/ */
static inline bool within_cpu_entry_area(unsigned long addr, unsigned long end) static inline bool within_cpu_entry(unsigned long addr, unsigned long end)
{ {
return within_area(addr, end, CPU_ENTRY_AREA_BASE, int cpu;
CPU_ENTRY_AREA_TOTAL_SIZE);
/* CPU entry erea is always used for CPU entry */
if (within_area(addr, end, CPU_ENTRY_AREA_BASE,
CPU_ENTRY_AREA_TOTAL_SIZE))
return true;
for_each_possible_cpu(cpu) {
/* The original rw GDT is being used after load_direct_gdt() */
if (within_area(addr, end, (unsigned long)get_cpu_gdt_rw(cpu),
GDT_SIZE))
return true;
}
return false;
} }
static int arch_build_bp_info(struct perf_event *bp, static int arch_build_bp_info(struct perf_event *bp,
...@@ -257,12 +271,12 @@ static int arch_build_bp_info(struct perf_event *bp, ...@@ -257,12 +271,12 @@ static int arch_build_bp_info(struct perf_event *bp,
return -EINVAL; return -EINVAL;
/* /*
* Prevent any breakpoint of any type that overlaps the * Prevent any breakpoint of any type that overlaps the CPU
* cpu_entry_area. This protects the IST stacks and also * entry area and data. This protects the IST stacks and also
* reduces the chance that we ever find out what happens if * reduces the chance that we ever find out what happens if
* there's a data breakpoint on the GDT, IDT, or TSS. * there's a data breakpoint on the GDT, IDT, or TSS.
*/ */
if (within_cpu_entry_area(attr->bp_addr, bp_end)) if (within_cpu_entry(attr->bp_addr, bp_end))
return -EINVAL; return -EINVAL;
hw->address = attr->bp_addr; hw->address = attr->bp_addr;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment