Patch "perf/x86: Fix 32-bit perf user callgraph collection" has been added to the 4.6-stable tree
Subsystems (3)
This is a note to let you know that I've just added the patch titled
perf/x86: Fix 32-bit perf user callgraph collection
to the 4.6-stable tree which can be found at:
http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary
The filename of the patch is:
perf-x86-fix-32-bit-perf-user-callgraph-collection.patch
and it can be found in the queue-4.6 subdirectory.
If you, or anyone else, feels it should not be added to the stable tree, please let <[email protected]> know about it.
Quoted 1 line
From
fc18822510721fe694d273c5211c71ea52796d76Mon Sep 17 00:00:00 2001
From: Josh Poimboeuf <[email protected]>
Date: Fri, 1 Jul 2016 23:02:05 -0500
Subject: perf/x86: Fix 32-bit perf user callgraph collection
From: Josh Poimboeuf <[email protected]>
commit fc18822510721fe694d273c5211c71ea52796d76 upstream.
A basic perf callgraph record operation causes an immediate panic on a 32-bit kernel compiled with CONFIG_CC_STACKPROTECTOR=y:
$ perf record -g ls Kernel panic - not syncing: stack-protector: Kernel stack is corrupted in: c0404fbd
CPU: 0 PID: 998 Comm: ls Not tainted 4.7.0-rc5+ #1 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.9.1-1.fc24 04/01/2014 c0dd5967 ff7afe1c 00000086 f41dbc2c c07445a0 464c457f f41dbca8 f41dbc44 c05646f4 f41dbca8 464c457f f41dbca8 464c457f f41dbc54 c04625be c0ce56fc c0404fbd f41dbc88 c0404fbd b74668f0 f41dc000 00000000 c0000000 00000000 Call Trace: [<c07445a0>] dump_stack+0x58/0x78 [<c05646f4>] panic+0x8e/0x1c6 [<c04625be>] __stack_chk_fail+0x1e/0x30 [<c0404fbd>] ? perf_callchain_user+0x22d/0x230 [<c0404fbd>] perf_callchain_user+0x22d/0x230 [<c055f89f>] get_perf_callchain+0x1ff/0x270 [<c055f988>] perf_callchain+0x78/0x90 [<c055c7eb>] perf_prepare_sample+0x24b/0x370 [<c055c934>] perf_event_output_forward+0x24/0x70 [<c05531c0>] __perf_event_overflow+0xa0/0x210 [<c0550a93>] ? cpu_clock_event_read+0x43/0x50 [<c0553431>] perf_swevent_hrtimer+0x101/0x180 [<c0456235>] ? kmap_atomic_prot+0x35/0x140 [<c056dc69>] ? get_page_from_freelist+0x279/0x950 [<c058fdd8>] ? vma_interval_tree_remove+0x158/0x230 [<c05939f4>] ? wp_page_copy.isra.82+0x2f4/0x630 [<c05a050d>] ? page_add_file_rmap+0x1d/0x50 [<c0565611>] ? unlock_page+0x61/0x80 [<c0566755>] ? filemap_map_pages+0x305/0x320 [<c059769f>] ? handle_mm_fault+0xb7f/0x1560 [<c074cbeb>] ? timerqueue_del+0x1b/0x70 [<c04cfefe>] ? __remove_hrtimer+0x2e/0x60 [<c04d017b>] __hrtimer_run_queues+0xcb/0x2a0 [<c0553330>] ? __perf_event_overflow+0x210/0x210 [<c04d0a2a>] hrtimer_interrupt+0x8a/0x180 [<c043ecc2>] local_apic_timer_interrupt+0x32/0x60 [<c043f643>] smp_apic_timer_interrupt+0x33/0x50 [<c0b0cd38>] apic_timer_interrupt+0x34/0x3c Kernel Offset: disabled ---[ end Kernel panic - not syncing: stack-protector: Kernel stack is corrupted in: c0404fbd
The panic is caused by the fact that perf_callchain_user() mistakenly assumes it's 64-bit only and ends up corrupting the stack.
--- arch/x86/events/core.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-)
arch/x86/events/core.c +6 -5
@@ -2313,7 +2313,7 @@ void perf_callchain_user(struct perf_callchain_entry *entry, struct pt_regs *regs) { struct stack_frame frame; -const void __user *fp; +const unsigned long __user *fp;if (perf_guest_cbs && perf_guest_cbs->is_in_guest ()) {/* TODO: We don't support guest os callchain now */
@@ -2326,7 +2326,7 @@ perf_callchain_user(struct perf_callchaiif (regs->flags & (X86_VM_MASK |PERF_EFLAGS_VM ))return ; - fp = (void __user *)regs->bp; + fp = (unsigned long __user *)regs->bp;perf_callchain_store (entry, regs->ip);
@@ -2339,16 +2339,17 @@ perf_callchain_user(struct perf_callchaipagefault_disable ();while (entry->nr <PERF_MAX_STACK_DEPTH ) {unsigned long bytes; + frame.next_frame =NULL ; frame.return_address =0 ; -if (!access_ok (VERIFY_READ , fp,16 )) +if (!access_ok (VERIFY_READ , fp,sizeof (*fp) *2 ))break ; - bytes =__copy_from_user_nmi (&frame.next_frame, fp,8 ); + bytes =__copy_from_user_nmi (&frame.next_frame, fp,sizeof (*fp));if (bytes !=0 )break ; - bytes =__copy_from_user_nmi (&frame.return_address, fp+8 ,8 ); + bytes =__copy_from_user_nmi (&frame.return_address, fp +1 ,sizeof (*fp));if (bytes !=0 )break ;
Patches currently in stable-queue which might be from [email protected] are
queue-4.6/perf-x86-fix-32-bit-perf-user-callgraph-collection.patch