Skip to content

Commit 97417cb

Browse files
Lai JiangshanKAGA-KOKO
authored andcommitted
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: Lai Jiangshan <[email protected]> Signed-off-by: Peter Zijlstra (Intel) <[email protected]> Signed-off-by: Thomas Gleixner <[email protected]> Link: https://lkml.kernel.org/r/[email protected] Link: https://lkml.kernel.org/r/[email protected]
1 parent d390e6d commit 97417cb

File tree

1 file changed

+22
-8
lines changed

1 file changed

+22
-8
lines changed

arch/x86/kernel/hw_breakpoint.c

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
#include <asm/processor.h>
3333
#include <asm/debugreg.h>
3434
#include <asm/user.h>
35+
#include <asm/desc.h>
3536

3637
/* Per cpu debug control register value */
3738
DEFINE_PER_CPU(unsigned long, cpu_dr7);
@@ -237,13 +238,26 @@ static inline bool within_area(unsigned long addr, unsigned long end,
237238
}
238239

239240
/*
240-
* Checks whether the range from addr to end, inclusive, overlaps the CPU
241-
* entry area range.
241+
* Checks whether the range from addr to end, inclusive, overlaps the fixed
242+
* mapped CPU entry area range or other ranges used for CPU entry.
242243
*/
243-
static inline bool within_cpu_entry_area(unsigned long addr, unsigned long end)
244+
static inline bool within_cpu_entry(unsigned long addr, unsigned long end)
244245
{
245-
return within_area(addr, end, CPU_ENTRY_AREA_BASE,
246-
CPU_ENTRY_AREA_TOTAL_SIZE);
246+
int cpu;
247+
248+
/* CPU entry erea is always used for CPU entry */
249+
if (within_area(addr, end, CPU_ENTRY_AREA_BASE,
250+
CPU_ENTRY_AREA_TOTAL_SIZE))
251+
return true;
252+
253+
for_each_possible_cpu(cpu) {
254+
/* The original rw GDT is being used after load_direct_gdt() */
255+
if (within_area(addr, end, (unsigned long)get_cpu_gdt_rw(cpu),
256+
GDT_SIZE))
257+
return true;
258+
}
259+
260+
return false;
247261
}
248262

249263
static int arch_build_bp_info(struct perf_event *bp,
@@ -257,12 +271,12 @@ static int arch_build_bp_info(struct perf_event *bp,
257271
return -EINVAL;
258272

259273
/*
260-
* Prevent any breakpoint of any type that overlaps the
261-
* cpu_entry_area. This protects the IST stacks and also
274+
* Prevent any breakpoint of any type that overlaps the CPU
275+
* entry area and data. This protects the IST stacks and also
262276
* reduces the chance that we ever find out what happens if
263277
* there's a data breakpoint on the GDT, IDT, or TSS.
264278
*/
265-
if (within_cpu_entry_area(attr->bp_addr, bp_end))
279+
if (within_cpu_entry(attr->bp_addr, bp_end))
266280
return -EINVAL;
267281

268282
hw->address = attr->bp_addr;

0 commit comments

Comments
 (0)