summaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
Diffstat (limited to 'arch')
-rw-r--r--arch/arm/include/asm/exception.h3
-rw-r--r--arch/arm/include/asm/sections.h21
-rw-r--r--arch/arm/include/asm/traps.h12
-rw-r--r--arch/arm/kernel/entry-armv.S6
-rw-r--r--arch/arm/kernel/entry-common.S1
-rw-r--r--arch/arm/kernel/stacktrace.c14
-rw-r--r--arch/arm/kernel/traps.c4
-rw-r--r--arch/arm/kernel/vmlinux-xip.lds.S6
-rw-r--r--arch/arm/kernel/vmlinux.lds.S6
-rw-r--r--arch/arm/mm/fault.c5
-rw-r--r--arch/arm/probes/kprobes/core.c14
11 files changed, 47 insertions, 45 deletions
diff --git a/arch/arm/include/asm/exception.h b/arch/arm/include/asm/exception.h
index a7273ad9587a..58e039a851af 100644
--- a/arch/arm/include/asm/exception.h
+++ b/arch/arm/include/asm/exception.h
@@ -10,11 +10,10 @@
10 10
11#include <linux/interrupt.h> 11#include <linux/interrupt.h>
12 12
13#define __exception __attribute__((section(".exception.text")))
14#ifdef CONFIG_FUNCTION_GRAPH_TRACER 13#ifdef CONFIG_FUNCTION_GRAPH_TRACER
15#define __exception_irq_entry __irq_entry 14#define __exception_irq_entry __irq_entry
16#else 15#else
17#define __exception_irq_entry __exception 16#define __exception_irq_entry
18#endif 17#endif
19 18
20#endif /* __ASM_ARM_EXCEPTION_H */ 19#endif /* __ASM_ARM_EXCEPTION_H */
diff --git a/arch/arm/include/asm/sections.h b/arch/arm/include/asm/sections.h
index 63dfe1f10335..4ceb4f757d4d 100644
--- a/arch/arm/include/asm/sections.h
+++ b/arch/arm/include/asm/sections.h
@@ -6,4 +6,25 @@
6 6
7extern char _exiprom[]; 7extern char _exiprom[];
8 8
9extern char __idmap_text_start[];
10extern char __idmap_text_end[];
11extern char __entry_text_start[];
12extern char __entry_text_end[];
13extern char __hyp_idmap_text_start[];
14extern char __hyp_idmap_text_end[];
15
16static inline bool in_entry_text(unsigned long addr)
17{
18 return memory_contains(__entry_text_start, __entry_text_end,
19 (void *)addr, 1);
20}
21
22static inline bool in_idmap_text(unsigned long addr)
23{
24 void *a = (void *)addr;
25 return memory_contains(__idmap_text_start, __idmap_text_end, a, 1) ||
26 memory_contains(__hyp_idmap_text_start, __hyp_idmap_text_end,
27 a, 1);
28}
29
9#endif /* _ASM_ARM_SECTIONS_H */ 30#endif /* _ASM_ARM_SECTIONS_H */
diff --git a/arch/arm/include/asm/traps.h b/arch/arm/include/asm/traps.h
index f9a6c5fc3fd1..a00288d75ee6 100644
--- a/arch/arm/include/asm/traps.h
+++ b/arch/arm/include/asm/traps.h
@@ -28,18 +28,6 @@ static inline int __in_irqentry_text(unsigned long ptr)
28 ptr < (unsigned long)&__irqentry_text_end; 28 ptr < (unsigned long)&__irqentry_text_end;
29} 29}
30 30
31static inline int in_exception_text(unsigned long ptr)
32{
33 extern char __exception_text_start[];
34 extern char __exception_text_end[];
35 int in;
36
37 in = ptr >= (unsigned long)&__exception_text_start &&
38 ptr < (unsigned long)&__exception_text_end;
39
40 return in ? : __in_irqentry_text(ptr);
41}
42
43extern void __init early_trap_init(void *); 31extern void __init early_trap_init(void *);
44extern void dump_backtrace_entry(unsigned long where, unsigned long from, unsigned long frame); 32extern void dump_backtrace_entry(unsigned long where, unsigned long from, unsigned long frame);
45extern void ptrace_break(struct task_struct *tsk, struct pt_regs *regs); 33extern void ptrace_break(struct task_struct *tsk, struct pt_regs *regs);
diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S
index fbc707626b3e..1752033b0070 100644
--- a/arch/arm/kernel/entry-armv.S
+++ b/arch/arm/kernel/entry-armv.S
@@ -82,11 +82,7 @@
82#endif 82#endif
83 .endm 83 .endm
84 84
85#ifdef CONFIG_KPROBES 85 .section .entry.text,"ax",%progbits
86 .section .kprobes.text,"ax",%progbits
87#else
88 .text
89#endif
90 86
91/* 87/*
92 * Invalid mode handlers 88 * Invalid mode handlers
diff --git a/arch/arm/kernel/entry-common.S b/arch/arm/kernel/entry-common.S
index e655dcd0a933..3c4f88701f22 100644
--- a/arch/arm/kernel/entry-common.S
+++ b/arch/arm/kernel/entry-common.S
@@ -37,6 +37,7 @@ saved_pc .req lr
37#define TRACE(x...) 37#define TRACE(x...)
38#endif 38#endif
39 39
40 .section .entry.text,"ax",%progbits
40 .align 5 41 .align 5
41#if !(IS_ENABLED(CONFIG_TRACE_IRQFLAGS) || IS_ENABLED(CONFIG_CONTEXT_TRACKING)) 42#if !(IS_ENABLED(CONFIG_TRACE_IRQFLAGS) || IS_ENABLED(CONFIG_CONTEXT_TRACKING))
42/* 43/*
diff --git a/arch/arm/kernel/stacktrace.c b/arch/arm/kernel/stacktrace.c
index 65228bf4c6df..a56e7c856ab5 100644
--- a/arch/arm/kernel/stacktrace.c
+++ b/arch/arm/kernel/stacktrace.c
@@ -3,6 +3,7 @@
3#include <linux/sched/debug.h> 3#include <linux/sched/debug.h>
4#include <linux/stacktrace.h> 4#include <linux/stacktrace.h>
5 5
6#include <asm/sections.h>
6#include <asm/stacktrace.h> 7#include <asm/stacktrace.h>
7#include <asm/traps.h> 8#include <asm/traps.h>
8 9
@@ -63,7 +64,6 @@ EXPORT_SYMBOL(walk_stackframe);
63#ifdef CONFIG_STACKTRACE 64#ifdef CONFIG_STACKTRACE
64struct stack_trace_data { 65struct stack_trace_data {
65 struct stack_trace *trace; 66 struct stack_trace *trace;
66 unsigned long last_pc;
67 unsigned int no_sched_functions; 67 unsigned int no_sched_functions;
68 unsigned int skip; 68 unsigned int skip;
69}; 69};
@@ -87,16 +87,7 @@ static int save_trace(struct stackframe *frame, void *d)
87 if (trace->nr_entries >= trace->max_entries) 87 if (trace->nr_entries >= trace->max_entries)
88 return 1; 88 return 1;
89 89
90 /* 90 if (!in_entry_text(frame->pc))
91 * in_exception_text() is designed to test if the PC is one of
92 * the functions which has an exception stack above it, but
93 * unfortunately what is in frame->pc is the return LR value,
94 * not the saved PC value. So, we need to track the previous
95 * frame PC value when doing this.
96 */
97 addr = data->last_pc;
98 data->last_pc = frame->pc;
99 if (!in_exception_text(addr))
100 return 0; 91 return 0;
101 92
102 regs = (struct pt_regs *)frame->sp; 93 regs = (struct pt_regs *)frame->sp;
@@ -114,7 +105,6 @@ static noinline void __save_stack_trace(struct task_struct *tsk,
114 struct stackframe frame; 105 struct stackframe frame;
115 106
116 data.trace = trace; 107 data.trace = trace;
117 data.last_pc = ULONG_MAX;
118 data.skip = trace->skip; 108 data.skip = trace->skip;
119 data.no_sched_functions = nosched; 109 data.no_sched_functions = nosched;
120 110
diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c
index 5cf04888c581..e344bdd2e5ac 100644
--- a/arch/arm/kernel/traps.c
+++ b/arch/arm/kernel/traps.c
@@ -72,7 +72,7 @@ void dump_backtrace_entry(unsigned long where, unsigned long from, unsigned long
72 printk("Function entered at [<%08lx>] from [<%08lx>]\n", where, from); 72 printk("Function entered at [<%08lx>] from [<%08lx>]\n", where, from);
73#endif 73#endif
74 74
75 if (in_exception_text(where)) 75 if (in_entry_text(from))
76 dump_mem("", "Exception stack", frame + 4, frame + 4 + sizeof(struct pt_regs)); 76 dump_mem("", "Exception stack", frame + 4, frame + 4 + sizeof(struct pt_regs));
77} 77}
78 78
@@ -433,7 +433,7 @@ static int call_undef_hook(struct pt_regs *regs, unsigned int instr)
433 return fn ? fn(regs, instr) : 1; 433 return fn ? fn(regs, instr) : 1;
434} 434}
435 435
436asmlinkage void __exception do_undefinstr(struct pt_regs *regs) 436asmlinkage void do_undefinstr(struct pt_regs *regs)
437{ 437{
438 unsigned int instr; 438 unsigned int instr;
439 siginfo_t info; 439 siginfo_t info;
diff --git a/arch/arm/kernel/vmlinux-xip.lds.S b/arch/arm/kernel/vmlinux-xip.lds.S
index ec4b3f94ad80..12b87591eb7c 100644
--- a/arch/arm/kernel/vmlinux-xip.lds.S
+++ b/arch/arm/kernel/vmlinux-xip.lds.S
@@ -96,9 +96,9 @@ SECTIONS
96 .text : { /* Real text segment */ 96 .text : { /* Real text segment */
97 _stext = .; /* Text and read-only data */ 97 _stext = .; /* Text and read-only data */
98 IDMAP_TEXT 98 IDMAP_TEXT
99 __exception_text_start = .; 99 __entry_text_start = .;
100 *(.exception.text) 100 *(.entry.text)
101 __exception_text_end = .; 101 __entry_text_end = .;
102 IRQENTRY_TEXT 102 IRQENTRY_TEXT
103 TEXT_TEXT 103 TEXT_TEXT
104 SCHED_TEXT 104 SCHED_TEXT
diff --git a/arch/arm/kernel/vmlinux.lds.S b/arch/arm/kernel/vmlinux.lds.S
index ee53f6518872..84a1ae3ce46e 100644
--- a/arch/arm/kernel/vmlinux.lds.S
+++ b/arch/arm/kernel/vmlinux.lds.S
@@ -105,9 +105,9 @@ SECTIONS
105 .text : { /* Real text segment */ 105 .text : { /* Real text segment */
106 _stext = .; /* Text and read-only data */ 106 _stext = .; /* Text and read-only data */
107 IDMAP_TEXT 107 IDMAP_TEXT
108 __exception_text_start = .; 108 __entry_text_start = .;
109 *(.exception.text) 109 *(.entry.text)
110 __exception_text_end = .; 110 __entry_text_end = .;
111 IRQENTRY_TEXT 111 IRQENTRY_TEXT
112 SOFTIRQENTRY_TEXT 112 SOFTIRQENTRY_TEXT
113 TEXT_TEXT 113 TEXT_TEXT
diff --git a/arch/arm/mm/fault.c b/arch/arm/mm/fault.c
index 42f585379e19..b75eada23d0a 100644
--- a/arch/arm/mm/fault.c
+++ b/arch/arm/mm/fault.c
@@ -21,7 +21,6 @@
21#include <linux/highmem.h> 21#include <linux/highmem.h>
22#include <linux/perf_event.h> 22#include <linux/perf_event.h>
23 23
24#include <asm/exception.h>
25#include <asm/pgtable.h> 24#include <asm/pgtable.h>
26#include <asm/system_misc.h> 25#include <asm/system_misc.h>
27#include <asm/system_info.h> 26#include <asm/system_info.h>
@@ -545,7 +544,7 @@ hook_fault_code(int nr, int (*fn)(unsigned long, unsigned int, struct pt_regs *)
545/* 544/*
546 * Dispatch a data abort to the relevant handler. 545 * Dispatch a data abort to the relevant handler.
547 */ 546 */
548asmlinkage void __exception 547asmlinkage void
549do_DataAbort(unsigned long addr, unsigned int fsr, struct pt_regs *regs) 548do_DataAbort(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
550{ 549{
551 const struct fsr_info *inf = fsr_info + fsr_fs(fsr); 550 const struct fsr_info *inf = fsr_info + fsr_fs(fsr);
@@ -578,7 +577,7 @@ hook_ifault_code(int nr, int (*fn)(unsigned long, unsigned int, struct pt_regs *
578 ifsr_info[nr].name = name; 577 ifsr_info[nr].name = name;
579} 578}
580 579
581asmlinkage void __exception 580asmlinkage void
582do_PrefetchAbort(unsigned long addr, unsigned int ifsr, struct pt_regs *regs) 581do_PrefetchAbort(unsigned long addr, unsigned int ifsr, struct pt_regs *regs)
583{ 582{
584 const struct fsr_info *inf = ifsr_info + fsr_fs(ifsr); 583 const struct fsr_info *inf = ifsr_info + fsr_fs(ifsr);
diff --git a/arch/arm/probes/kprobes/core.c b/arch/arm/probes/kprobes/core.c
index 52d1cd14fda4..e90cc8a08186 100644
--- a/arch/arm/probes/kprobes/core.c
+++ b/arch/arm/probes/kprobes/core.c
@@ -32,6 +32,7 @@
32#include <linux/percpu.h> 32#include <linux/percpu.h>
33#include <linux/bug.h> 33#include <linux/bug.h>
34#include <asm/patch.h> 34#include <asm/patch.h>
35#include <asm/sections.h>
35 36
36#include "../decode-arm.h" 37#include "../decode-arm.h"
37#include "../decode-thumb.h" 38#include "../decode-thumb.h"
@@ -64,9 +65,6 @@ int __kprobes arch_prepare_kprobe(struct kprobe *p)
64 int is; 65 int is;
65 const struct decode_checker **checkers; 66 const struct decode_checker **checkers;
66 67
67 if (in_exception_text(addr))
68 return -EINVAL;
69
70#ifdef CONFIG_THUMB2_KERNEL 68#ifdef CONFIG_THUMB2_KERNEL
71 thumb = true; 69 thumb = true;
72 addr &= ~1; /* Bit 0 would normally be set to indicate Thumb code */ 70 addr &= ~1; /* Bit 0 would normally be set to indicate Thumb code */
@@ -680,3 +678,13 @@ int __init arch_init_kprobes()
680#endif 678#endif
681 return 0; 679 return 0;
682} 680}
681
682bool arch_within_kprobe_blacklist(unsigned long addr)
683{
684 void *a = (void *)addr;
685
686 return __in_irqentry_text(addr) ||
687 in_entry_text(addr) ||
688 in_idmap_text(addr) ||
689 memory_contains(__kprobes_text_start, __kprobes_text_end, a, 1);
690}