Commit 75edb54a authored by Dmitry Vyukov's avatar Dmitry Vyukov Committed by Ingo Molnar

x86: Fix KASAN false positives in thread_saved_pc()

thread_saved_pc() reads stack of a potentially running task.
This can cause false KASAN stack-out-of-bounds reports,
because the running task concurrently poisons and unpoisons
own stack.

The same happens in get_wchan(), and get get_wchan() was fixed
by using READ_ONCE_NOCHECK(). Do the same here.

Example KASAN report triggered by sysrq-t:

  BUG: KASAN: out-of-bounds in sched_show_task+0x306/0x3b0 at addr ffff880043c97c18
  Read of size 8 by task syz-executor/23839
  [...]
  page dumped because: kasan: bad access detected
  [...]
  Call Trace:
   [<ffffffff8175ea0e>] __asan_report_load8_noabort+0x3e/0x40
   [<ffffffff813e7a26>] sched_show_task+0x306/0x3b0
   [<ffffffff813e7bf4>] show_state_filter+0x124/0x1a0
   [<ffffffff82d2ca00>] fn_show_state+0x10/0x20
   [<ffffffff82d2cf98>] k_spec+0xa8/0xe0
   [<ffffffff82d3354f>] kbd_event+0xb9f/0x4000
   [<ffffffff843ca8a7>] input_to_handler+0x3a7/0x4b0
   [<ffffffff843d1954>] input_pass_values.part.5+0x554/0x6b0
   [<ffffffff843d29bc>] input_handle_event+0x2ac/0x1070
   [<ffffffff843d3a47>] input_inject_event+0x237/0x280
   [<ffffffff843e8c28>] evdev_write+0x478/0x680
   [<ffffffff817ac653>] __vfs_write+0x113/0x480
   [<ffffffff817ae0e7>] vfs_write+0x167/0x4a0
   [<ffffffff817b13d1>] SyS_write+0x111/0x220
Signed-off-by: default avatarDmitry Vyukov <dvyukov@google.com>
Acked-by: default avatarAndrey Ryabinin <aryabinin@virtuozzo.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: glider@google.com
Cc: kasan-dev@googlegroups.com
Cc: kcc@google.com
Cc: linux-kernel@vger.kernel.org
Cc: ryabinin.a.a@gmail.com
Signed-off-by: default avatarIngo Molnar <mingo@kernel.org>
parent b37a05c0
...@@ -766,7 +766,7 @@ extern unsigned long thread_saved_pc(struct task_struct *tsk); ...@@ -766,7 +766,7 @@ extern unsigned long thread_saved_pc(struct task_struct *tsk);
* Return saved PC of a blocked thread. * Return saved PC of a blocked thread.
* What is this good for? it will be always the scheduler or ret_from_fork. * What is this good for? it will be always the scheduler or ret_from_fork.
*/ */
#define thread_saved_pc(t) (*(unsigned long *)((t)->thread.sp - 8)) #define thread_saved_pc(t) READ_ONCE_NOCHECK(*(unsigned long *)((t)->thread.sp - 8))
#define task_pt_regs(tsk) ((struct pt_regs *)(tsk)->thread.sp0 - 1) #define task_pt_regs(tsk) ((struct pt_regs *)(tsk)->thread.sp0 - 1)
extern unsigned long KSTK_ESP(struct task_struct *task); extern unsigned long KSTK_ESP(struct task_struct *task);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment