mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-05 02:21:52 +09:00
x86/vdso: Prevent segfaults due to hoisted vclock reads
commitff17bbe0bbupstream. GCC 5.5.0 sometimes cleverly hoists reads of the pvclock and/or hvclock pages before the vclock mode checks. This creates a path through vclock_gettime() in which no vclock is enabled at all (due to disabled TSC on old CPUs, for example) but the pvclock or hvclock page nevertheless read. This will segfault on bare metal. This fixes commit459e3a2153("gcc-9: properly declare the {pv,hv}clock_page storage") in the sense that, before that commit, GCC didn't seem to generate the offending code. There was nothing wrong with that commit per se, and -stable maintainers should backport this to all supported kernels regardless of whether the offending commit was present, since the same crash could just as easily be triggered by the phase of the moon. On GCC 9.1.1, this doesn't seem to affect the generated code at all, so I'm not too concerned about performance regressions from this fix. Cc: stable@vger.kernel.org Cc: x86@kernel.org Cc: Borislav Petkov <bp@alien8.de> Reported-by: Duncan Roe <duncan_roe@optusnet.com.au> Signed-off-by: Andy Lutomirski <luto@kernel.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
committed by
Greg Kroah-Hartman
parent
f73e824544
commit
2c04e80a6c
@@ -191,13 +191,24 @@ notrace static inline u64 vgetsns(int *mode)
|
||||
|
||||
if (gtod->vclock_mode == VCLOCK_TSC)
|
||||
cycles = vread_tsc();
|
||||
|
||||
/*
|
||||
* For any memory-mapped vclock type, we need to make sure that gcc
|
||||
* doesn't cleverly hoist a load before the mode check. Otherwise we
|
||||
* might end up touching the memory-mapped page even if the vclock in
|
||||
* question isn't enabled, which will segfault. Hence the barriers.
|
||||
*/
|
||||
#ifdef CONFIG_PARAVIRT_CLOCK
|
||||
else if (gtod->vclock_mode == VCLOCK_PVCLOCK)
|
||||
else if (gtod->vclock_mode == VCLOCK_PVCLOCK) {
|
||||
barrier();
|
||||
cycles = vread_pvclock(mode);
|
||||
}
|
||||
#endif
|
||||
#ifdef CONFIG_HYPERV_TSCPAGE
|
||||
else if (gtod->vclock_mode == VCLOCK_HVCLOCK)
|
||||
else if (gtod->vclock_mode == VCLOCK_HVCLOCK) {
|
||||
barrier();
|
||||
cycles = vread_hvclock(mode);
|
||||
}
|
||||
#endif
|
||||
else
|
||||
return 0;
|
||||
|
||||
Reference in New Issue
Block a user