Commit 4c4197ed authored by Daniel Thompson's avatar Daniel Thompson

kgdb: Add NOKPROBE labels on the trap handler functions

Currently kgdb honours the kprobe blocklist but doesn't place its own
trap handling code on the list. Add labels to discourage attempting to
use kgdb to debug itself.

Not every functions that executes from the trap handler needs to be
marked up: relatively early in the trap handler execution (just after
we bring the other CPUs to a halt) all breakpoints are replaced with
the original opcodes. This patch marks up code in the debug_core that
executes between trap entry and the breakpoints being deactivated
and, also, code that executes between breakpoint activation and trap
exit.

To be clear these changes are not sufficient to make recursive trapping
impossible since they do not include library calls made during kgdb's
entry/exit logic. However going much further whilst we are sharing the
kprobe blocklist risks reducing the capabilities of kprobe and this
would be a bad trade off (especially so given kgdb's users are currently
conditioned to avoid recursive traps).
Reviewed-by: default avatarDouglas Anderson <dianders@chromium.org>
Link: https://lore.kernel.org/r/20200927211531.1380577-3-daniel.thompson@linaro.orgSigned-off-by: default avatarDaniel Thompson <daniel.thompson@linaro.org>
parent f2d10ff4
...@@ -169,12 +169,14 @@ int __weak kgdb_arch_set_breakpoint(struct kgdb_bkpt *bpt) ...@@ -169,12 +169,14 @@ int __weak kgdb_arch_set_breakpoint(struct kgdb_bkpt *bpt)
arch_kgdb_ops.gdb_bpt_instr, BREAK_INSTR_SIZE); arch_kgdb_ops.gdb_bpt_instr, BREAK_INSTR_SIZE);
return err; return err;
} }
NOKPROBE_SYMBOL(kgdb_arch_set_breakpoint);
int __weak kgdb_arch_remove_breakpoint(struct kgdb_bkpt *bpt) int __weak kgdb_arch_remove_breakpoint(struct kgdb_bkpt *bpt)
{ {
return copy_to_kernel_nofault((char *)bpt->bpt_addr, return copy_to_kernel_nofault((char *)bpt->bpt_addr,
(char *)bpt->saved_instr, BREAK_INSTR_SIZE); (char *)bpt->saved_instr, BREAK_INSTR_SIZE);
} }
NOKPROBE_SYMBOL(kgdb_arch_remove_breakpoint);
int __weak kgdb_validate_break_address(unsigned long addr) int __weak kgdb_validate_break_address(unsigned long addr)
{ {
...@@ -204,6 +206,7 @@ unsigned long __weak kgdb_arch_pc(int exception, struct pt_regs *regs) ...@@ -204,6 +206,7 @@ unsigned long __weak kgdb_arch_pc(int exception, struct pt_regs *regs)
{ {
return instruction_pointer(regs); return instruction_pointer(regs);
} }
NOKPROBE_SYMBOL(kgdb_arch_pc);
int __weak kgdb_arch_init(void) int __weak kgdb_arch_init(void)
{ {
...@@ -214,6 +217,7 @@ int __weak kgdb_skipexception(int exception, struct pt_regs *regs) ...@@ -214,6 +217,7 @@ int __weak kgdb_skipexception(int exception, struct pt_regs *regs)
{ {
return 0; return 0;
} }
NOKPROBE_SYMBOL(kgdb_skipexception);
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
...@@ -235,6 +239,7 @@ void __weak kgdb_call_nmi_hook(void *ignored) ...@@ -235,6 +239,7 @@ void __weak kgdb_call_nmi_hook(void *ignored)
*/ */
kgdb_nmicallback(raw_smp_processor_id(), get_irq_regs()); kgdb_nmicallback(raw_smp_processor_id(), get_irq_regs());
} }
NOKPROBE_SYMBOL(kgdb_call_nmi_hook);
void __weak kgdb_roundup_cpus(void) void __weak kgdb_roundup_cpus(void)
{ {
...@@ -268,6 +273,7 @@ void __weak kgdb_roundup_cpus(void) ...@@ -268,6 +273,7 @@ void __weak kgdb_roundup_cpus(void)
kgdb_info[cpu].rounding_up = false; kgdb_info[cpu].rounding_up = false;
} }
} }
NOKPROBE_SYMBOL(kgdb_roundup_cpus);
#endif #endif
...@@ -294,6 +300,7 @@ static void kgdb_flush_swbreak_addr(unsigned long addr) ...@@ -294,6 +300,7 @@ static void kgdb_flush_swbreak_addr(unsigned long addr)
/* Force flush instruction cache if it was outside the mm */ /* Force flush instruction cache if it was outside the mm */
flush_icache_range(addr, addr + BREAK_INSTR_SIZE); flush_icache_range(addr, addr + BREAK_INSTR_SIZE);
} }
NOKPROBE_SYMBOL(kgdb_flush_swbreak_addr);
/* /*
* SW breakpoint management: * SW breakpoint management:
...@@ -321,6 +328,7 @@ int dbg_activate_sw_breakpoints(void) ...@@ -321,6 +328,7 @@ int dbg_activate_sw_breakpoints(void)
} }
return ret; return ret;
} }
NOKPROBE_SYMBOL(dbg_activate_sw_breakpoints);
int dbg_set_sw_break(unsigned long addr) int dbg_set_sw_break(unsigned long addr)
{ {
...@@ -384,6 +392,7 @@ int dbg_deactivate_sw_breakpoints(void) ...@@ -384,6 +392,7 @@ int dbg_deactivate_sw_breakpoints(void)
} }
return ret; return ret;
} }
NOKPROBE_SYMBOL(dbg_deactivate_sw_breakpoints);
int dbg_remove_sw_break(unsigned long addr) int dbg_remove_sw_break(unsigned long addr)
{ {
...@@ -505,6 +514,7 @@ static int kgdb_io_ready(int print_wait) ...@@ -505,6 +514,7 @@ static int kgdb_io_ready(int print_wait)
} }
return 1; return 1;
} }
NOKPROBE_SYMBOL(kgdb_io_ready);
static int kgdb_reenter_check(struct kgdb_state *ks) static int kgdb_reenter_check(struct kgdb_state *ks)
{ {
...@@ -552,6 +562,7 @@ static int kgdb_reenter_check(struct kgdb_state *ks) ...@@ -552,6 +562,7 @@ static int kgdb_reenter_check(struct kgdb_state *ks)
return 1; return 1;
} }
NOKPROBE_SYMBOL(kgdb_reenter_check);
static void dbg_touch_watchdogs(void) static void dbg_touch_watchdogs(void)
{ {
...@@ -559,6 +570,7 @@ static void dbg_touch_watchdogs(void) ...@@ -559,6 +570,7 @@ static void dbg_touch_watchdogs(void)
clocksource_touch_watchdog(); clocksource_touch_watchdog();
rcu_cpu_stall_reset(); rcu_cpu_stall_reset();
} }
NOKPROBE_SYMBOL(dbg_touch_watchdogs);
static int kgdb_cpu_enter(struct kgdb_state *ks, struct pt_regs *regs, static int kgdb_cpu_enter(struct kgdb_state *ks, struct pt_regs *regs,
int exception_state) int exception_state)
...@@ -790,6 +802,7 @@ static int kgdb_cpu_enter(struct kgdb_state *ks, struct pt_regs *regs, ...@@ -790,6 +802,7 @@ static int kgdb_cpu_enter(struct kgdb_state *ks, struct pt_regs *regs,
return kgdb_info[cpu].ret_state; return kgdb_info[cpu].ret_state;
} }
NOKPROBE_SYMBOL(kgdb_cpu_enter);
/* /*
* kgdb_handle_exception() - main entry point from a kernel exception * kgdb_handle_exception() - main entry point from a kernel exception
...@@ -834,6 +847,7 @@ kgdb_handle_exception(int evector, int signo, int ecode, struct pt_regs *regs) ...@@ -834,6 +847,7 @@ kgdb_handle_exception(int evector, int signo, int ecode, struct pt_regs *regs)
arch_kgdb_ops.enable_nmi(1); arch_kgdb_ops.enable_nmi(1);
return ret; return ret;
} }
NOKPROBE_SYMBOL(kgdb_handle_exception);
/* /*
* GDB places a breakpoint at this function to know dynamically loaded objects. * GDB places a breakpoint at this function to know dynamically loaded objects.
...@@ -868,6 +882,7 @@ int kgdb_nmicallback(int cpu, void *regs) ...@@ -868,6 +882,7 @@ int kgdb_nmicallback(int cpu, void *regs)
#endif #endif
return 1; return 1;
} }
NOKPROBE_SYMBOL(kgdb_nmicallback);
int kgdb_nmicallin(int cpu, int trapnr, void *regs, int err_code, int kgdb_nmicallin(int cpu, int trapnr, void *regs, int err_code,
atomic_t *send_ready) atomic_t *send_ready)
...@@ -893,6 +908,7 @@ int kgdb_nmicallin(int cpu, int trapnr, void *regs, int err_code, ...@@ -893,6 +908,7 @@ int kgdb_nmicallin(int cpu, int trapnr, void *regs, int err_code,
#endif #endif
return 1; return 1;
} }
NOKPROBE_SYMBOL(kgdb_nmicallin);
static void kgdb_console_write(struct console *co, const char *s, static void kgdb_console_write(struct console *co, const char *s,
unsigned count) unsigned count)
......
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