82d3edb50a
The current cmpxchg_double() loops within the perf hw sampling code do not have READ_ONCE() semantics to read the old value from memory. This allows the compiler to generate code which reads the "old" value several times from memory, which again allows for inconsistencies. For example: /* Reset trailer (using compare-double-and-swap) */ do { te_flags = te->flags & ~SDB_TE_BUFFER_FULL_MASK; te_flags |= SDB_TE_ALERT_REQ_MASK; } while (!cmpxchg_double(&te->flags, &te->overflow, te->flags, te->overflow, te_flags, 0ULL)); The compiler could generate code where te->flags used within the cmpxchg_double() call may be refetched from memory and which is not necessarily identical to the previous read version which was used to generate te_flags. Which in turn means that an incorrect update could happen. Fix this by adding READ_ONCE() semantics to all cmpxchg_double() loops. Given that READ_ONCE() cannot generate code on s390 which atomically reads 16 bytes, use a private compare-and-swap-double implementation to achieve that. Also replace cmpxchg_double() with the private implementation to be able to re-use the old value within the loops. As a side effect this converts the whole code to only use bit fields to read and modify bits within the hws trailer header. Reported-by: Alexander Gordeev <agordeev@linux.ibm.com> Acked-by: Alexander Gordeev <agordeev@linux.ibm.com> Acked-by: Hendrik Brueckner <brueckner@linux.ibm.com> Reviewed-by: Thomas Richter <tmricht@linux.ibm.com> Cc: <stable@vger.kernel.org> Link: https://lore.kernel.org/linux-s390/Y71QJBhNTIatvxUT@osiris/T/#ma14e2a5f7aa8ed4b94b6f9576799b3ad9c60f333 Signed-off-by: Heiko Carstens <hca@linux.ibm.com> |
||
---|---|---|
.. | ||
syscalls | ||
vdso32 | ||
vdso64 | ||
.gitignore | ||
abs_lowcore.c | ||
alternative.c | ||
asm-offsets.c | ||
audit.c | ||
audit.h | ||
cache.c | ||
compat_audit.c | ||
compat_linux.c | ||
compat_linux.h | ||
compat_ptrace.h | ||
compat_signal.c | ||
cpcmd.c | ||
cpufeature.c | ||
crash_dump.c | ||
debug.c | ||
diag.c | ||
dis.c | ||
dumpstack.c | ||
early_printk.c | ||
early.c | ||
earlypgm.S | ||
ebcdic.c | ||
entry.h | ||
entry.S | ||
fpu.c | ||
ftrace.c | ||
ftrace.h | ||
guarded_storage.c | ||
head64.S | ||
idle.c | ||
ima_arch.c | ||
ipl_vmparm.c | ||
ipl.c | ||
irq.c | ||
jump_label.c | ||
kdebugfs.c | ||
kexec_elf.c | ||
kexec_image.c | ||
kprobes_insn_page.S | ||
kprobes.c | ||
kprobes.h | ||
lgr.c | ||
machine_kexec_file.c | ||
machine_kexec_reloc.c | ||
machine_kexec.c | ||
Makefile | ||
mcount.S | ||
module.c | ||
nmi.c | ||
nospec-branch.c | ||
nospec-sysfs.c | ||
numa.c | ||
os_info.c | ||
perf_cpum_cf_common.c | ||
perf_cpum_cf_events.c | ||
perf_cpum_cf.c | ||
perf_cpum_sf.c | ||
perf_event.c | ||
perf_pai_crypto.c | ||
perf_pai_ext.c | ||
perf_regs.c | ||
process.c | ||
processor.c | ||
ptrace.c | ||
reipl.S | ||
relocate_kernel.S | ||
runtime_instr.c | ||
setup.c | ||
signal.c | ||
smp.c | ||
stacktrace.c | ||
sthyi.c | ||
syscall.c | ||
sysinfo.c | ||
text_amode31.S | ||
time.c | ||
topology.c | ||
trace.c | ||
traps.c | ||
unwind_bc.c | ||
uprobes.c | ||
uv.c | ||
vdso.c | ||
vmlinux.lds.S | ||
vtime.c |