• John Stultz's avatar
    time: Fix clock->read(clock) race around clocksource changes · ceea5e37
    John Stultz authored
    In tests, which excercise switching of clocksources, a NULL
    pointer dereference can be observed on AMR64 platforms in the
    clocksource read() function:
    
    u64 clocksource_mmio_readl_down(struct clocksource *c)
    {
    	return ~(u64)readl_relaxed(to_mmio_clksrc(c)->reg) & c->mask;
    }
    
    This is called from the core timekeeping code via:
    
    	cycle_now = tkr->read(tkr->clock);
    
    tkr->read is the cached tkr->clock->read() function pointer.
    When the clocksource is changed then tkr->clock and tkr->read
    are updated sequentially. The code above results in a sequential
    load operation of tkr->read and tkr->clock as well.
    
    If the store to tkr->clock hits between the loads of tkr->read
    and tkr->clock, then the old read() function is called with the
    new clock pointer. As a consequence the read() function
    dereferences a different data structure and the resulting 'reg'
    pointer can point anywhere including NULL.
    
    This problem was introduced when the timekeeping code was
    switched over to use struct tk_read_base. Before that, it was
    theoretically possible as well when the compiler decided to
    reload clock in the code sequence:
    
         now = tk->clock->read(tk->clock);
    
    Add a helper function which avoids the issue by reading
    tk_read_base->clock once into a local variable clk and then issue
    the read function via clk->read(clk). This guarantees that the
    read() function always gets the proper clocksource pointer handed
    in.
    
    Since there is now no use for the tkr.read pointer, this patch
    also removes it, and to address stopping the fast timekeeper
    during suspend/resume, it introduces a dummy clocksource to use
    rather then just a dummy read function.
    Signed-off-by: default avatarJohn Stultz <john.stultz@linaro.org>
    Acked-by: default avatarIngo Molnar <mingo@kernel.org>
    Cc: Prarit Bhargava <prarit@redhat.com>
    Cc: Richard Cochran <richardcochran@gmail.com>
    Cc: Stephen Boyd <stephen.boyd@linaro.org>
    Cc: stable <stable@vger.kernel.org>
    Cc: Miroslav Lichvar <mlichvar@redhat.com>
    Cc: Daniel Mentz <danielmentz@google.com>
    Link: http://lkml.kernel.org/r/1496965462-20003-2-git-send-email-john.stultz@linaro.orgSigned-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
    ceea5e37
timekeeping.c 64.3 KB