Commit-ID: 9f7d416c36124667c406978bcb39746589c35d7f
Gitweb: http://git.kernel.org/tip/9f7d416c36124667c406978bcb39746589c35d7f
Author: Dmitry Vyukov
AuthorDate: Fri, 14 Oct 2016 16:07:23 +0200
Committer: Ingo Molnar
CommitDate: Sun, 16 Oct 2016 11:02:31 +0200
kprobes: Unpoison stack in jprobe_return() for KASAN
I observed false KSAN positives in the sctp code, when
sctp uses jprobe_return() in jsctp_sf_eat_sack().
The stray 0xf4 in shadow memory are stack redzones:
[ ] ==
[ ] BUG: KASAN: stack-out-of-bounds in memcmp+0xe9/0x150 at addr
88005e48f480
[ ] Read of size 1 by task syz-executor/18535
[ ] page:ea00017923c0 count:0 mapcount:0 mapping: (null)
index:0x0
[ ] flags: 0x1fffc00()
[ ] page dumped because: kasan: bad access detected
[ ] CPU: 1 PID: 18535 Comm: syz-executor Not tainted 4.8.0+ #28
[ ] Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS
Google 01/01/2011
[ ] 88005e48f2d0 82d2b849 0bc91e90 fbfff10971e8
[ ] ed000bc91e90 ed000bc91e90 0001
[ ] 88005e48f480 88005e48f350 817d3169 88005e48f370
[ ] Call Trace:
[ ] [] dump_stack+0x12e/0x185
[ ] [] kasan_report+0x489/0x4b0
[ ] [] __asan_report_load1_noabort+0x19/0x20
[ ] [] memcmp+0xe9/0x150
[ ] [] depot_save_stack+0x176/0x5c0
[ ] [] save_stack+0xb1/0xd0
[ ] [] kasan_slab_free+0x72/0xc0
[ ] [] kfree+0xc8/0x2a0
[ ] [] skb_free_head+0x79/0xb0
[ ] [] skb_release_data+0x37a/0x420
[ ] [] skb_release_all+0x4f/0x60
[ ] [] consume_skb+0x138/0x370
[ ] [] sctp_chunk_put+0xcb/0x180
[ ] [] sctp_chunk_free+0x58/0x70
[ ] [] sctp_inq_pop+0x68f/0xef0
[ ] [] sctp_assoc_bh_rcv+0xd6/0x4b0
[ ] [] sctp_inq_push+0x131/0x190
[ ] [] sctp_backlog_rcv+0xe9/0xa20
[ ... ]
[ ] Memory state around the buggy address:
[ ] 88005e48f380: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[ ] 88005e48f400: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[ ] >88005e48f480: f4 f4 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[ ]^
[ ] 88005e48f500: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[ ] 88005e48f580: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[ ] ==
KASAN stack instrumentation poisons stack redzones on function entry
and unpoisons them on function exit. If a function exits abnormally
(e.g. with a longjmp like jprobe_return()), stack redzones are left
poisoned. Later this leads to random KASAN false reports.
Unpoison stack redzones in the frames we are going to jump over
before doing actual longjmp in jprobe_return().
Signed-off-by: Dmitry Vyukov
Acked-by: Masami Hiramatsu
Reviewed-by: Mark Rutland
Cc: Mark Rutland
Cc: Catalin Marinas
Cc: Andrey Ryabinin
Cc: Lorenzo Pieralisi
Cc: Alexander Potapenko
Cc: Will Deacon
Cc: Andrew Morton
Cc: Ananth N Mavinakayanahalli
Cc: Anil S Keshavamurthy
Cc: "David S. Miller"
Cc: Masami Hiramatsu
Cc: kasan-...@googlegroups.com
Cc: surove...@google.com
Cc: rost...@goodmis.org
Link:
http://lkml.kernel.org/r/1476454043-101898-1-git-send-email-dvyu...@google.com
Signed-off-by: Ingo Molnar
---
arch/arm64/kernel/sleep.S | 2 +-
arch/x86/kernel/kprobes/core.c | 4
include/linux/kasan.h | 2 ++
mm/kasan/kasan.c | 22 +++---
4 files changed, 26 insertions(+), 4 deletions(-)
diff --git a/arch/arm64/kernel/sleep.S b/arch/arm64/kernel/sleep.S
index b8799e7..1bec41b 100644
--- a/arch/arm64/kernel/sleep.S
+++ b/arch/arm64/kernel/sleep.S
@@ -135,7 +135,7 @@ ENTRY(_cpu_resume)
#ifdef CONFIG_KASAN
mov x0, sp
- bl kasan_unpoison_remaining_stack
+ bl kasan_unpoison_task_stack_below
#endif
ldp x19, x20, [x29, #16]
diff --git a/arch/x86/kernel/kprobes/core.c b/arch/x86/kernel/kprobes/core.c
index f423b0ef..d9d8d16 100644
--- a/arch/x86/kernel/kprobes/core.c
+++ b/arch/x86/kernel/kprobes/core.c
@@ -50,6 +50,7 @@
#include
#include
#include
+#include
#include
#include
@@ -1081,6 +1082,9 @@ void jprobe_return(void)
{
struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
+ /* Unpoison stack redzones in the frames we are going to jump over. */
+ kasan_unpoison_stack_above_sp_to(kcb->jprobe_saved_sp);
+
asm volatile (
#ifdef CONFIG_X86_64
" xchg %%rbx,%%rsp \n"
diff --git a/include/linux/kasan.h b/include/linux/kasan.h
index d600303..820c0ad 100644
--- a/include/linux/kasan.h
+++ b/include/linux/kasan.h
@@ -44,6 +44,7 @@ static inline void kasan_disable_current(void)
void kasan_unpoison_shadow(const void *address, size_t size);
void kasan_unpoison_task_stack(struct task_struct *task);
+void