diff options
Diffstat (limited to 'arch')
-rw-r--r-- | arch/arm/include/asm/exception.h | 3 | ||||
-rw-r--r-- | arch/arm/include/asm/sections.h | 21 | ||||
-rw-r--r-- | arch/arm/include/asm/traps.h | 12 | ||||
-rw-r--r-- | arch/arm/kernel/entry-armv.S | 6 | ||||
-rw-r--r-- | arch/arm/kernel/entry-common.S | 1 | ||||
-rw-r--r-- | arch/arm/kernel/stacktrace.c | 14 | ||||
-rw-r--r-- | arch/arm/kernel/traps.c | 4 | ||||
-rw-r--r-- | arch/arm/kernel/vmlinux-xip.lds.S | 6 | ||||
-rw-r--r-- | arch/arm/kernel/vmlinux.lds.S | 6 | ||||
-rw-r--r-- | arch/arm/mm/fault.c | 5 | ||||
-rw-r--r-- | arch/arm/probes/kprobes/core.c | 14 |
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 | ||
7 | extern char _exiprom[]; | 7 | extern char _exiprom[]; |
8 | 8 | ||
9 | extern char __idmap_text_start[]; | ||
10 | extern char __idmap_text_end[]; | ||
11 | extern char __entry_text_start[]; | ||
12 | extern char __entry_text_end[]; | ||
13 | extern char __hyp_idmap_text_start[]; | ||
14 | extern char __hyp_idmap_text_end[]; | ||
15 | |||
16 | static 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 | |||
22 | static 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 | ||
31 | static 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 | |||
43 | extern void __init early_trap_init(void *); | 31 | extern void __init early_trap_init(void *); |
44 | extern void dump_backtrace_entry(unsigned long where, unsigned long from, unsigned long frame); | 32 | extern void dump_backtrace_entry(unsigned long where, unsigned long from, unsigned long frame); |
45 | extern void ptrace_break(struct task_struct *tsk, struct pt_regs *regs); | 33 | extern 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 |
64 | struct stack_trace_data { | 65 | struct 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 | ||
436 | asmlinkage void __exception do_undefinstr(struct pt_regs *regs) | 436 | asmlinkage 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 | */ |
548 | asmlinkage void __exception | 547 | asmlinkage void |
549 | do_DataAbort(unsigned long addr, unsigned int fsr, struct pt_regs *regs) | 548 | do_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 | ||
581 | asmlinkage void __exception | 580 | asmlinkage void |
582 | do_PrefetchAbort(unsigned long addr, unsigned int ifsr, struct pt_regs *regs) | 581 | do_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 | |||
682 | bool 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 | } | ||