linux/kernel/time
John Stultz 189f6d3227 timekeeping: Cap array access in timekeeping_debug
[ Upstream commit a4f8f6667f ]

It was reported that hibernation could fail on the 2nd attempt, where the
system hangs at hibernate() -> syscore_resume() -> i8237A_resume() ->
claim_dma_lock(), because the lock has already been taken.

However there is actually no other process would like to grab this lock on
that problematic platform.

Further investigation showed that the problem is triggered by setting
/sys/power/pm_trace to 1 before the 1st hibernation.

Since once pm_trace is enabled, the rtc becomes unmeaningful after suspend,
and meanwhile some BIOSes would like to adjust the 'invalid' RTC (e.g, smaller
than 1970) to the release date of that motherboard during POST stage, thus
after resumed, it may seem that the system had a significant long sleep time
which is a completely meaningless value.

Then in timekeeping_resume -> tk_debug_account_sleep_time, if the bit31 of the
sleep time happened to be set to 1, fls() returns 32 and we add 1 to
sleep_time_bin[32], which causes an out of bounds array access and therefor
memory being overwritten.

As depicted by System.map:
0xffffffff81c9d080 b sleep_time_bin
0xffffffff81c9d100 B dma_spin_lock
the dma_spin_lock.val is set to 1, which caused this problem.

This patch adds a sanity check in tk_debug_account_sleep_time()
to ensure we don't index past the sleep_time_bin array.

[jstultz: Problem diagnosed and original patch by Chen Yu, I've solved the
 issue slightly differently, but borrowed his excelent explanation of the
 issue here.]

Fixes: 5c83545f24 "power: Add option to log time spent in suspend"
Reported-by: Janek Kozicki <cosurgi@gmail.com>
Reported-by: Chen Yu <yu.c.chen@intel.com>
Signed-off-by: John Stultz <john.stultz@linaro.org>
Cc: linux-pm@vger.kernel.org
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Xunlei Pang <xpang@redhat.com>
Cc: "Rafael J. Wysocki" <rjw@rjwysocki.net>
Cc: stable <stable@vger.kernel.org>
Cc: Zhang Rui <rui.zhang@intel.com>
Link: http://lkml.kernel.org/r/1471993702-29148-3-git-send-email-john.stultz@linaro.org
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Sasha Levin <alexander.levin@verizon.com>
History 2016-08-31 22:05:44 -04:00
..
alarmtimer.c alarmtimer: Lock k_itimer during timer callback 2014-09-12 13:59:12 -07:00
clockevents.c clockevents: Prevent shift out of bounds 2014-10-25 10:43:15 +02:00
clocksource.c clocksource: Make delta calculation a function 2014-07-23 15:01:51 -07:00
hrtimer.c ktime: Fix ktime_divns to do signed division 2015-06-09 13:43:50 -04:00
itimer.c time/timers: Move all time(r) related files into kernel/time 2014-06-23 11:22:35 +02:00
jiffies.c time: Fix overflow when HZ is smaller than 60 2014-02-06 16:01:40 +01:00
Kconfig clocksource: Move cycle_last validation to core code 2014-07-23 15:01:51 -07:00
Makefile kernel: time: Add udelay_test module to validate udelay 2014-07-23 10:16:35 -07:00
ntp.c ntp: Fixup adjtimex freq validation on 32-bit systems 2015-03-06 14:53:01 -08:00
ntp_internal.h timekeeping: Convert timekeeping core to use timespec64s 2014-07-23 10:17:54 -07:00
posix-clock.c posix-clock: Fix return code on the poll method's error path 2016-02-09 22:55:43 -05:00
posix-cpu-timers.c posix_cpu_timer: Exit early when process has been reaped 2016-08-07 21:47:27 -04:00
posix-timers.c posix-timers: Fix stack info leak in timer_create() 2014-10-25 10:43:15 +02:00
sched_clock.c sched_clock: Avoid corrupting hrtimer tree during suspend 2014-07-24 12:02:49 +02:00
tick-broadcast-hrtimer.c timers/tick/broadcast-hrtimer: Fix suspicious RCU usage in idle loop 2015-04-24 17:14:12 -04:00
tick-broadcast.c time: Replace __get_cpu_var uses 2014-08-26 13:45:44 -04:00
tick-common.c Merge branch 'for-3.18-consistent-ops' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/percpu 2014-10-15 07:48:18 +02:00
tick-internal.h nohz: Move nohz full init call to tick init 2014-09-13 18:34:44 +02:00
tick-oneshot.c time: Replace __get_cpu_var uses 2014-08-26 13:45:44 -04:00
tick-sched.c tick/powerclamp: Remove tick_nohz_idle abuse 2015-01-27 08:29:37 -08:00
time.c time: settimeofday: Validate the values of tv from user 2015-01-29 17:40:44 -08:00
timeconst.bc time/timers: Move all time(r) related files into kernel/time 2014-06-23 11:22:35 +02:00
timeconv.c time: add function to convert between calendar time and broken-down time for universal use 2009-09-24 07:20:56 -07:00
timekeeping.c time: Avoid signed overflow in timekeeping_get_ns() 2016-02-02 13:53:36 -05:00
timekeeping.h time: Consolidate the time accessor prototypes 2014-07-23 10:17:54 -07:00
timekeeping_debug.c timekeeping: Cap array access in timekeeping_debug 2016-08-31 22:05:44 -04:00
timekeeping_internal.h clocksource: Move cycle_last validation to core code 2014-07-23 15:01:51 -07:00
timer.c timers: Use proper base migration in add_timer_on() 2016-05-16 09:29:12 -04:00
timer_list.c timer_list: correct the iterator for timer_list 2013-08-28 19:26:38 -07:00
timer_stats.c timer stats: Add a 'Collection: active/inactive' line to timer usage statistics 2013-10-10 09:59:25 +02:00
udelay_test.c kernel: time: Add udelay_test module to validate udelay 2014-07-23 10:16:35 -07:00