[PATCH] rseq: Out-of-line rseq_exit_user_update() for KMSAN

Ilya Leoshkevich <[email protected]>
Newsgroups org.kernel.vger.linux-s390,org.kernel.vger.linux-kernel
Message-ID <[email protected]>
KMSAN produces the following false positive on s390x:

    [    4.232136] Kernel panic - not syncing: kmsan.panic set ...
    [    4.232339] CPU: 7 UID: 0 PID: 1 Comm: virtme-init Tainted: G    B            N  7.2.0-rc6-virtme #27 PREEMPTLAZY
    [    4.232676] Tainted: [B]=BAD_PAGE, [N]=TEST
    [    4.232808] Hardware name: IBM 3931 A01 701 (KVM/Linux)
    [    4.232971] Call Trace:
    [    4.233065]  [<000002dcfb993140>] vpanic+0xb50/0x1080
    [    4.239698]  [<000002dcfb9925ec>] panic+0x22c/0x230
    [    4.239879]  [<000002dcfcec5d32>] kmsan_report+0x322/0x330
    [    4.240081]  [<000002dcfcec3592>] kmsan_internal_check_memory+0x222/0x280
    [    4.240304]  [<000002dcffe3444e>] irqentry_exit+0x50e/0x8f0
    [    4.240522]  [<000002dcffe33454>] __do_pgm_check+0x1b4/0x2b0
    [    4.240740]  [<000002dcffe75304>] pgm_check_handler+0x114/0x160

The reason is that the following call chain inlined into the noinstr
irqentry_exit() function:

    irqentry_exit()
      irqentry_exit_to_user_mode()
        irqentry_exit_to_user_mode_prepare()
          __exit_to_user_mode_prepare()
            exit_to_user_mode_loop()
              rseq_exit_to_user_mode_restart()
                __rseq_exit_to_user_mode_restart()
                  rseq_exit_user_update()

does not set KMSAN shadow on struct rseq_ids, which is then verified by

    rseq_exit_user_update()
      rseq_update_usr()
        rseq_set_ids_get_csaddr()
          unsafe_put_user()

regardless of presence of KMSAN instrumentation.

Fix by out-of-lining rseq_exit_user_update() and compiling the
out-of-lined version with KMSAN instrumentation.

This should affect other architectures as well, but whether one
actually sees it depends on the leftover shadow of struct rseq_ids
stack location: s390 is not special here.

Fixes: 05b44aef709c ("rseq: Implement fast path for exit to user")
Signed-off-by: Ilya Leoshkevich <[email protected]>
---
 include/linux/rseq_entry.h | 9 ++++++++-
 kernel/rseq.c              | 7 +++++++
 2 files changed, 15 insertions(+), 1 deletion(-)

diff --git a/include/linux/rseq_entry.h b/include/linux/rseq_entry.h
index ed9da6e41a2aa..a396050f771cc 100644
--- a/include/linux/rseq_entry.h
+++ b/include/linux/rseq_entry.h
@@ -595,7 +595,8 @@ static rseq_inline bool rseq_update_usr(struct task_struct *t, struct pt_regs *r
  * tells the caller to loop back into exit_to_user_mode_loop(). The rseq
  * slow path there will handle the failure.
  */
-static __always_inline bool rseq_exit_user_update(struct pt_regs *regs, struct task_struct *t)
+static __always_inline bool rseq_exit_user_update_inline(struct pt_regs *regs,
+							 struct task_struct *t)
 {
 	/*
 	 * Page faults need to be disabled as this is called with
@@ -647,6 +648,12 @@ static __always_inline bool rseq_exit_user_update(struct pt_regs *regs, struct t
 	return false;
 }
 
+#ifdef CONFIG_KMSAN
+bool rseq_exit_user_update(struct pt_regs *regs, struct task_struct *t);
+#else
+#define rseq_exit_user_update rseq_exit_user_update_inline
+#endif
+
 static __always_inline bool __rseq_exit_to_user_mode_restart(struct pt_regs *regs)
 {
 	struct task_struct *t = current;
diff --git a/kernel/rseq.c b/kernel/rseq.c
index e75e3a5e312c8..be759d7d266b5 100644
--- a/kernel/rseq.c
+++ b/kernel/rseq.c
@@ -329,6 +329,13 @@ void __rseq_handle_slowpath(struct pt_regs *regs)
 	rseq_slowpath_update_usr(regs);
 }
 
+#if defined(CONFIG_KMSAN) && defined(CONFIG_GENERIC_ENTRY)
+bool rseq_exit_user_update(struct pt_regs *regs, struct task_struct *t)
+{
+	return rseq_exit_user_update_inline(regs, t);
+}
+#endif
+
 void __rseq_signal_deliver(int sig, struct pt_regs *regs)
 {
 	rseq_stat_inc(rseq_stats.signal);
-- 
2.55.0
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.