Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 8965291e authored by Thomas Gleixner's avatar Thomas Gleixner Committed by Runmin Wang
Browse files

timers: Plug locking race vs. timer migration



Linus noticed that lock_timer_base() lacks a READ_ONCE() for accessing the
timer flags. As a consequence the compiler is allowed to reload the flags
between the initial check for TIMER_MIGRATION and the following timer base
computation and the spin lock of the base.

While this has not been observed (yet), we need to make sure that it never
happens.

Change-Id: I577327e02ab77b6de951ac2aa936cb5d5a4f477a
Fixes: 0eeda71b ("timer: Replace timer base by a cpu index")
Reported-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
Link: http://lkml.kernel.org/r/alpine.DEB.2.20.1610241711220.4983@nanos
Cc: stable@vger.kernel.org
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Git-commit: b831275a3553c32091222ac619cfddd73a5553fb
Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git


[runminw@codeaurora.org: resolve trivial merge conflicts]
Signed-off-by: default avatarRunmin Wang <runminw@codeaurora.org>
parent 2116b44b
Loading
Loading
Loading
Loading
+8 −1
Original line number Diff line number Diff line
@@ -811,8 +811,15 @@ static struct tvec_base *lock_timer_base(struct timer_list *timer,
	__acquires(timer->base->lock)
{
	for (;;) {
		u32 tf = timer->flags;
		struct tvec_base *base;
		u32 tf;

		/*
		 * We need to use READ_ONCE() here, otherwise the compiler
		 * might re-read @tf between the check for TIMER_MIGRATING
		 * and spin_lock().
		 */
		tf = READ_ONCE(timer->flags);

		if (!(tf & TIMER_MIGRATING)) {
			base = get_timer_base(tf);