]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blob - releases/4.6.5/perf-x86-fix-32-bit-perf-user-callgraph-collection.patch
5.1-stable patches
[thirdparty/kernel/stable-queue.git] / releases / 4.6.5 / perf-x86-fix-32-bit-perf-user-callgraph-collection.patch
1 From fc18822510721fe694d273c5211c71ea52796d76 Mon Sep 17 00:00:00 2001
2 From: Josh Poimboeuf <jpoimboe@redhat.com>
3 Date: Fri, 1 Jul 2016 23:02:05 -0500
4 Subject: perf/x86: Fix 32-bit perf user callgraph collection
5
6 From: Josh Poimboeuf <jpoimboe@redhat.com>
7
8 commit fc18822510721fe694d273c5211c71ea52796d76 upstream.
9
10 A basic perf callgraph record operation causes an immediate panic on a
11 32-bit kernel compiled with CONFIG_CC_STACKPROTECTOR=y:
12
13 $ perf record -g ls
14 Kernel panic - not syncing: stack-protector: Kernel stack is corrupted in: c0404fbd
15
16 CPU: 0 PID: 998 Comm: ls Not tainted 4.7.0-rc5+ #1
17 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.9.1-1.fc24 04/01/2014
18 c0dd5967 ff7afe1c 00000086 f41dbc2c c07445a0 464c457f f41dbca8 f41dbc44
19 c05646f4 f41dbca8 464c457f f41dbca8 464c457f f41dbc54 c04625be c0ce56fc
20 c0404fbd f41dbc88 c0404fbd b74668f0 f41dc000 00000000 c0000000 00000000
21 Call Trace:
22 [<c07445a0>] dump_stack+0x58/0x78
23 [<c05646f4>] panic+0x8e/0x1c6
24 [<c04625be>] __stack_chk_fail+0x1e/0x30
25 [<c0404fbd>] ? perf_callchain_user+0x22d/0x230
26 [<c0404fbd>] perf_callchain_user+0x22d/0x230
27 [<c055f89f>] get_perf_callchain+0x1ff/0x270
28 [<c055f988>] perf_callchain+0x78/0x90
29 [<c055c7eb>] perf_prepare_sample+0x24b/0x370
30 [<c055c934>] perf_event_output_forward+0x24/0x70
31 [<c05531c0>] __perf_event_overflow+0xa0/0x210
32 [<c0550a93>] ? cpu_clock_event_read+0x43/0x50
33 [<c0553431>] perf_swevent_hrtimer+0x101/0x180
34 [<c0456235>] ? kmap_atomic_prot+0x35/0x140
35 [<c056dc69>] ? get_page_from_freelist+0x279/0x950
36 [<c058fdd8>] ? vma_interval_tree_remove+0x158/0x230
37 [<c05939f4>] ? wp_page_copy.isra.82+0x2f4/0x630
38 [<c05a050d>] ? page_add_file_rmap+0x1d/0x50
39 [<c0565611>] ? unlock_page+0x61/0x80
40 [<c0566755>] ? filemap_map_pages+0x305/0x320
41 [<c059769f>] ? handle_mm_fault+0xb7f/0x1560
42 [<c074cbeb>] ? timerqueue_del+0x1b/0x70
43 [<c04cfefe>] ? __remove_hrtimer+0x2e/0x60
44 [<c04d017b>] __hrtimer_run_queues+0xcb/0x2a0
45 [<c0553330>] ? __perf_event_overflow+0x210/0x210
46 [<c04d0a2a>] hrtimer_interrupt+0x8a/0x180
47 [<c043ecc2>] local_apic_timer_interrupt+0x32/0x60
48 [<c043f643>] smp_apic_timer_interrupt+0x33/0x50
49 [<c0b0cd38>] apic_timer_interrupt+0x34/0x3c
50 Kernel Offset: disabled
51 ---[ end Kernel panic - not syncing: stack-protector: Kernel stack is corrupted in: c0404fbd
52
53 The panic is caused by the fact that perf_callchain_user() mistakenly
54 assumes it's 64-bit only and ends up corrupting the stack.
55
56 Signed-off-by: Josh Poimboeuf <jpoimboe@redhat.com>
57 Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
58 Cc: Arnaldo Carvalho de Melo <acme@kernel.org>
59 Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
60 Cc: Jiri Olsa <jolsa@redhat.com>
61 Cc: Linus Torvalds <torvalds@linux-foundation.org>
62 Cc: Peter Zijlstra <peterz@infradead.org>
63 Cc: Stephane Eranian <eranian@google.com>
64 Cc: Thomas Gleixner <tglx@linutronix.de>
65 Cc: Vince Weaver <vincent.weaver@maine.edu>
66 Fixes: 75925e1ad7f5 ("perf/x86: Optimize stack walk user accesses")
67 Link: http://lkml.kernel.org/r/1a547f5077ec30f75f9b57074837c3c80df86e5e.1467432113.git.jpoimboe@redhat.com
68 Signed-off-by: Ingo Molnar <mingo@kernel.org>
69 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
70
71 ---
72 arch/x86/events/core.c | 11 ++++++-----
73 1 file changed, 6 insertions(+), 5 deletions(-)
74
75 --- a/arch/x86/events/core.c
76 +++ b/arch/x86/events/core.c
77 @@ -2313,7 +2313,7 @@ void
78 perf_callchain_user(struct perf_callchain_entry *entry, struct pt_regs *regs)
79 {
80 struct stack_frame frame;
81 - const void __user *fp;
82 + const unsigned long __user *fp;
83
84 if (perf_guest_cbs && perf_guest_cbs->is_in_guest()) {
85 /* TODO: We don't support guest os callchain now */
86 @@ -2326,7 +2326,7 @@ perf_callchain_user(struct perf_callchai
87 if (regs->flags & (X86_VM_MASK | PERF_EFLAGS_VM))
88 return;
89
90 - fp = (void __user *)regs->bp;
91 + fp = (unsigned long __user *)regs->bp;
92
93 perf_callchain_store(entry, regs->ip);
94
95 @@ -2339,16 +2339,17 @@ perf_callchain_user(struct perf_callchai
96 pagefault_disable();
97 while (entry->nr < PERF_MAX_STACK_DEPTH) {
98 unsigned long bytes;
99 +
100 frame.next_frame = NULL;
101 frame.return_address = 0;
102
103 - if (!access_ok(VERIFY_READ, fp, 16))
104 + if (!access_ok(VERIFY_READ, fp, sizeof(*fp) * 2))
105 break;
106
107 - bytes = __copy_from_user_nmi(&frame.next_frame, fp, 8);
108 + bytes = __copy_from_user_nmi(&frame.next_frame, fp, sizeof(*fp));
109 if (bytes != 0)
110 break;
111 - bytes = __copy_from_user_nmi(&frame.return_address, fp+8, 8);
112 + bytes = __copy_from_user_nmi(&frame.return_address, fp + 1, sizeof(*fp));
113 if (bytes != 0)
114 break;
115