linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCHv7 00/11]  thread_info: use helpers to snapshot thread flags
@ 2021-11-17 16:30 Mark Rutland
  2021-11-17 16:30 ` [PATCHv7 01/11] thread_info: add " Mark Rutland
                   ` (10 more replies)
  0 siblings, 11 replies; 23+ messages in thread
From: Mark Rutland @ 2021-11-17 16:30 UTC (permalink / raw)
  To: linux-kernel, tglx, mingo, peterz
  Cc: benh, boqun.feng, bp, catalin.marinas, dvyukov, efuller, elver,
	ink, joey.gouly, jonas, juri.lelli, linux, luto, mark.rutland,
	mattst88, michal.simek, mpe, npiggin, paulmck, paulus, rth,
	shorne, stefan.kristiansson, vincent.guittot, will

TIP folk (Peter?), I've been assuming this would go via the TIP tree. Are you
happy to pick this up nowish, or as a fixup after the next -rc1? There have
been no significant changes since v3 (aisde from the addition of the PPC fix
for v7), and this has continued to apply cleanly since then (with no conflicts
when rebasing up to v5.16-rc1).

If nothing else, it would be really nice to get the first patch (adding the
accessors) merged, so that we can convert each architecture in turn.

Usual blurb below...

As thread_info::flags scan be manipulated by remote threads, it is
necessary to use atomics or READ_ONCE() to ensure that code manipulates
a consistent snapshot, but we open-code plain accesses to
thread_info::flags across the kernel tree.

Generally we get away with this, but tools like KCSAN legitimately warn
that there is a data-race, and this is potentially fragile with compiler
optimizations, LTO, etc.

These patches introduce new helpers to snapshot the thread flags, with the
intent being that these should replace all plain accesses.

Since v1 [1]:
* Drop RFC
* Make read_ti_thread_flags() __always_inline
* Clarify commit messages
* Fix typo in arm64 patch
* Accumulate Reviewed-by / Acked-by tags
* Drop powerpc patch to avoid potential conflicts (per [2])

Since v2 [3]:
* Rebase to v5.14-rc1
* Reinstate powerpc patch

Since v3 [4]:
* Rebase to v5.14-rc4

Since v4 [5]:
* Rebase to v5.15-rc1
* Apply Acked-by / Tested-by tags

Since v5 [6]:
* Fix trivial whitespace bug in x86 patch

Since v6 [7]:
* Rebase to v5.16-rc1
* Fix new issue on PPC where thread flags could be discarded

[1] https://lore.kernel.org/r/20210609122001.18277-1-mark.rutland@arm.com
[2] https://lore.kernel.org/r/87k0mvtgeb.fsf@mpe.ellerman.id.au
[3] https://lore.kernel.org/r/20210621090602.16883-1-mark.rutland@arm.com
[4] https://lore.kernel.org/r/20210713113842.2106-1-mark.rutland@arm.com
[5] https://lore.kernel.org/r/20210803095428.17009-1-mark.rutland@arm.com
[6] https://lore.kernel.org/r/20210914103027.53565-1-mark.rutland@arm.com
[7] https://lore.kernel.org/lkml/20211022135643.7442-1-mark.rutland@arm.com

Thanks,
Mark.

Mark Rutland (11):
  thread_info: add helpers to snapshot thread flags
  entry: snapshot thread flags
  sched: snapshot thread flags
  alpha: snapshot thread flags
  arm: snapshot thread flags
  arm64: snapshot thread flags
  microblaze: snapshot thread flags
  openrisc: snapshot thread flags
  powerpc: avoid discarding flags in system_call_exception()
  powerpc: snapshot thread flags
  x86: snapshot thread flags

 arch/alpha/kernel/signal.c          |  2 +-
 arch/arm/kernel/signal.c            |  2 +-
 arch/arm/mm/alignment.c             |  2 +-
 arch/arm64/kernel/entry-common.c    |  2 +-
 arch/arm64/kernel/ptrace.c          |  4 ++--
 arch/arm64/kernel/signal.c          |  2 +-
 arch/arm64/kernel/syscall.c         |  4 ++--
 arch/microblaze/kernel/signal.c     |  2 +-
 arch/openrisc/kernel/signal.c       |  2 +-
 arch/powerpc/kernel/interrupt.c     | 15 +++++++--------
 arch/powerpc/kernel/ptrace/ptrace.c |  3 +--
 arch/x86/kernel/process.c           |  8 ++++----
 arch/x86/kernel/process.h           |  4 ++--
 arch/x86/mm/tlb.c                   |  2 +-
 include/linux/entry-kvm.h           |  2 +-
 include/linux/thread_info.h         | 14 ++++++++++++++
 kernel/entry/common.c               |  4 ++--
 kernel/entry/kvm.c                  |  4 ++--
 kernel/sched/core.c                 |  2 +-
 19 files changed, 46 insertions(+), 34 deletions(-)

-- 
2.11.0


^ permalink raw reply	[flat|nested] 23+ messages in thread

* [PATCHv7 01/11] thread_info: add helpers to snapshot thread flags
  2021-11-17 16:30 [PATCHv7 00/11] thread_info: use helpers to snapshot thread flags Mark Rutland
@ 2021-11-17 16:30 ` Mark Rutland
  2021-11-26 20:23   ` [tip: core/entry] thread_info: Add " tip-bot2 for Mark Rutland
  2021-11-17 16:30 ` [PATCHv7 02/11] entry: " Mark Rutland
                   ` (9 subsequent siblings)
  10 siblings, 1 reply; 23+ messages in thread
From: Mark Rutland @ 2021-11-17 16:30 UTC (permalink / raw)
  To: linux-kernel
  Cc: benh, boqun.feng, bp, catalin.marinas, dvyukov, efuller, elver,
	ink, joey.gouly, jonas, juri.lelli, linux, luto, mark.rutland,
	mattst88, michal.simek, mingo, mpe, npiggin, paulmck, paulus,
	peterz, rth, shorne, stefan.kristiansson, tglx, vincent.guittot,
	will

In <linux/thread_info.h> there are helpers to manipulate individual
thread flags, but where code wants to check several flags at once, it
must open code reading current_thread_info()->flags and operating on a
snapshot.

As some flags can be set remotely it's necessary to use READ_ONCE() to
get a consistent snapshot even when IRQs are disabled, but some code
forgets to do this. Generally this is unlike to cause a problem in
practice, but it is somewhat unsound, and KCSAN will legitimately warn
that there is a data race.

To make it easier to do the right thing, and to highlight that
concurrent modification is possible, add new helpers to snapshot the
flags, which should be used in preference to plain reads. Subsequent
patches will move existing code to use the new helpers.

Signed-off-by: Mark Rutland <mark.rutland@arm.com>
Reviewed-by: Thomas Gleixner <tglx@linutronix.de>
Acked-by: Marco Elver <elver@google.com>
Acked-by: Paul E. McKenney <paulmck@kernel.org>
Cc: Boqun Feng <boqun.feng@gmail.com>
Cc: Dmitry Vyukov <dvyukov@google.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Will Deacon <will@kernel.org>
---
 include/linux/thread_info.h | 14 ++++++++++++++
 1 file changed, 14 insertions(+)

diff --git a/include/linux/thread_info.h b/include/linux/thread_info.h
index ad0c4e041030..73a6f34b3847 100644
--- a/include/linux/thread_info.h
+++ b/include/linux/thread_info.h
@@ -118,6 +118,15 @@ static inline int test_ti_thread_flag(struct thread_info *ti, int flag)
 	return test_bit(flag, (unsigned long *)&ti->flags);
 }
 
+/*
+ * This may be used in noinstr code, and needs to be __always_inline to prevent
+ * inadvertent instrumentation.
+ */
+static __always_inline unsigned long read_ti_thread_flags(struct thread_info *ti)
+{
+	return READ_ONCE(ti->flags);
+}
+
 #define set_thread_flag(flag) \
 	set_ti_thread_flag(current_thread_info(), flag)
 #define clear_thread_flag(flag) \
@@ -130,6 +139,11 @@ static inline int test_ti_thread_flag(struct thread_info *ti, int flag)
 	test_and_clear_ti_thread_flag(current_thread_info(), flag)
 #define test_thread_flag(flag) \
 	test_ti_thread_flag(current_thread_info(), flag)
+#define read_thread_flags() \
+	read_ti_thread_flags(current_thread_info())
+
+#define read_task_thread_flags(t) \
+	read_ti_thread_flags(task_thread_info(t))
 
 #ifdef CONFIG_GENERIC_ENTRY
 #define set_syscall_work(fl) \
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCHv7 02/11] entry: snapshot thread flags
  2021-11-17 16:30 [PATCHv7 00/11] thread_info: use helpers to snapshot thread flags Mark Rutland
  2021-11-17 16:30 ` [PATCHv7 01/11] thread_info: add " Mark Rutland
@ 2021-11-17 16:30 ` Mark Rutland
  2021-11-26 20:22   ` [tip: core/entry] entry: Snapshot " tip-bot2 for Mark Rutland
  2021-11-17 16:30 ` [PATCHv7 03/11] sched: snapshot " Mark Rutland
                   ` (8 subsequent siblings)
  10 siblings, 1 reply; 23+ messages in thread
From: Mark Rutland @ 2021-11-17 16:30 UTC (permalink / raw)
  To: linux-kernel
  Cc: benh, boqun.feng, bp, catalin.marinas, dvyukov, efuller, elver,
	ink, joey.gouly, jonas, juri.lelli, linux, luto, mark.rutland,
	mattst88, michal.simek, mingo, mpe, npiggin, paulmck, paulus,
	peterz, rth, shorne, stefan.kristiansson, tglx, vincent.guittot,
	will

Some thread flags can be set remotely, and so even when IRQs are
disabled, the flags can change under our feet. Generally this is
unlikely to cause a problem in practice, but it is somewhat unsound, and
KCSAN will legitimately warn that there is a data race.

To avoid such issues, a snapshot of the flags has to be taken prior to
using them. Some places already use READ_ONCE() for that, others do not.

Convert them all to the new flag accessor helpers.

Signed-off-by: Mark Rutland <mark.rutland@arm.com>
Acked-by: Paul E. McKenney <paulmck@kernel.org>
Cc: Andy Lutomirski <luto@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
---
 include/linux/entry-kvm.h | 2 +-
 kernel/entry/common.c     | 4 ++--
 kernel/entry/kvm.c        | 4 ++--
 3 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/include/linux/entry-kvm.h b/include/linux/entry-kvm.h
index 0d7865a0731c..07c878d6e323 100644
--- a/include/linux/entry-kvm.h
+++ b/include/linux/entry-kvm.h
@@ -75,7 +75,7 @@ static inline void xfer_to_guest_mode_prepare(void)
  */
 static inline bool __xfer_to_guest_mode_work_pending(void)
 {
-	unsigned long ti_work = READ_ONCE(current_thread_info()->flags);
+	unsigned long ti_work = read_thread_flags();
 
 	return !!(ti_work & XFER_TO_GUEST_MODE_WORK);
 }
diff --git a/kernel/entry/common.c b/kernel/entry/common.c
index d5a61d565ad5..bad713684c2e 100644
--- a/kernel/entry/common.c
+++ b/kernel/entry/common.c
@@ -187,7 +187,7 @@ static unsigned long exit_to_user_mode_loop(struct pt_regs *regs,
 		/* Check if any of the above work has queued a deferred wakeup */
 		tick_nohz_user_enter_prepare();
 
-		ti_work = READ_ONCE(current_thread_info()->flags);
+		ti_work = read_thread_flags();
 	}
 
 	/* Return the latest work state for arch_exit_to_user_mode() */
@@ -196,7 +196,7 @@ static unsigned long exit_to_user_mode_loop(struct pt_regs *regs,
 
 static void exit_to_user_mode_prepare(struct pt_regs *regs)
 {
-	unsigned long ti_work = READ_ONCE(current_thread_info()->flags);
+	unsigned long ti_work = read_thread_flags();
 
 	lockdep_assert_irqs_disabled();
 
diff --git a/kernel/entry/kvm.c b/kernel/entry/kvm.c
index 49972ee99aff..96d476e06c77 100644
--- a/kernel/entry/kvm.c
+++ b/kernel/entry/kvm.c
@@ -26,7 +26,7 @@ static int xfer_to_guest_mode_work(struct kvm_vcpu *vcpu, unsigned long ti_work)
 		if (ret)
 			return ret;
 
-		ti_work = READ_ONCE(current_thread_info()->flags);
+		ti_work = read_thread_flags();
 	} while (ti_work & XFER_TO_GUEST_MODE_WORK || need_resched());
 	return 0;
 }
@@ -43,7 +43,7 @@ int xfer_to_guest_mode_handle_work(struct kvm_vcpu *vcpu)
 	 * disabled in the inner loop before going into guest mode. No need
 	 * to disable interrupts here.
 	 */
-	ti_work = READ_ONCE(current_thread_info()->flags);
+	ti_work = read_thread_flags();
 	if (!(ti_work & XFER_TO_GUEST_MODE_WORK))
 		return 0;
 
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCHv7 03/11] sched: snapshot thread flags
  2021-11-17 16:30 [PATCHv7 00/11] thread_info: use helpers to snapshot thread flags Mark Rutland
  2021-11-17 16:30 ` [PATCHv7 01/11] thread_info: add " Mark Rutland
  2021-11-17 16:30 ` [PATCHv7 02/11] entry: " Mark Rutland
@ 2021-11-17 16:30 ` Mark Rutland
  2021-11-26 20:22   ` [tip: core/entry] sched: Snapshot " tip-bot2 for Mark Rutland
  2021-11-17 16:30 ` [PATCHv7 04/11] alpha: snapshot " Mark Rutland
                   ` (7 subsequent siblings)
  10 siblings, 1 reply; 23+ messages in thread
From: Mark Rutland @ 2021-11-17 16:30 UTC (permalink / raw)
  To: linux-kernel
  Cc: benh, boqun.feng, bp, catalin.marinas, dvyukov, efuller, elver,
	ink, joey.gouly, jonas, juri.lelli, linux, luto, mark.rutland,
	mattst88, michal.simek, mingo, mpe, npiggin, paulmck, paulus,
	peterz, rth, shorne, stefan.kristiansson, tglx, vincent.guittot,
	will

Some thread flags can be set remotely, and so even when IRQs are
disabled, the flags can change under our feet. Generally this is
unlikely to cause a problem in practice, but it is somewhat unsound, and
KCSAN will legitimately warn that there is a data race.

To avoid such issues, a snapshot of the flags has to be taken prior to
using them. Some places already use READ_ONCE() for that, others do not.

Convert them all to the new flag accessor helpers.

The READ_ONCE(ti->flags) .. cmpxchg(ti->flags) loop in
set_nr_if_polling() is left as-is for clarity.

Signed-off-by: Mark Rutland <mark.rutland@arm.com>
Acked-by: Paul E. McKenney <paulmck@kernel.org>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Juri Lelli <juri.lelli@redhat.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Vincent Guittot <vincent.guittot@linaro.org>
---
 kernel/sched/core.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/kernel/sched/core.c b/kernel/sched/core.c
index 3c9b0fda64ac..7ba05dedaf5b 100644
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -8520,7 +8520,7 @@ void sched_show_task(struct task_struct *p)
 	rcu_read_unlock();
 	pr_cont(" stack:%5lu pid:%5d ppid:%6d flags:0x%08lx\n",
 		free, task_pid_nr(p), ppid,
-		(unsigned long)task_thread_info(p)->flags);
+		read_task_thread_flags(p));
 
 	print_worker_info(KERN_INFO, p);
 	print_stop_info(KERN_INFO, p);
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCHv7 04/11] alpha: snapshot thread flags
  2021-11-17 16:30 [PATCHv7 00/11] thread_info: use helpers to snapshot thread flags Mark Rutland
                   ` (2 preceding siblings ...)
  2021-11-17 16:30 ` [PATCHv7 03/11] sched: snapshot " Mark Rutland
@ 2021-11-17 16:30 ` Mark Rutland
  2021-11-26 20:22   ` [tip: core/entry] alpha: Snapshot " tip-bot2 for Mark Rutland
  2021-11-17 16:30 ` [PATCHv7 05/11] arm: snapshot " Mark Rutland
                   ` (6 subsequent siblings)
  10 siblings, 1 reply; 23+ messages in thread
From: Mark Rutland @ 2021-11-17 16:30 UTC (permalink / raw)
  To: linux-kernel
  Cc: benh, boqun.feng, bp, catalin.marinas, dvyukov, efuller, elver,
	ink, joey.gouly, jonas, juri.lelli, linux, luto, mark.rutland,
	mattst88, michal.simek, mingo, mpe, npiggin, paulmck, paulus,
	peterz, rth, shorne, stefan.kristiansson, tglx, vincent.guittot,
	will

Some thread flags can be set remotely, and so even when IRQs are
disabled, the flags can change under our feet. Generally this is
unlikely to cause a problem in practice, but it is somewhat unsound, and
KCSAN will legitimately warn that there is a data race.

To avoid such issues, a snapshot of the flags has to be taken prior to
using them. Some places already use READ_ONCE() for that, others do not.

Convert them all to the new flag accessor helpers.

Signed-off-by: Mark Rutland <mark.rutland@arm.com>
Acked-by: Paul E. McKenney <paulmck@kernel.org>
Cc: Ivan Kokshaysky <ink@jurassic.park.msu.ru>
Cc: Matt Turner <mattst88@gmail.com>
Cc: Richard Henderson <rth@twiddle.net>
---
 arch/alpha/kernel/signal.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/alpha/kernel/signal.c b/arch/alpha/kernel/signal.c
index bc077babafab..d8ed71d5bed3 100644
--- a/arch/alpha/kernel/signal.c
+++ b/arch/alpha/kernel/signal.c
@@ -535,6 +535,6 @@ do_work_pending(struct pt_regs *regs, unsigned long thread_flags,
 			}
 		}
 		local_irq_disable();
-		thread_flags = current_thread_info()->flags;
+		thread_flags = read_thread_flags();
 	} while (thread_flags & _TIF_WORK_MASK);
 }
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCHv7 05/11] arm: snapshot thread flags
  2021-11-17 16:30 [PATCHv7 00/11] thread_info: use helpers to snapshot thread flags Mark Rutland
                   ` (3 preceding siblings ...)
  2021-11-17 16:30 ` [PATCHv7 04/11] alpha: snapshot " Mark Rutland
@ 2021-11-17 16:30 ` Mark Rutland
  2021-11-26 20:22   ` [tip: core/entry] ARM: Snapshot " tip-bot2 for Mark Rutland
  2021-11-17 16:30 ` [PATCHv7 06/11] arm64: snapshot " Mark Rutland
                   ` (5 subsequent siblings)
  10 siblings, 1 reply; 23+ messages in thread
From: Mark Rutland @ 2021-11-17 16:30 UTC (permalink / raw)
  To: linux-kernel
  Cc: benh, boqun.feng, bp, catalin.marinas, dvyukov, efuller, elver,
	ink, joey.gouly, jonas, juri.lelli, linux, luto, mark.rutland,
	mattst88, michal.simek, mingo, mpe, npiggin, paulmck, paulus,
	peterz, rth, shorne, stefan.kristiansson, tglx, vincent.guittot,
	will

Some thread flags can be set remotely, and so even when IRQs are
disabled, the flags can change under our feet. Generally this is
unlikely to cause a problem in practice, but it is somewhat unsound, and
KCSAN will legitimately warn that there is a data race.

To avoid such issues, a snapshot of the flags has to be taken prior to
using them. Some places already use READ_ONCE() for that, others do not.

Convert them all to the new flag accessor helpers.

Signed-off-by: Mark Rutland <mark.rutland@arm.com>
Acked-by: Paul E. McKenney <paulmck@kernel.org>
Cc: Russell King <linux@armlinux.org.uk>
---
 arch/arm/kernel/signal.c | 2 +-
 arch/arm/mm/alignment.c  | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/arch/arm/kernel/signal.c b/arch/arm/kernel/signal.c
index a41e27ace391..c532a6041066 100644
--- a/arch/arm/kernel/signal.c
+++ b/arch/arm/kernel/signal.c
@@ -631,7 +631,7 @@ do_work_pending(struct pt_regs *regs, unsigned int thread_flags, int syscall)
 			}
 		}
 		local_irq_disable();
-		thread_flags = current_thread_info()->flags;
+		thread_flags = read_thread_flags();
 	} while (thread_flags & _TIF_WORK_MASK);
 	return 0;
 }
diff --git a/arch/arm/mm/alignment.c b/arch/arm/mm/alignment.c
index ea81e89e7740..adbb3817d0be 100644
--- a/arch/arm/mm/alignment.c
+++ b/arch/arm/mm/alignment.c
@@ -990,7 +990,7 @@ do_alignment(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
 		 * there is no work pending for this thread.
 		 */
 		raw_local_irq_disable();
-		if (!(current_thread_info()->flags & _TIF_WORK_MASK))
+		if (!(read_thread_flags() & _TIF_WORK_MASK))
 			set_cr(cr_no_alignment);
 	}
 
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCHv7 06/11] arm64: snapshot thread flags
  2021-11-17 16:30 [PATCHv7 00/11] thread_info: use helpers to snapshot thread flags Mark Rutland
                   ` (4 preceding siblings ...)
  2021-11-17 16:30 ` [PATCHv7 05/11] arm: snapshot " Mark Rutland
@ 2021-11-17 16:30 ` Mark Rutland
  2021-11-26 20:22   ` [tip: core/entry] " tip-bot2 for Mark Rutland
  2021-11-17 16:30 ` [PATCHv7 07/11] microblaze: " Mark Rutland
                   ` (4 subsequent siblings)
  10 siblings, 1 reply; 23+ messages in thread
From: Mark Rutland @ 2021-11-17 16:30 UTC (permalink / raw)
  To: linux-kernel
  Cc: benh, boqun.feng, bp, catalin.marinas, dvyukov, efuller, elver,
	ink, joey.gouly, jonas, juri.lelli, linux, luto, mark.rutland,
	mattst88, michal.simek, mingo, mpe, npiggin, paulmck, paulus,
	peterz, rth, shorne, stefan.kristiansson, tglx, vincent.guittot,
	will

Some thread flags can be set remotely, and so even when IRQs are
disabled, the flags can change under our feet. Generally this is
unlikely to cause a problem in practice, but it is somewhat unsound, and
KCSAN will legitimately warn that there is a data race.

To avoid such issues, a snapshot of the flags has to be taken prior to
using them. Some places already use READ_ONCE() for that, others do not.

Convert them all to the new flag accessor helpers.

Signed-off-by: Mark Rutland <mark.rutland@arm.com>
Acked-by: Will Deacon <will@kernel.org>
Acked-by: Paul E. McKenney <paulmck@kernel.org>
Cc: Catalin Marinas <catalin.marinas@arm.com>
---
 arch/arm64/kernel/entry-common.c | 2 +-
 arch/arm64/kernel/ptrace.c       | 4 ++--
 arch/arm64/kernel/signal.c       | 2 +-
 arch/arm64/kernel/syscall.c      | 4 ++--
 4 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/arch/arm64/kernel/entry-common.c b/arch/arm64/kernel/entry-common.c
index f7408edf8571..ef7fcefb96bd 100644
--- a/arch/arm64/kernel/entry-common.c
+++ b/arch/arm64/kernel/entry-common.c
@@ -129,7 +129,7 @@ static __always_inline void prepare_exit_to_user_mode(struct pt_regs *regs)
 
 	local_daif_mask();
 
-	flags = READ_ONCE(current_thread_info()->flags);
+	flags = read_thread_flags();
 	if (unlikely(flags & _TIF_WORK_MASK))
 		do_notify_resume(regs, flags);
 }
diff --git a/arch/arm64/kernel/ptrace.c b/arch/arm64/kernel/ptrace.c
index 88a9034fb9b5..33cac3d75150 100644
--- a/arch/arm64/kernel/ptrace.c
+++ b/arch/arm64/kernel/ptrace.c
@@ -1839,7 +1839,7 @@ static void tracehook_report_syscall(struct pt_regs *regs,
 
 int syscall_trace_enter(struct pt_regs *regs)
 {
-	unsigned long flags = READ_ONCE(current_thread_info()->flags);
+	unsigned long flags = read_thread_flags();
 
 	if (flags & (_TIF_SYSCALL_EMU | _TIF_SYSCALL_TRACE)) {
 		tracehook_report_syscall(regs, PTRACE_SYSCALL_ENTER);
@@ -1862,7 +1862,7 @@ int syscall_trace_enter(struct pt_regs *regs)
 
 void syscall_trace_exit(struct pt_regs *regs)
 {
-	unsigned long flags = READ_ONCE(current_thread_info()->flags);
+	unsigned long flags = read_thread_flags();
 
 	audit_syscall_exit(regs);
 
diff --git a/arch/arm64/kernel/signal.c b/arch/arm64/kernel/signal.c
index 8f6372b44b65..d8aaf4b6f432 100644
--- a/arch/arm64/kernel/signal.c
+++ b/arch/arm64/kernel/signal.c
@@ -948,7 +948,7 @@ void do_notify_resume(struct pt_regs *regs, unsigned long thread_flags)
 		}
 
 		local_daif_mask();
-		thread_flags = READ_ONCE(current_thread_info()->flags);
+		thread_flags = read_thread_flags();
 	} while (thread_flags & _TIF_WORK_MASK);
 }
 
diff --git a/arch/arm64/kernel/syscall.c b/arch/arm64/kernel/syscall.c
index 50a0f1a38e84..c938603b3ba0 100644
--- a/arch/arm64/kernel/syscall.c
+++ b/arch/arm64/kernel/syscall.c
@@ -81,7 +81,7 @@ void syscall_trace_exit(struct pt_regs *regs);
 static void el0_svc_common(struct pt_regs *regs, int scno, int sc_nr,
 			   const syscall_fn_t syscall_table[])
 {
-	unsigned long flags = current_thread_info()->flags;
+	unsigned long flags = read_thread_flags();
 
 	regs->orig_x0 = regs->regs[0];
 	regs->syscallno = scno;
@@ -148,7 +148,7 @@ static void el0_svc_common(struct pt_regs *regs, int scno, int sc_nr,
 	 */
 	if (!has_syscall_work(flags) && !IS_ENABLED(CONFIG_DEBUG_RSEQ)) {
 		local_daif_mask();
-		flags = current_thread_info()->flags;
+		flags = read_thread_flags();
 		if (!has_syscall_work(flags) && !(flags & _TIF_SINGLESTEP))
 			return;
 		local_daif_restore(DAIF_PROCCTX);
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCHv7 07/11] microblaze: snapshot thread flags
  2021-11-17 16:30 [PATCHv7 00/11] thread_info: use helpers to snapshot thread flags Mark Rutland
                   ` (5 preceding siblings ...)
  2021-11-17 16:30 ` [PATCHv7 06/11] arm64: snapshot " Mark Rutland
@ 2021-11-17 16:30 ` Mark Rutland
  2021-11-26 20:22   ` [tip: core/entry] microblaze: Snapshot " tip-bot2 for Mark Rutland
  2021-11-17 16:30 ` [PATCHv7 08/11] openrisc: snapshot " Mark Rutland
                   ` (3 subsequent siblings)
  10 siblings, 1 reply; 23+ messages in thread
From: Mark Rutland @ 2021-11-17 16:30 UTC (permalink / raw)
  To: linux-kernel
  Cc: benh, boqun.feng, bp, catalin.marinas, dvyukov, efuller, elver,
	ink, joey.gouly, jonas, juri.lelli, linux, luto, mark.rutland,
	mattst88, michal.simek, mingo, mpe, npiggin, paulmck, paulus,
	peterz, rth, shorne, stefan.kristiansson, tglx, vincent.guittot,
	will

Some thread flags can be set remotely, and so even when IRQs are
disabled, the flags can change under our feet. Generally this is
unlikely to cause a problem in practice, but it is somewhat unsound, and
KCSAN will legitimately warn that there is a data race.

To avoid such issues, a snapshot of the flags has to be taken prior to
using them. Some places already use READ_ONCE() for that, others do not.

Convert them all to the new flag accessor helpers.

Signed-off-by: Mark Rutland <mark.rutland@arm.com>
Acked-by: Paul E. McKenney <paulmck@kernel.org>
Tested-by: Michal Simek <michal.simek@xilinx.com>
---
 arch/microblaze/kernel/signal.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/microblaze/kernel/signal.c b/arch/microblaze/kernel/signal.c
index fc61eb0eb8dd..23e8a9336a29 100644
--- a/arch/microblaze/kernel/signal.c
+++ b/arch/microblaze/kernel/signal.c
@@ -283,7 +283,7 @@ static void do_signal(struct pt_regs *regs, int in_syscall)
 #ifdef DEBUG_SIG
 	pr_info("do signal: %p %d\n", regs, in_syscall);
 	pr_info("do signal2: %lx %lx %ld [%lx]\n", regs->pc, regs->r1,
-			regs->r12, current_thread_info()->flags);
+			regs->r12, read_thread_flags());
 #endif
 
 	if (get_signal(&ksig)) {
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCHv7 08/11] openrisc: snapshot thread flags
  2021-11-17 16:30 [PATCHv7 00/11] thread_info: use helpers to snapshot thread flags Mark Rutland
                   ` (6 preceding siblings ...)
  2021-11-17 16:30 ` [PATCHv7 07/11] microblaze: " Mark Rutland
@ 2021-11-17 16:30 ` Mark Rutland
  2021-11-26 20:22   ` [tip: core/entry] openrisc: Snapshot " tip-bot2 for Mark Rutland
  2021-11-17 16:30 ` [PATCHv7 09/11] powerpc: avoid discarding flags in system_call_exception() Mark Rutland
                   ` (2 subsequent siblings)
  10 siblings, 1 reply; 23+ messages in thread
From: Mark Rutland @ 2021-11-17 16:30 UTC (permalink / raw)
  To: linux-kernel
  Cc: benh, boqun.feng, bp, catalin.marinas, dvyukov, efuller, elver,
	ink, joey.gouly, jonas, juri.lelli, linux, luto, mark.rutland,
	mattst88, michal.simek, mingo, mpe, npiggin, paulmck, paulus,
	peterz, rth, shorne, stefan.kristiansson, tglx, vincent.guittot,
	will

Some thread flags can be set remotely, and so even when IRQs are
disabled, the flags can change under our feet. Generally this is
unlikely to cause a problem in practice, but it is somewhat unsound, and
KCSAN will legitimately warn that there is a data race.

To avoid such issues, a snapshot of the flags has to be taken prior to
using them. Some places already use READ_ONCE() for that, others do not.

Convert them all to the new flag accessor helpers.

Signed-off-by: Mark Rutland <mark.rutland@arm.com>
Acked-by: Stafford Horne <shorne@gmail.com>
Acked-by: Paul E. McKenney <paulmck@kernel.org>
Cc: Jonas Bonn <jonas@southpole.se>
Cc: Stefan Kristiansson <stefan.kristiansson@saunalahti.fi>
---
 arch/openrisc/kernel/signal.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/openrisc/kernel/signal.c b/arch/openrisc/kernel/signal.c
index 99516c9191c7..92c5b70740f5 100644
--- a/arch/openrisc/kernel/signal.c
+++ b/arch/openrisc/kernel/signal.c
@@ -313,7 +313,7 @@ do_work_pending(struct pt_regs *regs, unsigned int thread_flags, int syscall)
 			}
 		}
 		local_irq_disable();
-		thread_flags = current_thread_info()->flags;
+		thread_flags = read_thread_flags();
 	} while (thread_flags & _TIF_WORK_MASK);
 	return 0;
 }
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCHv7 09/11] powerpc: avoid discarding flags in system_call_exception()
  2021-11-17 16:30 [PATCHv7 00/11] thread_info: use helpers to snapshot thread flags Mark Rutland
                   ` (7 preceding siblings ...)
  2021-11-17 16:30 ` [PATCHv7 08/11] openrisc: snapshot " Mark Rutland
@ 2021-11-17 16:30 ` Mark Rutland
  2021-11-26 20:22   ` [tip: core/entry] powerpc: Avoid " tip-bot2 for Mark Rutland
  2021-11-17 16:30 ` [PATCHv7 10/11] powerpc: snapshot thread flags Mark Rutland
  2021-11-17 16:30 ` [PATCHv7 11/11] x86: snapshot " Mark Rutland
  10 siblings, 1 reply; 23+ messages in thread
From: Mark Rutland @ 2021-11-17 16:30 UTC (permalink / raw)
  To: linux-kernel, Michael Ellerman
  Cc: benh, boqun.feng, bp, catalin.marinas, dvyukov, efuller, elver,
	ink, joey.gouly, jonas, juri.lelli, linux, luto, mark.rutland,
	mattst88, michal.simek, mingo, npiggin, paulmck, paulus, peterz,
	rth, shorne, stefan.kristiansson, tglx, vincent.guittot, will

Some thread flags can be set remotely, and so even when IRQs are
disabled, the flags can change under our feet. Thus, when setting flags
we must use an atomic operation rather than a plain read-modify-write
sequence, as a plain read-modify-write may discard flags which are
concurrently set by a remote thread, e.g.

	// task A			// task B
	tmp = A->thread_info.flags;
					set_tsk_thread_flag(A, NEWFLAG_B);
	tmp |= NEWFLAG_A;
	A->thread_info.flags = tmp;

In arch/powerpc/kernel/interrupt.c's system_call_exception(), we set
_TIF_RESTOREALL in the thread info flags with a read-modify-write, which
may result in other flags being discarded.

Elsewhere in the file we use clear_bits() to atomically remove flag
bits, so let's use set_bits() here for consistency with those.

I presume there may be reasons (e.g. instrumentation) that prevent the
use of set_thread_flag() and clear_thread_flag() here, which would
otherwise be preferable.

Fixes: ae7aaecc3f2f78b7 ("powerpc/64s: system call rfscv workaround for TM bugs")
Signed-off-by: Mark Rutland <mark.rutland@arm.com>
Cc: Eirik Fuller <efuller@redhat.com>
Cc: Michael Ellerman <mpe@ellerman.id.au>
Cc: Nicholas Piggin <npiggin@gmail.com>
---
 arch/powerpc/kernel/interrupt.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

Michael, I found this by inspection when rebasing the rest of the series
to v5.16-rc1. Is this something you'd like to pick on its own? As the
commit message says, I'm not sure whether you can use
{set,clear}_thread_flag() here, or whether it was a deliberate choice to
avoid those.

Mark.

diff --git a/arch/powerpc/kernel/interrupt.c b/arch/powerpc/kernel/interrupt.c
index 835b626cd476..1c821b76c2d1 100644
--- a/arch/powerpc/kernel/interrupt.c
+++ b/arch/powerpc/kernel/interrupt.c
@@ -148,7 +148,7 @@ notrace long system_call_exception(long r3, long r4, long r5,
 	 */
 	if (IS_ENABLED(CONFIG_PPC_TRANSACTIONAL_MEM) &&
 			unlikely(MSR_TM_TRANSACTIONAL(regs->msr)))
-		current_thread_info()->flags |= _TIF_RESTOREALL;
+		set_bits(_TIF_RESTOREALL, current_thread_info()->flags);
 
 	/*
 	 * If the system call was made with a transaction active, doom it and
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCHv7 10/11] powerpc: snapshot thread flags
  2021-11-17 16:30 [PATCHv7 00/11] thread_info: use helpers to snapshot thread flags Mark Rutland
                   ` (8 preceding siblings ...)
  2021-11-17 16:30 ` [PATCHv7 09/11] powerpc: avoid discarding flags in system_call_exception() Mark Rutland
@ 2021-11-17 16:30 ` Mark Rutland
  2021-11-26 20:22   ` [tip: core/entry] powerpc: Snapshot " tip-bot2 for Mark Rutland
  2021-11-17 16:30 ` [PATCHv7 11/11] x86: snapshot " Mark Rutland
  10 siblings, 1 reply; 23+ messages in thread
From: Mark Rutland @ 2021-11-17 16:30 UTC (permalink / raw)
  To: linux-kernel
  Cc: benh, boqun.feng, bp, catalin.marinas, dvyukov, efuller, elver,
	ink, joey.gouly, jonas, juri.lelli, linux, luto, mark.rutland,
	mattst88, michal.simek, mingo, mpe, npiggin, paulmck, paulus,
	peterz, rth, shorne, stefan.kristiansson, tglx, vincent.guittot,
	will

Some thread flags can be set remotely, and so even when IRQs are
disabled, the flags can change under our feet. Generally this is
unlikely to cause a problem in practice, but it is somewhat unsound, and
KCSAN will legitimately warn that there is a data race.

To avoid such issues, a snapshot of the flags has to be taken prior to
using them. Some places already use READ_ONCE() for that, others do not.

Convert them all to the new flag accessor helpers.

Signed-off-by: Mark Rutland <mark.rutland@arm.com>
Acked-by: Paul E. McKenney <paulmck@kernel.org>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Michael Ellerman <mpe@ellerman.id.au>
Cc: Paul Mackerras <paulus@samba.org>
---
 arch/powerpc/kernel/interrupt.c     | 13 ++++++-------
 arch/powerpc/kernel/ptrace/ptrace.c |  3 +--
 2 files changed, 7 insertions(+), 9 deletions(-)

diff --git a/arch/powerpc/kernel/interrupt.c b/arch/powerpc/kernel/interrupt.c
index 1c821b76c2d1..ff25888ffc25 100644
--- a/arch/powerpc/kernel/interrupt.c
+++ b/arch/powerpc/kernel/interrupt.c
@@ -181,7 +181,7 @@ notrace long system_call_exception(long r3, long r4, long r5,
 
 	local_irq_enable();
 
-	if (unlikely(current_thread_info()->flags & _TIF_SYSCALL_DOTRACE)) {
+	if (unlikely(read_thread_flags() & _TIF_SYSCALL_DOTRACE)) {
 		if (unlikely(trap_is_unsupported_scv(regs))) {
 			/* Unsupported scv vector */
 			_exception(SIGILL, regs, ILL_ILLOPC, regs->nip);
@@ -343,7 +343,7 @@ interrupt_exit_user_prepare_main(unsigned long ret, struct pt_regs *regs)
 	unsigned long ti_flags;
 
 again:
-	ti_flags = READ_ONCE(current_thread_info()->flags);
+	ti_flags = read_thread_flags();
 	while (unlikely(ti_flags & (_TIF_USER_WORK_MASK & ~_TIF_RESTORE_TM))) {
 		local_irq_enable();
 		if (ti_flags & _TIF_NEED_RESCHED) {
@@ -359,7 +359,7 @@ interrupt_exit_user_prepare_main(unsigned long ret, struct pt_regs *regs)
 			do_notify_resume(regs, ti_flags);
 		}
 		local_irq_disable();
-		ti_flags = READ_ONCE(current_thread_info()->flags);
+		ti_flags = read_thread_flags();
 	}
 
 	if (IS_ENABLED(CONFIG_PPC_BOOK3S_64) && IS_ENABLED(CONFIG_PPC_FPU)) {
@@ -437,7 +437,7 @@ notrace unsigned long syscall_exit_prepare(unsigned long r3,
 	/* Check whether the syscall is issued inside a restartable sequence */
 	rseq_syscall(regs);
 
-	ti_flags = current_thread_info()->flags;
+	ti_flags = read_thread_flags();
 
 	if (unlikely(r3 >= (unsigned long)-MAX_ERRNO) && is_not_scv) {
 		if (likely(!(ti_flags & (_TIF_NOERROR | _TIF_RESTOREALL)))) {
@@ -532,8 +532,7 @@ notrace unsigned long interrupt_exit_kernel_prepare(struct pt_regs *regs)
 	unsigned long flags;
 	unsigned long ret = 0;
 	unsigned long kuap;
-	bool stack_store = current_thread_info()->flags &
-						_TIF_EMULATE_STACK_STORE;
+	bool stack_store = read_thread_flags() & _TIF_EMULATE_STACK_STORE;
 
 	if (regs_is_unrecoverable(regs))
 		unrecoverable_exception(regs);
@@ -554,7 +553,7 @@ notrace unsigned long interrupt_exit_kernel_prepare(struct pt_regs *regs)
 again:
 		if (IS_ENABLED(CONFIG_PREEMPT)) {
 			/* Return to preemptible kernel context */
-			if (unlikely(current_thread_info()->flags & _TIF_NEED_RESCHED)) {
+			if (unlikely(read_thread_flags() & _TIF_NEED_RESCHED)) {
 				if (preempt_count() == 0)
 					preempt_schedule_irq();
 			}
diff --git a/arch/powerpc/kernel/ptrace/ptrace.c b/arch/powerpc/kernel/ptrace/ptrace.c
index 7c7093c17c45..c43f77e2ac31 100644
--- a/arch/powerpc/kernel/ptrace/ptrace.c
+++ b/arch/powerpc/kernel/ptrace/ptrace.c
@@ -260,8 +260,7 @@ long do_syscall_trace_enter(struct pt_regs *regs)
 {
 	u32 flags;
 
-	flags = READ_ONCE(current_thread_info()->flags) &
-		(_TIF_SYSCALL_EMU | _TIF_SYSCALL_TRACE);
+	flags = read_thread_flags() & (_TIF_SYSCALL_EMU | _TIF_SYSCALL_TRACE);
 
 	if (flags) {
 		int rc = tracehook_report_syscall_entry(regs);
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCHv7 11/11] x86: snapshot thread flags
  2021-11-17 16:30 [PATCHv7 00/11] thread_info: use helpers to snapshot thread flags Mark Rutland
                   ` (9 preceding siblings ...)
  2021-11-17 16:30 ` [PATCHv7 10/11] powerpc: snapshot thread flags Mark Rutland
@ 2021-11-17 16:30 ` Mark Rutland
  2021-11-26 20:22   ` [tip: core/entry] x86: Snapshot " tip-bot2 for Mark Rutland
  10 siblings, 1 reply; 23+ messages in thread
From: Mark Rutland @ 2021-11-17 16:30 UTC (permalink / raw)
  To: linux-kernel
  Cc: benh, boqun.feng, bp, catalin.marinas, dvyukov, efuller, elver,
	ink, joey.gouly, jonas, juri.lelli, linux, luto, mark.rutland,
	mattst88, michal.simek, mingo, mpe, npiggin, paulmck, paulus,
	peterz, rth, shorne, stefan.kristiansson, tglx, vincent.guittot,
	will

Some thread flags can be set remotely, and so even when IRQs are
disabled, the flags can change under our feet. Generally this is
unlikely to cause a problem in practice, but it is somewhat unsound, and
KCSAN will legitimately warn that there is a data race.

To avoid such issues, a snapshot of the flags has to be taken prior to
using them. Some places already use READ_ONCE() for that, others do not.

Convert them all to the new flag accessor helpers.

Signed-off-by: Mark Rutland <mark.rutland@arm.com>
Reviewed-by: Thomas Gleixner <tglx@linutronix.de>
Acked-by: Paul E. McKenney <paulmck@kernel.org>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Ingo Molnar <mingo@redhat.com>
---
 arch/x86/kernel/process.c | 8 ++++----
 arch/x86/kernel/process.h | 4 ++--
 arch/x86/mm/tlb.c         | 2 +-
 3 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c
index e9ee8b526319..180d7a00cb66 100644
--- a/arch/x86/kernel/process.c
+++ b/arch/x86/kernel/process.c
@@ -365,7 +365,7 @@ void arch_setup_new_exec(void)
 		clear_thread_flag(TIF_SSBD);
 		task_clear_spec_ssb_disable(current);
 		task_clear_spec_ssb_noexec(current);
-		speculation_ctrl_update(task_thread_info(current)->flags);
+		speculation_ctrl_update(read_thread_flags());
 	}
 }
 
@@ -617,7 +617,7 @@ static unsigned long speculation_ctrl_update_tif(struct task_struct *tsk)
 			clear_tsk_thread_flag(tsk, TIF_SPEC_IB);
 	}
 	/* Return the updated threadinfo flags*/
-	return task_thread_info(tsk)->flags;
+	return read_task_thread_flags(tsk);
 }
 
 void speculation_ctrl_update(unsigned long tif)
@@ -653,8 +653,8 @@ void __switch_to_xtra(struct task_struct *prev_p, struct task_struct *next_p)
 {
 	unsigned long tifp, tifn;
 
-	tifn = READ_ONCE(task_thread_info(next_p)->flags);
-	tifp = READ_ONCE(task_thread_info(prev_p)->flags);
+	tifn = read_task_thread_flags(next_p);
+	tifp = read_task_thread_flags(prev_p);
 
 	switch_to_bitmap(tifp);
 
diff --git a/arch/x86/kernel/process.h b/arch/x86/kernel/process.h
index 1d0797b2338a..76b547b83232 100644
--- a/arch/x86/kernel/process.h
+++ b/arch/x86/kernel/process.h
@@ -13,8 +13,8 @@ void __switch_to_xtra(struct task_struct *prev_p, struct task_struct *next_p);
 static inline void switch_to_extra(struct task_struct *prev,
 				   struct task_struct *next)
 {
-	unsigned long next_tif = task_thread_info(next)->flags;
-	unsigned long prev_tif = task_thread_info(prev)->flags;
+	unsigned long next_tif = read_task_thread_flags(next);
+	unsigned long prev_tif = read_task_thread_flags(prev);
 
 	if (IS_ENABLED(CONFIG_SMP)) {
 		/*
diff --git a/arch/x86/mm/tlb.c b/arch/x86/mm/tlb.c
index 59ba2968af1b..92bb03b9ceb5 100644
--- a/arch/x86/mm/tlb.c
+++ b/arch/x86/mm/tlb.c
@@ -361,7 +361,7 @@ static void l1d_flush_evaluate(unsigned long prev_mm, unsigned long next_mm,
 
 static unsigned long mm_mangle_tif_spec_bits(struct task_struct *next)
 {
-	unsigned long next_tif = task_thread_info(next)->flags;
+	unsigned long next_tif = read_task_thread_flags(next);
 	unsigned long spec_bits = (next_tif >> TIF_SPEC_IB) & LAST_USER_MM_SPEC_MASK;
 
 	/*
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [tip: core/entry] x86: Snapshot thread flags
  2021-11-17 16:30 ` [PATCHv7 11/11] x86: snapshot " Mark Rutland
@ 2021-11-26 20:22   ` tip-bot2 for Mark Rutland
  0 siblings, 0 replies; 23+ messages in thread
From: tip-bot2 for Mark Rutland @ 2021-11-26 20:22 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: Mark Rutland, Thomas Gleixner, Paul E. McKenney, x86, linux-kernel

The following commit has been merged into the core/entry branch of tip:

Commit-ID:     5796ee48d26a18930a8b86fb865ba195282889d0
Gitweb:        https://git.kernel.org/tip/5796ee48d26a18930a8b86fb865ba195282889d0
Author:        Mark Rutland <mark.rutland@arm.com>
AuthorDate:    Wed, 17 Nov 2021 16:30:49 
Committer:     Thomas Gleixner <tglx@linutronix.de>
CommitterDate: Fri, 26 Nov 2021 21:20:14 +01:00

x86: Snapshot thread flags

Some thread flags can be set remotely, and so even when IRQs are
disabled, the flags can change under our feet. Generally this is
unlikely to cause a problem in practice, but it is somewhat unsound, and
KCSAN will legitimately warn that there is a data race.

To avoid such issues, a snapshot of the flags has to be taken prior to
using them. Some places already use READ_ONCE() for that, others do not.

Convert them all to the new flag accessor helpers.

Signed-off-by: Mark Rutland <mark.rutland@arm.com>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Reviewed-by: Thomas Gleixner <tglx@linutronix.de>
Acked-by: Paul E. McKenney <paulmck@kernel.org>
Link: https://lore.kernel.org/r/20211117163050.53986-12-mark.rutland@arm.com
---
 arch/x86/kernel/process.c | 8 ++++----
 arch/x86/kernel/process.h | 4 ++--
 arch/x86/mm/tlb.c         | 2 +-
 3 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c
index 04143a6..5d48103 100644
--- a/arch/x86/kernel/process.c
+++ b/arch/x86/kernel/process.c
@@ -365,7 +365,7 @@ void arch_setup_new_exec(void)
 		clear_thread_flag(TIF_SSBD);
 		task_clear_spec_ssb_disable(current);
 		task_clear_spec_ssb_noexec(current);
-		speculation_ctrl_update(task_thread_info(current)->flags);
+		speculation_ctrl_update(read_thread_flags());
 	}
 }
 
@@ -617,7 +617,7 @@ static unsigned long speculation_ctrl_update_tif(struct task_struct *tsk)
 			clear_tsk_thread_flag(tsk, TIF_SPEC_IB);
 	}
 	/* Return the updated threadinfo flags*/
-	return task_thread_info(tsk)->flags;
+	return read_task_thread_flags(tsk);
 }
 
 void speculation_ctrl_update(unsigned long tif)
@@ -653,8 +653,8 @@ void __switch_to_xtra(struct task_struct *prev_p, struct task_struct *next_p)
 {
 	unsigned long tifp, tifn;
 
-	tifn = READ_ONCE(task_thread_info(next_p)->flags);
-	tifp = READ_ONCE(task_thread_info(prev_p)->flags);
+	tifn = read_task_thread_flags(next_p);
+	tifp = read_task_thread_flags(prev_p);
 
 	switch_to_bitmap(tifp);
 
diff --git a/arch/x86/kernel/process.h b/arch/x86/kernel/process.h
index 1d0797b..76b547b 100644
--- a/arch/x86/kernel/process.h
+++ b/arch/x86/kernel/process.h
@@ -13,8 +13,8 @@ void __switch_to_xtra(struct task_struct *prev_p, struct task_struct *next_p);
 static inline void switch_to_extra(struct task_struct *prev,
 				   struct task_struct *next)
 {
-	unsigned long next_tif = task_thread_info(next)->flags;
-	unsigned long prev_tif = task_thread_info(prev)->flags;
+	unsigned long next_tif = read_task_thread_flags(next);
+	unsigned long prev_tif = read_task_thread_flags(prev);
 
 	if (IS_ENABLED(CONFIG_SMP)) {
 		/*
diff --git a/arch/x86/mm/tlb.c b/arch/x86/mm/tlb.c
index 59ba296..92bb03b 100644
--- a/arch/x86/mm/tlb.c
+++ b/arch/x86/mm/tlb.c
@@ -361,7 +361,7 @@ static void l1d_flush_evaluate(unsigned long prev_mm, unsigned long next_mm,
 
 static unsigned long mm_mangle_tif_spec_bits(struct task_struct *next)
 {
-	unsigned long next_tif = task_thread_info(next)->flags;
+	unsigned long next_tif = read_task_thread_flags(next);
 	unsigned long spec_bits = (next_tif >> TIF_SPEC_IB) & LAST_USER_MM_SPEC_MASK;
 
 	/*

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [tip: core/entry] powerpc: Snapshot thread flags
  2021-11-17 16:30 ` [PATCHv7 10/11] powerpc: snapshot thread flags Mark Rutland
@ 2021-11-26 20:22   ` tip-bot2 for Mark Rutland
  0 siblings, 0 replies; 23+ messages in thread
From: tip-bot2 for Mark Rutland @ 2021-11-26 20:22 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: Mark Rutland, Thomas Gleixner, Paul E. McKenney,
	Benjamin Herrenschmidt, Michael Ellerman, Paul Mackerras, x86,
	linux-kernel

The following commit has been merged into the core/entry branch of tip:

Commit-ID:     72e2920678507649ca100eadca8ec6f06744575d
Gitweb:        https://git.kernel.org/tip/72e2920678507649ca100eadca8ec6f06744575d
Author:        Mark Rutland <mark.rutland@arm.com>
AuthorDate:    Wed, 17 Nov 2021 16:30:48 
Committer:     Thomas Gleixner <tglx@linutronix.de>
CommitterDate: Fri, 26 Nov 2021 21:20:14 +01:00

powerpc: Snapshot thread flags

Some thread flags can be set remotely, and so even when IRQs are
disabled, the flags can change under our feet. Generally this is
unlikely to cause a problem in practice, but it is somewhat unsound, and
KCSAN will legitimately warn that there is a data race.

To avoid such issues, a snapshot of the flags has to be taken prior to
using them. Some places already use READ_ONCE() for that, others do not.

Convert them all to the new flag accessor helpers.

Signed-off-by: Mark Rutland <mark.rutland@arm.com>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Acked-by: Paul E. McKenney <paulmck@kernel.org>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Michael Ellerman <mpe@ellerman.id.au>
Cc: Paul Mackerras <paulus@samba.org>
Link: https://lore.kernel.org/r/20211117163050.53986-11-mark.rutland@arm.com
---
 arch/powerpc/kernel/interrupt.c     | 13 ++++++-------
 arch/powerpc/kernel/ptrace/ptrace.c |  3 +--
 2 files changed, 7 insertions(+), 9 deletions(-)

diff --git a/arch/powerpc/kernel/interrupt.c b/arch/powerpc/kernel/interrupt.c
index 1c821b7..ff25888 100644
--- a/arch/powerpc/kernel/interrupt.c
+++ b/arch/powerpc/kernel/interrupt.c
@@ -181,7 +181,7 @@ notrace long system_call_exception(long r3, long r4, long r5,
 
 	local_irq_enable();
 
-	if (unlikely(current_thread_info()->flags & _TIF_SYSCALL_DOTRACE)) {
+	if (unlikely(read_thread_flags() & _TIF_SYSCALL_DOTRACE)) {
 		if (unlikely(trap_is_unsupported_scv(regs))) {
 			/* Unsupported scv vector */
 			_exception(SIGILL, regs, ILL_ILLOPC, regs->nip);
@@ -343,7 +343,7 @@ interrupt_exit_user_prepare_main(unsigned long ret, struct pt_regs *regs)
 	unsigned long ti_flags;
 
 again:
-	ti_flags = READ_ONCE(current_thread_info()->flags);
+	ti_flags = read_thread_flags();
 	while (unlikely(ti_flags & (_TIF_USER_WORK_MASK & ~_TIF_RESTORE_TM))) {
 		local_irq_enable();
 		if (ti_flags & _TIF_NEED_RESCHED) {
@@ -359,7 +359,7 @@ again:
 			do_notify_resume(regs, ti_flags);
 		}
 		local_irq_disable();
-		ti_flags = READ_ONCE(current_thread_info()->flags);
+		ti_flags = read_thread_flags();
 	}
 
 	if (IS_ENABLED(CONFIG_PPC_BOOK3S_64) && IS_ENABLED(CONFIG_PPC_FPU)) {
@@ -437,7 +437,7 @@ notrace unsigned long syscall_exit_prepare(unsigned long r3,
 	/* Check whether the syscall is issued inside a restartable sequence */
 	rseq_syscall(regs);
 
-	ti_flags = current_thread_info()->flags;
+	ti_flags = read_thread_flags();
 
 	if (unlikely(r3 >= (unsigned long)-MAX_ERRNO) && is_not_scv) {
 		if (likely(!(ti_flags & (_TIF_NOERROR | _TIF_RESTOREALL)))) {
@@ -532,8 +532,7 @@ notrace unsigned long interrupt_exit_kernel_prepare(struct pt_regs *regs)
 	unsigned long flags;
 	unsigned long ret = 0;
 	unsigned long kuap;
-	bool stack_store = current_thread_info()->flags &
-						_TIF_EMULATE_STACK_STORE;
+	bool stack_store = read_thread_flags() & _TIF_EMULATE_STACK_STORE;
 
 	if (regs_is_unrecoverable(regs))
 		unrecoverable_exception(regs);
@@ -554,7 +553,7 @@ notrace unsigned long interrupt_exit_kernel_prepare(struct pt_regs *regs)
 again:
 		if (IS_ENABLED(CONFIG_PREEMPT)) {
 			/* Return to preemptible kernel context */
-			if (unlikely(current_thread_info()->flags & _TIF_NEED_RESCHED)) {
+			if (unlikely(read_thread_flags() & _TIF_NEED_RESCHED)) {
 				if (preempt_count() == 0)
 					preempt_schedule_irq();
 			}
diff --git a/arch/powerpc/kernel/ptrace/ptrace.c b/arch/powerpc/kernel/ptrace/ptrace.c
index 7c7093c..c43f77e 100644
--- a/arch/powerpc/kernel/ptrace/ptrace.c
+++ b/arch/powerpc/kernel/ptrace/ptrace.c
@@ -260,8 +260,7 @@ long do_syscall_trace_enter(struct pt_regs *regs)
 {
 	u32 flags;
 
-	flags = READ_ONCE(current_thread_info()->flags) &
-		(_TIF_SYSCALL_EMU | _TIF_SYSCALL_TRACE);
+	flags = read_thread_flags() & (_TIF_SYSCALL_EMU | _TIF_SYSCALL_TRACE);
 
 	if (flags) {
 		int rc = tracehook_report_syscall_entry(regs);

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [tip: core/entry] powerpc: Avoid discarding flags in system_call_exception()
  2021-11-17 16:30 ` [PATCHv7 09/11] powerpc: avoid discarding flags in system_call_exception() Mark Rutland
@ 2021-11-26 20:22   ` tip-bot2 for Mark Rutland
  0 siblings, 0 replies; 23+ messages in thread
From: tip-bot2 for Mark Rutland @ 2021-11-26 20:22 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: Mark Rutland, Thomas Gleixner, Eirik Fuller, Michael Ellerman,
	Nicholas Piggin, x86, linux-kernel

The following commit has been merged into the core/entry branch of tip:

Commit-ID:     51ed65dcfd9c61a15920a40178d471d236a7514c
Gitweb:        https://git.kernel.org/tip/51ed65dcfd9c61a15920a40178d471d236a7514c
Author:        Mark Rutland <mark.rutland@arm.com>
AuthorDate:    Wed, 17 Nov 2021 16:30:47 
Committer:     Thomas Gleixner <tglx@linutronix.de>
CommitterDate: Fri, 26 Nov 2021 21:20:13 +01:00

powerpc: Avoid discarding flags in system_call_exception()

Some thread flags can be set remotely, and so even when IRQs are
disabled, the flags can change under our feet. Thus, when setting flags
we must use an atomic operation rather than a plain read-modify-write
sequence, as a plain read-modify-write may discard flags which are
concurrently set by a remote thread, e.g.

	// task A			// task B
	tmp = A->thread_info.flags;
					set_tsk_thread_flag(A, NEWFLAG_B);
	tmp |= NEWFLAG_A;
	A->thread_info.flags = tmp;

In arch/powerpc/kernel/interrupt.c's system_call_exception(), we set
_TIF_RESTOREALL in the thread info flags with a read-modify-write, which
may result in other flags being discarded.

Elsewhere in the file we use clear_bits() to atomically remove flag
bits, so let's use set_bits() here for consistency with those.

I presume there may be reasons (e.g. instrumentation) that prevent the
use of set_thread_flag() and clear_thread_flag() here, which would
otherwise be preferable.

Fixes: ae7aaecc3f2f78b7 ("powerpc/64s: system call rfscv workaround for TM bugs")
Signed-off-by: Mark Rutland <mark.rutland@arm.com>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: Eirik Fuller <efuller@redhat.com>
Cc: Michael Ellerman <mpe@ellerman.id.au>
Cc: Nicholas Piggin <npiggin@gmail.com>
Link: https://lore.kernel.org/r/20211117163050.53986-10-mark.rutland@arm.com
---
 arch/powerpc/kernel/interrupt.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/powerpc/kernel/interrupt.c b/arch/powerpc/kernel/interrupt.c
index 835b626..1c821b7 100644
--- a/arch/powerpc/kernel/interrupt.c
+++ b/arch/powerpc/kernel/interrupt.c
@@ -148,7 +148,7 @@ notrace long system_call_exception(long r3, long r4, long r5,
 	 */
 	if (IS_ENABLED(CONFIG_PPC_TRANSACTIONAL_MEM) &&
 			unlikely(MSR_TM_TRANSACTIONAL(regs->msr)))
-		current_thread_info()->flags |= _TIF_RESTOREALL;
+		set_bits(_TIF_RESTOREALL, current_thread_info()->flags);
 
 	/*
 	 * If the system call was made with a transaction active, doom it and

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [tip: core/entry] openrisc: Snapshot thread flags
  2021-11-17 16:30 ` [PATCHv7 08/11] openrisc: snapshot " Mark Rutland
@ 2021-11-26 20:22   ` tip-bot2 for Mark Rutland
  0 siblings, 0 replies; 23+ messages in thread
From: tip-bot2 for Mark Rutland @ 2021-11-26 20:22 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: Mark Rutland, Thomas Gleixner, Stafford Horne, Paul E. McKenney,
	Jonas Bonn, Stefan Kristiansson, x86, linux-kernel

The following commit has been merged into the core/entry branch of tip:

Commit-ID:     b67c4b87d2a6893dd6bddc8b0400715cafc30cd5
Gitweb:        https://git.kernel.org/tip/b67c4b87d2a6893dd6bddc8b0400715cafc30cd5
Author:        Mark Rutland <mark.rutland@arm.com>
AuthorDate:    Wed, 17 Nov 2021 16:30:46 
Committer:     Thomas Gleixner <tglx@linutronix.de>
CommitterDate: Fri, 26 Nov 2021 21:20:13 +01:00

openrisc: Snapshot thread flags

Some thread flags can be set remotely, and so even when IRQs are
disabled, the flags can change under our feet. Generally this is
unlikely to cause a problem in practice, but it is somewhat unsound, and
KCSAN will legitimately warn that there is a data race.

To avoid such issues, a snapshot of the flags has to be taken prior to
using them. Some places already use READ_ONCE() for that, others do not.

Convert them all to the new flag accessor helpers.

Signed-off-by: Mark Rutland <mark.rutland@arm.com>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Acked-by: Stafford Horne <shorne@gmail.com>
Acked-by: Paul E. McKenney <paulmck@kernel.org>
Cc: Jonas Bonn <jonas@southpole.se>
Cc: Stefan Kristiansson <stefan.kristiansson@saunalahti.fi>
Link: https://lore.kernel.org/r/20211117163050.53986-9-mark.rutland@arm.com
---
 arch/openrisc/kernel/signal.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/openrisc/kernel/signal.c b/arch/openrisc/kernel/signal.c
index 99516c9..92c5b70 100644
--- a/arch/openrisc/kernel/signal.c
+++ b/arch/openrisc/kernel/signal.c
@@ -313,7 +313,7 @@ do_work_pending(struct pt_regs *regs, unsigned int thread_flags, int syscall)
 			}
 		}
 		local_irq_disable();
-		thread_flags = current_thread_info()->flags;
+		thread_flags = read_thread_flags();
 	} while (thread_flags & _TIF_WORK_MASK);
 	return 0;
 }

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [tip: core/entry] microblaze: Snapshot thread flags
  2021-11-17 16:30 ` [PATCHv7 07/11] microblaze: " Mark Rutland
@ 2021-11-26 20:22   ` tip-bot2 for Mark Rutland
  0 siblings, 0 replies; 23+ messages in thread
From: tip-bot2 for Mark Rutland @ 2021-11-26 20:22 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: Mark Rutland, Thomas Gleixner, Michal Simek, Paul E. McKenney,
	x86, linux-kernel

The following commit has been merged into the core/entry branch of tip:

Commit-ID:     a9455e33ce5f0516046ca0da3aedd80f147ecb38
Gitweb:        https://git.kernel.org/tip/a9455e33ce5f0516046ca0da3aedd80f147ecb38
Author:        Mark Rutland <mark.rutland@arm.com>
AuthorDate:    Wed, 17 Nov 2021 16:30:45 
Committer:     Thomas Gleixner <tglx@linutronix.de>
CommitterDate: Fri, 26 Nov 2021 21:20:13 +01:00

microblaze: Snapshot thread flags

Some thread flags can be set remotely, and so even when IRQs are
disabled, the flags can change under our feet. Generally this is
unlikely to cause a problem in practice, but it is somewhat unsound, and
KCSAN will legitimately warn that there is a data race.

To avoid such issues, a snapshot of the flags has to be taken prior to
using them. Some places already use READ_ONCE() for that, others do not.

Convert them all to the new flag accessor helpers.

Signed-off-by: Mark Rutland <mark.rutland@arm.com>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Tested-by: Michal Simek <michal.simek@xilinx.com>
Acked-by: Paul E. McKenney <paulmck@kernel.org>
Link: https://lore.kernel.org/r/20211117163050.53986-8-mark.rutland@arm.com
---
 arch/microblaze/kernel/signal.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/microblaze/kernel/signal.c b/arch/microblaze/kernel/signal.c
index fc61eb0..23e8a93 100644
--- a/arch/microblaze/kernel/signal.c
+++ b/arch/microblaze/kernel/signal.c
@@ -283,7 +283,7 @@ static void do_signal(struct pt_regs *regs, int in_syscall)
 #ifdef DEBUG_SIG
 	pr_info("do signal: %p %d\n", regs, in_syscall);
 	pr_info("do signal2: %lx %lx %ld [%lx]\n", regs->pc, regs->r1,
-			regs->r12, current_thread_info()->flags);
+			regs->r12, read_thread_flags());
 #endif
 
 	if (get_signal(&ksig)) {

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [tip: core/entry] arm64: snapshot thread flags
  2021-11-17 16:30 ` [PATCHv7 06/11] arm64: snapshot " Mark Rutland
@ 2021-11-26 20:22   ` tip-bot2 for Mark Rutland
  0 siblings, 0 replies; 23+ messages in thread
From: tip-bot2 for Mark Rutland @ 2021-11-26 20:22 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: Mark Rutland, Thomas Gleixner, Will Deacon, Paul E. McKenney,
	Catalin Marinas, x86, linux-kernel

The following commit has been merged into the core/entry branch of tip:

Commit-ID:     67c76c3dc0ef46f44715e866c7d4ef81a5a2872d
Gitweb:        https://git.kernel.org/tip/67c76c3dc0ef46f44715e866c7d4ef81a5a2872d
Author:        Mark Rutland <mark.rutland@arm.com>
AuthorDate:    Wed, 17 Nov 2021 16:30:44 
Committer:     Thomas Gleixner <tglx@linutronix.de>
CommitterDate: Fri, 26 Nov 2021 21:20:13 +01:00

arm64: snapshot thread flags

Some thread flags can be set remotely, and so even when IRQs are
disabled, the flags can change under our feet. Generally this is
unlikely to cause a problem in practice, but it is somewhat unsound, and
KCSAN will legitimately warn that there is a data race.

To avoid such issues, a snapshot of the flags has to be taken prior to
using them. Some places already use READ_ONCE() for that, others do not.

Convert them all to the new flag accessor helpers.

Signed-off-by: Mark Rutland <mark.rutland@arm.com>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Acked-by: Will Deacon <will@kernel.org>
Acked-by: Paul E. McKenney <paulmck@kernel.org>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Link: https://lore.kernel.org/r/20211117163050.53986-7-mark.rutland@arm.com
---
 arch/arm64/kernel/entry-common.c | 2 +-
 arch/arm64/kernel/ptrace.c       | 4 ++--
 arch/arm64/kernel/signal.c       | 2 +-
 arch/arm64/kernel/syscall.c      | 4 ++--
 4 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/arch/arm64/kernel/entry-common.c b/arch/arm64/kernel/entry-common.c
index f7408ed..ef7fcef 100644
--- a/arch/arm64/kernel/entry-common.c
+++ b/arch/arm64/kernel/entry-common.c
@@ -129,7 +129,7 @@ static __always_inline void prepare_exit_to_user_mode(struct pt_regs *regs)
 
 	local_daif_mask();
 
-	flags = READ_ONCE(current_thread_info()->flags);
+	flags = read_thread_flags();
 	if (unlikely(flags & _TIF_WORK_MASK))
 		do_notify_resume(regs, flags);
 }
diff --git a/arch/arm64/kernel/ptrace.c b/arch/arm64/kernel/ptrace.c
index 88a9034..33cac3d 100644
--- a/arch/arm64/kernel/ptrace.c
+++ b/arch/arm64/kernel/ptrace.c
@@ -1839,7 +1839,7 @@ static void tracehook_report_syscall(struct pt_regs *regs,
 
 int syscall_trace_enter(struct pt_regs *regs)
 {
-	unsigned long flags = READ_ONCE(current_thread_info()->flags);
+	unsigned long flags = read_thread_flags();
 
 	if (flags & (_TIF_SYSCALL_EMU | _TIF_SYSCALL_TRACE)) {
 		tracehook_report_syscall(regs, PTRACE_SYSCALL_ENTER);
@@ -1862,7 +1862,7 @@ int syscall_trace_enter(struct pt_regs *regs)
 
 void syscall_trace_exit(struct pt_regs *regs)
 {
-	unsigned long flags = READ_ONCE(current_thread_info()->flags);
+	unsigned long flags = read_thread_flags();
 
 	audit_syscall_exit(regs);
 
diff --git a/arch/arm64/kernel/signal.c b/arch/arm64/kernel/signal.c
index 8f6372b..d8aaf4b 100644
--- a/arch/arm64/kernel/signal.c
+++ b/arch/arm64/kernel/signal.c
@@ -948,7 +948,7 @@ void do_notify_resume(struct pt_regs *regs, unsigned long thread_flags)
 		}
 
 		local_daif_mask();
-		thread_flags = READ_ONCE(current_thread_info()->flags);
+		thread_flags = read_thread_flags();
 	} while (thread_flags & _TIF_WORK_MASK);
 }
 
diff --git a/arch/arm64/kernel/syscall.c b/arch/arm64/kernel/syscall.c
index 50a0f1a..c938603 100644
--- a/arch/arm64/kernel/syscall.c
+++ b/arch/arm64/kernel/syscall.c
@@ -81,7 +81,7 @@ void syscall_trace_exit(struct pt_regs *regs);
 static void el0_svc_common(struct pt_regs *regs, int scno, int sc_nr,
 			   const syscall_fn_t syscall_table[])
 {
-	unsigned long flags = current_thread_info()->flags;
+	unsigned long flags = read_thread_flags();
 
 	regs->orig_x0 = regs->regs[0];
 	regs->syscallno = scno;
@@ -148,7 +148,7 @@ static void el0_svc_common(struct pt_regs *regs, int scno, int sc_nr,
 	 */
 	if (!has_syscall_work(flags) && !IS_ENABLED(CONFIG_DEBUG_RSEQ)) {
 		local_daif_mask();
-		flags = current_thread_info()->flags;
+		flags = read_thread_flags();
 		if (!has_syscall_work(flags) && !(flags & _TIF_SINGLESTEP))
 			return;
 		local_daif_restore(DAIF_PROCCTX);

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [tip: core/entry] ARM: Snapshot thread flags
  2021-11-17 16:30 ` [PATCHv7 05/11] arm: snapshot " Mark Rutland
@ 2021-11-26 20:22   ` tip-bot2 for Mark Rutland
  0 siblings, 0 replies; 23+ messages in thread
From: tip-bot2 for Mark Rutland @ 2021-11-26 20:22 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: Mark Rutland, Thomas Gleixner, Paul E. McKenney, Russell King,
	x86, linux-kernel

The following commit has been merged into the core/entry branch of tip:

Commit-ID:     3fe5dec062dfc8344356823457f5f43e0730c074
Gitweb:        https://git.kernel.org/tip/3fe5dec062dfc8344356823457f5f43e0730c074
Author:        Mark Rutland <mark.rutland@arm.com>
AuthorDate:    Wed, 17 Nov 2021 16:30:43 
Committer:     Thomas Gleixner <tglx@linutronix.de>
CommitterDate: Fri, 26 Nov 2021 21:20:13 +01:00

ARM: Snapshot thread flags

Some thread flags can be set remotely, and so even when IRQs are
disabled, the flags can change under our feet. Generally this is
unlikely to cause a problem in practice, but it is somewhat unsound, and
KCSAN will legitimately warn that there is a data race.

To avoid such issues, a snapshot of the flags has to be taken prior to
using them. Some places already use READ_ONCE() for that, others do not.

Convert them all to the new flag accessor helpers.

Signed-off-by: Mark Rutland <mark.rutland@arm.com>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Acked-by: Paul E. McKenney <paulmck@kernel.org>
Cc: Russell King <linux@armlinux.org.uk>
Link: https://lore.kernel.org/r/20211117163050.53986-6-mark.rutland@arm.com
---
 arch/arm/kernel/signal.c | 2 +-
 arch/arm/mm/alignment.c  | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/arch/arm/kernel/signal.c b/arch/arm/kernel/signal.c
index a41e27a..c532a60 100644
--- a/arch/arm/kernel/signal.c
+++ b/arch/arm/kernel/signal.c
@@ -631,7 +631,7 @@ do_work_pending(struct pt_regs *regs, unsigned int thread_flags, int syscall)
 			}
 		}
 		local_irq_disable();
-		thread_flags = current_thread_info()->flags;
+		thread_flags = read_thread_flags();
 	} while (thread_flags & _TIF_WORK_MASK);
 	return 0;
 }
diff --git a/arch/arm/mm/alignment.c b/arch/arm/mm/alignment.c
index ea81e89..adbb381 100644
--- a/arch/arm/mm/alignment.c
+++ b/arch/arm/mm/alignment.c
@@ -990,7 +990,7 @@ do_alignment(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
 		 * there is no work pending for this thread.
 		 */
 		raw_local_irq_disable();
-		if (!(current_thread_info()->flags & _TIF_WORK_MASK))
+		if (!(read_thread_flags() & _TIF_WORK_MASK))
 			set_cr(cr_no_alignment);
 	}
 

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [tip: core/entry] alpha: Snapshot thread flags
  2021-11-17 16:30 ` [PATCHv7 04/11] alpha: snapshot " Mark Rutland
@ 2021-11-26 20:22   ` tip-bot2 for Mark Rutland
  0 siblings, 0 replies; 23+ messages in thread
From: tip-bot2 for Mark Rutland @ 2021-11-26 20:22 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: Mark Rutland, Thomas Gleixner, Paul E. McKenney, Ivan Kokshaysky,
	Matt Turner, Richard Henderson, x86, linux-kernel

The following commit has been merged into the core/entry branch of tip:

Commit-ID:     b8cdd8873327b967fe088ffab84c1f9456ef1767
Gitweb:        https://git.kernel.org/tip/b8cdd8873327b967fe088ffab84c1f9456ef1767
Author:        Mark Rutland <mark.rutland@arm.com>
AuthorDate:    Wed, 17 Nov 2021 16:30:42 
Committer:     Thomas Gleixner <tglx@linutronix.de>
CommitterDate: Fri, 26 Nov 2021 21:20:13 +01:00

alpha: Snapshot thread flags

Some thread flags can be set remotely, and so even when IRQs are
disabled, the flags can change under our feet. Generally this is
unlikely to cause a problem in practice, but it is somewhat unsound, and
KCSAN will legitimately warn that there is a data race.

To avoid such issues, a snapshot of the flags has to be taken prior to
using them. Some places already use READ_ONCE() for that, others do not.

Convert them all to the new flag accessor helpers.

Signed-off-by: Mark Rutland <mark.rutland@arm.com>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Acked-by: Paul E. McKenney <paulmck@kernel.org>
Cc: Ivan Kokshaysky <ink@jurassic.park.msu.ru>
Cc: Matt Turner <mattst88@gmail.com>
Cc: Richard Henderson <rth@twiddle.net>
Link: https://lore.kernel.org/r/20211117163050.53986-5-mark.rutland@arm.com
---
 arch/alpha/kernel/signal.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/alpha/kernel/signal.c b/arch/alpha/kernel/signal.c
index bc077ba..d8ed71d 100644
--- a/arch/alpha/kernel/signal.c
+++ b/arch/alpha/kernel/signal.c
@@ -535,6 +535,6 @@ do_work_pending(struct pt_regs *regs, unsigned long thread_flags,
 			}
 		}
 		local_irq_disable();
-		thread_flags = current_thread_info()->flags;
+		thread_flags = read_thread_flags();
 	} while (thread_flags & _TIF_WORK_MASK);
 }

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [tip: core/entry] entry: Snapshot thread flags
  2021-11-17 16:30 ` [PATCHv7 02/11] entry: " Mark Rutland
@ 2021-11-26 20:22   ` tip-bot2 for Mark Rutland
  0 siblings, 0 replies; 23+ messages in thread
From: tip-bot2 for Mark Rutland @ 2021-11-26 20:22 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: Mark Rutland, Thomas Gleixner, Paul E. McKenney, Andy Lutomirski,
	x86, linux-kernel

The following commit has been merged into the core/entry branch of tip:

Commit-ID:     f6af43531342c55c34a851bd455508edc29f6e06
Gitweb:        https://git.kernel.org/tip/f6af43531342c55c34a851bd455508edc29f6e06
Author:        Mark Rutland <mark.rutland@arm.com>
AuthorDate:    Wed, 17 Nov 2021 16:30:40 
Committer:     Thomas Gleixner <tglx@linutronix.de>
CommitterDate: Fri, 26 Nov 2021 21:20:13 +01:00

entry: Snapshot thread flags

Some thread flags can be set remotely, and so even when IRQs are
disabled, the flags can change under our feet. Generally this is
unlikely to cause a problem in practice, but it is somewhat unsound, and
KCSAN will legitimately warn that there is a data race.

To avoid such issues, a snapshot of the flags has to be taken prior to
using them. Some places already use READ_ONCE() for that, others do not.

Convert them all to the new flag accessor helpers.

Signed-off-by: Mark Rutland <mark.rutland@arm.com>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Acked-by: Paul E. McKenney <paulmck@kernel.org>
Cc: Andy Lutomirski <luto@kernel.org>
Link: https://lore.kernel.org/r/20211117163050.53986-3-mark.rutland@arm.com
---
 include/linux/entry-kvm.h | 2 +-
 kernel/entry/common.c     | 4 ++--
 kernel/entry/kvm.c        | 4 ++--
 3 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/include/linux/entry-kvm.h b/include/linux/entry-kvm.h
index 0d7865a..07c878d 100644
--- a/include/linux/entry-kvm.h
+++ b/include/linux/entry-kvm.h
@@ -75,7 +75,7 @@ static inline void xfer_to_guest_mode_prepare(void)
  */
 static inline bool __xfer_to_guest_mode_work_pending(void)
 {
-	unsigned long ti_work = READ_ONCE(current_thread_info()->flags);
+	unsigned long ti_work = read_thread_flags();
 
 	return !!(ti_work & XFER_TO_GUEST_MODE_WORK);
 }
diff --git a/kernel/entry/common.c b/kernel/entry/common.c
index d5a61d5..bad7136 100644
--- a/kernel/entry/common.c
+++ b/kernel/entry/common.c
@@ -187,7 +187,7 @@ static unsigned long exit_to_user_mode_loop(struct pt_regs *regs,
 		/* Check if any of the above work has queued a deferred wakeup */
 		tick_nohz_user_enter_prepare();
 
-		ti_work = READ_ONCE(current_thread_info()->flags);
+		ti_work = read_thread_flags();
 	}
 
 	/* Return the latest work state for arch_exit_to_user_mode() */
@@ -196,7 +196,7 @@ static unsigned long exit_to_user_mode_loop(struct pt_regs *regs,
 
 static void exit_to_user_mode_prepare(struct pt_regs *regs)
 {
-	unsigned long ti_work = READ_ONCE(current_thread_info()->flags);
+	unsigned long ti_work = read_thread_flags();
 
 	lockdep_assert_irqs_disabled();
 
diff --git a/kernel/entry/kvm.c b/kernel/entry/kvm.c
index 49972ee..96d476e 100644
--- a/kernel/entry/kvm.c
+++ b/kernel/entry/kvm.c
@@ -26,7 +26,7 @@ static int xfer_to_guest_mode_work(struct kvm_vcpu *vcpu, unsigned long ti_work)
 		if (ret)
 			return ret;
 
-		ti_work = READ_ONCE(current_thread_info()->flags);
+		ti_work = read_thread_flags();
 	} while (ti_work & XFER_TO_GUEST_MODE_WORK || need_resched());
 	return 0;
 }
@@ -43,7 +43,7 @@ int xfer_to_guest_mode_handle_work(struct kvm_vcpu *vcpu)
 	 * disabled in the inner loop before going into guest mode. No need
 	 * to disable interrupts here.
 	 */
-	ti_work = READ_ONCE(current_thread_info()->flags);
+	ti_work = read_thread_flags();
 	if (!(ti_work & XFER_TO_GUEST_MODE_WORK))
 		return 0;
 

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [tip: core/entry] sched: Snapshot thread flags
  2021-11-17 16:30 ` [PATCHv7 03/11] sched: snapshot " Mark Rutland
@ 2021-11-26 20:22   ` tip-bot2 for Mark Rutland
  0 siblings, 0 replies; 23+ messages in thread
From: tip-bot2 for Mark Rutland @ 2021-11-26 20:22 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: Mark Rutland, Thomas Gleixner, Paul E. McKenney, Juri Lelli,
	Vincent Guittot, x86, linux-kernel

The following commit has been merged into the core/entry branch of tip:

Commit-ID:     13a405dc6f7f01635c1e849c42b2b8941cec2968
Gitweb:        https://git.kernel.org/tip/13a405dc6f7f01635c1e849c42b2b8941cec2968
Author:        Mark Rutland <mark.rutland@arm.com>
AuthorDate:    Wed, 17 Nov 2021 16:30:41 
Committer:     Thomas Gleixner <tglx@linutronix.de>
CommitterDate: Fri, 26 Nov 2021 21:20:13 +01:00

sched: Snapshot thread flags

Some thread flags can be set remotely, and so even when IRQs are
disabled, the flags can change under our feet. Generally this is
unlikely to cause a problem in practice, but it is somewhat unsound, and
KCSAN will legitimately warn that there is a data race.

To avoid such issues, a snapshot of the flags has to be taken prior to
using them. Some places already use READ_ONCE() for that, others do not.

Convert them all to the new flag accessor helpers.

The READ_ONCE(ti->flags) .. cmpxchg(ti->flags) loop in set_nr_if_polling()
is left as-is for clarity.

Signed-off-by: Mark Rutland <mark.rutland@arm.com>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Acked-by: Paul E. McKenney <paulmck@kernel.org>
Cc: Juri Lelli <juri.lelli@redhat.com>
Cc: Vincent Guittot <vincent.guittot@linaro.org>
Link: https://lore.kernel.org/r/20211117163050.53986-4-mark.rutland@arm.com
---
 kernel/sched/core.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/kernel/sched/core.c b/kernel/sched/core.c
index 3c9b0fd..7ba05de 100644
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -8520,7 +8520,7 @@ void sched_show_task(struct task_struct *p)
 	rcu_read_unlock();
 	pr_cont(" stack:%5lu pid:%5d ppid:%6d flags:0x%08lx\n",
 		free, task_pid_nr(p), ppid,
-		(unsigned long)task_thread_info(p)->flags);
+		read_task_thread_flags(p));
 
 	print_worker_info(KERN_INFO, p);
 	print_stop_info(KERN_INFO, p);

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [tip: core/entry] thread_info: Add helpers to snapshot thread flags
  2021-11-17 16:30 ` [PATCHv7 01/11] thread_info: add " Mark Rutland
@ 2021-11-26 20:23   ` tip-bot2 for Mark Rutland
  0 siblings, 0 replies; 23+ messages in thread
From: tip-bot2 for Mark Rutland @ 2021-11-26 20:23 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: Mark Rutland, Thomas Gleixner, Marco Elver, Paul E. McKenney,
	Boqun Feng, Dmitry Vyukov, Will Deacon, x86, linux-kernel

The following commit has been merged into the core/entry branch of tip:

Commit-ID:     669bcfc0ffe06d9623b48babf5d609d6a36ebdfa
Gitweb:        https://git.kernel.org/tip/669bcfc0ffe06d9623b48babf5d609d6a36ebdfa
Author:        Mark Rutland <mark.rutland@arm.com>
AuthorDate:    Wed, 17 Nov 2021 16:30:39 
Committer:     Thomas Gleixner <tglx@linutronix.de>
CommitterDate: Fri, 26 Nov 2021 21:20:12 +01:00

thread_info: Add helpers to snapshot thread flags

In <linux/thread_info.h> there are helpers to manipulate individual
thread flags, but where code wants to check several flags at once, it
must open code reading current_thread_info()->flags and operating on a
snapshot.

As some flags can be set remotely it's necessary to use READ_ONCE() to
get a consistent snapshot even when IRQs are disabled, but some code
forgets to do this. Generally this is unlike to cause a problem in
practice, but it is somewhat unsound, and KCSAN will legitimately warn
that there is a data race.

To make it easier to do the right thing, and to highlight that
concurrent modification is possible, add new helpers to snapshot the
flags, which should be used in preference to plain reads. Subsequent
patches will move existing code to use the new helpers.

Signed-off-by: Mark Rutland <mark.rutland@arm.com>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Reviewed-by: Thomas Gleixner <tglx@linutronix.de>
Acked-by: Marco Elver <elver@google.com>
Acked-by: Paul E. McKenney <paulmck@kernel.org>
Cc: Boqun Feng <boqun.feng@gmail.com>
Cc: Dmitry Vyukov <dvyukov@google.com>
Cc: Will Deacon <will@kernel.org>
Link: https://lore.kernel.org/r/20211117163050.53986-2-mark.rutland@arm.com
---
 include/linux/thread_info.h | 14 ++++++++++++++
 1 file changed, 14 insertions(+)

diff --git a/include/linux/thread_info.h b/include/linux/thread_info.h
index ad0c4e0..73a6f34 100644
--- a/include/linux/thread_info.h
+++ b/include/linux/thread_info.h
@@ -118,6 +118,15 @@ static inline int test_ti_thread_flag(struct thread_info *ti, int flag)
 	return test_bit(flag, (unsigned long *)&ti->flags);
 }
 
+/*
+ * This may be used in noinstr code, and needs to be __always_inline to prevent
+ * inadvertent instrumentation.
+ */
+static __always_inline unsigned long read_ti_thread_flags(struct thread_info *ti)
+{
+	return READ_ONCE(ti->flags);
+}
+
 #define set_thread_flag(flag) \
 	set_ti_thread_flag(current_thread_info(), flag)
 #define clear_thread_flag(flag) \
@@ -130,6 +139,11 @@ static inline int test_ti_thread_flag(struct thread_info *ti, int flag)
 	test_and_clear_ti_thread_flag(current_thread_info(), flag)
 #define test_thread_flag(flag) \
 	test_ti_thread_flag(current_thread_info(), flag)
+#define read_thread_flags() \
+	read_ti_thread_flags(current_thread_info())
+
+#define read_task_thread_flags(t) \
+	read_ti_thread_flags(task_thread_info(t))
 
 #ifdef CONFIG_GENERIC_ENTRY
 #define set_syscall_work(fl) \

^ permalink raw reply related	[flat|nested] 23+ messages in thread

end of thread, other threads:[~2021-11-26 20:26 UTC | newest]

Thread overview: 23+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-11-17 16:30 [PATCHv7 00/11] thread_info: use helpers to snapshot thread flags Mark Rutland
2021-11-17 16:30 ` [PATCHv7 01/11] thread_info: add " Mark Rutland
2021-11-26 20:23   ` [tip: core/entry] thread_info: Add " tip-bot2 for Mark Rutland
2021-11-17 16:30 ` [PATCHv7 02/11] entry: " Mark Rutland
2021-11-26 20:22   ` [tip: core/entry] entry: Snapshot " tip-bot2 for Mark Rutland
2021-11-17 16:30 ` [PATCHv7 03/11] sched: snapshot " Mark Rutland
2021-11-26 20:22   ` [tip: core/entry] sched: Snapshot " tip-bot2 for Mark Rutland
2021-11-17 16:30 ` [PATCHv7 04/11] alpha: snapshot " Mark Rutland
2021-11-26 20:22   ` [tip: core/entry] alpha: Snapshot " tip-bot2 for Mark Rutland
2021-11-17 16:30 ` [PATCHv7 05/11] arm: snapshot " Mark Rutland
2021-11-26 20:22   ` [tip: core/entry] ARM: Snapshot " tip-bot2 for Mark Rutland
2021-11-17 16:30 ` [PATCHv7 06/11] arm64: snapshot " Mark Rutland
2021-11-26 20:22   ` [tip: core/entry] " tip-bot2 for Mark Rutland
2021-11-17 16:30 ` [PATCHv7 07/11] microblaze: " Mark Rutland
2021-11-26 20:22   ` [tip: core/entry] microblaze: Snapshot " tip-bot2 for Mark Rutland
2021-11-17 16:30 ` [PATCHv7 08/11] openrisc: snapshot " Mark Rutland
2021-11-26 20:22   ` [tip: core/entry] openrisc: Snapshot " tip-bot2 for Mark Rutland
2021-11-17 16:30 ` [PATCHv7 09/11] powerpc: avoid discarding flags in system_call_exception() Mark Rutland
2021-11-26 20:22   ` [tip: core/entry] powerpc: Avoid " tip-bot2 for Mark Rutland
2021-11-17 16:30 ` [PATCHv7 10/11] powerpc: snapshot thread flags Mark Rutland
2021-11-26 20:22   ` [tip: core/entry] powerpc: Snapshot " tip-bot2 for Mark Rutland
2021-11-17 16:30 ` [PATCHv7 11/11] x86: snapshot " Mark Rutland
2021-11-26 20:22   ` [tip: core/entry] x86: Snapshot " tip-bot2 for Mark Rutland

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).