ARM: probes: avoid adding kprobes to sensitive kernel-entry/exit code
Avoid adding kprobes to any of the kernel entry/exit or startup assembly code, or code in the identity-mapped region. This code does not conform to the standard C conventions, which means that the expectations of the kprobes code is not forfilled. Placing kprobes at some of these locations results in the kernel trying to return to userspace addresses while retaining the CPU in kernel mode. Tested-by: Naresh Kamboju <naresh.kamboju@linaro.org> Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
This commit is contained in:
@@ -82,11 +82,7 @@
|
||||
#endif
|
||||
.endm
|
||||
|
||||
#ifdef CONFIG_KPROBES
|
||||
.section .kprobes.text,"ax",%progbits
|
||||
#else
|
||||
.text
|
||||
#endif
|
||||
.section .entry.text,"ax",%progbits
|
||||
|
||||
/*
|
||||
* Invalid mode handlers
|
||||
|
@@ -37,6 +37,7 @@ saved_pc .req lr
|
||||
#define TRACE(x...)
|
||||
#endif
|
||||
|
||||
.section .entry.text,"ax",%progbits
|
||||
.align 5
|
||||
#if !(IS_ENABLED(CONFIG_TRACE_IRQFLAGS) || IS_ENABLED(CONFIG_CONTEXT_TRACKING))
|
||||
/*
|
||||
|
@@ -3,6 +3,7 @@
|
||||
#include <linux/sched/debug.h>
|
||||
#include <linux/stacktrace.h>
|
||||
|
||||
#include <asm/sections.h>
|
||||
#include <asm/stacktrace.h>
|
||||
#include <asm/traps.h>
|
||||
|
||||
@@ -63,7 +64,6 @@ EXPORT_SYMBOL(walk_stackframe);
|
||||
#ifdef CONFIG_STACKTRACE
|
||||
struct stack_trace_data {
|
||||
struct stack_trace *trace;
|
||||
unsigned long last_pc;
|
||||
unsigned int no_sched_functions;
|
||||
unsigned int skip;
|
||||
};
|
||||
@@ -87,16 +87,7 @@ static int save_trace(struct stackframe *frame, void *d)
|
||||
if (trace->nr_entries >= trace->max_entries)
|
||||
return 1;
|
||||
|
||||
/*
|
||||
* in_exception_text() is designed to test if the PC is one of
|
||||
* the functions which has an exception stack above it, but
|
||||
* unfortunately what is in frame->pc is the return LR value,
|
||||
* not the saved PC value. So, we need to track the previous
|
||||
* frame PC value when doing this.
|
||||
*/
|
||||
addr = data->last_pc;
|
||||
data->last_pc = frame->pc;
|
||||
if (!in_exception_text(addr))
|
||||
if (!in_entry_text(frame->pc))
|
||||
return 0;
|
||||
|
||||
regs = (struct pt_regs *)frame->sp;
|
||||
@@ -114,7 +105,6 @@ static noinline void __save_stack_trace(struct task_struct *tsk,
|
||||
struct stackframe frame;
|
||||
|
||||
data.trace = trace;
|
||||
data.last_pc = ULONG_MAX;
|
||||
data.skip = trace->skip;
|
||||
data.no_sched_functions = nosched;
|
||||
|
||||
|
@@ -72,7 +72,7 @@ void dump_backtrace_entry(unsigned long where, unsigned long from, unsigned long
|
||||
printk("Function entered at [<%08lx>] from [<%08lx>]\n", where, from);
|
||||
#endif
|
||||
|
||||
if (in_exception_text(where))
|
||||
if (in_entry_text(from))
|
||||
dump_mem("", "Exception stack", frame + 4, frame + 4 + sizeof(struct pt_regs));
|
||||
}
|
||||
|
||||
@@ -433,7 +433,7 @@ static int call_undef_hook(struct pt_regs *regs, unsigned int instr)
|
||||
return fn ? fn(regs, instr) : 1;
|
||||
}
|
||||
|
||||
asmlinkage void __exception do_undefinstr(struct pt_regs *regs)
|
||||
asmlinkage void do_undefinstr(struct pt_regs *regs)
|
||||
{
|
||||
unsigned int instr;
|
||||
siginfo_t info;
|
||||
|
@@ -96,9 +96,9 @@ SECTIONS
|
||||
.text : { /* Real text segment */
|
||||
_stext = .; /* Text and read-only data */
|
||||
IDMAP_TEXT
|
||||
__exception_text_start = .;
|
||||
*(.exception.text)
|
||||
__exception_text_end = .;
|
||||
__entry_text_start = .;
|
||||
*(.entry.text)
|
||||
__entry_text_end = .;
|
||||
IRQENTRY_TEXT
|
||||
TEXT_TEXT
|
||||
SCHED_TEXT
|
||||
|
@@ -105,9 +105,9 @@ SECTIONS
|
||||
.text : { /* Real text segment */
|
||||
_stext = .; /* Text and read-only data */
|
||||
IDMAP_TEXT
|
||||
__exception_text_start = .;
|
||||
*(.exception.text)
|
||||
__exception_text_end = .;
|
||||
__entry_text_start = .;
|
||||
*(.entry.text)
|
||||
__entry_text_end = .;
|
||||
IRQENTRY_TEXT
|
||||
SOFTIRQENTRY_TEXT
|
||||
TEXT_TEXT
|
||||
|
Reference in New Issue
Block a user