linux-stable/arch/arm/kernel
Sean Christopherson 723acd75a0 perf: Protect perf_guest_cbs with RCU
commit ff083a2d97 upstream.

Protect perf_guest_cbs with RCU to fix multiple possible errors.  Luckily,
all paths that read perf_guest_cbs already require RCU protection, e.g. to
protect the callback chains, so only the direct perf_guest_cbs touchpoints
need to be modified.

Bug #1 is a simple lack of WRITE_ONCE/READ_ONCE behavior to ensure
perf_guest_cbs isn't reloaded between a !NULL check and a dereference.
Fixed via the READ_ONCE() in rcu_dereference().

Bug #2 is that on weakly-ordered architectures, updates to the callbacks
themselves are not guaranteed to be visible before the pointer is made
visible to readers.  Fixed by the smp_store_release() in
rcu_assign_pointer() when the new pointer is non-NULL.

Bug #3 is that, because the callbacks are global, it's possible for
readers to run in parallel with an unregisters, and thus a module
implementing the callbacks can be unloaded while readers are in flight,
resulting in a use-after-free.  Fixed by a synchronize_rcu() call when
unregistering callbacks.

Bug #1 escaped notice because it's extremely unlikely a compiler will
reload perf_guest_cbs in this sequence.  perf_guest_cbs does get reloaded
for future derefs, e.g. for ->is_user_mode(), but the ->is_in_guest()
guard all but guarantees the consumer will win the race, e.g. to nullify
perf_guest_cbs, KVM has to completely exit the guest and teardown down
all VMs before KVM start its module unload / unregister sequence.  This
also makes it all but impossible to encounter bug #3.

Bug #2 has not been a problem because all architectures that register
callbacks are strongly ordered and/or have a static set of callbacks.

But with help, unloading kvm_intel can trigger bug #1 e.g. wrapping
perf_guest_cbs with READ_ONCE in perf_misc_flags() while spamming
kvm_intel module load/unload leads to:

  BUG: kernel NULL pointer dereference, address: 0000000000000000
  #PF: supervisor read access in kernel mode
  #PF: error_code(0x0000) - not-present page
  PGD 0 P4D 0
  Oops: 0000 [#1] PREEMPT SMP
  CPU: 6 PID: 1825 Comm: stress Not tainted 5.14.0-rc2+ #459
  Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 0.0.0 02/06/2015
  RIP: 0010:perf_misc_flags+0x1c/0x70
  Call Trace:
   perf_prepare_sample+0x53/0x6b0
   perf_event_output_forward+0x67/0x160
   __perf_event_overflow+0x52/0xf0
   handle_pmi_common+0x207/0x300
   intel_pmu_handle_irq+0xcf/0x410
   perf_event_nmi_handler+0x28/0x50
   nmi_handle+0xc7/0x260
   default_do_nmi+0x6b/0x170
   exc_nmi+0x103/0x130
   asm_exc_nmi+0x76/0xbf

Fixes: 39447b386c ("perf: Enhance perf to allow for guest statistic collection from host")
Signed-off-by: Sean Christopherson <seanjc@google.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Cc: stable@vger.kernel.org
Link: https://lore.kernel.org/r/20211111020738.2512932-2-seanjc@google.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2022-01-20 09:17:50 +01:00
..
.gitignore .gitignore: add SPDX License Identifier 2020-03-25 11:50:48 +01:00
arch_timer.c ARM: 8913/1: arch_timer: include <asm/arch_timer.h> 2019-10-27 21:14:43 +00:00
armksyms.c crypto: lib/sha1 - remove unnecessary includes of linux/cryptohash.h 2020-05-08 15:32:17 +10:00
asm-offsets.c ARM: 9075/1: kernel: Fix interrupted SMC calls 2021-05-22 11:40:53 +02:00
atags.h ARM: 9011/1: centralize phys-to-virt conversion of DT/ATAGS address 2021-05-19 10:13:18 +02:00
atags_compat.c treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 500 2019-06-19 17:09:55 +02:00
atags_parse.c ARM: 9011/1: centralize phys-to-virt conversion of DT/ATAGS address 2021-05-19 10:13:18 +02:00
atags_proc.c ARM: 8973/1: Add missing newline terminator to kernel message 2020-05-07 20:53:10 +01:00
bios32.c ARM/PCI: Remove unused fields from struct hw_pci 2020-09-18 22:39:09 +01:00
bugs.c treewide: fix typos of SPDX-License-Identifier 2019-06-01 18:29:58 +02:00
cpuidle.c treewide: Convert macro and uses of __section(foo) to __section("foo") 2020-10-25 14:51:49 -07:00
crash_dump.c treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 500 2019-06-19 17:09:55 +02:00
debug.S ARM: 9005/1: debug: Select flow control for all debug UARTs 2020-09-15 14:35:28 +01:00
devtree.c ARM: 9011/1: centralize phys-to-virt conversion of DT/ATAGS address 2021-05-19 10:13:18 +02:00
dma-isa.c treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 500 2019-06-19 17:09:55 +02:00
dma.c treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 500 2019-06-19 17:09:55 +02:00
early_printk.c treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 500 2019-06-19 17:09:55 +02:00
efi.c mm/pgtable: drop pgtable_t variable from pte_fn_t functions 2019-07-12 11:05:46 -07:00
elf.c arm32/64/elf: Split READ_IMPLIES_EXEC from executable PT_GNU_STACK 2020-04-20 19:42:19 +02:00
entry-armv.S ARM: 9169/1: entry: fix Thumb2 bug in iWMMXt exception handling 2021-12-29 12:26:04 +01:00
entry-common.S treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 500 2019-06-19 17:09:55 +02:00
entry-ftrace.S treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 500 2019-06-19 17:09:55 +02:00
entry-header.S ARM: uaccess: consolidate uaccess asm to asm/uaccess-asm.h 2020-05-03 17:30:24 +01:00
entry-v7m.S treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 500 2019-06-19 17:09:55 +02:00
fiq.c arm: fix the flush_icache_range arguments in set_fiq_handler 2020-06-08 11:05:57 -07:00
fiqasm.S
ftrace.c ARM: 9079/1: ftrace: Add MODULE_PLTS support 2021-09-26 14:08:56 +02:00
head-common.S ARM: 8914/1: NOMMU: Fix exc_ret for XIP 2019-10-10 22:23:20 +01:00
head-inflate-data.c treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 500 2019-06-19 17:09:55 +02:00
head-nommu.S ARM: 8914/1: NOMMU: Fix exc_ret for XIP 2019-10-10 22:23:20 +01:00
head.S ARM: 9027/1: head.S: explicitly map DT even if it lives in the first physical section 2021-05-19 10:13:18 +02:00
hibernate.c treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 194 2019-05-30 11:29:22 -07:00
hw_breakpoint.c ARM: 9064/1: hw_breakpoint: Do not directly check the event's overflow_handler hook 2021-05-19 10:13:01 +02:00
hyp-stub.S arm: Remove the ability to set HYP vectors outside of the decompressor 2020-03-24 10:56:05 +00:00
insn.c ARM: 9078/1: Add warn suppress parameter to arm_gen_branch_link() 2021-09-26 14:08:56 +02:00
io.c
irq.c ARM: Remove custom IRQ stat accounting 2020-09-17 16:37:28 +01:00
isa.c treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 152 2019-05-30 11:26:32 -07:00
iwmmxt.h ARM: 9029/1: Make iwmmxt.S support Clang's integrated assembler 2021-03-17 17:06:26 +01:00
iwmmxt.S ARM: 9029/1: Make iwmmxt.S support Clang's integrated assembler 2021-03-17 17:06:26 +01:00
jump_label.c jump_label: move 'asm goto' support test to Kconfig 2019-01-06 09:46:51 +09:00
kgdb.c maccess: rename probe_kernel_{read,write} to copy_{from,to}_kernel_nofault 2020-06-17 10:57:41 -07:00
machine_kexec.c ARM: kexec: fix oops after TLB are invalidated 2021-02-17 11:02:24 +01:00
Makefile Linux 5.5-rc1 2019-12-10 10:11:00 +01:00
module-plts.c ARM: 9098/1: ftrace: MODULE_PLT: Fix build problem without DYNAMIC_FTRACE 2021-09-26 14:08:56 +02:00
module.c mm: don't include asm/pgtable.h if linux/mm.h is already included 2020-06-09 09:39:13 -07:00
opcodes.c treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 500 2019-06-19 17:09:55 +02:00
paravirt.c treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 174 2019-05-30 11:26:41 -07:00
patch.c arm/patch: Fix !MMU compile 2020-02-11 12:56:27 +01:00
perf_callchain.c perf: Protect perf_guest_cbs with RCU 2022-01-20 09:17:50 +01:00
perf_event_v6.c
perf_event_v7.c arm_pmu: Fix write counter incorrect in ARMv7 big-endian mode 2021-07-14 16:55:39 +02:00
perf_event_xscale.c
perf_regs.c perf/arch: Remove perf_sample_data::regs_user_copy 2020-11-09 18:12:34 +01:00
pj4-cp0.c treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 500 2019-06-19 17:09:55 +02:00
process.c sched/idle: Fix arch_cpu_idle() vs tracing 2020-11-24 16:47:35 +01:00
psci_smp.c ARM: 8919/1: make unexported functions static 2019-10-31 16:58:52 +00:00
ptrace.c arm: switch to ->regset_get() 2020-07-27 14:31:09 -04:00
reboot.c ARM: Use reboot_cpu instead of hardcoding it to 0 2020-03-25 12:59:33 +01:00
reboot.h
relocate_kernel.S ARM: kexec: fix oops after TLB are invalidated 2021-02-17 11:02:24 +01:00
return_address.c ARM: 8918/2: only build return_address() if needed 2019-11-15 22:21:07 +00:00
setup.c ARM: 9081/1: fix gcc-10 thumb2-kernel regression 2021-06-30 08:47:16 -04:00
signal.c ARM: ensure the signal page contains defined contents 2021-02-17 11:02:24 +01:00
signal.h ARM: 8920/1: share get_signal_page from signal.c to process.c 2019-10-31 16:58:53 +00:00
sigreturn_codes.S treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 174 2019-05-30 11:26:41 -07:00
sleep.S ARM: 8847/1: pm: fix HYP/SVC mode mismatch when MCPM is used 2019-02-26 11:32:54 +00:00
smccc-call.S ARM: 9075/1: kernel: Fix interrupted SMC calls 2021-05-22 11:40:53 +02:00
smp.c sched/core: Initialize the idle task with preemption disabled 2021-07-14 16:55:50 +02:00
smp_scu.c treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 500 2019-06-19 17:09:55 +02:00
smp_tlb.c treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 500 2019-06-19 17:09:55 +02:00
smp_twd.c treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 500 2019-06-19 17:09:55 +02:00
stacktrace.c ARM: clang: Do not rely on lr register for stacktrace 2021-11-18 14:03:59 +01:00
suspend.c ARM: 9066/1: ftrace: pause/unpause function graph tracer in cpu_suspend() 2021-05-22 11:40:52 +02:00
swp_emulate.c mmap locking API: use coccinelle to convert mmap_sem rwsem call sites 2020-06-09 09:39:14 -07:00
sys_arm.c treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 500 2019-06-19 17:09:55 +02:00
sys_oabi-compat.c ARM: 9065/1: OABI compat: fix build when EPOLL is not enabled 2021-03-04 11:38:10 +01:00
tcm.c ARM: 8925/1: tcm: include <asm/tcm.h> for missing declarations 2019-10-31 16:58:56 +00:00
thumbee.c treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 333 2019-06-05 17:37:06 +02:00
time.c ARM/time: Replace <linux/clk-provider.h> by <linux/of_clk.h> 2020-05-15 22:54:57 +02:00
topology.c ARM, sched/topology: Revert back to default scheduler topology 2020-08-19 10:49:47 +02:00
traps.c maccess: make get_kernel_nofault() check for minimal type compatibility 2020-06-18 12:10:37 -07:00
unwind.c arm: add loglvl to unwind_backtrace() 2020-06-09 09:39:10 -07:00
v7m.c treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 500 2019-06-19 17:09:55 +02:00
vdso.c ARM: 8987/1: VDSO: Fix incorrect clock_gettime64 2020-07-21 16:32:55 +01:00
vmlinux-xip.lds.S ARM: 9141/1: only warn about XIP address when not compile testing 2021-11-02 19:48:18 +01:00
vmlinux.lds.S arm/build: Always handle .ARM.exidx and .ARM.extab sections 2020-10-27 11:32:21 -07:00
xscale-cp0.c treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 500 2019-06-19 17:09:55 +02:00