Skip to content

Commit c4bed4b

Browse files
Lai JiangshanKAGA-KOKO
Lai Jiangshan
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 <laijs@linux.alibaba.com> Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Cc: stable@vger.kernel.org Link: https://lore.kernel.org/r/20210204152708.21308-1-jiangshanlai@gmail.com
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

+14
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)