android_kernel_samsung_univ.../kernel/time
John Stultz 1fecf3977d time: Fix clock->read(clock) race around clocksource changes
commit ceea5e3771ed2378668455fa21861bead7504df5 upstream.

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: John Stultz <john.stultz@linaro.org>
Acked-by: Ingo Molnar <mingo@kernel.org>
Cc: Prarit Bhargava <prarit@redhat.com>
Cc: Richard Cochran <richardcochran@gmail.com>
Cc: Stephen Boyd <stephen.boyd@linaro.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.org
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2017-06-29 12:48:51 +02:00
..
alarmtimer.c alarmtimer: Rate limit periodic intervals 2017-06-26 07:13:11 +02:00
clockevents.c clockevents: Remove unused set_mode() callback 2015-09-14 11:00:55 +02:00
clocksource.c clocksource: Allow unregistering the watchdog 2016-09-15 08:27:47 +02:00
hrtimer.c hrtimer: Catch illegal clockids 2016-09-15 08:27:44 +02:00
itimer.c itimers: Handle relative timers with CONFIG_TIME_LOW_RES proper 2016-02-25 12:01:25 -08:00
jiffies.c
Kconfig rcu: Drop RCU_USER_QS in favor of NO_HZ_FULL 2015-07-06 13:52:18 -07:00
Makefile
ntp_internal.h ntp/pps: use timespec64 for hardpps() 2015-10-01 09:57:59 -07:00
ntp.c ntp: Fix ADJ_SETOFFSET being used w/ ADJ_NANO 2016-09-15 08:27:47 +02:00
posix-clock.c posix-clock: Fix return code on the poll method's error path 2016-03-03 15:07:15 -08:00
posix-cpu-timers.c posix_cpu_timer: Exit early when process has been reaped 2016-08-10 11:49:29 +02:00
posix-timers.c posix-timers: Handle relative timers with CONFIG_TIME_LOW_RES proper 2016-02-25 12:01:25 -08:00
sched_clock.c
test_udelay.c
tick-broadcast-hrtimer.c kernel: broadcast-hrtimer: Migrate to new 'set-state' interface 2015-08-10 11:41:08 +02:00
tick-broadcast.c tick/broadcast: Prevent NULL pointer dereference 2017-01-12 11:22:51 +01:00
tick-common.c clockevents: Remove unused set_mode() callback 2015-09-14 11:00:55 +02:00
tick-internal.h
tick-oneshot.c
tick-sched.c tick/nohz: Set the correct expiry when switching to nohz/lowres mode 2016-03-03 15:07:26 -08:00
tick-sched.h tick/broadcast: Make idle check independent from mode and config 2015-07-07 18:46:47 +02:00
time.c Merge branch 'timers-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip 2015-09-01 14:04:50 -07:00
timeconst.bc timeconst: Update path in comment 2015-10-26 10:06:06 +09:00
timeconv.c
timecounter.c
timekeeping_debug.c timekeeping: Cap array access in timekeeping_debug 2016-09-15 08:27:52 +02:00
timekeeping_internal.h
timekeeping.c time: Fix clock->read(clock) race around clocksource changes 2017-06-29 12:48:51 +02:00
timekeeping.h
timer_list.c hrtimer: Handle remaining time proper for TIME_LOW_RES 2016-02-17 12:30:57 -08:00
timer_stats.c
timer.c timers: Use proper base migration in add_timer_on() 2015-11-04 20:23:19 +01:00