lkml.org 
[lkml]   [2019]   [Aug]   [5]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 4.19 73/74] x86/vdso: Prevent segfaults due to hoisted vclock reads
    Date
    From: Andy Lutomirski <luto@kernel.org>

    commit ff17bbe0bb405ad8b36e55815d381841f9fdeebc upstream.

    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 commit 459e3a21535a ("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>

    ---
    arch/x86/entry/vdso/vclock_gettime.c | 15 +++++++++++++--
    1 file changed, 13 insertions(+), 2 deletions(-)

    --- a/arch/x86/entry/vdso/vclock_gettime.c
    +++ b/arch/x86/entry/vdso/vclock_gettime.c
    @@ -191,13 +191,24 @@ notrace static inline u64 vgetsns(int *m

    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;

    \
     
     \ /
      Last update: 2019-08-05 15:20    [W:2.588 / U:0.024 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site