Skip to content

Commit c4bed4b

Browse files
Lai JiangshanKAGA-KOKO
authored andcommitted
x86/debug: Prevent data breakpoints on __per_cpu_offset
When FSGSBASE is enabled, paranoid_entry() fetches the per-CPU GSBASE value via __per_cpu_offset or pcpu_unit_offsets. When a data breakpoint is set on __per_cpu_offset[cpu] (read-write operation), the specific CPU will be stuck in an infinite #DB loop. RCU will try to send an NMI to the specific CPU, but it is not working either since NMI also relies on paranoid_entry(). Which means it's undebuggable. Fixes: eaad981("x86/entry/64: Introduce the FIND_PERCPU_BASE macro") Signed-off-by: Lai Jiangshan <[email protected]> Signed-off-by: Thomas Gleixner <[email protected]> Cc: [email protected] Link: https://lore.kernel.org/r/[email protected]
1 parent 25a068b commit c4bed4b

File tree

1 file changed

+14
-0
lines changed

1 file changed

+14
-0
lines changed

arch/x86/kernel/hw_breakpoint.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,20 @@ static inline bool within_cpu_entry(unsigned long addr, unsigned long end)
269269
CPU_ENTRY_AREA_TOTAL_SIZE))
270270
return true;
271271

272+
/*
273+
* When FSGSBASE is enabled, paranoid_entry() fetches the per-CPU
274+
* GSBASE value via __per_cpu_offset or pcpu_unit_offsets.
275+
*/
276+
#ifdef CONFIG_SMP
277+
if (within_area(addr, end, (unsigned long)__per_cpu_offset,
278+
sizeof(unsigned long) * nr_cpu_ids))
279+
return true;
280+
#else
281+
if (within_area(addr, end, (unsigned long)&pcpu_unit_offsets,
282+
sizeof(pcpu_unit_offsets)))
283+
return true;
284+
#endif
285+
272286
for_each_possible_cpu(cpu) {
273287
/* The original rw GDT is being used after load_direct_gdt() */
274288
if (within_area(addr, end, (unsigned long)get_cpu_gdt_rw(cpu),

0 commit comments

Comments
 (0)