[PATCH v2] task_work: kasan: record task_work_add() call stack

2021-03-15 Thread Walter Wu
Why record task_work_add() call stack?
Syzbot reports many use-after-free issues for task_work, see [1].
After see the free stack and the current auxiliary stack, we think
they are useless, we don't know where register the work, this work
may be the free call stack, so that we miss the root cause and
don't solve the use-after-free.

Add task_work_add() call stack into KASAN auxiliary stack in
order to improve KASAN report. It is useful for programmers
to solve use-after-free issues.

[1]: 
https://groups.google.com/g/syzkaller-bugs/search?q=kasan%20use-after-free%20task_work_run

Signed-off-by: Walter Wu 
Suggested-by: Dmitry Vyukov 
Cc: Andrey Konovalov 
Cc: Andrey Ryabinin 
Cc: Dmitry Vyukov 
Cc: Alexander Potapenko 
Cc: Andrew Morton 
Cc: Matthias Brugger 
Cc: Jens Axboe 
Cc: Oleg Nesterov 
---

v2: Fix kasan_record_aux_stack() calling sequence issue.
Thanks for Dmitry's suggestion

---
 kernel/task_work.c | 3 +++
 mm/kasan/kasan.h   | 2 +-
 2 files changed, 4 insertions(+), 1 deletion(-)

diff --git a/kernel/task_work.c b/kernel/task_work.c
index 9cde961875c0..3d4852891fa8 100644
--- a/kernel/task_work.c
+++ b/kernel/task_work.c
@@ -34,6 +34,9 @@ int task_work_add(struct task_struct *task, struct 
callback_head *work,
 {
struct callback_head *head;
 
+   /* record the work call stack in order to print it in KASAN reports */
+   kasan_record_aux_stack(work);
+
do {
head = READ_ONCE(task->task_works);
if (unlikely(head == _exited))
diff --git a/mm/kasan/kasan.h b/mm/kasan/kasan.h
index 3436c6bf7c0c..e4629a971a3c 100644
--- a/mm/kasan/kasan.h
+++ b/mm/kasan/kasan.h
@@ -146,7 +146,7 @@ struct kasan_alloc_meta {
struct kasan_track alloc_track;
 #ifdef CONFIG_KASAN_GENERIC
/*
-* call_rcu() call stack is stored into struct kasan_alloc_meta.
+* The auxiliary stack is stored into struct kasan_alloc_meta.
 * The free stack is stored into struct kasan_free_meta.
 */
depot_stack_handle_t aux_stack[2];
-- 
2.18.0



Re: [PATCH] task_work: kasan: record task_work_add() call stack

2021-03-15 Thread Walter Wu
On Mon, 2021-03-15 at 11:03 +0100, 'Dmitry Vyukov' via kasan-dev wrote:
> On Mon, Mar 15, 2021 at 10:38 AM Walter Wu  wrote:
> >
> > On Mon, 2021-03-15 at 07:58 +0100, 'Dmitry Vyukov' via kasan-dev wrote:
> > > On Mon, Mar 15, 2021 at 3:00 AM Walter Wu  
> > > wrote:
> > > >
> > > > Why record task_work_add() call stack?
> > > > Syzbot reports many use-after-free issues for task_work, see [1].
> > > > After see the free stack and the current auxiliary stack, we think
> > > > they are useless, we don't know where register the work, this work
> > > > may be the free call stack, so that we miss the root cause and
> > > > don't solve the use-after-free.
> > > >
> > > > Add task_work_add() call stack into KASAN auxiliary stack in
> > > > order to improve KASAN report. It is useful for programmers
> > > > to solve use-after-free issues.
> > > >
> > > > [1]: 
> > > > https://groups.google.com/g/syzkaller-bugs/search?q=kasan%20use-after-free%20task_work_run
> > > >
> > > > Signed-off-by: Walter Wu 
> > > > Suggested-by: Dmitry Vyukov 
> > > > Cc: Andrey Ryabinin 
> > > > Cc: Dmitry Vyukov 
> > > > Cc: Andrey Konovalov 
> > > > Cc: Alexander Potapenko 
> > > > Cc: Andrew Morton 
> > > > Cc: Matthias Brugger 
> > > > Cc: Jens Axboe 
> > > > Cc: Oleg Nesterov 
> > > > ---
> > > >  kernel/task_work.c | 3 +++
> > > >  mm/kasan/kasan.h   | 2 +-
> > > >  2 files changed, 4 insertions(+), 1 deletion(-)
> > > >
> > > > diff --git a/kernel/task_work.c b/kernel/task_work.c
> > > > index 9cde961875c0..f255294377da 100644
> > > > --- a/kernel/task_work.c
> > > > +++ b/kernel/task_work.c
> > > > @@ -55,6 +55,9 @@ int task_work_add(struct task_struct *task, struct 
> > > > callback_head *work,
> > > > break;
> > > > }
> > > >
> > > > +   /* record the work call stack in order to print it in KASAN 
> > > > reports */
> > > > +   kasan_record_aux_stack(work);
> > >
> > > I think this call should be done _before_ we actually queue the work,
> > > because this function may operate on non-current task.
> > > Consider, we queue the work, the other task already executes it and
> > > triggers use-after-free, now only now we record the stack.
> >
> > agree, what do you think below change?
> >
> > --- a/kernel/task_work.c
> > +++ b/kernel/task_work.c
> > @@ -34,6 +34,9 @@ int task_work_add(struct task_struct *task, struct
> > callback_head *work,
> >  {
> > struct callback_head *head;
> >
> > +   /* record the work call stack in order to print it in KASAN reports
> > */
> > +   kasan_record_aux_stack(work);
> > +
> 
> This looks good to me.
> 
> 
> > do {
> > head = READ_ONCE(task->task_works);
> > if (unlikely(head == _exited))
> > @@ -55,9 +58,6 @@ int task_work_add(struct task_struct *task, struct
> > callback_head *work,
> > break;
> > }
> >
> > -   /* record the work call stack in order to print it in KASAN reports
> > */
> > -   kasan_record_aux_stack(work);
> > -
> > return 0;
> >  }
> >
> > > Moreover, I think we can trigger use-after-free here ourselves while
> > > recording the aux stack. We queued the work, and the work can cause
> > > own free, so it's not necessary live by now.
> >
> > Sorry, I don't fully know your meaning, do you mean we should add an
> > abort when detect use-after-free?
> 
> I meant that where we had the kasan_record_aux_stack(work) call in the
> first version of the patch, work can be already freed. We must not
> access work after queueing it.
> 

Got it. Now I must treat urgent issue, I will send v2 patch tomorrow.

Thanks for your review.

> > > > return 0;
> > > >  }
> > > >
> > > > diff --git a/mm/kasan/kasan.h b/mm/kasan/kasan.h
> > > > index 3436c6bf7c0c..d300fe9415bd 100644
> > > > --- a/mm/kasan/kasan.h
> > > > +++ b/mm/kasan/kasan.h
> > > > @@ -146,7 +146,7 @@ struct kasan_alloc_meta {
> > > > struct kasan_track alloc_track;
> > > >  #ifdef CONFIG_KASAN_GENERIC
> > > > /*
> > > > -* call_rcu() call stack is stored into struct kasan_alloc_meta.
> > > > +* Auxiliary stack is stored into struct kasan_alloc_meta.
> > > >  * The free stack is stored into struct kasan_free_meta.
> > > >  */
> > > > depot_stack_handle_t aux_stack[2];
> > > > --
> > > > 2.18.0
> > >
> >
> > --
> > You received this message because you are subscribed to the Google Groups 
> > "kasan-dev" group.
> > To unsubscribe from this group and stop receiving emails from it, send an 
> > email to kasan-dev+unsubscr...@googlegroups.com.
> > To view this discussion on the web visit 
> > https://groups.google.com/d/msgid/kasan-dev/1615801102.24887.4.camel%40mtksdccf07.
> 



Re: [PATCH] task_work: kasan: record task_work_add() call stack

2021-03-15 Thread Walter Wu
On Mon, 2021-03-15 at 07:58 +0100, 'Dmitry Vyukov' via kasan-dev wrote:
> On Mon, Mar 15, 2021 at 3:00 AM Walter Wu  wrote:
> >
> > Why record task_work_add() call stack?
> > Syzbot reports many use-after-free issues for task_work, see [1].
> > After see the free stack and the current auxiliary stack, we think
> > they are useless, we don't know where register the work, this work
> > may be the free call stack, so that we miss the root cause and
> > don't solve the use-after-free.
> >
> > Add task_work_add() call stack into KASAN auxiliary stack in
> > order to improve KASAN report. It is useful for programmers
> > to solve use-after-free issues.
> >
> > [1]: 
> > https://groups.google.com/g/syzkaller-bugs/search?q=kasan%20use-after-free%20task_work_run
> >
> > Signed-off-by: Walter Wu 
> > Suggested-by: Dmitry Vyukov 
> > Cc: Andrey Ryabinin 
> > Cc: Dmitry Vyukov 
> > Cc: Andrey Konovalov 
> > Cc: Alexander Potapenko 
> > Cc: Andrew Morton 
> > Cc: Matthias Brugger 
> > Cc: Jens Axboe 
> > Cc: Oleg Nesterov 
> > ---
> >  kernel/task_work.c | 3 +++
> >  mm/kasan/kasan.h   | 2 +-
> >  2 files changed, 4 insertions(+), 1 deletion(-)
> >
> > diff --git a/kernel/task_work.c b/kernel/task_work.c
> > index 9cde961875c0..f255294377da 100644
> > --- a/kernel/task_work.c
> > +++ b/kernel/task_work.c
> > @@ -55,6 +55,9 @@ int task_work_add(struct task_struct *task, struct 
> > callback_head *work,
> > break;
> > }
> >
> > +   /* record the work call stack in order to print it in KASAN reports 
> > */
> > +   kasan_record_aux_stack(work);
> 
> I think this call should be done _before_ we actually queue the work,
> because this function may operate on non-current task.
> Consider, we queue the work, the other task already executes it and
> triggers use-after-free, now only now we record the stack.

agree, what do you think below change?

--- a/kernel/task_work.c
+++ b/kernel/task_work.c
@@ -34,6 +34,9 @@ int task_work_add(struct task_struct *task, struct
callback_head *work,
 {
struct callback_head *head;

+   /* record the work call stack in order to print it in KASAN reports
*/
+   kasan_record_aux_stack(work);
+
do {
head = READ_ONCE(task->task_works);
if (unlikely(head == _exited))
@@ -55,9 +58,6 @@ int task_work_add(struct task_struct *task, struct
callback_head *work,
break;
}

-   /* record the work call stack in order to print it in KASAN reports
*/
-   kasan_record_aux_stack(work);
-
return 0;
 }

> Moreover, I think we can trigger use-after-free here ourselves while
> recording the aux stack. We queued the work, and the work can cause
> own free, so it's not necessary live by now.

Sorry, I don't fully know your meaning, do you mean we should add an
abort when detect use-after-free?

> 
> > return 0;
> >  }
> >
> > diff --git a/mm/kasan/kasan.h b/mm/kasan/kasan.h
> > index 3436c6bf7c0c..d300fe9415bd 100644
> > --- a/mm/kasan/kasan.h
> > +++ b/mm/kasan/kasan.h
> > @@ -146,7 +146,7 @@ struct kasan_alloc_meta {
> > struct kasan_track alloc_track;
> >  #ifdef CONFIG_KASAN_GENERIC
> > /*
> > -* call_rcu() call stack is stored into struct kasan_alloc_meta.
> > +* Auxiliary stack is stored into struct kasan_alloc_meta.
> >  * The free stack is stored into struct kasan_free_meta.
> >  */
> > depot_stack_handle_t aux_stack[2];
> > --
> > 2.18.0
> 



[PATCH] task_work: kasan: record task_work_add() call stack

2021-03-14 Thread Walter Wu
Why record task_work_add() call stack?
Syzbot reports many use-after-free issues for task_work, see [1].
After see the free stack and the current auxiliary stack, we think
they are useless, we don't know where register the work, this work
may be the free call stack, so that we miss the root cause and
don't solve the use-after-free.

Add task_work_add() call stack into KASAN auxiliary stack in
order to improve KASAN report. It is useful for programmers
to solve use-after-free issues.

[1]: 
https://groups.google.com/g/syzkaller-bugs/search?q=kasan%20use-after-free%20task_work_run

Signed-off-by: Walter Wu 
Suggested-by: Dmitry Vyukov 
Cc: Andrey Ryabinin 
Cc: Dmitry Vyukov 
Cc: Andrey Konovalov 
Cc: Alexander Potapenko 
Cc: Andrew Morton 
Cc: Matthias Brugger 
Cc: Jens Axboe 
Cc: Oleg Nesterov 
---
 kernel/task_work.c | 3 +++
 mm/kasan/kasan.h   | 2 +-
 2 files changed, 4 insertions(+), 1 deletion(-)

diff --git a/kernel/task_work.c b/kernel/task_work.c
index 9cde961875c0..f255294377da 100644
--- a/kernel/task_work.c
+++ b/kernel/task_work.c
@@ -55,6 +55,9 @@ int task_work_add(struct task_struct *task, struct 
callback_head *work,
break;
}
 
+   /* record the work call stack in order to print it in KASAN reports */
+   kasan_record_aux_stack(work);
+
return 0;
 }
 
diff --git a/mm/kasan/kasan.h b/mm/kasan/kasan.h
index 3436c6bf7c0c..d300fe9415bd 100644
--- a/mm/kasan/kasan.h
+++ b/mm/kasan/kasan.h
@@ -146,7 +146,7 @@ struct kasan_alloc_meta {
struct kasan_track alloc_track;
 #ifdef CONFIG_KASAN_GENERIC
/*
-* call_rcu() call stack is stored into struct kasan_alloc_meta.
+* Auxiliary stack is stored into struct kasan_alloc_meta.
 * The free stack is stored into struct kasan_free_meta.
 */
depot_stack_handle_t aux_stack[2];
-- 
2.18.0



Re: [PATCH v4] kasan: remove redundant config option

2021-03-10 Thread Walter Wu
On Wed, 2021-03-03 at 19:48 +0800, Walter Wu wrote:
> On Fri, 2021-02-26 at 09:25 +0800, Walter Wu wrote:
> > CONFIG_KASAN_STACK and CONFIG_KASAN_STACK_ENABLE both enable KASAN stack
> > instrumentation, but we should only need one config, so that we remove
> > CONFIG_KASAN_STACK_ENABLE and make CONFIG_KASAN_STACK workable.  see [1].
> > 
> > When enable KASAN stack instrumentation, then for gcc we could do no
> > prompt and default value y, and for clang prompt and default value n.
> > 
> > [1]: https://bugzilla.kernel.org/show_bug.cgi?id=210221
> > 
> > Signed-off-by: Walter Wu 
> > Suggested-by: Dmitry Vyukov 
> > Reviewed-by: Nathan Chancellor 
> > Acked-by: Arnd Bergmann 
> > Reviewed-by: Andrey Konovalov 
> > Cc: Andrey Ryabinin 
> > Cc: Dmitry Vyukov 
> > Cc: Alexander Potapenko 
> > Cc: Andrew Morton 
> > ---
> > 
> > v4: After this patch sent, someone had modification about KASAN_STACK,
> > so I need to rebase codebase. Thank Andrey for your pointing.
> > 
> Hi Andrew,
> 
> Could you pick this v4 patch up into mm?
> Thanks.
> 
> Walter
> 
> > ---
> >  arch/arm64/kernel/sleep.S|  2 +-
> >  arch/x86/kernel/acpi/wakeup_64.S |  2 +-
> >  include/linux/kasan.h|  2 +-
> >  lib/Kconfig.kasan|  8 ++--
> >  mm/kasan/common.c|  2 +-
> >  mm/kasan/kasan.h |  2 +-
> >  mm/kasan/report_generic.c|  2 +-
> >  scripts/Makefile.kasan   | 10 --
> >  security/Kconfig.hardening   |  4 ++--
> >  9 files changed, 18 insertions(+), 16 deletions(-)
> > 
> > diff --git a/arch/arm64/kernel/sleep.S b/arch/arm64/kernel/sleep.S
> > index 5bfd9b87f85d..4ea9392f86e0 100644
> > --- a/arch/arm64/kernel/sleep.S
> > +++ b/arch/arm64/kernel/sleep.S
> > @@ -134,7 +134,7 @@ SYM_FUNC_START(_cpu_resume)
> >  */
> > bl  cpu_do_resume
> >  
> > -#if defined(CONFIG_KASAN) && CONFIG_KASAN_STACK
> > +#if defined(CONFIG_KASAN) && defined(CONFIG_KASAN_STACK)
> > mov x0, sp
> > bl  kasan_unpoison_task_stack_below
> >  #endif
> > diff --git a/arch/x86/kernel/acpi/wakeup_64.S 
> > b/arch/x86/kernel/acpi/wakeup_64.S
> > index 56b6865afb2a..d5d8a352eafa 100644
> > --- a/arch/x86/kernel/acpi/wakeup_64.S
> > +++ b/arch/x86/kernel/acpi/wakeup_64.S
> > @@ -115,7 +115,7 @@ SYM_FUNC_START(do_suspend_lowlevel)
> > movqpt_regs_r14(%rax), %r14
> > movqpt_regs_r15(%rax), %r15
> >  
> > -#if defined(CONFIG_KASAN) && CONFIG_KASAN_STACK
> > +#if defined(CONFIG_KASAN) && defined(CONFIG_KASAN_STACK)
> > /*
> >  * The suspend path may have poisoned some areas deeper in the stack,
> >  * which we now need to unpoison.
> > diff --git a/include/linux/kasan.h b/include/linux/kasan.h
> > index b91732bd05d7..14f72ec96492 100644
> > --- a/include/linux/kasan.h
> > +++ b/include/linux/kasan.h
> > @@ -330,7 +330,7 @@ static inline bool kasan_check_byte(const void *address)
> >  
> >  #endif /* CONFIG_KASAN */
> >  
> > -#if defined(CONFIG_KASAN) && CONFIG_KASAN_STACK
> > +#if defined(CONFIG_KASAN) && defined(CONFIG_KASAN_STACK)
> >  void kasan_unpoison_task_stack(struct task_struct *task);
> >  #else
> >  static inline void kasan_unpoison_task_stack(struct task_struct *task) {}
> > diff --git a/lib/Kconfig.kasan b/lib/Kconfig.kasan
> > index 624ae1df7984..cffc2ebbf185 100644
> > --- a/lib/Kconfig.kasan
> > +++ b/lib/Kconfig.kasan
> > @@ -138,9 +138,10 @@ config KASAN_INLINE
> >  
> >  endchoice
> >  
> > -config KASAN_STACK_ENABLE
> > +config KASAN_STACK
> > bool "Enable stack instrumentation (unsafe)" if CC_IS_CLANG && 
> > !COMPILE_TEST
> > depends on KASAN_GENERIC || KASAN_SW_TAGS
> > +   default y if CC_IS_GCC
> > help
> >   The LLVM stack address sanitizer has a know problem that
> >   causes excessive stack usage in a lot of functions, see
> > @@ -154,11 +155,6 @@ config KASAN_STACK_ENABLE
> >   CONFIG_COMPILE_TEST.  On gcc it is assumed to always be safe
> >   to use and enabled by default.
> >  
> > -config KASAN_STACK
> > -   int
> > -   default 1 if KASAN_STACK_ENABLE || CC_IS_GCC
> > -   default 0
> > -

Hi Andrew,

I see my v4 patch is different in the next tree now. please see below
information.
https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git/commit/?id=ebced5fb0ef969620e

Re: [PATCH v4] kasan: remove redundant config option

2021-03-03 Thread Walter Wu
On Fri, 2021-02-26 at 09:25 +0800, Walter Wu wrote:
> CONFIG_KASAN_STACK and CONFIG_KASAN_STACK_ENABLE both enable KASAN stack
> instrumentation, but we should only need one config, so that we remove
> CONFIG_KASAN_STACK_ENABLE and make CONFIG_KASAN_STACK workable.  see [1].
> 
> When enable KASAN stack instrumentation, then for gcc we could do no
> prompt and default value y, and for clang prompt and default value n.
> 
> [1]: https://bugzilla.kernel.org/show_bug.cgi?id=210221
> 
> Signed-off-by: Walter Wu 
> Suggested-by: Dmitry Vyukov 
> Reviewed-by: Nathan Chancellor 
> Acked-by: Arnd Bergmann 
> Reviewed-by: Andrey Konovalov 
> Cc: Andrey Ryabinin 
> Cc: Dmitry Vyukov 
> Cc: Alexander Potapenko 
> Cc: Andrew Morton 
> ---
> 
> v4: After this patch sent, someone had modification about KASAN_STACK,
> so I need to rebase codebase. Thank Andrey for your pointing.
> 
Hi Andrew,

Could you pick this v4 patch up into mm?
Thanks.

Walter

> ---
>  arch/arm64/kernel/sleep.S|  2 +-
>  arch/x86/kernel/acpi/wakeup_64.S |  2 +-
>  include/linux/kasan.h|  2 +-
>  lib/Kconfig.kasan|  8 ++--
>  mm/kasan/common.c|  2 +-
>  mm/kasan/kasan.h |  2 +-
>  mm/kasan/report_generic.c|  2 +-
>  scripts/Makefile.kasan   | 10 --
>  security/Kconfig.hardening   |  4 ++--
>  9 files changed, 18 insertions(+), 16 deletions(-)
> 
> diff --git a/arch/arm64/kernel/sleep.S b/arch/arm64/kernel/sleep.S
> index 5bfd9b87f85d..4ea9392f86e0 100644
> --- a/arch/arm64/kernel/sleep.S
> +++ b/arch/arm64/kernel/sleep.S
> @@ -134,7 +134,7 @@ SYM_FUNC_START(_cpu_resume)
>*/
>   bl  cpu_do_resume
>  
> -#if defined(CONFIG_KASAN) && CONFIG_KASAN_STACK
> +#if defined(CONFIG_KASAN) && defined(CONFIG_KASAN_STACK)
>   mov x0, sp
>   bl  kasan_unpoison_task_stack_below
>  #endif
> diff --git a/arch/x86/kernel/acpi/wakeup_64.S 
> b/arch/x86/kernel/acpi/wakeup_64.S
> index 56b6865afb2a..d5d8a352eafa 100644
> --- a/arch/x86/kernel/acpi/wakeup_64.S
> +++ b/arch/x86/kernel/acpi/wakeup_64.S
> @@ -115,7 +115,7 @@ SYM_FUNC_START(do_suspend_lowlevel)
>   movqpt_regs_r14(%rax), %r14
>   movqpt_regs_r15(%rax), %r15
>  
> -#if defined(CONFIG_KASAN) && CONFIG_KASAN_STACK
> +#if defined(CONFIG_KASAN) && defined(CONFIG_KASAN_STACK)
>   /*
>* The suspend path may have poisoned some areas deeper in the stack,
>* which we now need to unpoison.
> diff --git a/include/linux/kasan.h b/include/linux/kasan.h
> index b91732bd05d7..14f72ec96492 100644
> --- a/include/linux/kasan.h
> +++ b/include/linux/kasan.h
> @@ -330,7 +330,7 @@ static inline bool kasan_check_byte(const void *address)
>  
>  #endif /* CONFIG_KASAN */
>  
> -#if defined(CONFIG_KASAN) && CONFIG_KASAN_STACK
> +#if defined(CONFIG_KASAN) && defined(CONFIG_KASAN_STACK)
>  void kasan_unpoison_task_stack(struct task_struct *task);
>  #else
>  static inline void kasan_unpoison_task_stack(struct task_struct *task) {}
> diff --git a/lib/Kconfig.kasan b/lib/Kconfig.kasan
> index 624ae1df7984..cffc2ebbf185 100644
> --- a/lib/Kconfig.kasan
> +++ b/lib/Kconfig.kasan
> @@ -138,9 +138,10 @@ config KASAN_INLINE
>  
>  endchoice
>  
> -config KASAN_STACK_ENABLE
> +config KASAN_STACK
>   bool "Enable stack instrumentation (unsafe)" if CC_IS_CLANG && 
> !COMPILE_TEST
>   depends on KASAN_GENERIC || KASAN_SW_TAGS
> + default y if CC_IS_GCC
>   help
> The LLVM stack address sanitizer has a know problem that
> causes excessive stack usage in a lot of functions, see
> @@ -154,11 +155,6 @@ config KASAN_STACK_ENABLE
> CONFIG_COMPILE_TEST.  On gcc it is assumed to always be safe
> to use and enabled by default.
>  
> -config KASAN_STACK
> - int
> - default 1 if KASAN_STACK_ENABLE || CC_IS_GCC
> - default 0
> -
>  config KASAN_SW_TAGS_IDENTIFY
>   bool "Enable memory corruption identification"
>   depends on KASAN_SW_TAGS
> diff --git a/mm/kasan/common.c b/mm/kasan/common.c
> index b5e08d4cefec..7b53291dafa1 100644
> --- a/mm/kasan/common.c
> +++ b/mm/kasan/common.c
> @@ -63,7 +63,7 @@ void __kasan_unpoison_range(const void *address, size_t 
> size)
>   kasan_unpoison(address, size);
>  }
>  
> -#if CONFIG_KASAN_STACK
> +#ifdef CONFIG_KASAN_STACK
>  /* Unpoison the entire stack for a task. */
>  void kasan_unpoison_task_stack(struct task_struct *task)
>  {
> diff --git a/mm/kasan/kasan.h b/mm/kasan/kasan.h
> index 8c55634d6edd..3436c6bf7c0c 100644
> --- a/mm/kasa

[PATCH v4] kasan: remove redundant config option

2021-02-25 Thread Walter Wu
CONFIG_KASAN_STACK and CONFIG_KASAN_STACK_ENABLE both enable KASAN stack
instrumentation, but we should only need one config, so that we remove
CONFIG_KASAN_STACK_ENABLE and make CONFIG_KASAN_STACK workable.  see [1].

When enable KASAN stack instrumentation, then for gcc we could do no
prompt and default value y, and for clang prompt and default value n.

[1]: https://bugzilla.kernel.org/show_bug.cgi?id=210221

Signed-off-by: Walter Wu 
Suggested-by: Dmitry Vyukov 
Reviewed-by: Nathan Chancellor 
Acked-by: Arnd Bergmann 
Reviewed-by: Andrey Konovalov 
Cc: Andrey Ryabinin 
Cc: Dmitry Vyukov 
Cc: Alexander Potapenko 
Cc: Andrew Morton 
---

v4: After this patch sent, someone had modification about KASAN_STACK,
so I need to rebase codebase. Thank Andrey for your pointing.

---
 arch/arm64/kernel/sleep.S|  2 +-
 arch/x86/kernel/acpi/wakeup_64.S |  2 +-
 include/linux/kasan.h|  2 +-
 lib/Kconfig.kasan|  8 ++--
 mm/kasan/common.c|  2 +-
 mm/kasan/kasan.h |  2 +-
 mm/kasan/report_generic.c|  2 +-
 scripts/Makefile.kasan   | 10 --
 security/Kconfig.hardening   |  4 ++--
 9 files changed, 18 insertions(+), 16 deletions(-)

diff --git a/arch/arm64/kernel/sleep.S b/arch/arm64/kernel/sleep.S
index 5bfd9b87f85d..4ea9392f86e0 100644
--- a/arch/arm64/kernel/sleep.S
+++ b/arch/arm64/kernel/sleep.S
@@ -134,7 +134,7 @@ SYM_FUNC_START(_cpu_resume)
 */
bl  cpu_do_resume
 
-#if defined(CONFIG_KASAN) && CONFIG_KASAN_STACK
+#if defined(CONFIG_KASAN) && defined(CONFIG_KASAN_STACK)
mov x0, sp
bl  kasan_unpoison_task_stack_below
 #endif
diff --git a/arch/x86/kernel/acpi/wakeup_64.S b/arch/x86/kernel/acpi/wakeup_64.S
index 56b6865afb2a..d5d8a352eafa 100644
--- a/arch/x86/kernel/acpi/wakeup_64.S
+++ b/arch/x86/kernel/acpi/wakeup_64.S
@@ -115,7 +115,7 @@ SYM_FUNC_START(do_suspend_lowlevel)
movqpt_regs_r14(%rax), %r14
movqpt_regs_r15(%rax), %r15
 
-#if defined(CONFIG_KASAN) && CONFIG_KASAN_STACK
+#if defined(CONFIG_KASAN) && defined(CONFIG_KASAN_STACK)
/*
 * The suspend path may have poisoned some areas deeper in the stack,
 * which we now need to unpoison.
diff --git a/include/linux/kasan.h b/include/linux/kasan.h
index b91732bd05d7..14f72ec96492 100644
--- a/include/linux/kasan.h
+++ b/include/linux/kasan.h
@@ -330,7 +330,7 @@ static inline bool kasan_check_byte(const void *address)
 
 #endif /* CONFIG_KASAN */
 
-#if defined(CONFIG_KASAN) && CONFIG_KASAN_STACK
+#if defined(CONFIG_KASAN) && defined(CONFIG_KASAN_STACK)
 void kasan_unpoison_task_stack(struct task_struct *task);
 #else
 static inline void kasan_unpoison_task_stack(struct task_struct *task) {}
diff --git a/lib/Kconfig.kasan b/lib/Kconfig.kasan
index 624ae1df7984..cffc2ebbf185 100644
--- a/lib/Kconfig.kasan
+++ b/lib/Kconfig.kasan
@@ -138,9 +138,10 @@ config KASAN_INLINE
 
 endchoice
 
-config KASAN_STACK_ENABLE
+config KASAN_STACK
bool "Enable stack instrumentation (unsafe)" if CC_IS_CLANG && 
!COMPILE_TEST
depends on KASAN_GENERIC || KASAN_SW_TAGS
+   default y if CC_IS_GCC
help
  The LLVM stack address sanitizer has a know problem that
  causes excessive stack usage in a lot of functions, see
@@ -154,11 +155,6 @@ config KASAN_STACK_ENABLE
  CONFIG_COMPILE_TEST.  On gcc it is assumed to always be safe
  to use and enabled by default.
 
-config KASAN_STACK
-   int
-   default 1 if KASAN_STACK_ENABLE || CC_IS_GCC
-   default 0
-
 config KASAN_SW_TAGS_IDENTIFY
bool "Enable memory corruption identification"
depends on KASAN_SW_TAGS
diff --git a/mm/kasan/common.c b/mm/kasan/common.c
index b5e08d4cefec..7b53291dafa1 100644
--- a/mm/kasan/common.c
+++ b/mm/kasan/common.c
@@ -63,7 +63,7 @@ void __kasan_unpoison_range(const void *address, size_t size)
kasan_unpoison(address, size);
 }
 
-#if CONFIG_KASAN_STACK
+#ifdef CONFIG_KASAN_STACK
 /* Unpoison the entire stack for a task. */
 void kasan_unpoison_task_stack(struct task_struct *task)
 {
diff --git a/mm/kasan/kasan.h b/mm/kasan/kasan.h
index 8c55634d6edd..3436c6bf7c0c 100644
--- a/mm/kasan/kasan.h
+++ b/mm/kasan/kasan.h
@@ -231,7 +231,7 @@ void *kasan_find_first_bad_addr(void *addr, size_t size);
 const char *kasan_get_bug_type(struct kasan_access_info *info);
 void kasan_metadata_fetch_row(char *buffer, void *row);
 
-#if defined(CONFIG_KASAN_GENERIC) && CONFIG_KASAN_STACK
+#if defined(CONFIG_KASAN_GENERIC) && defined(CONFIG_KASAN_STACK)
 void kasan_print_address_stack_frame(const void *addr);
 #else
 static inline void kasan_print_address_stack_frame(const void *addr) { }
diff --git a/mm/kasan/report_generic.c b/mm/kasan/report_generic.c
index 41f374585144..de732bc341c5 100644
--- a/mm/kasan/report_generic.c
+++ b/mm/kasan/report_generic.c
@@ -

[PATCH v3] kasan: remove redundant config option

2021-01-07 Thread Walter Wu
CONFIG_KASAN_STACK and CONFIG_KASAN_STACK_ENABLE both enable KASAN stack
instrumentation, but we should only need one config, so that we remove
CONFIG_KASAN_STACK_ENABLE and make CONFIG_KASAN_STACK workable. see [1].

When enable KASAN stack instrumentation, then for gcc we could do
no prompt and default value y, and for clang prompt and default
value n.

[1]: https://bugzilla.kernel.org/show_bug.cgi?id=210221

Signed-off-by: Walter Wu 
Suggested-by: Dmitry Vyukov 
Cc: Andrey Ryabinin 
Cc: Dmitry Vyukov 
Cc: Andrey Konovalov 
Cc: Alexander Potapenko 
Cc: Andrew Morton 
Cc: Nathan Chancellor 
---

v2: make commit log to be more readable.
v3: remain CONFIG_KASAN_STACK_ENABLE setting
fix the pre-processors syntax

---
 arch/arm64/kernel/sleep.S|  2 +-
 arch/x86/kernel/acpi/wakeup_64.S |  2 +-
 include/linux/kasan.h|  2 +-
 lib/Kconfig.kasan|  8 ++--
 mm/kasan/common.c|  2 +-
 mm/kasan/kasan.h |  2 +-
 mm/kasan/report_generic.c|  2 +-
 scripts/Makefile.kasan   | 10 --
 8 files changed, 16 insertions(+), 14 deletions(-)

diff --git a/arch/arm64/kernel/sleep.S b/arch/arm64/kernel/sleep.S
index 6bdef7362c0e..7c44ede122a9 100644
--- a/arch/arm64/kernel/sleep.S
+++ b/arch/arm64/kernel/sleep.S
@@ -133,7 +133,7 @@ SYM_FUNC_START(_cpu_resume)
 */
bl  cpu_do_resume
 
-#if defined(CONFIG_KASAN) && CONFIG_KASAN_STACK
+#if defined(CONFIG_KASAN) && defined(CONFIG_KASAN_STACK)
mov x0, sp
bl  kasan_unpoison_task_stack_below
 #endif
diff --git a/arch/x86/kernel/acpi/wakeup_64.S b/arch/x86/kernel/acpi/wakeup_64.S
index 5d3a0b8fd379..c7f412f4e07d 100644
--- a/arch/x86/kernel/acpi/wakeup_64.S
+++ b/arch/x86/kernel/acpi/wakeup_64.S
@@ -112,7 +112,7 @@ SYM_FUNC_START(do_suspend_lowlevel)
movqpt_regs_r14(%rax), %r14
movqpt_regs_r15(%rax), %r15
 
-#if defined(CONFIG_KASAN) && CONFIG_KASAN_STACK
+#if defined(CONFIG_KASAN) && defined(CONFIG_KASAN_STACK)
/*
 * The suspend path may have poisoned some areas deeper in the stack,
 * which we now need to unpoison.
diff --git a/include/linux/kasan.h b/include/linux/kasan.h
index 5e0655fb2a6f..35d1e9b2cbfa 100644
--- a/include/linux/kasan.h
+++ b/include/linux/kasan.h
@@ -302,7 +302,7 @@ static inline void kasan_kfree_large(void *ptr, unsigned 
long ip) {}
 
 #endif /* CONFIG_KASAN */
 
-#if defined(CONFIG_KASAN) && CONFIG_KASAN_STACK
+#if defined(CONFIG_KASAN) && defined(CONFIG_KASAN_STACK)
 void kasan_unpoison_task_stack(struct task_struct *task);
 #else
 static inline void kasan_unpoison_task_stack(struct task_struct *task) {}
diff --git a/lib/Kconfig.kasan b/lib/Kconfig.kasan
index f5fa4ba126bf..fde82ec85f8f 100644
--- a/lib/Kconfig.kasan
+++ b/lib/Kconfig.kasan
@@ -138,9 +138,10 @@ config KASAN_INLINE
 
 endchoice
 
-config KASAN_STACK_ENABLE
+config KASAN_STACK
bool "Enable stack instrumentation (unsafe)" if CC_IS_CLANG && 
!COMPILE_TEST
depends on KASAN_GENERIC || KASAN_SW_TAGS
+   default y if CC_IS_GCC
help
  The LLVM stack address sanitizer has a know problem that
  causes excessive stack usage in a lot of functions, see
@@ -154,11 +155,6 @@ config KASAN_STACK_ENABLE
  CONFIG_COMPILE_TEST.  On gcc it is assumed to always be safe
  to use and enabled by default.
 
-config KASAN_STACK
-   int
-   default 1 if KASAN_STACK_ENABLE || CC_IS_GCC
-   default 0
-
 config KASAN_SW_TAGS_IDENTIFY
bool "Enable memory corruption identification"
depends on KASAN_SW_TAGS
diff --git a/mm/kasan/common.c b/mm/kasan/common.c
index 38ba2aecd8f4..bf8b073eed62 100644
--- a/mm/kasan/common.c
+++ b/mm/kasan/common.c
@@ -63,7 +63,7 @@ void __kasan_unpoison_range(const void *address, size_t size)
unpoison_range(address, size);
 }
 
-#if CONFIG_KASAN_STACK
+#ifdef CONFIG_KASAN_STACK
 /* Unpoison the entire stack for a task. */
 void kasan_unpoison_task_stack(struct task_struct *task)
 {
diff --git a/mm/kasan/kasan.h b/mm/kasan/kasan.h
index cc4d9e1d49b1..bdfdb1cff653 100644
--- a/mm/kasan/kasan.h
+++ b/mm/kasan/kasan.h
@@ -224,7 +224,7 @@ void *find_first_bad_addr(void *addr, size_t size);
 const char *get_bug_type(struct kasan_access_info *info);
 void metadata_fetch_row(char *buffer, void *row);
 
-#if defined(CONFIG_KASAN_GENERIC) && CONFIG_KASAN_STACK
+#if defined(CONFIG_KASAN_GENERIC) && defined(CONFIG_KASAN_STACK)
 void print_address_stack_frame(const void *addr);
 #else
 static inline void print_address_stack_frame(const void *addr) { }
diff --git a/mm/kasan/report_generic.c b/mm/kasan/report_generic.c
index 8a9c889872da..4e16518d9877 100644
--- a/mm/kasan/report_generic.c
+++ b/mm/kasan/report_generic.c
@@ -128,7 +128,7 @@ void metadata_fetch_row(char *buffer, void *row)
memcpy(buffer, kasan_mem_to_shadow(row

Re: [PATCH] kasan: remove redundant config option

2021-01-07 Thread Walter Wu
On Thu, 2021-01-07 at 14:00 -0700, Nathan Chancellor wrote:
> On Thu, Jan 07, 2021 at 02:21:52PM +0800, Walter Wu wrote:
> > CONFIG_KASAN_STACK and CONFIG_KASAN_STACK_ENABLE both enable KASAN
> > stack instrumentation, but we should only need one config option,
> > so that we remove CONFIG_KASAN_STACK_ENABLE. see [1].
> > 
> > For gcc we could do no prompt and default value y, and for clang
> > prompt and default value n.
> > 
> > [1]: https://bugzilla.kernel.org/show_bug.cgi?id=210221
> > 
> > Signed-off-by: Walter Wu 
> > Suggested-by: Dmitry Vyukov 
> > Cc: Andrey Ryabinin 
> > Cc: Dmitry Vyukov 
> > Cc: Andrey Konovalov 
> > Cc: Alexander Potapenko 
> > Cc: Andrew Morton 
> > ---
> >  arch/arm64/kernel/sleep.S|  2 +-
> >  arch/x86/kernel/acpi/wakeup_64.S |  2 +-
> >  include/linux/kasan.h|  2 +-
> >  lib/Kconfig.kasan| 11 ---
> >  mm/kasan/common.c|  2 +-
> >  mm/kasan/kasan.h |  2 +-
> >  mm/kasan/report_generic.c|  2 +-
> >  scripts/Makefile.kasan   | 10 --
> >  8 files changed, 18 insertions(+), 15 deletions(-)
> > 
> > diff --git a/arch/arm64/kernel/sleep.S b/arch/arm64/kernel/sleep.S
> > index 6bdef7362c0e..7c44ede122a9 100644
> > --- a/arch/arm64/kernel/sleep.S
> > +++ b/arch/arm64/kernel/sleep.S
> > @@ -133,7 +133,7 @@ SYM_FUNC_START(_cpu_resume)
> >  */
> > bl  cpu_do_resume
> >  
> > -#if defined(CONFIG_KASAN) && CONFIG_KASAN_STACK
> > +#if defined(CONFIG_KASAN) && defined(CONFIG_KASAN_STACK)
> > mov x0, sp
> > bl  kasan_unpoison_task_stack_below
> >  #endif
> > diff --git a/arch/x86/kernel/acpi/wakeup_64.S 
> > b/arch/x86/kernel/acpi/wakeup_64.S
> > index 5d3a0b8fd379..c7f412f4e07d 100644
> > --- a/arch/x86/kernel/acpi/wakeup_64.S
> > +++ b/arch/x86/kernel/acpi/wakeup_64.S
> > @@ -112,7 +112,7 @@ SYM_FUNC_START(do_suspend_lowlevel)
> > movqpt_regs_r14(%rax), %r14
> > movqpt_regs_r15(%rax), %r15
> >  
> > -#if defined(CONFIG_KASAN) && CONFIG_KASAN_STACK
> > +#if defined(CONFIG_KASAN) && defined(CONFIG_KASAN_STACK)
> > /*
> >  * The suspend path may have poisoned some areas deeper in the stack,
> >  * which we now need to unpoison.
> > diff --git a/include/linux/kasan.h b/include/linux/kasan.h
> > index 5e0655fb2a6f..35d1e9b2cbfa 100644
> > --- a/include/linux/kasan.h
> > +++ b/include/linux/kasan.h
> > @@ -302,7 +302,7 @@ static inline void kasan_kfree_large(void *ptr, 
> > unsigned long ip) {}
> >  
> >  #endif /* CONFIG_KASAN */
> >  
> > -#if defined(CONFIG_KASAN) && CONFIG_KASAN_STACK
> > +#if defined(CONFIG_KASAN) && defined(CONFIG_KASAN_STACK)
> >  void kasan_unpoison_task_stack(struct task_struct *task);
> >  #else
> >  static inline void kasan_unpoison_task_stack(struct task_struct *task) {}
> > diff --git a/lib/Kconfig.kasan b/lib/Kconfig.kasan
> > index f5fa4ba126bf..59de74293454 100644
> > --- a/lib/Kconfig.kasan
> > +++ b/lib/Kconfig.kasan
> > @@ -138,9 +138,11 @@ config KASAN_INLINE
> >  
> >  endchoice
> >  
> > -config KASAN_STACK_ENABLE
> > -   bool "Enable stack instrumentation (unsafe)" if CC_IS_CLANG && 
> > !COMPILE_TEST
> 
> You are effectively undoing commits 6baec880d7a5 ("kasan: turn off
> asan-stack for clang-8 and earlier") and ebb6d35a74ce ("kasan: remove
> clang version check for KASAN_STACK") with this change. This change
> should still remain around so that all{mod,yes}config remain mostly
> clean for clang builds. This should not change anything from the user's
> perspective because this option was never user selectable for GCC and
> the default y keeps it on.
> 

Ok, I will remain this.

> > +config KASAN_STACK
> > +   bool "Enable stack instrumentation (unsafe)"
> > depends on KASAN_GENERIC || KASAN_SW_TAGS
> > +   default y if CC_IS_GCC
> > +   default n if CC_IS_CLANG
> 
> This is implied and can be removed.
> 
> > help
> >   The LLVM stack address sanitizer has a know problem that
> >   causes excessive stack usage in a lot of functions, see
> > @@ -154,11 +156,6 @@ config KASAN_STACK_ENABLE
> >   CONFIG_COMPILE_TEST.  On gcc it is assumed to always be safe
> >   to use and enabled by default.
> >  
> > -config KASAN_STACK
> > -   int
> > -   default 1 if KASAN_STACK_ENABLE || CC_I

[PATCH v2] kasan: remove redundant config option

2021-01-06 Thread Walter Wu
CONFIG_KASAN_STACK and CONFIG_KASAN_STACK_ENABLE both enable KASAN stack
instrumentation, but we should only need one config, so that we remove
CONFIG_KASAN_STACK_ENABLE and make CONFIG_KASAN_STACK workable. see [1].

When enable KASAN stack instrumentation, then for gcc we could do no
prompt and default value y, and for clang prompt and default value n.

[1]: https://bugzilla.kernel.org/show_bug.cgi?id=210221

Signed-off-by: Walter Wu 
Suggested-by: Dmitry Vyukov 
Cc: Andrey Ryabinin 
Cc: Dmitry Vyukov 
Cc: Andrey Konovalov 
Cc: Alexander Potapenko 
Cc: Andrew Morton 
---

v2: make commit log to be more readable.

---
 arch/arm64/kernel/sleep.S|  2 +-
 arch/x86/kernel/acpi/wakeup_64.S |  2 +-
 include/linux/kasan.h|  2 +-
 lib/Kconfig.kasan| 11 ---
 mm/kasan/common.c|  2 +-
 mm/kasan/kasan.h |  2 +-
 mm/kasan/report_generic.c|  2 +-
 scripts/Makefile.kasan   | 10 --
 8 files changed, 18 insertions(+), 15 deletions(-)

diff --git a/arch/arm64/kernel/sleep.S b/arch/arm64/kernel/sleep.S
index 6bdef7362c0e..7c44ede122a9 100644
--- a/arch/arm64/kernel/sleep.S
+++ b/arch/arm64/kernel/sleep.S
@@ -133,7 +133,7 @@ SYM_FUNC_START(_cpu_resume)
 */
bl  cpu_do_resume
 
-#if defined(CONFIG_KASAN) && CONFIG_KASAN_STACK
+#if defined(CONFIG_KASAN) && defined(CONFIG_KASAN_STACK)
mov x0, sp
bl  kasan_unpoison_task_stack_below
 #endif
diff --git a/arch/x86/kernel/acpi/wakeup_64.S b/arch/x86/kernel/acpi/wakeup_64.S
index 5d3a0b8fd379..c7f412f4e07d 100644
--- a/arch/x86/kernel/acpi/wakeup_64.S
+++ b/arch/x86/kernel/acpi/wakeup_64.S
@@ -112,7 +112,7 @@ SYM_FUNC_START(do_suspend_lowlevel)
movqpt_regs_r14(%rax), %r14
movqpt_regs_r15(%rax), %r15
 
-#if defined(CONFIG_KASAN) && CONFIG_KASAN_STACK
+#if defined(CONFIG_KASAN) && defined(CONFIG_KASAN_STACK)
/*
 * The suspend path may have poisoned some areas deeper in the stack,
 * which we now need to unpoison.
diff --git a/include/linux/kasan.h b/include/linux/kasan.h
index 5e0655fb2a6f..35d1e9b2cbfa 100644
--- a/include/linux/kasan.h
+++ b/include/linux/kasan.h
@@ -302,7 +302,7 @@ static inline void kasan_kfree_large(void *ptr, unsigned 
long ip) {}
 
 #endif /* CONFIG_KASAN */
 
-#if defined(CONFIG_KASAN) && CONFIG_KASAN_STACK
+#if defined(CONFIG_KASAN) && defined(CONFIG_KASAN_STACK)
 void kasan_unpoison_task_stack(struct task_struct *task);
 #else
 static inline void kasan_unpoison_task_stack(struct task_struct *task) {}
diff --git a/lib/Kconfig.kasan b/lib/Kconfig.kasan
index f5fa4ba126bf..59de74293454 100644
--- a/lib/Kconfig.kasan
+++ b/lib/Kconfig.kasan
@@ -138,9 +138,11 @@ config KASAN_INLINE
 
 endchoice
 
-config KASAN_STACK_ENABLE
-   bool "Enable stack instrumentation (unsafe)" if CC_IS_CLANG && 
!COMPILE_TEST
+config KASAN_STACK
+   bool "Enable stack instrumentation (unsafe)"
depends on KASAN_GENERIC || KASAN_SW_TAGS
+   default y if CC_IS_GCC
+   default n if CC_IS_CLANG
help
  The LLVM stack address sanitizer has a know problem that
  causes excessive stack usage in a lot of functions, see
@@ -154,11 +156,6 @@ config KASAN_STACK_ENABLE
  CONFIG_COMPILE_TEST.  On gcc it is assumed to always be safe
  to use and enabled by default.
 
-config KASAN_STACK
-   int
-   default 1 if KASAN_STACK_ENABLE || CC_IS_GCC
-   default 0
-
 config KASAN_SW_TAGS_IDENTIFY
bool "Enable memory corruption identification"
depends on KASAN_SW_TAGS
diff --git a/mm/kasan/common.c b/mm/kasan/common.c
index 38ba2aecd8f4..02ec7f81dc16 100644
--- a/mm/kasan/common.c
+++ b/mm/kasan/common.c
@@ -63,7 +63,7 @@ void __kasan_unpoison_range(const void *address, size_t size)
unpoison_range(address, size);
 }
 
-#if CONFIG_KASAN_STACK
+#if defined(CONFIG_KASAN_STACK)
 /* Unpoison the entire stack for a task. */
 void kasan_unpoison_task_stack(struct task_struct *task)
 {
diff --git a/mm/kasan/kasan.h b/mm/kasan/kasan.h
index cc4d9e1d49b1..bdfdb1cff653 100644
--- a/mm/kasan/kasan.h
+++ b/mm/kasan/kasan.h
@@ -224,7 +224,7 @@ void *find_first_bad_addr(void *addr, size_t size);
 const char *get_bug_type(struct kasan_access_info *info);
 void metadata_fetch_row(char *buffer, void *row);
 
-#if defined(CONFIG_KASAN_GENERIC) && CONFIG_KASAN_STACK
+#if defined(CONFIG_KASAN_GENERIC) && defined(CONFIG_KASAN_STACK)
 void print_address_stack_frame(const void *addr);
 #else
 static inline void print_address_stack_frame(const void *addr) { }
diff --git a/mm/kasan/report_generic.c b/mm/kasan/report_generic.c
index 8a9c889872da..137a1dba1978 100644
--- a/mm/kasan/report_generic.c
+++ b/mm/kasan/report_generic.c
@@ -128,7 +128,7 @@ void metadata_fetch_row(char *buffer, void *row)
memcpy(buffer, kasan_mem_to_shadow(row), META_B

[PATCH] kasan: remove redundant config option

2021-01-06 Thread Walter Wu
CONFIG_KASAN_STACK and CONFIG_KASAN_STACK_ENABLE both enable KASAN
stack instrumentation, but we should only need one config option,
so that we remove CONFIG_KASAN_STACK_ENABLE. see [1].

For gcc we could do no prompt and default value y, and for clang
prompt and default value n.

[1]: https://bugzilla.kernel.org/show_bug.cgi?id=210221

Signed-off-by: Walter Wu 
Suggested-by: Dmitry Vyukov 
Cc: Andrey Ryabinin 
Cc: Dmitry Vyukov 
Cc: Andrey Konovalov 
Cc: Alexander Potapenko 
Cc: Andrew Morton 
---
 arch/arm64/kernel/sleep.S|  2 +-
 arch/x86/kernel/acpi/wakeup_64.S |  2 +-
 include/linux/kasan.h|  2 +-
 lib/Kconfig.kasan| 11 ---
 mm/kasan/common.c|  2 +-
 mm/kasan/kasan.h |  2 +-
 mm/kasan/report_generic.c|  2 +-
 scripts/Makefile.kasan   | 10 --
 8 files changed, 18 insertions(+), 15 deletions(-)

diff --git a/arch/arm64/kernel/sleep.S b/arch/arm64/kernel/sleep.S
index 6bdef7362c0e..7c44ede122a9 100644
--- a/arch/arm64/kernel/sleep.S
+++ b/arch/arm64/kernel/sleep.S
@@ -133,7 +133,7 @@ SYM_FUNC_START(_cpu_resume)
 */
bl  cpu_do_resume
 
-#if defined(CONFIG_KASAN) && CONFIG_KASAN_STACK
+#if defined(CONFIG_KASAN) && defined(CONFIG_KASAN_STACK)
mov x0, sp
bl  kasan_unpoison_task_stack_below
 #endif
diff --git a/arch/x86/kernel/acpi/wakeup_64.S b/arch/x86/kernel/acpi/wakeup_64.S
index 5d3a0b8fd379..c7f412f4e07d 100644
--- a/arch/x86/kernel/acpi/wakeup_64.S
+++ b/arch/x86/kernel/acpi/wakeup_64.S
@@ -112,7 +112,7 @@ SYM_FUNC_START(do_suspend_lowlevel)
movqpt_regs_r14(%rax), %r14
movqpt_regs_r15(%rax), %r15
 
-#if defined(CONFIG_KASAN) && CONFIG_KASAN_STACK
+#if defined(CONFIG_KASAN) && defined(CONFIG_KASAN_STACK)
/*
 * The suspend path may have poisoned some areas deeper in the stack,
 * which we now need to unpoison.
diff --git a/include/linux/kasan.h b/include/linux/kasan.h
index 5e0655fb2a6f..35d1e9b2cbfa 100644
--- a/include/linux/kasan.h
+++ b/include/linux/kasan.h
@@ -302,7 +302,7 @@ static inline void kasan_kfree_large(void *ptr, unsigned 
long ip) {}
 
 #endif /* CONFIG_KASAN */
 
-#if defined(CONFIG_KASAN) && CONFIG_KASAN_STACK
+#if defined(CONFIG_KASAN) && defined(CONFIG_KASAN_STACK)
 void kasan_unpoison_task_stack(struct task_struct *task);
 #else
 static inline void kasan_unpoison_task_stack(struct task_struct *task) {}
diff --git a/lib/Kconfig.kasan b/lib/Kconfig.kasan
index f5fa4ba126bf..59de74293454 100644
--- a/lib/Kconfig.kasan
+++ b/lib/Kconfig.kasan
@@ -138,9 +138,11 @@ config KASAN_INLINE
 
 endchoice
 
-config KASAN_STACK_ENABLE
-   bool "Enable stack instrumentation (unsafe)" if CC_IS_CLANG && 
!COMPILE_TEST
+config KASAN_STACK
+   bool "Enable stack instrumentation (unsafe)"
depends on KASAN_GENERIC || KASAN_SW_TAGS
+   default y if CC_IS_GCC
+   default n if CC_IS_CLANG
help
  The LLVM stack address sanitizer has a know problem that
  causes excessive stack usage in a lot of functions, see
@@ -154,11 +156,6 @@ config KASAN_STACK_ENABLE
  CONFIG_COMPILE_TEST.  On gcc it is assumed to always be safe
  to use and enabled by default.
 
-config KASAN_STACK
-   int
-   default 1 if KASAN_STACK_ENABLE || CC_IS_GCC
-   default 0
-
 config KASAN_SW_TAGS_IDENTIFY
bool "Enable memory corruption identification"
depends on KASAN_SW_TAGS
diff --git a/mm/kasan/common.c b/mm/kasan/common.c
index 38ba2aecd8f4..02ec7f81dc16 100644
--- a/mm/kasan/common.c
+++ b/mm/kasan/common.c
@@ -63,7 +63,7 @@ void __kasan_unpoison_range(const void *address, size_t size)
unpoison_range(address, size);
 }
 
-#if CONFIG_KASAN_STACK
+#if defined(CONFIG_KASAN_STACK)
 /* Unpoison the entire stack for a task. */
 void kasan_unpoison_task_stack(struct task_struct *task)
 {
diff --git a/mm/kasan/kasan.h b/mm/kasan/kasan.h
index cc4d9e1d49b1..bdfdb1cff653 100644
--- a/mm/kasan/kasan.h
+++ b/mm/kasan/kasan.h
@@ -224,7 +224,7 @@ void *find_first_bad_addr(void *addr, size_t size);
 const char *get_bug_type(struct kasan_access_info *info);
 void metadata_fetch_row(char *buffer, void *row);
 
-#if defined(CONFIG_KASAN_GENERIC) && CONFIG_KASAN_STACK
+#if defined(CONFIG_KASAN_GENERIC) && defined(CONFIG_KASAN_STACK)
 void print_address_stack_frame(const void *addr);
 #else
 static inline void print_address_stack_frame(const void *addr) { }
diff --git a/mm/kasan/report_generic.c b/mm/kasan/report_generic.c
index 8a9c889872da..137a1dba1978 100644
--- a/mm/kasan/report_generic.c
+++ b/mm/kasan/report_generic.c
@@ -128,7 +128,7 @@ void metadata_fetch_row(char *buffer, void *row)
memcpy(buffer, kasan_mem_to_shadow(row), META_BYTES_PER_ROW);
 }
 
-#if CONFIG_KASAN_STACK
+#if defined(CONFIG_KASAN_STACK)
 static bool __must_check tokenize_f

[PATCH] kasan: fix null pointer dereference in kasan_record_aux_stack

2020-12-28 Thread Walter Wu
Syzbot reported the following [1]:

 BUG: kernel NULL pointer dereference, address: 0008
 #PF: supervisor read access in kernel mode
 #PF: error_code(0x) - not-present page
 PGD 2d993067 P4D 2d993067 PUD 19a3c067 PMD 0
 Oops:  [#1] PREEMPT SMP KASAN
 CPU: 1 PID: 3852 Comm: kworker/1:2 Not tainted 5.10.0-syzkaller #0
 Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 
01/01/2011
 Workqueue: events free_ipc
 RIP: 0010:kasan_record_aux_stack+0x77/0xb0

Add null checking slab object from kasan_get_alloc_meta()
in order to avoid null pointer dereference.

[1] https://syzkaller.appspot.com/x/log.txt?x=10a82a50d0

Signed-off-by: Walter Wu 
Suggested-by: Dmitry Vyukov 
Cc: Andrey Ryabinin 
CC: Dmitry Vyukov 
CC: Andrey Konovalov 
Cc: Alexander Potapenko 
Cc: Andrew Morton 
---
 mm/kasan/generic.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/mm/kasan/generic.c b/mm/kasan/generic.c
index 1dd5a0f99372..5106b84b07d4 100644
--- a/mm/kasan/generic.c
+++ b/mm/kasan/generic.c
@@ -337,6 +337,8 @@ void kasan_record_aux_stack(void *addr)
cache = page->slab_cache;
object = nearest_obj(cache, page, addr);
alloc_meta = kasan_get_alloc_meta(cache, object);
+   if (!alloc_meta)
+   return;
 
alloc_meta->aux_stack[1] = alloc_meta->aux_stack[0];
alloc_meta->aux_stack[0] = kasan_save_stack(GFP_NOWAIT);
-- 
2.18.0



Re: BUG: unable to handle kernel NULL pointer dereference in call_rcu

2020-12-27 Thread Walter Wu
On Sun, 2020-12-27 at 20:51 +0100, Dmitry Vyukov wrote:
> /\/\/\/\On Sun, Dec 27, 2020 at 8:45 PM Andrew Morton
>  wrote:
> >
> > (cc KASAN developers)
> >
> > On Sat, 26 Dec 2020 15:25:14 -0800 syzbot 
> >  wrote:
> >
> > > Hello,
> > >
> > > syzbot found the following issue on:
> > >
> > > HEAD commit:614cb589 Merge tag 'acpi-5.11-rc1-2' of 
> > > git://git.kernel.o..
> > > git tree:   upstream
> > > console output: https://syzkaller.appspot.com/x/log.txt?x=10a82a50d0
> > > kernel config:  https://syzkaller.appspot.com/x/.config?x=bf519e1e96191576
> > > dashboard link: 
> > > https://syzkaller.appspot.com/bug?extid=9d3ede723bdc58553f13
> > > compiler:   gcc (GCC) 10.1.0-syz 20200507
> > > syz repro:  https://syzkaller.appspot.com/x/repro.syz?x=11830e9350
> > > C reproducer:   https://syzkaller.appspot.com/x/repro.c?x=13d9205750
> > >
> > > IMPORTANT: if you fix the issue, please add the following tag to the 
> > > commit:
> > > Reported-by: syzbot+9d3ede723bdc58553...@syzkaller.appspotmail.com
> > >
> > > BUG: kernel NULL pointer dereference, address: 0008
> > > #PF: supervisor read access in kernel mode
> > > #PF: error_code(0x) - not-present page
> > > PGD 2d993067 P4D 2d993067 PUD 19a3c067 PMD 0
> > > Oops:  [#1] PREEMPT SMP KASAN
> > > CPU: 1 PID: 3852 Comm: kworker/1:2 Not tainted 5.10.0-syzkaller #0
> > > Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS 
> > > Google 01/01/2011
> > > Workqueue: events free_ipc
> > > RIP: 0010:kasan_record_aux_stack+0x77/0xb0 mm/kasan/generic.c:341
> 
> +Walter, Andrey
> 
> void kasan_record_aux_stack(void *addr)
> {
> ...
> alloc_meta = kasan_get_alloc_meta(cache, object);
> alloc_meta->aux_stack[1] = alloc_meta->aux_stack[0];
> 
> /\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\
> It crashes on NULL deref here, I assume alloc_meta is NULL. We may not
> have it for some slabs. Do we miss a NULL check here?
> 
Hi Dmitry,

Yes, I will send a patch to fix it.

Thanks for your suggestion.

Walter

> 
> 
> 
> > > Code: 48 f7 fe 8b 47 24 49 89 f0 48 29 d3 8d 70 ff 41 0f af f0 48 01 ce 
> > > 48 39 f3 48 0f 46 f3 e8 81 e9 ff ff bf 00 08 00 00 48 89 c3 <8b> 40 08 89 
> > > 43 0c e8 1e e6 ff ff 89 43 08 5b c3 48 8b 50 08 48 c7
> > > RSP: 0018:c90002e6fae8 EFLAGS: 00010046
> > > RAX:  RBX:  RCX: 88803980
> > > RDX: 0078 RSI: 88803980 RDI: 0800
> > > RBP: 837ef3a0 R08: 0040 R09: 002e
> > > R10: 8132b7ea R11: 003f R12: 00035b40
> > > R13: 888039800088 R14: c90002e6fc08 R15: 0200
> > > FS:  () GS:8880b9d0() 
> > > knlGS:
> > > CS:  0010 DS:  ES:  CR0: 80050033
> > > CR2: 0008 CR3: 11841000 CR4: 001506e0
> > > DR0:  DR1:  DR2: 
> > > DR3:  DR6: fffe0ff0 DR7: 0400
> > > Call Trace:
> > >  __call_rcu kernel/rcu/tree.c:2965 [inline]
> > >  call_rcu+0xbb/0x710 kernel/rcu/tree.c:3038
> > >  ipc_rcu_putref+0x83/0xb0 ipc/util.c:505
> > >  freeary+0x139c/0x1b30 ipc/sem.c:1188
> > >  free_ipcs+0x98/0x1e0 ipc/namespace.c:112
> > >  sem_exit_ns+0x1b/0x40 ipc/sem.c:260
> > >  free_ipc_ns ipc/namespace.c:124 [inline]
> > >  free_ipc+0xf8/0x200 ipc/namespace.c:141
> > >  process_one_work+0x98d/0x1630 kernel/workqueue.c:2275
> > >  worker_thread+0x64c/0x1120 kernel/workqueue.c:2421
> > >  kthread+0x3b1/0x4a0 kernel/kthread.c:292
> > >  ret_from_fork+0x1f/0x30 arch/x86/entry/entry_64.S:296
> > > Modules linked in:
> > > CR2: 0008
> > > ---[ end trace 28dc093e61d44dc2 ]---
> > > RIP: 0010:kasan_record_aux_stack+0x77/0xb0 mm/kasan/generic.c:341
> > > Code: 48 f7 fe 8b 47 24 49 89 f0 48 29 d3 8d 70 ff 41 0f af f0 48 01 ce 
> > > 48 39 f3 48 0f 46 f3 e8 81 e9 ff ff bf 00 08 00 00 48 89 c3 <8b> 40 08 89 
> > > 43 0c e8 1e e6 ff ff 89 43 08 5b c3 48 8b 50 08 48 c7
> > > RSP: 0018:c90002e6fae8 EFLAGS: 00010046
> > > RAX:  RBX:  RCX: 88803980
> > > RDX: 0078 RSI: 88803980 RDI: 0800
> > > RBP: 837ef3a0 R08: 0040 R09: 002e
> > > R10: 8132b7ea R11: 003f R12: 00035b40
> > > R13: 888039800088 R14: c90002e6fc08 R15: 0200
> > > FS:  () GS:8880b9d0() 
> > > knlGS:
> > > CS:  0010 DS:  ES:  CR0: 80050033
> > > CR2: 0008 CR3: 11841000 CR4: 001506e0
> > > DR0:  DR1:  DR2: 
> > > DR3:  DR6: fffe0ff0 DR7: 0400
> > >
> > >
> > > ---
> > > This report is generated by a bot. It may contain errors.
> > > See https://goo.gl/tpsmEJ for more information about syzbot.
> > > syzbot 

Re: [PATCH v5 3/4] lib/test_kasan.c: add workqueue test case

2020-12-03 Thread Walter Wu
On Thu, 2020-12-03 at 11:29 +0100, Marco Elver wrote:
> On Thu, 3 Dec 2020 at 03:27, Walter Wu  wrote:
> >
> > Adds a test to verify workqueue stack recording and print it in
> > KASAN report.
> >
> > The KASAN report was as follows(cleaned up slightly):
> >
> >  BUG: KASAN: use-after-free in kasan_workqueue_uaf
> >
> >  Freed by task 54:
> >   kasan_save_stack+0x24/0x50
> >   kasan_set_track+0x24/0x38
> >   kasan_set_free_info+0x20/0x40
> >   __kasan_slab_free+0x10c/0x170
> >   kasan_slab_free+0x10/0x18
> >   kfree+0x98/0x270
> >   kasan_workqueue_work+0xc/0x18
> >
> >  Last potentially related work creation:
> >   kasan_save_stack+0x24/0x50
> >   kasan_record_wq_stack+0xa8/0xb8
> >   insert_work+0x48/0x288
> >   __queue_work+0x3e8/0xc40
> >   queue_work_on+0xf4/0x118
> >   kasan_workqueue_uaf+0xfc/0x190
> >
> > Signed-off-by: Walter Wu 
> > Acked-by: Marco Elver 
> > Reviewed-by: Dmitry Vyukov 
> > Reviewed-by: Andrey Konovalov 
> > Cc: Andrey Ryabinin 
> > Cc: Alexander Potapenko 
> > Cc: Matthias Brugger 
> > ---
> >
> > v4:
> > - testcase has merge conflict, so that rebase onto the KASAN-KUNIT
> >
> > ---
> >  lib/test_kasan_module.c | 29 +
> >  1 file changed, 29 insertions(+)
> >
> > diff --git a/lib/test_kasan_module.c b/lib/test_kasan_module.c
> > index 2d68db6ae67b..62a87854b120 100644
> > --- a/lib/test_kasan_module.c
> > +++ b/lib/test_kasan_module.c
> > @@ -91,6 +91,34 @@ static noinline void __init kasan_rcu_uaf(void)
> > call_rcu(_rcu_ptr->rcu, kasan_rcu_reclaim);
> >  }
> >
> > +static noinline void __init kasan_workqueue_work(struct work_struct *work)
> > +{
> > +   kfree(work);
> > +}
> > +
> > +static noinline void __init kasan_workqueue_uaf(void)
> > +{
> > +   struct workqueue_struct *workqueue;
> > +   struct work_struct *work;
> > +
> > +   workqueue = create_workqueue("kasan_wq_test");
> > +   if (!workqueue) {
> > +   pr_err("Allocation failed\n");
> > +   return;
> > +   }
> > +   work = kmalloc(sizeof(struct work_struct), GFP_KERNEL);
> > +   if (!work) {
> > +   pr_err("Allocation failed\n");
> > +   return;
> > +   }
> > +
> > +   INIT_WORK(work, kasan_workqueue_work);
> > +   queue_work(workqueue, work);
> > +   destroy_workqueue(workqueue);
> > +
> > +   pr_info("use-after-free on workqueue\n");
> > +   ((volatile struct work_struct *)work)->data;
> > +}
> >
> >  static int __init test_kasan_module_init(void)
> >  {
> > @@ -102,6 +130,7 @@ static int __init test_kasan_module_init(void)
> >
> > copy_user_test();
> > kasan_rcu_uaf();
> > +   kasan_workqueue_uaf();
> 
> 
> Why can't this go into the KUnit based KASAN test?

This test case has not been ported to KUnit, because KUnit's expect
failure will not check whether the work stack is exist. So it remains in
test_kasan_module, it is the same with kasan_rcu_uaf()[1].

[1]https://lkml.org/lkml/2020/8/1/45

Thanks.
Walter





[PATCH v5 4/4] kasan: update documentation for generic kasan

2020-12-02 Thread Walter Wu
Generic KASAN also supports to record the last two workqueue
stacks and print them in KASAN report. So that need to update
documentation.

Signed-off-by: Walter Wu 
Suggested-by: Marco Elver 
Acked-by: Marco Elver 
Reviewed-by: Dmitry Vyukov 
Reviewed-by: Andrey Konovalov 
Cc: Andrey Ryabinin 
Cc: Alexander Potapenko 
Cc: Jonathan Corbet 
---

v4:
- remove timer stack description

v3:
- Thanks for Marco suggestion

---
 Documentation/dev-tools/kasan.rst | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/Documentation/dev-tools/kasan.rst 
b/Documentation/dev-tools/kasan.rst
index c09c9ca2ff1c..3cb556ceb4a5 100644
--- a/Documentation/dev-tools/kasan.rst
+++ b/Documentation/dev-tools/kasan.rst
@@ -190,8 +190,9 @@ function calls GCC directly inserts the code to check the 
shadow memory.
 This option significantly enlarges kernel but it gives x1.1-x2 performance
 boost over outline instrumented kernel.
 
-Generic KASAN prints up to 2 call_rcu() call stacks in reports, the last one
-and the second to last.
+Generic KASAN also reports the last 2 call stacks to creation of work that
+potentially has access to an object. Call stacks for the following are shown:
+call_rcu() and workqueue queuing.
 
 Software tag-based KASAN
 
-- 
2.18.0



[PATCH v5 3/4] lib/test_kasan.c: add workqueue test case

2020-12-02 Thread Walter Wu
Adds a test to verify workqueue stack recording and print it in
KASAN report.

The KASAN report was as follows(cleaned up slightly):

 BUG: KASAN: use-after-free in kasan_workqueue_uaf

 Freed by task 54:
  kasan_save_stack+0x24/0x50
  kasan_set_track+0x24/0x38
  kasan_set_free_info+0x20/0x40
  __kasan_slab_free+0x10c/0x170
  kasan_slab_free+0x10/0x18
  kfree+0x98/0x270
  kasan_workqueue_work+0xc/0x18

 Last potentially related work creation:
  kasan_save_stack+0x24/0x50
  kasan_record_wq_stack+0xa8/0xb8
  insert_work+0x48/0x288
  __queue_work+0x3e8/0xc40
  queue_work_on+0xf4/0x118
  kasan_workqueue_uaf+0xfc/0x190

Signed-off-by: Walter Wu 
Acked-by: Marco Elver 
Reviewed-by: Dmitry Vyukov 
Reviewed-by: Andrey Konovalov 
Cc: Andrey Ryabinin 
Cc: Alexander Potapenko 
Cc: Matthias Brugger 
---

v4:
- testcase has merge conflict, so that rebase onto the KASAN-KUNIT

---
 lib/test_kasan_module.c | 29 +
 1 file changed, 29 insertions(+)

diff --git a/lib/test_kasan_module.c b/lib/test_kasan_module.c
index 2d68db6ae67b..62a87854b120 100644
--- a/lib/test_kasan_module.c
+++ b/lib/test_kasan_module.c
@@ -91,6 +91,34 @@ static noinline void __init kasan_rcu_uaf(void)
call_rcu(_rcu_ptr->rcu, kasan_rcu_reclaim);
 }
 
+static noinline void __init kasan_workqueue_work(struct work_struct *work)
+{
+   kfree(work);
+}
+
+static noinline void __init kasan_workqueue_uaf(void)
+{
+   struct workqueue_struct *workqueue;
+   struct work_struct *work;
+
+   workqueue = create_workqueue("kasan_wq_test");
+   if (!workqueue) {
+   pr_err("Allocation failed\n");
+   return;
+   }
+   work = kmalloc(sizeof(struct work_struct), GFP_KERNEL);
+   if (!work) {
+   pr_err("Allocation failed\n");
+   return;
+   }
+
+   INIT_WORK(work, kasan_workqueue_work);
+   queue_work(workqueue, work);
+   destroy_workqueue(workqueue);
+
+   pr_info("use-after-free on workqueue\n");
+   ((volatile struct work_struct *)work)->data;
+}
 
 static int __init test_kasan_module_init(void)
 {
@@ -102,6 +130,7 @@ static int __init test_kasan_module_init(void)
 
copy_user_test();
kasan_rcu_uaf();
+   kasan_workqueue_uaf();
 
kasan_restore_multi_shot(multishot);
return -EAGAIN;
-- 
2.18.0



[PATCH v5 2/4] kasan: print workqueue stack

2020-12-02 Thread Walter Wu
The aux_stack[2] is reused to record the call_rcu() call stack
and enqueuing work call stacks. So that we need to change the
auxiliary stack title for common title, print them in KASAN report.

Signed-off-by: Walter Wu 
Suggested-by: Marco Elver 
Acked-by: Marco Elver 
Reviewed-by: Dmitry Vyukov 
Reviewed-by: Andrey Konovalov 
Cc: Andrey Ryabinin 
Cc: Alexander Potapenko 
---

v4:
- remove a mention of call_rcu() at kasan_record_aux_stack()
  Thanks for Alexander reminder.

v2:
- Thanks for Marco suggestion.
- We modify aux stack title name in KASAN report
  in order to print call_rcu()/timer/workqueue stack.

---
 mm/kasan/generic.c | 3 ---
 mm/kasan/report.c  | 4 ++--
 2 files changed, 2 insertions(+), 5 deletions(-)

diff --git a/mm/kasan/generic.c b/mm/kasan/generic.c
index 248264b9cb76..30c0a5038b5c 100644
--- a/mm/kasan/generic.c
+++ b/mm/kasan/generic.c
@@ -339,9 +339,6 @@ void kasan_record_aux_stack(void *addr)
object = nearest_obj(cache, page, addr);
alloc_info = get_alloc_info(cache, object);
 
-   /*
-* record the last two call_rcu() call stacks.
-*/
alloc_info->aux_stack[1] = alloc_info->aux_stack[0];
alloc_info->aux_stack[0] = kasan_save_stack(GFP_NOWAIT);
 }
diff --git a/mm/kasan/report.c b/mm/kasan/report.c
index 00a53f1355ae..5a0102f37171 100644
--- a/mm/kasan/report.c
+++ b/mm/kasan/report.c
@@ -185,12 +185,12 @@ static void describe_object(struct kmem_cache *cache, 
void *object,
 
 #ifdef CONFIG_KASAN_GENERIC
if (alloc_info->aux_stack[0]) {
-   pr_err("Last call_rcu():\n");
+   pr_err("Last potentially related work creation:\n");
print_stack(alloc_info->aux_stack[0]);
pr_err("\n");
}
if (alloc_info->aux_stack[1]) {
-   pr_err("Second to last call_rcu():\n");
+   pr_err("Second to last potentially related work 
creation:\n");
print_stack(alloc_info->aux_stack[1]);
pr_err("\n");
}
-- 
2.18.0



[PATCH v5 1/4] workqueue: kasan: record workqueue stack

2020-12-02 Thread Walter Wu
When analyze use-after-free or double-free issue, recording the
enqueuing work stacks is helpful to preserve usage history which
potentially gives a hint about the affected code.

For workqueue it has turned out to be useful to record the enqueuing
work call stacks. Because user can see KASAN report to determine
whether it is root cause. They don't need to enable debugobjects,
but they have a chance to find out the root cause.

Signed-off-by: Walter Wu 
Suggested-by: Marco Elver 
Acked-by: Marco Elver 
Acked-by: Tejun Heo 
Reviewed-by: Dmitry Vyukov 
Reviewed-by: Andrey Konovalov 
Cc: Andrey Ryabinin 
Cc: Alexander Potapenko 
Cc: Lai Jiangshan 
---

v2:
- Thanks for Marco suggestion.
- Remove unnecessary code
- reuse kasan_record_aux_stack() and aux_stack
  to record timer and workqueue stack

---
 kernel/workqueue.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/kernel/workqueue.c b/kernel/workqueue.c
index c41c3c17b86a..9dd65ac60d6e 100644
--- a/kernel/workqueue.c
+++ b/kernel/workqueue.c
@@ -1324,6 +1324,9 @@ static void insert_work(struct pool_workqueue *pwq, 
struct work_struct *work,
 {
struct worker_pool *pool = pwq->pool;
 
+   /* record the work call stack in order to print it in KASAN reports */
+   kasan_record_aux_stack(work);
+
/* we own @work, set data and link */
set_work_pwq(work, pwq, extra_flags);
list_add_tail(>entry, head);
-- 
2.18.0



[PATCH v5 0/4] kasan: add workqueue stack for generic KASAN

2020-12-02 Thread Walter Wu
Syzbot reports many UAF issues for workqueue, see [1].
In some of these access/allocation happened in process_one_work(),
we see the free stack is useless in KASAN report, it doesn't help
programmers to solve UAF for workqueue issue.

This patchset improves KASAN reports by making them to have workqueue
queueing stack. It is useful for programmers to solve use-after-free
or double-free memory issue.

Generic KASAN also records the last two workqueue stacks and prints
them in KASAN report. It is only suitable for generic KASAN.

[1]https://groups.google.com/g/syzkaller-bugs/search?q=%22use-after-free%22+process_one_work
[2]https://bugzilla.kernel.org/show_bug.cgi?id=198437

Walter Wu (4):
workqueue: kasan: record workqueue stack
kasan: print workqueue stack
lib/test_kasan.c: add workqueue test case
kasan: update documentation for generic kasan

---
Changes since v4:
- Not found timer use case, so that remove timer patch
- remove a mention of call_rcu() from the kasan_record_aux_stack()
  Thanks for Dmitry and Alexander suggestion.

Changes since v3:
- testcases have merge conflict, so that need to
  be rebased onto the KASAN-KUNIT.

Changes since v2:
- modify kasan document to be readable,
  Thanks for Marco suggestion.

Changes since v1:
- Thanks for Marco and Thomas suggestion.
- Remove unnecessary code and fix commit log
- reuse kasan_record_aux_stack() and aux_stack
  to record timer and workqueue stack.
- change the aux stack title for common name.

---
Documentation/dev-tools/kasan.rst |  5 +++--
kernel/workqueue.c|  3 +++
lib/test_kasan_module.c   | 29 +
mm/kasan/generic.c|  4 +---
mm/kasan/report.c |  4 ++--
5 files changed, 38 insertions(+), 7 deletions(-)


Re: [PATCH v4 0/6] kasan: add workqueue and timer stack for generic KASAN

2020-12-01 Thread Walter Wu
On Tue, 2020-12-01 at 15:02 +0100, 'Dmitry Vyukov' via kasan-dev wrote:
> On Tue, Dec 1, 2020 at 12:17 PM Walter Wu  wrote:
> >
> > Hi Dmitry,
> >
> > On Tue, 2020-12-01 at 08:59 +0100, 'Dmitry Vyukov' via kasan-dev wrote:
> > > On Wed, Sep 30, 2020 at 5:29 PM Thomas Gleixner  
> > > wrote:
> > > >
> > > > On Thu, Sep 24 2020 at 12:01, Walter Wu wrote:
> > > > > Syzbot reports many UAF issues for workqueue or timer, see [1] and 
> > > > > [2].
> > > > > In some of these access/allocation happened in process_one_work(),
> > > > > we see the free stack is useless in KASAN report, it doesn't help
> > > > > programmers to solve UAF on workqueue. The same may stand for times.
> > > > >
> > > > > This patchset improves KASAN reports by making them to have workqueue
> > > > > queueing stack and timer stack information. It is useful for 
> > > > > programmers
> > > > > to solve use-after-free or double-free memory issue.
> > > > >
> > > > > Generic KASAN also records the last two workqueue and timer stacks and
> > > > > prints them in KASAN report. It is only suitable for generic KASAN.
> > >
> > > Walter, did you mail v5?
> > > Checking statuses of KASAN issues and this seems to be not in linux-next.
> > >
> >
> > Sorry for the delay in responding to this patch. I'm busy these few
> > months, so that suspend processing it.
> > Yes, I will send it next week. But v4 need to confirm the timer stack is
> > useful. I haven't found an example. Do you have some suggestion about
> > timer?
> 
> Good question.
> 
> We had some use-after-free's what mention call_timer_fn:
> https://groups.google.com/g/syzkaller-bugs/search?q=%22kasan%22%20%22use-after-free%22%20%22expire_timers%22%20%22call_timer_fn%22%20
> In the reports I checked call_timer_fn appears in the "access" stack
> rather in the "free" stack.
> 
Yes, call stack already is useful for it in KASAN report.

> Looking at these reports I cannot conclude that do_init_timer stack
> would be useful.
> I am mildly leaning towards not memorizing do_init_timer stack for now
> (until we have clear use cases) as the number of aux stacks is very
> limited (2).
> 
Got it. I will remove timer patch and send v5.
Thanks for your suggestion.

Walter



Re: [PATCH v4 0/6] kasan: add workqueue and timer stack for generic KASAN

2020-12-01 Thread Walter Wu
Hi Dmitry,

On Tue, 2020-12-01 at 08:59 +0100, 'Dmitry Vyukov' via kasan-dev wrote:
> On Wed, Sep 30, 2020 at 5:29 PM Thomas Gleixner  wrote:
> >
> > On Thu, Sep 24 2020 at 12:01, Walter Wu wrote:
> > > Syzbot reports many UAF issues for workqueue or timer, see [1] and [2].
> > > In some of these access/allocation happened in process_one_work(),
> > > we see the free stack is useless in KASAN report, it doesn't help
> > > programmers to solve UAF on workqueue. The same may stand for times.
> > >
> > > This patchset improves KASAN reports by making them to have workqueue
> > > queueing stack and timer stack information. It is useful for programmers
> > > to solve use-after-free or double-free memory issue.
> > >
> > > Generic KASAN also records the last two workqueue and timer stacks and
> > > prints them in KASAN report. It is only suitable for generic KASAN.
> 
> Walter, did you mail v5?
> Checking statuses of KASAN issues and this seems to be not in linux-next.
> 

Sorry for the delay in responding to this patch. I'm busy these few
months, so that suspend processing it.
Yes, I will send it next week. But v4 need to confirm the timer stack is
useful. I haven't found an example. Do you have some suggestion about
timer?

Thanks.
Walter

> > > [1]https://groups.google.com/g/syzkaller-bugs/search?q=%22use-after-free%22+process_one_work
> > > [2]https://groups.google.com/g/syzkaller-bugs/search?q=%22use-after-free%22%20expire_timers
> >
> > How are these links useful for people who do not have a gurgle account?
> 
> This is a public mailing list archive, so effectively the same way as
> lore links ;)
> 



Re: [PATCH v4 1/6] timer: kasan: record timer stack

2020-09-26 Thread Walter Wu
Hi Thomas,

On Sat, 2020-09-26 at 00:59 +0200, Thomas Gleixner wrote:
> On Fri, Sep 25 2020 at 17:15, Walter Wu wrote:
> > On Fri, 2020-09-25 at 10:55 +0200, Thomas Gleixner wrote:
> >> > We don't want to replace DEBUG_OBJECTS_TIMERS with this patches, only
> >> > hope to use low overhead(compare with DEBUG_OBJECTS_TIMERS) to debug
> >> 
> >> KASAN has lower overhead than DEBUG_OBJECTS_TIMERS? Maybe in a different
> >> universe.
> >> 
> > I mean KASAN + our patch vs KASAN + DEBUG_OBJECTS_TIMERS. The front one
> > have the information to the original caller and help to debug. It is
> > smaller overhead than the one behind.
> 
> For ONE specific problem related to timers and you have still not shown
> a single useful debug output where this information helps to debug
> anything.
> 
> > I agree your saying, so that I need to find out a use case to explain to
> > you.
> 
> Indeed.
> 

First, I think the commit log “Because if the UAF root cause is in timer
init …” needs to be removed, this patch hopes to help programmer gets
timer callback is where is registered. It is useful only if free stack
is called from timer callback, because programmer can see why & where
register this function.

Second, see [1], it should satisfies first point. The free stack is from
timer callback, if we know where register this function, then it should
be useful to solve UAF.

[1]https://lore.kernel.org/linux-usb/590f6b05a1c05...@google.com/



Thanks

Walter





> Thanks,
> 
> tglx
> 



Re: [PATCH v4 1/6] timer: kasan: record timer stack

2020-09-25 Thread Walter Wu
On Fri, 2020-09-25 at 10:55 +0200, Thomas Gleixner wrote:
> Walter,
> 
> On Fri, Sep 25 2020 at 15:18, Walter Wu wrote:
> > On Thu, 2020-09-24 at 23:41 +0200, Thomas Gleixner wrote:
> >> > For timers it has turned out to be useful to record the stack trace
> >> > of the timer init call.
> >> 
> >> In which way? And what kind of bug does it catch which cannot be catched
> >> by existing debug mechanisms already?
> >> 
> > We only provide another debug mechanisms to debug use-after-free or
> > double-free, it can be displayed together in KASAN report and have a
> > chance to debug, and it doesn't need to enable existing debug mechanisms
> > at the same time. then it has a chance to resolve issue.
> 
> Again. KASAN can only cover UAF, but there are a dozen other ways to
> wreck the system with wrong usage of timers which can't be caught by
> KASAN.
> 
> >> > Because if the UAF root cause is in timer init, then user can see
> >> > KASAN report to get where it is registered and find out the root
> >> > cause.
> >> 
> >> What? If the UAF root cause is in timer init, then registering it after
> >> using it in that very same function is pretty pointless.
> >> 
> > See [1], the call stack shows UAF happen at dummy_timer(), it is the
> > callback function and set by timer_setup(), if KASAN report shows the
> > timer call stack, it should be useful for programmer.
> 
> The report you linked to has absolutely nothing to do with a timer
> related UAF. The timer callback calls kfree_skb() on something which is
> already freed. So the root cause of this is NOT in timer init as you
> claimed above. The timer callback is just exposing a problem in the URB
> management of this driver. IOW the recording of the timer init stack is
> completely useless for decoding this problem.
> 
> >> There is a lot of handwaving how useful this is, but TBH I don't see the
> >> value at all.
> >> 
> >> DEBUG_OBJECTS_TIMERS does a lot more than crashing on UAF. If KASAN
> >> provides additional value over DEBUG_OBJECTS_TIMERS then spell it out,
> >> but just saying that you don't need to enable DEBUG_OBJECTS_TIMERS is
> >> not making an argument for that change.
> >> 
> > We don't want to replace DEBUG_OBJECTS_TIMERS with this patches, only
> > hope to use low overhead(compare with DEBUG_OBJECTS_TIMERS) to debug
> 
> KASAN has lower overhead than DEBUG_OBJECTS_TIMERS? Maybe in a different
> universe.
> 

I mean KASAN + our patch vs KASAN + DEBUG_OBJECTS_TIMERS. The front one
have the information to the original caller and help to debug. It is
smaller overhead than the one behind.

> That said, I'm not opposed to the change per se, but without a sensible
> justification this is just pointless.
> 
> Sprinkling kasan_foo() all over the place and claiming it's useful
> without a valid example does not provide any value.
> 
> Quite the contrary it gives the completely wrong sense what KASAN can do
> and what not.
> 

I agree your saying, so that I need to find out a use case to explain to
you.

Thanks

Walter

> Thanks,
> 
> tglx
> 



Re: [PATCH v4 1/6] timer: kasan: record timer stack

2020-09-25 Thread Walter Wu
On Thu, 2020-09-24 at 23:41 +0200, Thomas Gleixner wrote:
> On Thu, Sep 24 2020 at 12:03, Walter Wu wrote:
> > When analyze use-after-free or double-free issue, recording the timer
> > stacks is helpful to preserve usage history which potentially gives
> > a hint about the affected code.
> >
> > Record the most recent two timer init calls in KASAN which are printed
> > on failure in the KASAN report.
> >
> > For timers it has turned out to be useful to record the stack trace
> > of the timer init call.
> 
> In which way? And what kind of bug does it catch which cannot be catched
> by existing debug mechanisms already?
> 

We only provide another debug mechanisms to debug use-after-free or
double-free, it can be displayed together in KASAN report and have a
chance to debug, and it doesn't need to enable existing debug mechanisms
at the same time. then it has a chance to resolve issue.

> > Because if the UAF root cause is in timer init, then user can see
> > KASAN report to get where it is registered and find out the root
> > cause.
> 
> What? If the UAF root cause is in timer init, then registering it after
> using it in that very same function is pretty pointless.
> 

See [1], the call stack shows UAF happen at dummy_timer(), it is the
callback function and set by timer_setup(), if KASAN report shows the
timer call stack, it should be useful for programmer.

[1]
https://syzkaller.appspot.com/bug?id=34e69b7c8c0165658cbc987da0b61dadec644b6b


> > It don't need to enable DEBUG_OBJECTS_TIMERS, but they have a chance
> > to find out the root cause.
> 
> There is a lot of handwaving how useful this is, but TBH I don't see the
> value at all.
> 
> DEBUG_OBJECTS_TIMERS does a lot more than crashing on UAF. If KASAN
> provides additional value over DEBUG_OBJECTS_TIMERS then spell it out,
> but just saying that you don't need to enable DEBUG_OBJECTS_TIMERS is
> not making an argument for that change.
> 

We don't want to replace DEBUG_OBJECTS_TIMERS with this patches, only
hope to use low overhead(compare with DEBUG_OBJECTS_TIMERS) to debug
use-after-free/double-free issue. If you have some concerns, we can add
those message into commit log.

Thanks.

Walter


Re: [PATCH v4 0/6] kasan: add workqueue and timer stack for generic KASAN

2020-09-24 Thread Walter Wu
On Thu, 2020-09-24 at 13:51 +0200, 'Alexander Potapenko' via kasan-dev
wrote:
> > ---
> > Documentation/dev-tools/kasan.rst |  5 +++--
> > kernel/time/timer.c   |  3 +++
> > kernel/workqueue.c|  3 +++
> > lib/test_kasan_module.c   | 55 
> > +++
> > mm/kasan/report.c |  4 ++--
> > 5 files changed, 66 insertions(+), 4 deletions(-)
> 
> While at it, can you remove a mention of call_rcu() from the
> kasan_record_aux_stack() implementation, as it is no more
> RCU-specific?
> 

Thank you for your reminder. v5 will do it. 

Walter


[PATCH v4 6/6] kasan: update documentation for generic kasan

2020-09-23 Thread Walter Wu
Generic KASAN also supports to record the last two timer and workqueue
stacks and print them in KASAN report. So that need to update
documentation.

Signed-off-by: Walter Wu 
Suggested-by: Marco Elver 
Acked-by: Marco Elver 
Reviewed-by: Dmitry Vyukov 
Reviewed-by: Andrey Konovalov 
Cc: Andrey Ryabinin 
Cc: Alexander Potapenko 
Cc: Jonathan Corbet 
---

v3:
- Thanks for Marco suggestion

---
 Documentation/dev-tools/kasan.rst | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/Documentation/dev-tools/kasan.rst 
b/Documentation/dev-tools/kasan.rst
index 38fd5681fade..698ccb65e634 100644
--- a/Documentation/dev-tools/kasan.rst
+++ b/Documentation/dev-tools/kasan.rst
@@ -190,8 +190,9 @@ function calls GCC directly inserts the code to check the 
shadow memory.
 This option significantly enlarges kernel but it gives x1.1-x2 performance
 boost over outline instrumented kernel.
 
-Generic KASAN prints up to 2 call_rcu() call stacks in reports, the last one
-and the second to last.
+Generic KASAN also reports the last 2 call stacks to creation of work that
+potentially has access to an object. Call stacks for the following are shown:
+call_rcu(), timer and workqueue queuing.
 
 Software tag-based KASAN
 
-- 
2.18.0


[PATCH v4 3/6] kasan: print timer and workqueue stack

2020-09-23 Thread Walter Wu
The aux_stack[2] is reused to record the call_rcu() call stack,
timer init call stack, and enqueuing work call stacks. So that
we need to change the auxiliary stack title for common title,
print them in KASAN report.

Signed-off-by: Walter Wu 
Suggested-by: Marco Elver 
Acked-by: Marco Elver 
Reviewed-by: Dmitry Vyukov 
Reviewed-by: Andrey Konovalov 
Cc: Andrey Ryabinin 
Cc: Alexander Potapenko 
---

v2:
- Thanks for Marco suggestion.
- We modify aux stack title name in KASAN report
  in order to print call_rcu()/timer/workqueue stack.

---
 mm/kasan/report.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/mm/kasan/report.c b/mm/kasan/report.c
index 4f49fa6cd1aa..886809d0a8dd 100644
--- a/mm/kasan/report.c
+++ b/mm/kasan/report.c
@@ -183,12 +183,12 @@ static void describe_object(struct kmem_cache *cache, 
void *object,
 
 #ifdef CONFIG_KASAN_GENERIC
if (alloc_info->aux_stack[0]) {
-   pr_err("Last call_rcu():\n");
+   pr_err("Last potentially related work creation:\n");
print_stack(alloc_info->aux_stack[0]);
pr_err("\n");
}
if (alloc_info->aux_stack[1]) {
-   pr_err("Second to last call_rcu():\n");
+   pr_err("Second to last potentially related work 
creation:\n");
print_stack(alloc_info->aux_stack[1]);
pr_err("\n");
}
-- 
2.18.0


[PATCH v4 2/6] workqueue: kasan: record workqueue stack

2020-09-23 Thread Walter Wu
Records the last two enqueuing work call stacks in order to print them
in KASAN report. It is useful for programmers to solve use-after-free
or double-free memory workqueue issue.

For workqueue it has turned out to be useful to record the enqueuing
work call stacks. Because user can see KASAN report to determine
whether it is root cause. They don't need to enable debugobjects,
but they have a chance to find out the root cause.

Signed-off-by: Walter Wu 
Suggested-by: Marco Elver 
Acked-by: Marco Elver 
Acked-by: Tejun Heo 
Reviewed-by: Dmitry Vyukov 
Reviewed-by: Andrey Konovalov 
Cc: Andrey Ryabinin 
Cc: Alexander Potapenko 
Cc: Lai Jiangshan 
---

v2:
- Thanks for Marco suggestion.
- Remove unnecessary code
- reuse kasan_record_aux_stack() and aux_stack
  to record timer and workqueue stack

---

 kernel/workqueue.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/kernel/workqueue.c b/kernel/workqueue.c
index c41c3c17b86a..5fea7dc9180f 100644
--- a/kernel/workqueue.c
+++ b/kernel/workqueue.c
@@ -1324,6 +1324,9 @@ static void insert_work(struct pool_workqueue *pwq, 
struct work_struct *work,
 {
struct worker_pool *pool = pwq->pool;
 
+   /* record the work call stack in order to print it in KASAN reports */
+   kasan_record_aux_stack(work);
+
/* we own @work, set data and link */
set_work_pwq(work, pwq, extra_flags);
list_add_tail(>entry, head);
-- 
2.18.0


[PATCH v4 1/6] timer: kasan: record timer stack

2020-09-23 Thread Walter Wu
When analyze use-after-free or double-free issue, recording the timer
stacks is helpful to preserve usage history which potentially gives
a hint about the affected code.

Record the most recent two timer init calls in KASAN which are printed
on failure in the KASAN report.

For timers it has turned out to be useful to record the stack trace
of the timer init call. Because if the UAF root cause is in timer init,
then user can see KASAN report to get where it is registered and find
out the root cause. It don't need to enable DEBUG_OBJECTS_TIMERS,
but they have a chance to find out the root cause.

Signed-off-by: Walter Wu 
Suggested-by: Marco Elver 
Suggested-by: Thomas Gleixner 
Acked-by: Marco Elver 
Reviewed-by: Dmitry Vyukov 
Reviewed-by: Andrey Konovalov 
Cc: Andrey Ryabinin 
Cc: Alexander Potapenko 
Cc: John Stultz 
Cc: Thomas Gleixner 
Cc: Stephen Boyd 
---

v2:
- Thanks for Marco and Thomas suggestion.
- Remove unnecessary code and fix commit log
- reuse kasan_record_aux_stack() and aux_stack
  to record timer and workqueue stack.

---
 kernel/time/timer.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/kernel/time/timer.c b/kernel/time/timer.c
index a16764b0116e..1ed8f8aca7f5 100644
--- a/kernel/time/timer.c
+++ b/kernel/time/timer.c
@@ -796,6 +796,9 @@ static void do_init_timer(struct timer_list *timer,
timer->function = func;
timer->flags = flags | raw_smp_processor_id();
lockdep_init_map(>lockdep_map, name, key, 0);
+
+   /* record the timer stack in order to print it in KASAN report */
+   kasan_record_aux_stack(timer);
 }
 
 /**
-- 
2.18.0


PATCH v4 5/6] kasan: add tests for workqueue stack recording

2020-09-23 Thread Walter Wu
Adds a test to verify workqueue stack recording and print it in
KASAN report.

The KASAN report was as follows(cleaned up slightly):

 BUG: KASAN: use-after-free in kasan_workqueue_uaf

 Freed by task 54:
  kasan_save_stack+0x24/0x50
  kasan_set_track+0x24/0x38
  kasan_set_free_info+0x20/0x40
  __kasan_slab_free+0x10c/0x170
  kasan_slab_free+0x10/0x18
  kfree+0x98/0x270
  kasan_workqueue_work+0xc/0x18

 Last potentially related work creation:
  kasan_save_stack+0x24/0x50
  kasan_record_wq_stack+0xa8/0xb8
  insert_work+0x48/0x288
  __queue_work+0x3e8/0xc40
  queue_work_on+0xf4/0x118
  kasan_workqueue_uaf+0xfc/0x190

Signed-off-by: Walter Wu 
Acked-by: Marco Elver 
Reviewed-by: Dmitry Vyukov 
Reviewed-by: Andrey Konovalov 
Cc: Andrey Ryabinin 
Cc: Alexander Potapenko 
Cc: Matthias Brugger 
---

v4:
- testcase has merge conflict, so that rebase onto the KASAN-KUNIT

---
 lib/test_kasan_module.c | 30 ++
 1 file changed, 30 insertions(+)

diff --git a/lib/test_kasan_module.c b/lib/test_kasan_module.c
index 2e5e7be96955..c3a2d113e757 100644
--- a/lib/test_kasan_module.c
+++ b/lib/test_kasan_module.c
@@ -115,6 +115,35 @@ static noinline void __init kasan_timer_uaf(void)
((volatile struct timer_list *)timer)->expires;
 }
 
+static noinline void __init kasan_workqueue_work(struct work_struct *work)
+{
+   kfree(work);
+}
+
+static noinline void __init kasan_workqueue_uaf(void)
+{
+   struct workqueue_struct *workqueue;
+   struct work_struct *work;
+
+   workqueue = create_workqueue("kasan_wq_test");
+   if (!workqueue) {
+   pr_err("Allocation failed\n");
+   return;
+   }
+   work = kmalloc(sizeof(struct work_struct), GFP_KERNEL);
+   if (!work) {
+   pr_err("Allocation failed\n");
+   return;
+   }
+
+   INIT_WORK(work, kasan_workqueue_work);
+   queue_work(workqueue, work);
+   destroy_workqueue(workqueue);
+
+   pr_info("use-after-free on workqueue\n");
+   ((volatile struct work_struct *)work)->data;
+}
+
 static int __init test_kasan_module_init(void)
 {
/*
@@ -126,6 +155,7 @@ static int __init test_kasan_module_init(void)
copy_user_test();
kasan_rcu_uaf();
kasan_timer_uaf();
+   kasan_workqueue_uaf();
 
kasan_restore_multi_shot(multishot);
return -EAGAIN;
-- 
2.18.0


[PATCH v4 4/6] kasan: add tests for timer stack recording

2020-09-23 Thread Walter Wu
Adds a test to verify timer stack recording and print it
in KASAN report.

The KASAN report was as follows(cleaned up slightly):

 BUG: KASAN: use-after-free in kasan_timer_uaf

 Freed by task 0:
  kasan_save_stack+0x24/0x50
  kasan_set_track+0x24/0x38
  kasan_set_free_info+0x20/0x40
  __kasan_slab_free+0x10c/0x170
  kasan_slab_free+0x10/0x18
  kfree+0x98/0x270
  kasan_timer_function+0x1c/0x28

 Last potentially related work creation:
  kasan_save_stack+0x24/0x50
  kasan_record_tmr_stack+0xa8/0xb8
  init_timer_key+0xf0/0x248
  kasan_timer_uaf+0x5c/0xd8

Signed-off-by: Walter Wu 
Acked-by: Marco Elver 
Reviewed-by: Dmitry Vyukov 
Reviewed-by: Andrey Konovalov 
Cc: Andrey Ryabinin 
Cc: Alexander Potapenko 
Cc: Matthias Brugger 
---

v4:
- testcase has merge conflict, so that rebase onto the KASAN-KUNIT

---
 lib/test_kasan_module.c | 25 +
 1 file changed, 25 insertions(+)

diff --git a/lib/test_kasan_module.c b/lib/test_kasan_module.c
index 2d68db6ae67b..d8234a1db8c9 100644
--- a/lib/test_kasan_module.c
+++ b/lib/test_kasan_module.c
@@ -12,6 +12,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include "../mm/kasan/kasan.h"
 
@@ -91,6 +92,29 @@ static noinline void __init kasan_rcu_uaf(void)
call_rcu(_rcu_ptr->rcu, kasan_rcu_reclaim);
 }
 
+static noinline void __init kasan_timer_function(struct timer_list *timer)
+{
+   del_timer(timer);
+   kfree(timer);
+}
+
+static noinline void __init kasan_timer_uaf(void)
+{
+   struct timer_list *timer;
+
+   timer = kmalloc(sizeof(struct timer_list), GFP_KERNEL);
+   if (!timer) {
+   pr_err("Allocation failed\n");
+   return;
+   }
+
+   timer_setup(timer, kasan_timer_function, 0);
+   add_timer(timer);
+   msleep(100);
+
+   pr_info("use-after-free on timer\n");
+   ((volatile struct timer_list *)timer)->expires;
+}
 
 static int __init test_kasan_module_init(void)
 {
@@ -102,6 +126,7 @@ static int __init test_kasan_module_init(void)
 
copy_user_test();
kasan_rcu_uaf();
+   kasan_timer_uaf();
 
kasan_restore_multi_shot(multishot);
return -EAGAIN;
-- 
2.18.0


[PATCH v4 0/6] kasan: add workqueue and timer stack for generic KASAN

2020-09-23 Thread Walter Wu
Syzbot reports many UAF issues for workqueue or timer, see [1] and [2].
In some of these access/allocation happened in process_one_work(),
we see the free stack is useless in KASAN report, it doesn't help
programmers to solve UAF on workqueue. The same may stand for times.

This patchset improves KASAN reports by making them to have workqueue
queueing stack and timer stack information. It is useful for programmers
to solve use-after-free or double-free memory issue.

Generic KASAN also records the last two workqueue and timer stacks and
prints them in KASAN report. It is only suitable for generic KASAN.

[1]https://groups.google.com/g/syzkaller-bugs/search?q=%22use-after-free%22+process_one_work
[2]https://groups.google.com/g/syzkaller-bugs/search?q=%22use-after-free%22%20expire_timers
[3]https://bugzilla.kernel.org/show_bug.cgi?id=198437

Walter Wu (6):
timer: kasan: record timer stack
workqueue: kasan: record workqueue stack
kasan: print timer and workqueue stack
lib/test_kasan.c: add timer test case
lib/test_kasan.c: add workqueue test case
kasan: update documentation for generic kasan

---
Changes since v3:
- testcases have merge conflict, so that need to
  be rebased onto the KASAN-KUNIT.

Changes since v2:
- modify kasan document to be readable,
  Thanks for Marco suggestion.

Changes since v1:
- Thanks for Marco and Thomas suggestion.
- Remove unnecessary code and fix commit log
- reuse kasan_record_aux_stack() and aux_stack
  to record timer and workqueue stack.
- change the aux stack title for common name.

---
Documentation/dev-tools/kasan.rst |  5 +++--
kernel/time/timer.c   |  3 +++
kernel/workqueue.c|  3 +++
lib/test_kasan_module.c   | 55 
+++
mm/kasan/report.c |  4 ++--
5 files changed, 66 insertions(+), 4 deletions(-)

Re: [PATCH v3 0/6] kasan: add workqueue and timer stack for generic KASAN

2020-09-15 Thread Walter Wu
On Mon, 2020-09-14 at 14:25 +0200, Andrey Konovalov wrote:
> On Sun, Sep 13, 2020 at 12:17 PM Dmitry Vyukov 
> wrote:
> 
> On Wed, Aug 26, 2020 at 2:30 PM 'Andrey Konovalov' via
> kasan-dev
>  wrote:
> >
> > On Tue, Aug 25, 2020 at 10:26 AM 'Marco Elver' via kasan-dev
> >  wrote:
> > >
>     > > On Tue, 25 Aug 2020 at 03:57, Walter Wu
>  wrote:
> > > >
> > > > Syzbot reports many UAF issues for workqueue or timer,
> see [1] and [2].
> > > > In some of these access/allocation happened in
> process_one_work(),
> > > > we see the free stack is useless in KASAN report, it
> doesn't help
> > > > programmers to solve UAF on workqueue. The same may
> stand for times.
> > > >
> > > > This patchset improves KASAN reports by making them to
> have workqueue
> > > > queueing stack and timer stack information. It is useful
> for programmers
> > > > to solve use-after-free or double-free memory issue.
> > > >
> > > > Generic KASAN also records the last two workqueue and
> timer stacks and
> > > > prints them in KASAN report. It is only suitable for
> generic KASAN.
> > > >
> > > > [1]https://groups.google.com/g/syzkaller-bugs/search?q=%
> 22use-after-free%22+process_one_work
> > > > [2]https://groups.google.com/g/syzkaller-bugs/search?q=%
> 22use-after-free%22%20expire_timers
> > > > [3]https://bugzilla.kernel.org/show_bug.cgi?id=198437
> > > >
> > > > Walter Wu (6):
> > > > timer: kasan: record timer stack
> > > > workqueue: kasan: record workqueue stack
> > > > kasan: print timer and workqueue stack
> > > > lib/test_kasan.c: add timer test case
> > > > lib/test_kasan.c: add workqueue test case
> > > > kasan: update documentation for generic kasan
> > >
> > > Acked-by: Marco Elver 
> >
> > Reviewed-by: Andrey Konovalov 
> 
> Reviewed-by: Dmitry Vyukov 
> 
> Thanks! The UAF reports with RCU stacks that I see now are
> just 
> 
> 
> Hi Walter,
> 
> 
> This patchset needs to be rebased onto the KASAN-KUNIT patches, which
> just recently went into the mm tree.
> 
> 
> Thanks!

Hi Dmitry, Andrey,

Got it. 

Thanks for your review and reminder.

Walter


Re: [PATCH v2 0/6] kasan: add workqueue and timer stack for generic KASAN

2020-08-24 Thread Walter Wu
On Mon, 2020-08-24 at 13:50 +0200, Marco Elver wrote:
> On Mon, 24 Aug 2020 at 10:07, Walter Wu  wrote:
> >
> > Syzbot reports many UAF issues for workqueue or timer, see [1] and [2].
> > In some of these access/allocation happened in process_one_work(),
> > we see the free stack is useless in KASAN report, it doesn't help
> > programmers to solve UAF on workqueue. The same may stand for times.
> >
> > This patchset improves KASAN reports by making them to have workqueue
> > queueing stack and timer queueing stack information. It is useful for
> > programmers to solve use-after-free or double-free memory issue.
> >
> > Generic KASAN will record the last two workqueue and timer stacks,
> > print them in KASAN report. It is only suitable for generic KASAN.
> >
> > [1]https://groups.google.com/g/syzkaller-bugs/search?q=%22use-after-free%22+process_one_work
> > [2]https://groups.google.com/g/syzkaller-bugs/search?q=%22use-after-free%22%20expire_timers
> > [3]https://bugzilla.kernel.org/show_bug.cgi?id=198437
> >
> > Walter Wu (6):
> > timer: kasan: record timer stack
> > workqueue: kasan: record workqueue stack
> > kasan: print timer and workqueue stack
> > lib/test_kasan.c: add timer test case
> > lib/test_kasan.c: add workqueue test case
> > kasan: update documentation for generic kasan
> >
> > ---
> >
> > Changes since v1:
> > - Thanks for Marco and Thomas suggestion.
> > - Remove unnecessary code and fix commit log
> > - reuse kasan_record_aux_stack() and aux_stack
> >   to record timer and workqueue stack.
> > - change the aux stack title for common name.
> 
> Much cleaner.
> 
> In general,
> 
> Acked-by: Marco Elver 
> 
> but I left some more comments. I'm a bit worried about the tests,
> because of KASAN-test KUnit rework, but probably not much we can do
> until these are added to -mm tree.
> 

Hi Marco,

Thanks for your review and friendly reminder.

If needed, I will rebase and resend the test case.


Walter

> Thanks,
> -- Marco



[PATCH v3 6/6] kasan: update documentation for generic kasan

2020-08-24 Thread Walter Wu
Generic KASAN also supports to record the last two timer and workqueue
stacks and print them in KASAN report. So that need to update
documentation.

Signed-off-by: Walter Wu 
Suggested-by: Marco Elver 
Cc: Andrey Ryabinin 
Cc: Dmitry Vyukov 
Cc: Alexander Potapenko 
Cc: Jonathan Corbet 
---

v3:
- Thanks for Macro suggestion

---
 Documentation/dev-tools/kasan.rst | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/Documentation/dev-tools/kasan.rst 
b/Documentation/dev-tools/kasan.rst
index 38fd5681fade..698ccb65e634 100644
--- a/Documentation/dev-tools/kasan.rst
+++ b/Documentation/dev-tools/kasan.rst
@@ -190,8 +190,9 @@ function calls GCC directly inserts the code to check the 
shadow memory.
 This option significantly enlarges kernel but it gives x1.1-x2 performance
 boost over outline instrumented kernel.
 
-Generic KASAN prints up to 2 call_rcu() call stacks in reports, the last one
-and the second to last.
+Generic KASAN also reports the last 2 call stacks to creation of work that
+potentially has access to an object. Call stacks for the following are shown:
+call_rcu(), timer and workqueue queuing.
 
 Software tag-based KASAN
 
-- 
2.18.0


[PATCH v3 5/6] kasan: add tests for workqueue stack recording

2020-08-24 Thread Walter Wu
Adds a test to verify workqueue stack recording and print it in
KASAN report.

The KASAN report was as follows(cleaned up slightly):

 BUG: KASAN: use-after-free in kasan_workqueue_uaf

 Freed by task 54:
  kasan_save_stack+0x24/0x50
  kasan_set_track+0x24/0x38
  kasan_set_free_info+0x20/0x40
  __kasan_slab_free+0x10c/0x170
  kasan_slab_free+0x10/0x18
  kfree+0x98/0x270
  kasan_workqueue_work+0xc/0x18

 Last potentially related work creation:
  kasan_save_stack+0x24/0x50
  kasan_record_wq_stack+0xa8/0xb8
  insert_work+0x48/0x288
  __queue_work+0x3e8/0xc40
  queue_work_on+0xf4/0x118
  kasan_workqueue_uaf+0xfc/0x190

Signed-off-by: Walter Wu 
Cc: Andrey Ryabinin 
Cc: Dmitry Vyukov 
Cc: Alexander Potapenko 
Cc: Matthias Brugger 
Cc: Andrey Konovalov 
---
 lib/test_kasan.c | 29 +
 1 file changed, 29 insertions(+)

diff --git a/lib/test_kasan.c b/lib/test_kasan.c
index 2bd61674c7a3..7293a55ff51c 100644
--- a/lib/test_kasan.c
+++ b/lib/test_kasan.c
@@ -845,6 +845,34 @@ static noinline void __init kasan_timer_uaf(void)
((volatile struct timer_list *)timer)->expires;
 }
 
+static noinline void __init kasan_workqueue_work(struct work_struct *work)
+{
+   kfree(work);
+}
+
+static noinline void __init kasan_workqueue_uaf(void)
+{
+   struct workqueue_struct *workqueue;
+   struct work_struct *work;
+
+   workqueue = create_workqueue("kasan_wq_test");
+   if (!workqueue) {
+   pr_err("Allocation failed\n");
+   return;
+   }
+   work = kmalloc(sizeof(struct work_struct), GFP_KERNEL);
+   if (!work) {
+   pr_err("Allocation failed\n");
+   return;
+   }
+
+   INIT_WORK(work, kasan_workqueue_work);
+   queue_work(workqueue, work);
+   destroy_workqueue(workqueue);
+
+   pr_info("use-after-free on workqueue\n");
+   ((volatile struct work_struct *)work)->data;
+}
 static int __init kmalloc_tests_init(void)
 {
/*
@@ -894,6 +922,7 @@ static int __init kmalloc_tests_init(void)
vmalloc_oob();
kasan_rcu_uaf();
kasan_timer_uaf();
+   kasan_workqueue_uaf();
 
kasan_restore_multi_shot(multishot);
 
-- 
2.18.0


[PATCH v3 4/6] kasan: add tests for timer stack recording

2020-08-24 Thread Walter Wu
Adds a test to verify timer stack recording and print it
in KASAN report.

The KASAN report was as follows(cleaned up slightly):

 BUG: KASAN: use-after-free in kasan_timer_uaf
 
 Freed by task 0:
  kasan_save_stack+0x24/0x50
  kasan_set_track+0x24/0x38
  kasan_set_free_info+0x20/0x40
  __kasan_slab_free+0x10c/0x170
  kasan_slab_free+0x10/0x18
  kfree+0x98/0x270
  kasan_timer_function+0x1c/0x28
 
 Last potentially related work creation:
  kasan_save_stack+0x24/0x50
  kasan_record_tmr_stack+0xa8/0xb8
  init_timer_key+0xf0/0x248
  kasan_timer_uaf+0x5c/0xd8

Signed-off-by: Walter Wu 
Cc: Andrey Ryabinin 
Cc: Dmitry Vyukov 
Cc: Alexander Potapenko 
Cc: Matthias Brugger 
Cc: Andrey Konovalov 
---
 lib/test_kasan.c | 25 +
 1 file changed, 25 insertions(+)

diff --git a/lib/test_kasan.c b/lib/test_kasan.c
index 6e5fb05d42d8..2bd61674c7a3 100644
--- a/lib/test_kasan.c
+++ b/lib/test_kasan.c
@@ -821,6 +821,30 @@ static noinline void __init kasan_rcu_uaf(void)
call_rcu(_ptr->rcu, kasan_rcu_reclaim);
 }
 
+static noinline void __init kasan_timer_function(struct timer_list *timer)
+{
+   del_timer(timer);
+   kfree(timer);
+}
+
+static noinline void __init kasan_timer_uaf(void)
+{
+   struct timer_list *timer;
+
+   timer = kmalloc(sizeof(struct timer_list), GFP_KERNEL);
+   if (!timer) {
+   pr_err("Allocation failed\n");
+   return;
+   }
+
+   timer_setup(timer, kasan_timer_function, 0);
+   add_timer(timer);
+   msleep(100);
+
+   pr_info("use-after-free on timer\n");
+   ((volatile struct timer_list *)timer)->expires;
+}
+
 static int __init kmalloc_tests_init(void)
 {
/*
@@ -869,6 +893,7 @@ static int __init kmalloc_tests_init(void)
kmalloc_double_kzfree();
vmalloc_oob();
kasan_rcu_uaf();
+   kasan_timer_uaf();
 
kasan_restore_multi_shot(multishot);
 
-- 
2.18.0


[PATCH v3 3/6] kasan: print timer and workqueue stack

2020-08-24 Thread Walter Wu
The aux_stack[2] is reused to record the call_rcu() call stack,
timer init call stack, and enqueuing work call stacks. So that
we need to change the auxiliary stack title for common title,
print them in KASAN report.

Signed-off-by: Walter Wu 
Suggested-by: Marco Elver 
Cc: Andrey Ryabinin 
Cc: Dmitry Vyukov 
Cc: Alexander Potapenko 
---

v2:
- Thanks for Marco suggestion.
- We modify aux stack title name in KASAN report
  in order to print call_rcu()/timer/workqueue stack.

---
 mm/kasan/report.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/mm/kasan/report.c b/mm/kasan/report.c
index 4f49fa6cd1aa..886809d0a8dd 100644
--- a/mm/kasan/report.c
+++ b/mm/kasan/report.c
@@ -183,12 +183,12 @@ static void describe_object(struct kmem_cache *cache, 
void *object,
 
 #ifdef CONFIG_KASAN_GENERIC
if (alloc_info->aux_stack[0]) {
-   pr_err("Last call_rcu():\n");
+   pr_err("Last potentially related work creation:\n");
print_stack(alloc_info->aux_stack[0]);
pr_err("\n");
}
if (alloc_info->aux_stack[1]) {
-   pr_err("Second to last call_rcu():\n");
+   pr_err("Second to last potentially related work 
creation:\n");
print_stack(alloc_info->aux_stack[1]);
pr_err("\n");
}
-- 
2.18.0


[PATCH v3 1/6] timer: kasan: record timer stack

2020-08-24 Thread Walter Wu
When analyze use-after-free or double-free issue, recording the timer
stacks is helpful to to preserve usage history which potentially gives
a hint about the affected code.

Record the most recent two timer init calls in KASAN which are printed
on failure in the KASAN report.

For timers it has turned out to be useful to record the stack trace
of the timer init call. Because if the UAF root cause is in timer init,
then user can see KASAN report to get where it is registered and find
out the root cause. It don't need to enable DEBUG_OBJECTS_TIMERS,
but they have a chance to find out the root cause.

Signed-off-by: Walter Wu 
Suggested-by: Marco Elver 
Suggested-by: Thomas Gleixner 
Cc: Andrey Ryabinin 
Cc: Dmitry Vyukov 
Cc: Alexander Potapenko 
Cc: John Stultz 
Cc: Thomas Gleixner 
Cc: Stephen Boyd 
---

v2:
- Thanks for Marco and Thomas suggestion.
- Remove unnecessary code and fix commit log
- reuse kasan_record_aux_stack() and aux_stack
  to record timer and workqueue stack.

---
 kernel/time/timer.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/kernel/time/timer.c b/kernel/time/timer.c
index a16764b0116e..1ed8f8aca7f5 100644
--- a/kernel/time/timer.c
+++ b/kernel/time/timer.c
@@ -796,6 +796,9 @@ static void do_init_timer(struct timer_list *timer,
timer->function = func;
timer->flags = flags | raw_smp_processor_id();
lockdep_init_map(>lockdep_map, name, key, 0);
+
+   /* record the timer stack in order to print it in KASAN report */
+   kasan_record_aux_stack(timer);
 }
 
 /**
-- 
2.18.0


[PATCH v3 2/6] workqueue: kasan: record workqueue stack

2020-08-24 Thread Walter Wu
Records the last two enqueuing work call stacks in order to print them
in KASAN report. It is useful for programmers to solve use-after-free
or double-free memory workqueue issue.

For workqueue it has turned out to be useful to record the enqueuing
work call stacks. Because user can see KASAN report to determine
whether it is root cause. They don't need to enable debugobjects,
but they have a chance to find out the root cause.

Signed-off-by: Walter Wu 
Suggested-by: Marco Elver 
Cc: Andrey Ryabinin 
Cc: Dmitry Vyukov 
Cc: Alexander Potapenko 
Cc: Tejun Heo 
Cc: Lai Jiangshan 
---

v2:
- Thanks for Marco suggestion.
- Remove unnecessary code
- reuse kasan_record_aux_stack() and aux_stack
  to record timer and workqueue stack

---

 kernel/workqueue.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/kernel/workqueue.c b/kernel/workqueue.c
index c41c3c17b86a..5fea7dc9180f 100644
--- a/kernel/workqueue.c
+++ b/kernel/workqueue.c
@@ -1324,6 +1324,9 @@ static void insert_work(struct pool_workqueue *pwq, 
struct work_struct *work,
 {
struct worker_pool *pool = pwq->pool;
 
+   /* record the work call stack in order to print it in KASAN reports */
+   kasan_record_aux_stack(work);
+
/* we own @work, set data and link */
set_work_pwq(work, pwq, extra_flags);
list_add_tail(>entry, head);
-- 
2.18.0


[PATCH v3 0/6] kasan: add workqueue and timer stack for generic KASAN

2020-08-24 Thread Walter Wu
Syzbot reports many UAF issues for workqueue or timer, see [1] and [2].
In some of these access/allocation happened in process_one_work(),
we see the free stack is useless in KASAN report, it doesn't help
programmers to solve UAF on workqueue. The same may stand for times.

This patchset improves KASAN reports by making them to have workqueue
queueing stack and timer stack information. It is useful for programmers
to solve use-after-free or double-free memory issue.

Generic KASAN also records the last two workqueue and timer stacks and
prints them in KASAN report. It is only suitable for generic KASAN.

[1]https://groups.google.com/g/syzkaller-bugs/search?q=%22use-after-free%22+process_one_work
[2]https://groups.google.com/g/syzkaller-bugs/search?q=%22use-after-free%22%20expire_timers
[3]https://bugzilla.kernel.org/show_bug.cgi?id=198437

Walter Wu (6):
timer: kasan: record timer stack
workqueue: kasan: record workqueue stack
kasan: print timer and workqueue stack
lib/test_kasan.c: add timer test case
lib/test_kasan.c: add workqueue test case
kasan: update documentation for generic kasan

---

Changes since v2:
- modify kasan document to be more readable.
  Thanks for Marco suggestion.

Changes since v1:
- Thanks for Marco and Thomas suggestion.
- Remove unnecessary code and fix commit log
- reuse kasan_record_aux_stack() and aux_stack
  to record timer and workqueue stack.
- change the aux stack title for common name.

---

Documentation/dev-tools/kasan.rst |  4 ++--
kernel/time/timer.c   |  3 +++
kernel/workqueue.c|  3 +++
lib/test_kasan.c  | 54 
++
mm/kasan/report.c |  4 ++--
5 files changed, 64 insertions(+), 4 deletions(-)

[PATCH v2 6/6] kasan: update documentation for generic kasan

2020-08-24 Thread Walter Wu
Generic KASAN support to record the last two timer and workqueue
stacks and print them in KASAN report. So that need to update
documentation.

Signed-off-by: Walter Wu 
Cc: Andrey Ryabinin 
Cc: Dmitry Vyukov 
Cc: Alexander Potapenko 
Cc: Jonathan Corbet 
---
 Documentation/dev-tools/kasan.rst | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/Documentation/dev-tools/kasan.rst 
b/Documentation/dev-tools/kasan.rst
index fede42e6536b..5a4c5da8bda8 100644
--- a/Documentation/dev-tools/kasan.rst
+++ b/Documentation/dev-tools/kasan.rst
@@ -193,8 +193,8 @@ function calls GCC directly inserts the code to check the 
shadow memory.
 This option significantly enlarges kernel but it gives x1.1-x2 performance
 boost over outline instrumented kernel.
 
-Generic KASAN prints up to 2 call_rcu() call stacks in reports, the last one
-and the second to last.
+Generic KASAN prints up to 2 call_rcu() call stacks, timer queueing stacks,
+or workqueue queueing stacks in reports, the last one and the second to last.
 
 Software tag-based KASAN
 
-- 
2.18.0


[PATCH v2 5/6] kasan: add tests for workqueue stack recording

2020-08-24 Thread Walter Wu
Adds a test to verify workqueue stack recording and print it in
KASAN report.

The KASAN report was as follows(cleaned up slightly):

 BUG: KASAN: use-after-free in kasan_workqueue_uaf

 Freed by task 54:
  kasan_save_stack+0x24/0x50
  kasan_set_track+0x24/0x38
  kasan_set_free_info+0x20/0x40
  __kasan_slab_free+0x10c/0x170
  kasan_slab_free+0x10/0x18
  kfree+0x98/0x270
  kasan_workqueue_work+0xc/0x18

 Last potentially related work creation:
  kasan_save_stack+0x24/0x50
  kasan_record_wq_stack+0xa8/0xb8
  insert_work+0x48/0x288
  __queue_work+0x3e8/0xc40
  queue_work_on+0xf4/0x118
  kasan_workqueue_uaf+0xfc/0x190

Signed-off-by: Walter Wu 
Cc: Andrey Ryabinin 
Cc: Dmitry Vyukov 
Cc: Alexander Potapenko 
Cc: Matthias Brugger 
Cc: Andrey Konovalov 
---
 lib/test_kasan.c | 29 +
 1 file changed, 29 insertions(+)

diff --git a/lib/test_kasan.c b/lib/test_kasan.c
index 2bd61674c7a3..7293a55ff51c 100644
--- a/lib/test_kasan.c
+++ b/lib/test_kasan.c
@@ -845,6 +845,34 @@ static noinline void __init kasan_timer_uaf(void)
((volatile struct timer_list *)timer)->expires;
 }
 
+static noinline void __init kasan_workqueue_work(struct work_struct *work)
+{
+   kfree(work);
+}
+
+static noinline void __init kasan_workqueue_uaf(void)
+{
+   struct workqueue_struct *workqueue;
+   struct work_struct *work;
+
+   workqueue = create_workqueue("kasan_wq_test");
+   if (!workqueue) {
+   pr_err("Allocation failed\n");
+   return;
+   }
+   work = kmalloc(sizeof(struct work_struct), GFP_KERNEL);
+   if (!work) {
+   pr_err("Allocation failed\n");
+   return;
+   }
+
+   INIT_WORK(work, kasan_workqueue_work);
+   queue_work(workqueue, work);
+   destroy_workqueue(workqueue);
+
+   pr_info("use-after-free on workqueue\n");
+   ((volatile struct work_struct *)work)->data;
+}
 static int __init kmalloc_tests_init(void)
 {
/*
@@ -894,6 +922,7 @@ static int __init kmalloc_tests_init(void)
vmalloc_oob();
kasan_rcu_uaf();
kasan_timer_uaf();
+   kasan_workqueue_uaf();
 
kasan_restore_multi_shot(multishot);
 
-- 
2.18.0


[PATCH v2 4/6] kasan: add tests for timer stack recording

2020-08-24 Thread Walter Wu
Adds a test to verify timer stack recording and print it
in KASAN report.

The KASAN report was as follows(cleaned up slightly):

 BUG: KASAN: use-after-free in kasan_timer_uaf
 
 Freed by task 0:
  kasan_save_stack+0x24/0x50
  kasan_set_track+0x24/0x38
  kasan_set_free_info+0x20/0x40
  __kasan_slab_free+0x10c/0x170
  kasan_slab_free+0x10/0x18
  kfree+0x98/0x270
  kasan_timer_function+0x1c/0x28
 
 Last potentially related work creation:
  kasan_save_stack+0x24/0x50
  kasan_record_tmr_stack+0xa8/0xb8
  init_timer_key+0xf0/0x248
  kasan_timer_uaf+0x5c/0xd8

Signed-off-by: Walter Wu 
Cc: Andrey Ryabinin 
Cc: Dmitry Vyukov 
Cc: Alexander Potapenko 
Cc: Matthias Brugger 
Cc: Andrey Konovalov 
---
 lib/test_kasan.c | 25 +
 1 file changed, 25 insertions(+)

diff --git a/lib/test_kasan.c b/lib/test_kasan.c
index 6e5fb05d42d8..2bd61674c7a3 100644
--- a/lib/test_kasan.c
+++ b/lib/test_kasan.c
@@ -821,6 +821,30 @@ static noinline void __init kasan_rcu_uaf(void)
call_rcu(_ptr->rcu, kasan_rcu_reclaim);
 }
 
+static noinline void __init kasan_timer_function(struct timer_list *timer)
+{
+   del_timer(timer);
+   kfree(timer);
+}
+
+static noinline void __init kasan_timer_uaf(void)
+{
+   struct timer_list *timer;
+
+   timer = kmalloc(sizeof(struct timer_list), GFP_KERNEL);
+   if (!timer) {
+   pr_err("Allocation failed\n");
+   return;
+   }
+
+   timer_setup(timer, kasan_timer_function, 0);
+   add_timer(timer);
+   msleep(100);
+
+   pr_info("use-after-free on timer\n");
+   ((volatile struct timer_list *)timer)->expires;
+}
+
 static int __init kmalloc_tests_init(void)
 {
/*
@@ -869,6 +893,7 @@ static int __init kmalloc_tests_init(void)
kmalloc_double_kzfree();
vmalloc_oob();
kasan_rcu_uaf();
+   kasan_timer_uaf();
 
kasan_restore_multi_shot(multishot);
 
-- 
2.18.0


[PATCH v2 3/6] kasan: print timer and workqueue stack

2020-08-24 Thread Walter Wu
The aux_stack[2] is reused to record the call_rcu() call stack,
timer init call stack, and enqueuing work call stacks. So that
we need to change the auxiliary stack title for common title,
print them in KASAN report.

Signed-off-by: Walter Wu 
Suggested-by: Marco Elver 
Cc: Andrey Ryabinin 
Cc: Dmitry Vyukov 
Cc: Alexander Potapenko 
---

v2:
- Thanks for Marco suggestion.
- We modify aux stack title name in KASAN report
  in order to print call_rcu()/timer/workqueue stack.

---
 mm/kasan/report.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/mm/kasan/report.c b/mm/kasan/report.c
index 4f49fa6cd1aa..886809d0a8dd 100644
--- a/mm/kasan/report.c
+++ b/mm/kasan/report.c
@@ -183,12 +183,12 @@ static void describe_object(struct kmem_cache *cache, 
void *object,
 
 #ifdef CONFIG_KASAN_GENERIC
if (alloc_info->aux_stack[0]) {
-   pr_err("Last call_rcu():\n");
+   pr_err("Last potentially related work creation:\n");
print_stack(alloc_info->aux_stack[0]);
pr_err("\n");
}
if (alloc_info->aux_stack[1]) {
-   pr_err("Second to last call_rcu():\n");
+   pr_err("Second to last potentially related work 
creation:\n");
print_stack(alloc_info->aux_stack[1]);
pr_err("\n");
}
-- 
2.18.0


[PATCH v2 2/6] workqueue: kasan: record workqueue stack

2020-08-24 Thread Walter Wu
Records the last two enqueuing work call stacks in order to print them
in KASAN report. It is useful for programmers to solve use-after-free
or double-free memory workqueue issue.

For workqueue it has turned out to be useful to record the enqueuing
work call stacks. Because user can see KASAN report to determine
whether it is root cause. They don't need to enable debugobjects,
but they have a chance to find out the root cause.

Signed-off-by: Walter Wu 
Suggested-by: Marco Elver 
Cc: Andrey Ryabinin 
Cc: Dmitry Vyukov 
Cc: Alexander Potapenko 
Cc: Tejun Heo 
Cc: Lai Jiangshan 
---

v2:
- Thanks for Marco suggestion.
- Remove unnecessary code
- reuse kasan_record_aux_stack() and aux_stack
  to record timer and workqueue stack

---

 kernel/workqueue.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/kernel/workqueue.c b/kernel/workqueue.c
index c41c3c17b86a..5fea7dc9180f 100644
--- a/kernel/workqueue.c
+++ b/kernel/workqueue.c
@@ -1324,6 +1324,9 @@ static void insert_work(struct pool_workqueue *pwq, 
struct work_struct *work,
 {
struct worker_pool *pool = pwq->pool;
 
+   /* record the work call stack in order to print it in KASAN reports */
+   kasan_record_aux_stack(work);
+
/* we own @work, set data and link */
set_work_pwq(work, pwq, extra_flags);
list_add_tail(>entry, head);
-- 
2.18.0


[PATCH v2 1/6] timer: kasan: record timer stack

2020-08-24 Thread Walter Wu
When analyze use-after-free or double-free issue, recording the timer
stacks is helpful to to preserve usage history which potentially gives
a hint about the affected code.

Record the most recent two timer init calls in KASAN which are printed
on failure in the KASAN report.

For timers it has turned out to be useful to record the stack trace
of the timer init call. Because if the UAF root cause is in timer init,
then user can see KASAN report to get where it is registered and find
out the root cause. It don't need to enable DEBUG_OBJECTS_TIMERS,
but they have a chance to find out the root cause.

Signed-off-by: Walter Wu 
Suggested-by: Marco Elver 
Suggested-by: Thomas Gleixner 
Cc: Andrey Ryabinin 
Cc: Dmitry Vyukov 
Cc: Alexander Potapenko 
Cc: John Stultz 
Cc: Thomas Gleixner 
Cc: Stephen Boyd 
---

v2:
- Thanks for Marco and Thomas suggestion.
- Remove unnecessary code and fix commit log
- reuse kasan_record_aux_stack() and aux_stack
  to record timer and workqueue stack.

---
 kernel/time/timer.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/kernel/time/timer.c b/kernel/time/timer.c
index a16764b0116e..1ed8f8aca7f5 100644
--- a/kernel/time/timer.c
+++ b/kernel/time/timer.c
@@ -796,6 +796,9 @@ static void do_init_timer(struct timer_list *timer,
timer->function = func;
timer->flags = flags | raw_smp_processor_id();
lockdep_init_map(>lockdep_map, name, key, 0);
+
+   /* record the timer stack in order to print it in KASAN report */
+   kasan_record_aux_stack(timer);
 }
 
 /**
-- 
2.18.0


[PATCH v2 0/6] kasan: add workqueue and timer stack for generic KASAN

2020-08-24 Thread Walter Wu
Syzbot reports many UAF issues for workqueue or timer, see [1] and [2].
In some of these access/allocation happened in process_one_work(),
we see the free stack is useless in KASAN report, it doesn't help
programmers to solve UAF on workqueue. The same may stand for times.

This patchset improves KASAN reports by making them to have workqueue
queueing stack and timer queueing stack information. It is useful for
programmers to solve use-after-free or double-free memory issue.

Generic KASAN will record the last two workqueue and timer stacks,
print them in KASAN report. It is only suitable for generic KASAN.

[1]https://groups.google.com/g/syzkaller-bugs/search?q=%22use-after-free%22+process_one_work
[2]https://groups.google.com/g/syzkaller-bugs/search?q=%22use-after-free%22%20expire_timers
[3]https://bugzilla.kernel.org/show_bug.cgi?id=198437

Walter Wu (6):
timer: kasan: record timer stack
workqueue: kasan: record workqueue stack
kasan: print timer and workqueue stack
lib/test_kasan.c: add timer test case
lib/test_kasan.c: add workqueue test case
kasan: update documentation for generic kasan

---

Changes since v1:
- Thanks for Marco and Thomas suggestion.
- Remove unnecessary code and fix commit log
- reuse kasan_record_aux_stack() and aux_stack
  to record timer and workqueue stack.
- change the aux stack title for common name.

---

Documentation/dev-tools/kasan.rst |  4 ++--
kernel/time/timer.c   |  3 +++
kernel/workqueue.c|  3 +++
lib/test_kasan.c  | 54 
++
mm/kasan/report.c |  4 ++--
5 files changed, 64 insertions(+), 4 deletions(-)

Re: [PATCH 1/5] timer: kasan: record and print timer stack

2020-08-13 Thread Walter Wu
Hi Thomas,

Please ignore my previous mail. Thanks.


On Thu, 2020-08-13 at 13:48 +0200, Thomas Gleixner wrote:
> Walter,
> 
> Walter Wu  writes:
> > This patch records the last two timer queueing stacks and prints
> 
> "This patch" is useless information as we already know from the subject
> line that this is a patch.
> 
> git grep 'This patch' Documentation/process/
> 

Thanks for your information.

> > up to 2 timer stacks in KASAN report. It is useful for programmers
> > to solve use-after-free or double-free memory timer issues.
> >
> > When timer_setup() or timer_setup_on_stack() is called, then it
> > prepares to use this timer and sets timer callback, we store
> > this call stack in order to print it in KASAN report.
> 
> we store nothing. Don't impersonate code please.
> 
> Also please structure the changelog in a way that it's easy to
> understand what this is about instead of telling first what the patch
> does and then some half baken information why this is useful followed by
> more information about what it does.
> 
> Something like this:
> 
>   For analysing use after free or double free of objects it is helpful
>   to preserve usage history which potentially gives a hint about the
>   affected code.
> 
>   For timers it has turned out to be useful to record the stack trace
>   of the timer init call. 
>  
>   Record the most recent two timer init calls in KASAN which are printed
>   on failure in the KASAN report.
> 
> See, this gives a clear context, an explanation why it is useful and a
> high level description of what it does. The details are in the patch
> ifself and do not have to be epxlained in the changelog.
> 

Thanks for your explanation, Our patch will use this as a template from
now on.

> For the technical explanation which you need to add, you really need to
> tell what's the advantage or additional coverage vs. existing debug
> facilities like debugobjects. Just claiming that it's useful does not
> make an argument.
> 

We originally wanted him to have similar functions. Maybe he can't
completely replace, but KASAN can ave this ability.

> The UAF problem with timers is nasty because if you free an active timer
> then either the softirq which expires the timer will corrupt potentially
> reused memory or the reuse will corrupt the linked list which makes the
> softirq or some unrelated code which adds/removes a different timer
> explode in undebuggable ways. debugobject prevents that because it
> tracks per timer state and invokes the fixup function which keeps the
> system alive and also tells you exactly where the free of the active
> object happens which is the really interesting place to look at. The
> init function is pretty uninteresting in that case because you really
> want to know where the freeing of the active object happens.
> 
> So if KASAN detects UAF in the timer softirq then the init trace is not
> giving any information especially not in cases where the timer is part
> of a common and frequently allocated/freed other data structure.
> 

I don't have experience using this tool, but I will survey it.

> >  static inline void kasan_cache_shrink(struct kmem_cache *cache) {}
> >  static inline void kasan_cache_shutdown(struct kmem_cache *cache) {}
> >  static inline void kasan_record_aux_stack(void *ptr) {}
> > +static inline void kasan_record_tmr_stack(void *ptr) {}
> 
> Duh, so you are adding per object type functions and storage? That's
> going to be a huge copy and pasta orgy as every object requires the same
> code and extra storage space.
> 
> Why not just using kasan_record_aux_stack() for all of this?
> 
> The 'call_rcu' 'timer' 'whatever next' printout is not really required
> because the stack trace already tells you the function which was
> invoked. If TOS is call_rcu() or do_timer_init() then it's entirely
> clear which object is affected. If the two aux records are not enough
> then making the array larger is not the end of the world.
> 

My previous mail say that we will re-use kasan_record_aux_stack() and
only have aux_stack.

> >  #endif /* CONFIG_KASAN_GENERIC */
> >  
> > diff --git a/kernel/time/timer.c b/kernel/time/timer.c
> > index a5221abb4594..ef2da9ddfac7 100644
> > --- a/kernel/time/timer.c
> > +++ b/kernel/time/timer.c
> > @@ -783,6 +783,8 @@ static void do_init_timer(struct timer_list *timer,
> > timer->function = func;
> > timer->flags = flags | raw_smp_processor_id();
> > lockdep_init_map(>lockdep_map, name, key, 0);
> > +
> > +   kasan_record_tmr_stack(timer);
> >  }
> 
> Are you sure this is correct for all timers?
> 
> This is also called for timers whi

Re: [PATCH 1/5] timer: kasan: record and print timer stack

2020-08-13 Thread Walter Wu
On Thu, 2020-08-13 at 13:48 +0200, Thomas Gleixner wrote:
> Walter,
> 
> Walter Wu  writes:
> > This patch records the last two timer queueing stacks and prints
> 
> "This patch" is useless information as we already know from the subject
> line that this is a patch.
> 
> git grep 'This patch' Documentation/process/
> 

Thanks for your information.

> > up to 2 timer stacks in KASAN report. It is useful for programmers
> > to solve use-after-free or double-free memory timer issues.
> >
> > When timer_setup() or timer_setup_on_stack() is called, then it
> > prepares to use this timer and sets timer callback, we store
> > this call stack in order to print it in KASAN report.
> 
> we store nothing. Don't impersonate code please.
> 
> Also please structure the changelog in a way that it's easy to
> understand what this is about instead of telling first what the patch
> does and then some half baken information why this is useful followed by
> more information about what it does.
> 
> Something like this:
> 
>   For analysing use after free or double free of objects it is helpful
>   to preserve usage history which potentially gives a hint about the
>   affected code.
> 
>   For timers it has turned out to be useful to record the stack trace
>   of the timer init call. 
>  
>   Record the most recent two timer init calls in KASAN which are printed
>   on failure in the KASAN report.
> 
> See, this gives a clear context, an explanation why it is useful and a
> high level description of what it does. The details are in the patch
> ifself and do not have to be epxlained in the changelog.
> 

> For the technical explanation which you need to add, you really need to
> tell what's the advantage or additional coverage vs. existing debug
> facilities like debugobjects. Just claiming that it's useful does not
> make an argument.
> 



> The UAF problem with timers is nasty because if you free an active timer
> then either the softirq which expires the timer will corrupt potentially
> reused memory or the reuse will corrupt the linked list which makes the
> softirq or some unrelated code which adds/removes a different timer
> explode in undebuggable ways. debugobject prevents that because it
> tracks per timer state and invokes the fixup function which keeps the
> system alive and also tells you exactly where the free of the active
> object happens which is the really interesting place to look at. The
> init function is pretty uninteresting in that case because you really
> want to know where the freeing of the active object happens.
> 

It is what we want to achieve, maybe we have shortcomings, but my patch

> So if KASAN detects UAF in the timer softirq then the init trace is not
> giving any information especially not in cases where the timer is part
> of a common and frequently allocated/freed other data structure.
> 
> >  static inline void kasan_cache_shrink(struct kmem_cache *cache) {}
> >  static inline void kasan_cache_shutdown(struct kmem_cache *cache) {}
> >  static inline void kasan_record_aux_stack(void *ptr) {}
> > +static inline void kasan_record_tmr_stack(void *ptr) {}
> 
> Duh, so you are adding per object type functions and storage? That's
> going to be a huge copy and pasta orgy as every object requires the same
> code and extra storage space.
> 
> Why not just using kasan_record_aux_stack() for all of this?
> 
> The 'call_rcu' 'timer' 'whatever next' printout is not really required
> because the stack trace already tells you the function which was
> invoked. If TOS is call_rcu() or do_timer_init() then it's entirely
> clear which object is affected. If the two aux records are not enough
> then making the array larger is not the end of the world.
> 
> >  #endif /* CONFIG_KASAN_GENERIC */
> >  
> > diff --git a/kernel/time/timer.c b/kernel/time/timer.c
> > index a5221abb4594..ef2da9ddfac7 100644
> > --- a/kernel/time/timer.c
> > +++ b/kernel/time/timer.c
> > @@ -783,6 +783,8 @@ static void do_init_timer(struct timer_list *timer,
> > timer->function = func;
> > timer->flags = flags | raw_smp_processor_id();
> > lockdep_init_map(>lockdep_map, name, key, 0);
> > +
> > +   kasan_record_tmr_stack(timer);
> >  }
> 
> Are you sure this is correct for all timers?
> 
> This is also called for timers which are temporarily allocated on stack
> and for timers which are statically allocated at compile time. How is
> that supposed to work?
> 
> These kind of things want to be explained upfront an not left to the
> reviewer as an exercise.
> 
> Thanks,
> 
> tglx

I have already 



Re: [PATCH 1/5] timer: kasan: record and print timer stack

2020-08-12 Thread Walter Wu
On Wed, 2020-08-12 at 16:13 +0200, Marco Elver wrote:
> On Mon, 10 Aug 2020 at 09:23, Walter Wu  wrote:
> > This patch records the last two timer queueing stacks and prints
> > up to 2 timer stacks in KASAN report. It is useful for programmers
> > to solve use-after-free or double-free memory timer issues.
> >
> > When timer_setup() or timer_setup_on_stack() is called, then it
> > prepares to use this timer and sets timer callback, we store
> > this call stack in order to print it in KASAN report.
> >
> > Signed-off-by: Walter Wu 
> > Cc: Andrey Ryabinin 
> > Cc: Dmitry Vyukov 
> > Cc: Alexander Potapenko 
> > Cc: Thomas Gleixner 
> > Cc: John Stultz 
> > Cc: Stephen Boyd 
> > Cc: Andrew Morton 
> > ---
> >  include/linux/kasan.h |  2 ++
> >  kernel/time/timer.c   |  2 ++
> >  mm/kasan/generic.c| 21 +
> >  mm/kasan/kasan.h  |  4 +++-
> >  mm/kasan/report.c | 11 +++
> >  5 files changed, 39 insertions(+), 1 deletion(-)
> 
> I'm commenting on the code here, but it also applies to patch 2/5, as
> it's almost a copy-paste.
> 
> In general, I'd say the solution to get this feature is poorly
> designed, resulting in excessive LOC added. The logic added already
> exists for the aux stacks.
> 

That's true, we will have refactoring for it.

> > diff --git a/include/linux/kasan.h b/include/linux/kasan.h
> > index 23b7ee00572d..763664b36dc6 100644
> > --- a/include/linux/kasan.h
> > +++ b/include/linux/kasan.h
> > @@ -175,12 +175,14 @@ static inline size_t kasan_metadata_size(struct 
> > kmem_cache *cache) { return 0; }
> >  void kasan_cache_shrink(struct kmem_cache *cache);
> >  void kasan_cache_shutdown(struct kmem_cache *cache);
> >  void kasan_record_aux_stack(void *ptr);
> > +void kasan_record_tmr_stack(void *ptr);
> >
> >  #else /* CONFIG_KASAN_GENERIC */
> >
> >  static inline void kasan_cache_shrink(struct kmem_cache *cache) {}
> >  static inline void kasan_cache_shutdown(struct kmem_cache *cache) {}
> >  static inline void kasan_record_aux_stack(void *ptr) {}
> > +static inline void kasan_record_tmr_stack(void *ptr) {}
> 
> It appears that the 'aux' stack is currently only used for call_rcu
> stacks, but this interface does not inherently tie it to call_rcu. The
> only thing tying it to call_rcu is the fact that the report calls out
> call_rcu.
> 
> >  /**
> > diff --git a/mm/kasan/generic.c b/mm/kasan/generic.c
> > index 4b3cbad7431b..f35dcec990ab 100644
> > --- a/mm/kasan/generic.c
> > +++ b/mm/kasan/generic.c
> > @@ -347,6 +347,27 @@ void kasan_record_aux_stack(void *addr)
> > alloc_info->aux_stack[0] = kasan_save_stack(GFP_NOWAIT);
> >  }
> >
> > +void kasan_record_tmr_stack(void *addr)
> > +{
> > +   struct page *page = kasan_addr_to_page(addr);
> > +   struct kmem_cache *cache;
> > +   struct kasan_alloc_meta *alloc_info;
> > +   void *object;
> > +
> > +   if (!(page && PageSlab(page)))
> > +   return;
> > +
> > +   cache = page->slab_cache;
> > +   object = nearest_obj(cache, page, addr);
> > +   alloc_info = get_alloc_info(cache, object);
> > +
> > +   /*
> > +* record the last two timer stacks.
> > +*/
> > +   alloc_info->tmr_stack[1] = alloc_info->tmr_stack[0];
> > +   alloc_info->tmr_stack[0] = kasan_save_stack(GFP_NOWAIT);
> > +}
> 
> The solution here is, unfortunately, poorly designed. This is a
> copy-paste of the kasan_record_aux_stack() function.
> 

kasan_record_aux_stack() will be re-used for call_rcu, timer, and
workqueue.

> >  void kasan_set_free_info(struct kmem_cache *cache,
> > void *object, u8 tag)
> >  {
> > diff --git a/mm/kasan/kasan.h b/mm/kasan/kasan.h
> > index ef655a1c6e15..c50827f388a3 100644
> > --- a/mm/kasan/kasan.h
> > +++ b/mm/kasan/kasan.h
> > @@ -108,10 +108,12 @@ struct kasan_alloc_meta {
> > struct kasan_track alloc_track;
> >  #ifdef CONFIG_KASAN_GENERIC
> > /*
> > -* call_rcu() call stack is stored into struct kasan_alloc_meta.
> > +* call_rcu() call stack and timer queueing stack are stored
> > +* into struct kasan_alloc_meta.
> >  * The free stack is stored into struct kasan_free_meta.
> >  */
> > depot_stack_handle_t aux_stack[2];
> > +   depot_stack_handle_t tmr_stack[2];
> >  #else
> > struct kasan_tr

Re: [PATCH 0/5] kasan: add workqueue and timer stack for generic KASAN

2020-08-10 Thread Walter Wu
On Mon, 2020-08-10 at 08:44 -0400, Qian Cai wrote:
> On Mon, Aug 10, 2020 at 07:50:57PM +0800, Walter Wu wrote:
> > On Mon, 2020-08-10 at 07:19 -0400, Qian Cai wrote:
> > > 
> > > > On Aug 10, 2020, at 3:21 AM, Walter Wu  
> > > > wrote:
> > > > 
> > > > Syzbot reports many UAF issues for workqueue or timer, see [1] and [2].
> > > > In some of these access/allocation happened in process_one_work(),
> > > > we see the free stack is useless in KASAN report, it doesn't help
> > > > programmers to solve UAF on workqueue. The same may stand for times.
> > > > 
> > > > This patchset improves KASAN reports by making them to have workqueue
> > > > queueing stack and timer queueing stack information. It is useful for
> > > > programmers to solve use-after-free or double-free memory issue.
> > > > 
> > > > Generic KASAN will record the last two workqueue and timer stacks,
> > > > print them in KASAN report. It is only suitable for generic KASAN.
> > > > 
> > > > In order to print the last two workqueue and timer stacks, so that
> > > > we add new members in struct kasan_alloc_meta.
> > > > - two workqueue queueing work stacks, total size is 8 bytes.
> > > > - two timer queueing stacks, total size is 8 bytes.
> > > > 
> > > > Orignial struct kasan_alloc_meta size is 16 bytes. After add new
> > > > members, then the struct kasan_alloc_meta total size is 32 bytes,
> > > > It is a good number of alignment. Let it get better memory consumption.
> > > 
> > > Getting debugging tools complicated surely is the best way to kill it. I 
> > > would argue that it only make sense to complicate it if it is useful most 
> > > of the time which I never feel or hear that is the case. This reminds me 
> > > your recent call_rcu() stacks that most of time just makes parsing the 
> > > report cumbersome. Thus, I urge this exercise to over-engineer on special 
> > > cases need to stop entirely.
> > > 
> > 
> > A good debug tool is to have complete information in order to solve
> > issue. We should focus on if KASAN reports always show this debug
> > information or create a option to decide if show it. Because this
> > feature is Dimitry's suggestion. see [1]. So I think it need to be
> > implemented. Maybe we can wait his response. 
> > 
> > [1]https://lkml.org/lkml/2020/6/23/256
> 
> I don't know if it is Dmitry's pipe-dream which every KASAN report would 
> enable
> developers to fix it without reproducing it. It is always an ongoing 
> struggling
> between to make kernel easier to debug and the things less cumbersome.
> 
> On the other hand, Dmitry's suggestion makes sense only if the price we are
> going to pay is fair. With the current diffstat and the recent experience of
> call_rcu() stacks "waste" screen spaces as a heavy KASAN user myself, I can't
> really get that exciting for pushing the limit again at all.
> 

If you are concerned that the report is long, maybe we can create an
option for the user decide whether print them (include call_rcu).
So this should satisfy everyone?

> > 
> > > > 
> > > > [1]https://groups.google.com/g/syzkaller-bugs/search?q=%22use-after-free%22+process_one_work
> > > > [2]https://groups.google.com/g/syzkaller-bugs/search?q=%22use-after-free%22%20expire_timers
> > > > [3]https://bugzilla.kernel.org/show_bug.cgi?id=198437
> > > > 
> > > > Walter Wu (5):
> > > > timer: kasan: record and print timer stack
> > > > workqueue: kasan: record and print workqueue stack
> > > > lib/test_kasan.c: add timer test case
> > > > lib/test_kasan.c: add workqueue test case
> > > > kasan: update documentation for generic kasan
> > > > 
> > > > Documentation/dev-tools/kasan.rst |  4 ++--
> > > > include/linux/kasan.h |  4 
> > > > kernel/time/timer.c   |  2 ++
> > > > kernel/workqueue.c|  3 +++
> > > > lib/test_kasan.c  | 54 
> > > > ++
> > > > mm/kasan/generic.c| 42 
> > > > ++
> > > > mm/kasan/kasan.h  |  6 +-
> > > > mm/kasan/report.c | 22 ++
> > > > 8 files changed, 134 insertions(+), 3 deletions(-)
> > > > 
> > > > -- 
> > > > You received this message because you are subscribed to the Google 
> > > > Groups "kasan-dev" group.
> > > > To unsubscribe from this group and stop receiving emails from it, send 
> > > > an email to kasan-dev+unsubscr...@googlegroups.com.
> > > > To view this discussion on the web visit 
> > > > https://groups.google.com/d/msgid/kasan-dev/20200810072115.429-1-walter-zh.wu%40mediatek.com.
> > 



Re: [PATCH 0/5] kasan: add workqueue and timer stack for generic KASAN

2020-08-10 Thread Walter Wu
On Mon, 2020-08-10 at 19:50 +0800, Walter Wu wrote:
> On Mon, 2020-08-10 at 07:19 -0400, Qian Cai wrote:
> > 
> > > On Aug 10, 2020, at 3:21 AM, Walter Wu  wrote:
> > > 
> > > Syzbot reports many UAF issues for workqueue or timer, see [1] and [2].
> > > In some of these access/allocation happened in process_one_work(),
> > > we see the free stack is useless in KASAN report, it doesn't help
> > > programmers to solve UAF on workqueue. The same may stand for times.
> > > 
> > > This patchset improves KASAN reports by making them to have workqueue
> > > queueing stack and timer queueing stack information. It is useful for
> > > programmers to solve use-after-free or double-free memory issue.
> > > 
> > > Generic KASAN will record the last two workqueue and timer stacks,
> > > print them in KASAN report. It is only suitable for generic KASAN.
> > > 
> > > In order to print the last two workqueue and timer stacks, so that
> > > we add new members in struct kasan_alloc_meta.
> > > - two workqueue queueing work stacks, total size is 8 bytes.
> > > - two timer queueing stacks, total size is 8 bytes.
> > > 
> > > Orignial struct kasan_alloc_meta size is 16 bytes. After add new
> > > members, then the struct kasan_alloc_meta total size is 32 bytes,
> > > It is a good number of alignment. Let it get better memory consumption.
> > 
> > Getting debugging tools complicated surely is the best way to kill it. I 
> > would argue that it only make sense to complicate it if it is useful most 
> > of the time which I never feel or hear that is the case. This reminds me 
> > your recent call_rcu() stacks that most of time just makes parsing the 
> > report cumbersome. Thus, I urge this exercise to over-engineer on special 
> > cases need to stop entirely.
> > 
> 
> A good debug tool is to have complete information in order to solve
> issue. We should focus on if KASAN reports always show this debug
> information or create a option to decide if show it. Because this
> feature is Dmitry's suggestion. see [1]. So I think it need to be
> implemented. Maybe we can wait his response. 
> 
> [1]https://lkml.org/lkml/2020/6/23/256
> 
> Thanks.
> 

Fix name typo. I am sorry to him.
And add a bugzilla to show why need to do it. please see [1].

[1] https://bugzilla.kernel.org/show_bug.cgi?id=198437

> > > 
> > > [1]https://groups.google.com/g/syzkaller-bugs/search?q=%22use-after-free%22+process_one_work
> > > [2]https://groups.google.com/g/syzkaller-bugs/search?q=%22use-after-free%22%20expire_timers
> > > [3]https://bugzilla.kernel.org/show_bug.cgi?id=198437
> > > 
> > > Walter Wu (5):
> > > timer: kasan: record and print timer stack
> > > workqueue: kasan: record and print workqueue stack
> > > lib/test_kasan.c: add timer test case
> > > lib/test_kasan.c: add workqueue test case
> > > kasan: update documentation for generic kasan
> > > 
> > > Documentation/dev-tools/kasan.rst |  4 ++--
> > > include/linux/kasan.h |  4 
> > > kernel/time/timer.c   |  2 ++
> > > kernel/workqueue.c|  3 +++
> > > lib/test_kasan.c  | 54 
> > > ++
> > > mm/kasan/generic.c| 42 
> > > ++
> > > mm/kasan/kasan.h  |  6 +-
> > > mm/kasan/report.c | 22 ++
> > > 8 files changed, 134 insertions(+), 3 deletions(-)
> > > 
> > > -- 
> > > You received this message because you are subscribed to the Google Groups 
> > > "kasan-dev" group.
> > > To unsubscribe from this group and stop receiving emails from it, send an 
> > > email to kasan-dev+unsubscr...@googlegroups.com.
> > > To view this discussion on the web visit 
> > > https://groups.google.com/d/msgid/kasan-dev/20200810072115.429-1-walter-zh.wu%40mediatek.com.
> 



Re: [PATCH 0/5] kasan: add workqueue and timer stack for generic KASAN

2020-08-10 Thread Walter Wu
On Mon, 2020-08-10 at 07:19 -0400, Qian Cai wrote:
> 
> > On Aug 10, 2020, at 3:21 AM, Walter Wu  wrote:
> > 
> > Syzbot reports many UAF issues for workqueue or timer, see [1] and [2].
> > In some of these access/allocation happened in process_one_work(),
> > we see the free stack is useless in KASAN report, it doesn't help
> > programmers to solve UAF on workqueue. The same may stand for times.
> > 
> > This patchset improves KASAN reports by making them to have workqueue
> > queueing stack and timer queueing stack information. It is useful for
> > programmers to solve use-after-free or double-free memory issue.
> > 
> > Generic KASAN will record the last two workqueue and timer stacks,
> > print them in KASAN report. It is only suitable for generic KASAN.
> > 
> > In order to print the last two workqueue and timer stacks, so that
> > we add new members in struct kasan_alloc_meta.
> > - two workqueue queueing work stacks, total size is 8 bytes.
> > - two timer queueing stacks, total size is 8 bytes.
> > 
> > Orignial struct kasan_alloc_meta size is 16 bytes. After add new
> > members, then the struct kasan_alloc_meta total size is 32 bytes,
> > It is a good number of alignment. Let it get better memory consumption.
> 
> Getting debugging tools complicated surely is the best way to kill it. I 
> would argue that it only make sense to complicate it if it is useful most of 
> the time which I never feel or hear that is the case. This reminds me your 
> recent call_rcu() stacks that most of time just makes parsing the report 
> cumbersome. Thus, I urge this exercise to over-engineer on special cases need 
> to stop entirely.
> 

A good debug tool is to have complete information in order to solve
issue. We should focus on if KASAN reports always show this debug
information or create a option to decide if show it. Because this
feature is Dimitry's suggestion. see [1]. So I think it need to be
implemented. Maybe we can wait his response. 

[1]https://lkml.org/lkml/2020/6/23/256

Thanks.

> > 
> > [1]https://groups.google.com/g/syzkaller-bugs/search?q=%22use-after-free%22+process_one_work
> > [2]https://groups.google.com/g/syzkaller-bugs/search?q=%22use-after-free%22%20expire_timers
> > [3]https://bugzilla.kernel.org/show_bug.cgi?id=198437
> > 
> > Walter Wu (5):
> > timer: kasan: record and print timer stack
> > workqueue: kasan: record and print workqueue stack
> > lib/test_kasan.c: add timer test case
> > lib/test_kasan.c: add workqueue test case
> > kasan: update documentation for generic kasan
> > 
> > Documentation/dev-tools/kasan.rst |  4 ++--
> > include/linux/kasan.h |  4 
> > kernel/time/timer.c   |  2 ++
> > kernel/workqueue.c|  3 +++
> > lib/test_kasan.c  | 54 
> > ++
> > mm/kasan/generic.c| 42 
> > ++
> > mm/kasan/kasan.h  |  6 +-
> > mm/kasan/report.c | 22 ++
> > 8 files changed, 134 insertions(+), 3 deletions(-)
> > 
> > -- 
> > You received this message because you are subscribed to the Google Groups 
> > "kasan-dev" group.
> > To unsubscribe from this group and stop receiving emails from it, send an 
> > email to kasan-dev+unsubscr...@googlegroups.com.
> > To view this discussion on the web visit 
> > https://groups.google.com/d/msgid/kasan-dev/20200810072115.429-1-walter-zh.wu%40mediatek.com.



[PATCH 5/5] kasan: update documentation for generic KASAN

2020-08-10 Thread Walter Wu
Generic KASAN support to record the last two timer and workqueue
stacks and print them in KASAN report. So that need to update
documentation.

Signed-off-by: Walter Wu 
Cc: Andrey Ryabinin 
Cc: Dmitry Vyukov 
Cc: Alexander Potapenko 
Cc: Jonathan Corbet 
---
 Documentation/dev-tools/kasan.rst | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/Documentation/dev-tools/kasan.rst 
b/Documentation/dev-tools/kasan.rst
index fede42e6536b..5a4c5da8bda8 100644
--- a/Documentation/dev-tools/kasan.rst
+++ b/Documentation/dev-tools/kasan.rst
@@ -193,8 +193,8 @@ function calls GCC directly inserts the code to check the 
shadow memory.
 This option significantly enlarges kernel but it gives x1.1-x2 performance
 boost over outline instrumented kernel.
 
-Generic KASAN prints up to 2 call_rcu() call stacks in reports, the last one
-and the second to last.
+Generic KASAN prints up to 2 call_rcu() call stacks, timer queueing stacks,
+and workqueue queueing stacks in reports, the last one and the second to last.
 
 Software tag-based KASAN
 
-- 
2.18.0


[PATCH 4/5] lib/test_kasan.c: add workqueue test case

2020-08-10 Thread Walter Wu
Adds a test case to verify workqueue stack recording
and print the last workqueue stack in KASAN report.

The KASAN report was as follows(cleaned up slightly):

 BUG: KASAN: use-after-free in kasan_workqueue_uaf

 Freed by task 54:
  kasan_save_stack+0x24/0x50
  kasan_set_track+0x24/0x38
  kasan_set_free_info+0x20/0x40
  __kasan_slab_free+0x10c/0x170
  kasan_slab_free+0x10/0x18
  kfree+0x98/0x270
  kasan_workqueue_work+0xc/0x18

 Last workqueue stack:
  kasan_save_stack+0x24/0x50
  kasan_record_wq_stack+0xa8/0xb8
  insert_work+0x48/0x288
  __queue_work+0x3e8/0xc40
  queue_work_on+0xf4/0x118
  kasan_workqueue_uaf+0xfc/0x190

Signed-off-by: Walter Wu 
Cc: Andrey Ryabinin 
Cc: Dmitry Vyukov 
Cc: Alexander Potapenko 
Cc: Matthias Brugger 
---
 lib/test_kasan.c | 30 ++
 1 file changed, 30 insertions(+)

diff --git a/lib/test_kasan.c b/lib/test_kasan.c
index c3c6e22ec959..2c6c20cd154b 100644
--- a/lib/test_kasan.c
+++ b/lib/test_kasan.c
@@ -869,6 +869,35 @@ static noinline void __init kasan_timer_uaf(void)
((volatile struct timer_list *)timer)->expires;
 }
 
+static noinline void __init kasan_workqueue_work(struct work_struct *work)
+{
+   kfree(work);
+}
+
+static noinline void __init kasan_workqueue_uaf(void)
+{
+   struct workqueue_struct *workqueue;
+   struct work_struct *work;
+
+   workqueue = create_workqueue("kasan_wq_test");
+   if (!workqueue) {
+   pr_err("Allocation failed\n");
+   return;
+   }
+   work = kmalloc(sizeof(struct work_struct), GFP_KERNEL);
+   if (!work) {
+   pr_err("Allocation failed\n");
+   return;
+   }
+
+   INIT_WORK(work, kasan_workqueue_work);
+   queue_work(workqueue, work);
+   destroy_workqueue(workqueue);
+
+   pr_info("use-after-free on workqueue\n");
+   ((volatile struct work_struct *)work)->data;
+}
+
 static int __init kmalloc_tests_init(void)
 {
/*
@@ -918,6 +947,7 @@ static int __init kmalloc_tests_init(void)
vmalloc_oob();
kasan_rcu_uaf();
kasan_timer_uaf();
+   kasan_workqueue_uaf();
 
kasan_restore_multi_shot(multishot);
 
-- 
2.18.0


[PATCH 3/5] lib/test_kasan.c: add timer test case

2020-08-10 Thread Walter Wu
Adds a test case to verify timer stack recording
and print the last timer stack in KASAN report.

The KASAN report was as follows(cleaned up slightly):

 BUG: KASAN: use-after-free in kasan_timer_uaf

 Freed by task 0:
  kasan_save_stack+0x24/0x50
  kasan_set_track+0x24/0x38
  kasan_set_free_info+0x20/0x40
  __kasan_slab_free+0x10c/0x170
  kasan_slab_free+0x10/0x18
  kfree+0x98/0x270
  kasan_timer_function+0x1c/0x28

 Last timer stack:
  kasan_save_stack+0x24/0x50
  kasan_record_tmr_stack+0xa8/0xb8
  init_timer_key+0xf0/0x248
  kasan_timer_uaf+0x5c/0xd8

Signed-off-by: Walter Wu 
Cc: Andrey Ryabinin 
Cc: Dmitry Vyukov 
Cc: Alexander Potapenko 
Cc: Matthias Brugger 
---
 lib/test_kasan.c | 25 +
 1 file changed, 25 insertions(+)

diff --git a/lib/test_kasan.c b/lib/test_kasan.c
index 6e5fb05d42d8..2bd61674c7a3 100644
--- a/lib/test_kasan.c
+++ b/lib/test_kasan.c
@@ -821,6 +821,30 @@ static noinline void __init kasan_rcu_uaf(void)
call_rcu(_ptr->rcu, kasan_rcu_reclaim);
 }
 
+static noinline void __init kasan_timer_function(struct timer_list *timer)
+{
+   del_timer(timer);
+   kfree(timer);
+}
+
+static noinline void __init kasan_timer_uaf(void)
+{
+   struct timer_list *timer;
+
+   timer = kmalloc(sizeof(struct timer_list), GFP_KERNEL);
+   if (!timer) {
+   pr_err("Allocation failed\n");
+   return;
+   }
+
+   timer_setup(timer, kasan_timer_function, 0);
+   add_timer(timer);
+   msleep(100);
+
+   pr_info("use-after-free on timer\n");
+   ((volatile struct timer_list *)timer)->expires;
+}
+
 static int __init kmalloc_tests_init(void)
 {
/*
@@ -869,6 +893,7 @@ static int __init kmalloc_tests_init(void)
kmalloc_double_kzfree();
vmalloc_oob();
kasan_rcu_uaf();
+   kasan_timer_uaf();
 
kasan_restore_multi_shot(multishot);
 
-- 
2.18.0


[PATCH 2/5] workqueue: kasan: record and print workqueue stack

2020-08-10 Thread Walter Wu
This patch records the last two enqueueing work call stacks on workqueue
and prints up to 2 workqueue stacks in KASAN report. It is useful for
programmers to solve use-after-free or double-free memory wq issue.

When queue_work() is called, then queue the work into a workqueue, we
store this call stack in order to print it in KASAN report.

Signed-off-by: Walter Wu 
Cc: Andrey Ryabinin 
Cc: Dmitry Vyukov 
Cc: Alexander Potapenko 
Cc: Tejun Heo 
Cc: Lai Jiangshan 
Cc: Andrew Morton 
---
 include/linux/kasan.h |  2 ++
 kernel/workqueue.c|  3 +++
 mm/kasan/generic.c| 21 +
 mm/kasan/kasan.h  |  8 +---
 mm/kasan/report.c | 11 +++
 5 files changed, 42 insertions(+), 3 deletions(-)

diff --git a/include/linux/kasan.h b/include/linux/kasan.h
index 43ae040ae9b2..687cbf2faf83 100644
--- a/include/linux/kasan.h
+++ b/include/linux/kasan.h
@@ -174,6 +174,7 @@ void kasan_cache_shrink(struct kmem_cache *cache);
 void kasan_cache_shutdown(struct kmem_cache *cache);
 void kasan_record_aux_stack(void *ptr);
 void kasan_record_tmr_stack(void *ptr);
+void kasan_record_wq_stack(void *ptr);
 
 #else /* CONFIG_KASAN_GENERIC */
 
@@ -181,6 +182,7 @@ static inline void kasan_cache_shrink(struct kmem_cache 
*cache) {}
 static inline void kasan_cache_shutdown(struct kmem_cache *cache) {}
 static inline void kasan_record_aux_stack(void *ptr) {}
 static inline void kasan_record_tmr_stack(void *ptr) {}
+static inline void kasan_record_wq_stack(void *ptr) {}
 
 #endif /* CONFIG_KASAN_GENERIC */
 
diff --git a/kernel/workqueue.c b/kernel/workqueue.c
index c41c3c17b86a..0e5963e06730 100644
--- a/kernel/workqueue.c
+++ b/kernel/workqueue.c
@@ -1324,6 +1324,9 @@ static void insert_work(struct pool_workqueue *pwq, 
struct work_struct *work,
 {
struct worker_pool *pool = pwq->pool;
 
+   /* record the work in order to print it in KASAN reports */
+   kasan_record_wq_stack(work);
+
/* we own @work, set data and link */
set_work_pwq(work, pwq, extra_flags);
list_add_tail(>entry, head);
diff --git a/mm/kasan/generic.c b/mm/kasan/generic.c
index 627792d11569..592dc58fbe42 100644
--- a/mm/kasan/generic.c
+++ b/mm/kasan/generic.c
@@ -367,6 +367,27 @@ void kasan_record_tmr_stack(void *addr)
alloc_info->tmr_stack[0] = kasan_save_stack(GFP_NOWAIT);
 }
 
+void kasan_record_wq_stack(void *addr)
+{
+   struct page *page = kasan_addr_to_page(addr);
+   struct kmem_cache *cache;
+   struct kasan_alloc_meta *alloc_info;
+   void *object;
+
+   if (!(page && PageSlab(page)))
+   return;
+
+   cache = page->slab_cache;
+   object = nearest_obj(cache, page, addr);
+   alloc_info = get_alloc_info(cache, object);
+
+   /*
+* record the last two workqueue stacks.
+*/
+   alloc_info->wq_stack[1] = alloc_info->wq_stack[0];
+   alloc_info->wq_stack[0] = kasan_save_stack(GFP_NOWAIT);
+}
+
 void kasan_set_free_info(struct kmem_cache *cache,
void *object, u8 tag)
 {
diff --git a/mm/kasan/kasan.h b/mm/kasan/kasan.h
index 4059f327767c..a4f76b1bde0a 100644
--- a/mm/kasan/kasan.h
+++ b/mm/kasan/kasan.h
@@ -108,12 +108,14 @@ struct kasan_alloc_meta {
struct kasan_track alloc_track;
 #ifdef CONFIG_KASAN_GENERIC
/*
-* call_rcu() call stack and timer queueing stack are stored
-* into struct kasan_alloc_meta.
-* The free stack is stored into struct kasan_free_meta.
+* call_rcu() call stack, timer queueing stack, and workqueue
+* queueing stack are stored into kasan_alloc_meta.
+*
+* With generic KASAN the free stack is stored into kasan_free_meta.
 */
depot_stack_handle_t aux_stack[2];
depot_stack_handle_t tmr_stack[2];
+   depot_stack_handle_t wq_stack[2];
 #else
struct kasan_track free_track[KASAN_NR_FREE_STACKS];
 #endif
diff --git a/mm/kasan/report.c b/mm/kasan/report.c
index f602f090d90b..e6bc470fcd0a 100644
--- a/mm/kasan/report.c
+++ b/mm/kasan/report.c
@@ -203,6 +203,17 @@ static void describe_object(struct kmem_cache *cache, void 
*object,
print_stack(alloc_info->tmr_stack[1]);
pr_err("\n");
}
+
+   if (alloc_info->wq_stack[0]) {
+   pr_err("Last workqueue stack:\n");
+   print_stack(alloc_info->wq_stack[0]);
+   pr_err("\n");
+   }
+   if (alloc_info->wq_stack[1]) {
+   pr_err("Second to last workqueue stack:\n");
+   print_stack(alloc_info->wq_stack[1]);
+   pr_err("\n");
+   }
 #endif
}
 
-- 
2.18.0


[PATCH 1/5] timer: kasan: record and print timer stack

2020-08-10 Thread Walter Wu
This patch records the last two timer queueing stacks and prints
up to 2 timer stacks in KASAN report. It is useful for programmers
to solve use-after-free or double-free memory timer issues.

When timer_setup() or timer_setup_on_stack() is called, then it
prepares to use this timer and sets timer callback, we store
this call stack in order to print it in KASAN report.

Signed-off-by: Walter Wu 
Cc: Andrey Ryabinin 
Cc: Dmitry Vyukov 
Cc: Alexander Potapenko 
Cc: Thomas Gleixner 
Cc: John Stultz 
Cc: Stephen Boyd 
Cc: Andrew Morton 
---
 include/linux/kasan.h |  2 ++
 kernel/time/timer.c   |  2 ++
 mm/kasan/generic.c| 21 +
 mm/kasan/kasan.h  |  4 +++-
 mm/kasan/report.c | 11 +++
 5 files changed, 39 insertions(+), 1 deletion(-)

diff --git a/include/linux/kasan.h b/include/linux/kasan.h
index 23b7ee00572d..763664b36dc6 100644
--- a/include/linux/kasan.h
+++ b/include/linux/kasan.h
@@ -175,12 +175,14 @@ static inline size_t kasan_metadata_size(struct 
kmem_cache *cache) { return 0; }
 void kasan_cache_shrink(struct kmem_cache *cache);
 void kasan_cache_shutdown(struct kmem_cache *cache);
 void kasan_record_aux_stack(void *ptr);
+void kasan_record_tmr_stack(void *ptr);
 
 #else /* CONFIG_KASAN_GENERIC */
 
 static inline void kasan_cache_shrink(struct kmem_cache *cache) {}
 static inline void kasan_cache_shutdown(struct kmem_cache *cache) {}
 static inline void kasan_record_aux_stack(void *ptr) {}
+static inline void kasan_record_tmr_stack(void *ptr) {}
 
 #endif /* CONFIG_KASAN_GENERIC */
 
diff --git a/kernel/time/timer.c b/kernel/time/timer.c
index a5221abb4594..ef2da9ddfac7 100644
--- a/kernel/time/timer.c
+++ b/kernel/time/timer.c
@@ -783,6 +783,8 @@ static void do_init_timer(struct timer_list *timer,
timer->function = func;
timer->flags = flags | raw_smp_processor_id();
lockdep_init_map(>lockdep_map, name, key, 0);
+
+   kasan_record_tmr_stack(timer);
 }
 
 /**
diff --git a/mm/kasan/generic.c b/mm/kasan/generic.c
index 4b3cbad7431b..f35dcec990ab 100644
--- a/mm/kasan/generic.c
+++ b/mm/kasan/generic.c
@@ -347,6 +347,27 @@ void kasan_record_aux_stack(void *addr)
alloc_info->aux_stack[0] = kasan_save_stack(GFP_NOWAIT);
 }
 
+void kasan_record_tmr_stack(void *addr)
+{
+   struct page *page = kasan_addr_to_page(addr);
+   struct kmem_cache *cache;
+   struct kasan_alloc_meta *alloc_info;
+   void *object;
+
+   if (!(page && PageSlab(page)))
+   return;
+
+   cache = page->slab_cache;
+   object = nearest_obj(cache, page, addr);
+   alloc_info = get_alloc_info(cache, object);
+
+   /*
+* record the last two timer stacks.
+*/
+   alloc_info->tmr_stack[1] = alloc_info->tmr_stack[0];
+   alloc_info->tmr_stack[0] = kasan_save_stack(GFP_NOWAIT);
+}
+
 void kasan_set_free_info(struct kmem_cache *cache,
void *object, u8 tag)
 {
diff --git a/mm/kasan/kasan.h b/mm/kasan/kasan.h
index ef655a1c6e15..c50827f388a3 100644
--- a/mm/kasan/kasan.h
+++ b/mm/kasan/kasan.h
@@ -108,10 +108,12 @@ struct kasan_alloc_meta {
struct kasan_track alloc_track;
 #ifdef CONFIG_KASAN_GENERIC
/*
-* call_rcu() call stack is stored into struct kasan_alloc_meta.
+* call_rcu() call stack and timer queueing stack are stored
+* into struct kasan_alloc_meta.
 * The free stack is stored into struct kasan_free_meta.
 */
depot_stack_handle_t aux_stack[2];
+   depot_stack_handle_t tmr_stack[2];
 #else
struct kasan_track free_track[KASAN_NR_FREE_STACKS];
 #endif
diff --git a/mm/kasan/report.c b/mm/kasan/report.c
index fed3c8fdfd25..6fa3bfee381f 100644
--- a/mm/kasan/report.c
+++ b/mm/kasan/report.c
@@ -191,6 +191,17 @@ static void describe_object(struct kmem_cache *cache, void 
*object,
print_stack(alloc_info->aux_stack[1]);
pr_err("\n");
}
+
+   if (alloc_info->tmr_stack[0]) {
+   pr_err("Last timer stack:\n");
+   print_stack(alloc_info->tmr_stack[0]);
+   pr_err("\n");
+   }
+   if (alloc_info->tmr_stack[1]) {
+   pr_err("Second to last timer stack:\n");
+   print_stack(alloc_info->tmr_stack[1]);
+   pr_err("\n");
+   }
 #endif
}
 
-- 
2.18.0


[PATCH 0/5] kasan: add workqueue and timer stack for generic KASAN

2020-08-10 Thread Walter Wu
Syzbot reports many UAF issues for workqueue or timer, see [1] and [2].
In some of these access/allocation happened in process_one_work(),
we see the free stack is useless in KASAN report, it doesn't help
programmers to solve UAF on workqueue. The same may stand for times.

This patchset improves KASAN reports by making them to have workqueue
queueing stack and timer queueing stack information. It is useful for
programmers to solve use-after-free or double-free memory issue.

Generic KASAN will record the last two workqueue and timer stacks,
print them in KASAN report. It is only suitable for generic KASAN.

In order to print the last two workqueue and timer stacks, so that
we add new members in struct kasan_alloc_meta.
- two workqueue queueing work stacks, total size is 8 bytes.
- two timer queueing stacks, total size is 8 bytes.

Orignial struct kasan_alloc_meta size is 16 bytes. After add new
members, then the struct kasan_alloc_meta total size is 32 bytes,
It is a good number of alignment. Let it get better memory consumption.

[1]https://groups.google.com/g/syzkaller-bugs/search?q=%22use-after-free%22+process_one_work
[2]https://groups.google.com/g/syzkaller-bugs/search?q=%22use-after-free%22%20expire_timers
[3]https://bugzilla.kernel.org/show_bug.cgi?id=198437

Walter Wu (5):
timer: kasan: record and print timer stack
workqueue: kasan: record and print workqueue stack
lib/test_kasan.c: add timer test case
lib/test_kasan.c: add workqueue test case
kasan: update documentation for generic kasan

Documentation/dev-tools/kasan.rst |  4 ++--
include/linux/kasan.h |  4 
kernel/time/timer.c   |  2 ++
kernel/workqueue.c|  3 +++
lib/test_kasan.c  | 54 
++
mm/kasan/generic.c| 42 
++
mm/kasan/kasan.h  |  6 +-
mm/kasan/report.c | 22 ++
8 files changed, 134 insertions(+), 3 deletions(-)

[PATCH v8 4/4] kasan: update documentation for generic kasan

2020-07-10 Thread Walter Wu
Generic KASAN will support to record the last two call_rcu() call stacks
and print them in KASAN report. So that need to update documentation.

Signed-off-by: Walter Wu 
Reviewed-and-tested-by: Dmitry Vyukov 
Reviewed-by: Andrey Konovalov 
Cc: Andrey Ryabinin 
Cc: Alexander Potapenko 
Cc: Jonathan Corbet 
---
 Documentation/dev-tools/kasan.rst | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/Documentation/dev-tools/kasan.rst 
b/Documentation/dev-tools/kasan.rst
index c652d740735d..fede42e6536b 100644
--- a/Documentation/dev-tools/kasan.rst
+++ b/Documentation/dev-tools/kasan.rst
@@ -193,6 +193,9 @@ function calls GCC directly inserts the code to check the 
shadow memory.
 This option significantly enlarges kernel but it gives x1.1-x2 performance
 boost over outline instrumented kernel.
 
+Generic KASAN prints up to 2 call_rcu() call stacks in reports, the last one
+and the second to last.
+
 Software tag-based KASAN
 
 
-- 
2.18.0


[PATCH v8 3/4] kasan: add tests for call_rcu stack recording

2020-07-10 Thread Walter Wu
Test call_rcu() call stack recording and verify whether it correctly
is printed in KASAN report.

Signed-off-by: Walter Wu 
Reviewed-and-tested-by: Dmitry Vyukov 
Reviewed-by: Andrey Konovalov 
Cc: Andrey Ryabinin 
Cc: Alexander Potapenko 
Cc: Matthias Brugger 
---

Changes since v6:
- renamed the variable name in testcase

---
 lib/test_kasan.c | 30 ++
 1 file changed, 30 insertions(+)

diff --git a/lib/test_kasan.c b/lib/test_kasan.c
index e3087d90e00d..19c72c1501ef 100644
--- a/lib/test_kasan.c
+++ b/lib/test_kasan.c
@@ -792,6 +792,35 @@ static noinline void __init vmalloc_oob(void)
 static void __init vmalloc_oob(void) {}
 #endif
 
+static struct kasan_rcu_info {
+   int i;
+   struct rcu_head rcu;
+} *global_rcu_ptr;
+
+static noinline void __init kasan_rcu_reclaim(struct rcu_head *rp)
+{
+   struct kasan_rcu_info *fp = container_of(rp,
+   struct kasan_rcu_info, rcu);
+
+   kfree(fp);
+   fp->i = 1;
+}
+
+static noinline void __init kasan_rcu_uaf(void)
+{
+   struct kasan_rcu_info *ptr;
+
+   pr_info("use-after-free in kasan_rcu_reclaim\n");
+   ptr = kmalloc(sizeof(struct kasan_rcu_info), GFP_KERNEL);
+   if (!ptr) {
+   pr_err("Allocation failed\n");
+   return;
+   }
+
+   global_rcu_ptr = rcu_dereference_protected(ptr, NULL);
+   call_rcu(_rcu_ptr->rcu, kasan_rcu_reclaim);
+}
+
 static int __init kmalloc_tests_init(void)
 {
/*
@@ -839,6 +868,7 @@ static int __init kmalloc_tests_init(void)
kasan_bitops();
kmalloc_double_kzfree();
vmalloc_oob();
+   kasan_rcu_uaf();
 
kasan_restore_multi_shot(multishot);
 
-- 
2.18.0


[PATCH v8 2/4] kasan: record and print the free track

2020-07-10 Thread Walter Wu
Move free track from kasan_alloc_meta to kasan_free_meta in order
to make struct kasan_alloc_meta and kasan_free_meta size are both
16 bytes. It is a good size because it is the minimal redzone size
and a good number of alignment.

For free track, we make some modifications as shown below:
1) Remove the free_track from struct kasan_alloc_meta.
2) Add the free_track into struct kasan_free_meta.
3) Add a macro KASAN_KMALLOC_FREETRACK in order to check whether
   it can print free stack in KASAN report.

[1]https://bugzilla.kernel.org/show_bug.cgi?id=198437

Signed-off-by: Walter Wu 
Suggested-by: Dmitry Vyukov 
Co-developed-by: Dmitry Vyukov 
Reviewed-and-tested-by: Dmitry Vyukov 
Reviewed-by: Andrey Konovalov 
Cc: Andrey Ryabinin 
Cc: Alexander Potapenko 
---

Changes since v7:
- fix this commit dependence in the series

---
 mm/kasan/common.c | 22 ++
 mm/kasan/generic.c| 22 ++
 mm/kasan/generic_report.c |  1 +
 mm/kasan/kasan.h  | 16 +---
 mm/kasan/quarantine.c |  1 +
 mm/kasan/report.c | 26 --
 mm/kasan/tags.c   | 37 +
 7 files changed, 80 insertions(+), 45 deletions(-)

diff --git a/mm/kasan/common.c b/mm/kasan/common.c
index 8bc618289bb1..47b53912f322 100644
--- a/mm/kasan/common.c
+++ b/mm/kasan/common.c
@@ -51,7 +51,7 @@ depot_stack_handle_t kasan_save_stack(gfp_t flags)
return stack_depot_save(entries, nr_entries, flags);
 }
 
-static inline void set_track(struct kasan_track *track, gfp_t flags)
+void kasan_set_track(struct kasan_track *track, gfp_t flags)
 {
track->pid = current->pid;
track->stack = kasan_save_stack(flags);
@@ -299,24 +299,6 @@ struct kasan_free_meta *get_free_info(struct kmem_cache 
*cache,
return (void *)object + cache->kasan_info.free_meta_offset;
 }
 
-
-static void kasan_set_free_info(struct kmem_cache *cache,
-   void *object, u8 tag)
-{
-   struct kasan_alloc_meta *alloc_meta;
-   u8 idx = 0;
-
-   alloc_meta = get_alloc_info(cache, object);
-
-#ifdef CONFIG_KASAN_SW_TAGS_IDENTIFY
-   idx = alloc_meta->free_track_idx;
-   alloc_meta->free_pointer_tag[idx] = tag;
-   alloc_meta->free_track_idx = (idx + 1) % KASAN_NR_FREE_STACKS;
-#endif
-
-   set_track(_meta->free_track[idx], GFP_NOWAIT);
-}
-
 void kasan_poison_slab(struct page *page)
 {
unsigned long i;
@@ -492,7 +474,7 @@ static void *__kasan_kmalloc(struct kmem_cache *cache, 
const void *object,
KASAN_KMALLOC_REDZONE);
 
if (cache->flags & SLAB_KASAN)
-   set_track(_alloc_info(cache, object)->alloc_track, flags);
+   kasan_set_track(_alloc_info(cache, object)->alloc_track, 
flags);
 
return set_tag(object, tag);
 }
diff --git a/mm/kasan/generic.c b/mm/kasan/generic.c
index 8acf48882ba2..4b3cbad7431b 100644
--- a/mm/kasan/generic.c
+++ b/mm/kasan/generic.c
@@ -346,3 +346,25 @@ void kasan_record_aux_stack(void *addr)
alloc_info->aux_stack[1] = alloc_info->aux_stack[0];
alloc_info->aux_stack[0] = kasan_save_stack(GFP_NOWAIT);
 }
+
+void kasan_set_free_info(struct kmem_cache *cache,
+   void *object, u8 tag)
+{
+   struct kasan_free_meta *free_meta;
+
+   free_meta = get_free_info(cache, object);
+   kasan_set_track(_meta->free_track, GFP_NOWAIT);
+
+   /*
+*  the object was freed and has free track set
+*/
+   *(u8 *)kasan_mem_to_shadow(object) = KASAN_KMALLOC_FREETRACK;
+}
+
+struct kasan_track *kasan_get_free_track(struct kmem_cache *cache,
+   void *object, u8 tag)
+{
+   if (*(u8 *)kasan_mem_to_shadow(object) != KASAN_KMALLOC_FREETRACK)
+   return NULL;
+   return _free_info(cache, object)->free_track;
+}
diff --git a/mm/kasan/generic_report.c b/mm/kasan/generic_report.c
index e200acb2d292..a38c7a9e192a 100644
--- a/mm/kasan/generic_report.c
+++ b/mm/kasan/generic_report.c
@@ -80,6 +80,7 @@ static const char *get_shadow_bug_type(struct 
kasan_access_info *info)
break;
case KASAN_FREE_PAGE:
case KASAN_KMALLOC_FREE:
+   case KASAN_KMALLOC_FREETRACK:
bug_type = "use-after-free";
break;
case KASAN_ALLOCA_LEFT:
diff --git a/mm/kasan/kasan.h b/mm/kasan/kasan.h
index b1a88c75416a..ef655a1c6e15 100644
--- a/mm/kasan/kasan.h
+++ b/mm/kasan/kasan.h
@@ -17,15 +17,17 @@
 #define KASAN_PAGE_REDZONE  0xFE  /* redzone for kmalloc_large allocations 
*/
 #define KASAN_KMALLOC_REDZONE   0xFC  /* redzone inside slub object */
 #define KASAN_KMALLOC_FREE  0xFB  /* object was freed 
(kmem_cache_free/kfree) */
+#define KASAN_KMALLOC_FREETRACK 0xFA  /* object was freed and has free track 
set */
 #else
 #define KASAN_FREE_PAGE KASAN_TAG_INVALID
 #define KASAN_PAGE

[PATCH v8 1/4] rcu: kasan: record and print call_rcu() call stack

2020-07-10 Thread Walter Wu
This feature will record the last two call_rcu() call stacks and
prints up to 2 call_rcu() call stacks in KASAN report.

When call_rcu() is called, we store the call_rcu() call stack into
slub alloc meta-data, so that the KASAN report can print rcu stack.

[1]https://bugzilla.kernel.org/show_bug.cgi?id=198437
[2]https://groups.google.com/forum/#!searchin/kasan-dev/better$20stack$20traces$20for$20rcu%7Csort:date/kasan-dev/KQsjT_88hDE/7rNUZprRBgAJ

Signed-off-by: Walter Wu 
Suggested-by: Dmitry Vyukov 
Acked-by: Paul E. McKenney 
Reviewed-and-tested-by: Dmitry Vyukov 
Reviewed-by: Andrey Konovalov 
Cc: Andrey Ryabinin 
Cc: Alexander Potapenko 
Cc: Andrew Morton 
Cc: Josh Triplett 
Cc: Mathieu Desnoyers 
Cc: Lai Jiangshan 
Cc: Joel Fernandes 
---

Changes since v7:
- fix this commit dependence in the series

Changes since v6:
- fix typo

---
 include/linux/kasan.h |  2 ++
 kernel/rcu/tree.c |  2 ++
 mm/kasan/common.c |  4 ++--
 mm/kasan/generic.c| 21 +
 mm/kasan/kasan.h  |  9 +
 mm/kasan/report.c | 28 +++-
 6 files changed, 59 insertions(+), 7 deletions(-)

diff --git a/include/linux/kasan.h b/include/linux/kasan.h
index 31314ca7c635..23b7ee00572d 100644
--- a/include/linux/kasan.h
+++ b/include/linux/kasan.h
@@ -174,11 +174,13 @@ static inline size_t kasan_metadata_size(struct 
kmem_cache *cache) { return 0; }
 
 void kasan_cache_shrink(struct kmem_cache *cache);
 void kasan_cache_shutdown(struct kmem_cache *cache);
+void kasan_record_aux_stack(void *ptr);
 
 #else /* CONFIG_KASAN_GENERIC */
 
 static inline void kasan_cache_shrink(struct kmem_cache *cache) {}
 static inline void kasan_cache_shutdown(struct kmem_cache *cache) {}
+static inline void kasan_record_aux_stack(void *ptr) {}
 
 #endif /* CONFIG_KASAN_GENERIC */
 
diff --git a/kernel/rcu/tree.c b/kernel/rcu/tree.c
index 06548e2ebb72..36a4ff7f320b 100644
--- a/kernel/rcu/tree.c
+++ b/kernel/rcu/tree.c
@@ -57,6 +57,7 @@
 #include 
 #include 
 #include 
+#include 
 #include "../time/tick-internal.h"
 
 #include "tree.h"
@@ -2668,6 +2669,7 @@ __call_rcu(struct rcu_head *head, rcu_callback_t func)
head->func = func;
head->next = NULL;
local_irq_save(flags);
+   kasan_record_aux_stack(head);
rdp = this_cpu_ptr(_data);
 
/* Add the callback to our list. */
diff --git a/mm/kasan/common.c b/mm/kasan/common.c
index 2906358e42f0..8bc618289bb1 100644
--- a/mm/kasan/common.c
+++ b/mm/kasan/common.c
@@ -41,7 +41,7 @@
 #include "kasan.h"
 #include "../slab.h"
 
-static inline depot_stack_handle_t save_stack(gfp_t flags)
+depot_stack_handle_t kasan_save_stack(gfp_t flags)
 {
unsigned long entries[KASAN_STACK_DEPTH];
unsigned int nr_entries;
@@ -54,7 +54,7 @@ static inline depot_stack_handle_t save_stack(gfp_t flags)
 static inline void set_track(struct kasan_track *track, gfp_t flags)
 {
track->pid = current->pid;
-   track->stack = save_stack(flags);
+   track->stack = kasan_save_stack(flags);
 }
 
 void kasan_enable_current(void)
diff --git a/mm/kasan/generic.c b/mm/kasan/generic.c
index 56ff8885fe2e..8acf48882ba2 100644
--- a/mm/kasan/generic.c
+++ b/mm/kasan/generic.c
@@ -325,3 +325,24 @@ DEFINE_ASAN_SET_SHADOW(f2);
 DEFINE_ASAN_SET_SHADOW(f3);
 DEFINE_ASAN_SET_SHADOW(f5);
 DEFINE_ASAN_SET_SHADOW(f8);
+
+void kasan_record_aux_stack(void *addr)
+{
+   struct page *page = kasan_addr_to_page(addr);
+   struct kmem_cache *cache;
+   struct kasan_alloc_meta *alloc_info;
+   void *object;
+
+   if (!(page && PageSlab(page)))
+   return;
+
+   cache = page->slab_cache;
+   object = nearest_obj(cache, page, addr);
+   alloc_info = get_alloc_info(cache, object);
+
+   /*
+* record the last two call_rcu() call stacks.
+*/
+   alloc_info->aux_stack[1] = alloc_info->aux_stack[0];
+   alloc_info->aux_stack[0] = kasan_save_stack(GFP_NOWAIT);
+}
diff --git a/mm/kasan/kasan.h b/mm/kasan/kasan.h
index e8f37199d885..b1a88c75416a 100644
--- a/mm/kasan/kasan.h
+++ b/mm/kasan/kasan.h
@@ -104,6 +104,13 @@ struct kasan_track {
 
 struct kasan_alloc_meta {
struct kasan_track alloc_track;
+#ifdef CONFIG_KASAN_GENERIC
+   /*
+* call_rcu() call stack is stored into struct kasan_alloc_meta.
+* The free stack is stored into struct kasan_free_meta.
+*/
+   depot_stack_handle_t aux_stack[2];
+#endif
struct kasan_track free_track[KASAN_NR_FREE_STACKS];
 #ifdef CONFIG_KASAN_SW_TAGS_IDENTIFY
u8 free_pointer_tag[KASAN_NR_FREE_STACKS];
@@ -159,6 +166,8 @@ void kasan_report_invalid_free(void *object, unsigned long 
ip);
 
 struct page *kasan_addr_to_page(const void *addr);
 
+depot_stack_handle_t kasan_save_stack(gfp_t flags);
+
 #if defined(CONFIG_KASAN_GENERIC) && \
(defined(CONFIG_SLAB) || defined(CONFIG_SLUB))
 void quarant

[PATCH v8 0/4] kasan: memorize and print call_rcu stack

2020-07-10 Thread Walter Wu
This patchset improves KASAN reports by making them to have
call_rcu() call stack information. It is useful for programmers
to solve use-after-free or double-free memory issue.

The KASAN report was as follows(cleaned up slightly):

BUG: KASAN: use-after-free in kasan_rcu_reclaim+0x58/0x60

Freed by task 0:
 kasan_save_stack+0x24/0x50
 kasan_set_track+0x24/0x38
 kasan_set_free_info+0x18/0x20
 __kasan_slab_free+0x10c/0x170
 kasan_slab_free+0x10/0x18
 kfree+0x98/0x270
 kasan_rcu_reclaim+0x1c/0x60

Last call_rcu():
 kasan_save_stack+0x24/0x50
 kasan_record_aux_stack+0xbc/0xd0
 call_rcu+0x8c/0x580
 kasan_rcu_uaf+0xf4/0xf8

Generic KASAN will record the last two call_rcu() call stacks and
print up to 2 call_rcu() call stacks in KASAN report. it is only
suitable for generic KASAN.

This feature considers the size of struct kasan_alloc_meta and
kasan_free_meta, we try to optimize the structure layout and size
, lets it get better memory consumption.

[1]https://bugzilla.kernel.org/show_bug.cgi?id=198437
[2]https://groups.google.com/forum/#!searchin/kasan-dev/better$20stack$20traces$20for$20rcu%7Csort:date/kasan-dev/KQsjT_88hDE/7rNUZprRBgAJ

Changes since v1:
- remove new config option, default enable it in generic KASAN
- test this feature in SLAB/SLUB, it is pass.
- modify macro to be more clearly
- modify documentation

Changes since v2:
- change recording from first/last to the last two call stacks
- move free track into kasan free meta
- init slab_free_meta on object slot creation
- modify documentation

Changes since v3:
- change variable name to be more clearly
- remove the redundant condition
- remove init free meta-data and increasing object condition

Changes since v4:
- add a macro KASAN_KMALLOC_FREETRACK in order to check whether
  print free stack
- change printing message
- remove descriptions in Kocong.kasan

Changes since v5:
- reuse print_stack() in print_track()

Changes since v6:
- fix typo
- renamed the variable name in testcase

Changes since v7:
- fix this commit dependence in the series

Walter Wu (4):
rcu: kasan: record and print call_rcu() call stack
kasan: record and print the free track
kasan: add tests for call_rcu stack recording
kasan: update documentation for generic kasan

Documentation/dev-tools/kasan.rst |  3 +++
include/linux/kasan.h |  2 ++
kernel/rcu/tree.c |  2 ++
lib/test_kasan.c  | 30 ++
mm/kasan/common.c | 26 --
mm/kasan/generic.c| 43 
+++
mm/kasan/generic_report.c |  1 +
mm/kasan/kasan.h  | 23 +--
mm/kasan/quarantine.c |  1 +
mm/kasan/report.c | 54 
+++---
mm/kasan/tags.c   | 37 +
11 files changed, 171 insertions(+), 51 deletions(-)

[PATCH v4] kasan: fix KASAN unit tests for tag-based KASAN

2020-07-08 Thread Walter Wu
We use tag-based KASAN, then KASAN unit tests don't detect out-of-bounds
memory access. They need to be fixed.

With tag-based KASAN, the state of each 16 aligned bytes of memory is
encoded in one shadow byte and the shadow value is tag of pointer, so
we need to read next shadow byte, the shadow value is not equal to tag
value of pointer, so that tag-based KASAN will detect out-of-bounds
memory access.

Signed-off-by: Walter Wu 
Suggested-by: Dmitry Vyukov 
Acked-by: Dmitry Vyukov 
Reviewed-by: Andrey Konovalov 
Cc: Andrey Ryabinin 
Cc: Alexander Potapenko 
Cc: Matthias Brugger 
Cc: Andrew Morton 
---

changes since v1:
- Reduce amount of non-compiled code.
- KUnit-KASAN Integration patchset is not merged yet. My patch should
  have conflict with it, if needed, we can continue to wait it.

changes since v2:
- Add one marco to make unit tests more readability.

changes since v3:
- use KASAN_SHADOW_SCALE_SIZE instead of 13.

---
 lib/test_kasan.c | 49 +++-
 1 file changed, 32 insertions(+), 17 deletions(-)

diff --git a/lib/test_kasan.c b/lib/test_kasan.c
index 61a3cc11556f..003ea5b49f4c 100644
--- a/lib/test_kasan.c
+++ b/lib/test_kasan.c
@@ -23,6 +23,10 @@
 
 #include 
 
+#include "../mm/kasan/kasan.h"
+
+#define OOB_TAG_OFF (IS_ENABLED(CONFIG_KASAN_GENERIC) ? 0 : 
KASAN_SHADOW_SCALE_SIZE)
+
 /*
  * Note: test functions are marked noinline so that their names appear in
  * reports.
@@ -40,7 +44,8 @@ static noinline void __init kmalloc_oob_right(void)
return;
}
 
-   ptr[size] = 'x';
+   ptr[size + OOB_TAG_OFF] = 'x';
+
kfree(ptr);
 }
 
@@ -92,7 +97,8 @@ static noinline void __init kmalloc_pagealloc_oob_right(void)
return;
}
 
-   ptr[size] = 0;
+   ptr[size + OOB_TAG_OFF] = 0;
+
kfree(ptr);
 }
 
@@ -162,7 +168,8 @@ static noinline void __init kmalloc_oob_krealloc_more(void)
return;
}
 
-   ptr2[size2] = 'x';
+   ptr2[size2 + OOB_TAG_OFF] = 'x';
+
kfree(ptr2);
 }
 
@@ -180,7 +187,9 @@ static noinline void __init kmalloc_oob_krealloc_less(void)
kfree(ptr1);
return;
}
-   ptr2[size2] = 'x';
+
+   ptr2[size2 + OOB_TAG_OFF] = 'x';
+
kfree(ptr2);
 }
 
@@ -216,7 +225,8 @@ static noinline void __init kmalloc_oob_memset_2(void)
return;
}
 
-   memset(ptr+7, 0, 2);
+   memset(ptr + 7 + OOB_TAG_OFF, 0, 2);
+
kfree(ptr);
 }
 
@@ -232,7 +242,8 @@ static noinline void __init kmalloc_oob_memset_4(void)
return;
}
 
-   memset(ptr+5, 0, 4);
+   memset(ptr + 5 + OOB_TAG_OFF, 0, 4);
+
kfree(ptr);
 }
 
@@ -249,7 +260,8 @@ static noinline void __init kmalloc_oob_memset_8(void)
return;
}
 
-   memset(ptr+1, 0, 8);
+   memset(ptr + 1 + OOB_TAG_OFF, 0, 8);
+
kfree(ptr);
 }
 
@@ -265,7 +277,8 @@ static noinline void __init kmalloc_oob_memset_16(void)
return;
}
 
-   memset(ptr+1, 0, 16);
+   memset(ptr + 1 + OOB_TAG_OFF, 0, 16);
+
kfree(ptr);
 }
 
@@ -281,7 +294,8 @@ static noinline void __init kmalloc_oob_in_memset(void)
return;
}
 
-   memset(ptr, 0, size+5);
+   memset(ptr, 0, size + 5 + OOB_TAG_OFF);
+
kfree(ptr);
 }
 
@@ -415,7 +429,8 @@ static noinline void __init kmem_cache_oob(void)
return;
}
 
-   *p = p[size];
+   *p = p[size + OOB_TAG_OFF];
+
kmem_cache_free(cache, p);
kmem_cache_destroy(cache);
 }
@@ -512,25 +527,25 @@ static noinline void __init copy_user_test(void)
}
 
pr_info("out-of-bounds in copy_from_user()\n");
-   unused = copy_from_user(kmem, usermem, size + 1);
+   unused = copy_from_user(kmem, usermem, size + 1 + OOB_TAG_OFF);
 
pr_info("out-of-bounds in copy_to_user()\n");
-   unused = copy_to_user(usermem, kmem, size + 1);
+   unused = copy_to_user(usermem, kmem, size + 1 + OOB_TAG_OFF);
 
pr_info("out-of-bounds in __copy_from_user()\n");
-   unused = __copy_from_user(kmem, usermem, size + 1);
+   unused = __copy_from_user(kmem, usermem, size + 1 + OOB_TAG_OFF);
 
pr_info("out-of-bounds in __copy_to_user()\n");
-   unused = __copy_to_user(usermem, kmem, size + 1);
+   unused = __copy_to_user(usermem, kmem, size + 1 + OOB_TAG_OFF);
 
pr_info("out-of-bounds in __copy_from_user_inatomic()\n");
-   unused = __copy_from_user_inatomic(kmem, usermem, size + 1);
+   unused = __copy_from_user_inatomic(kmem, usermem, size + 1 + 
OOB_TAG_OFF);
 
pr_info("out-of-bounds in __copy_to_user_inatomic()\n");
-   unused = __copy_to_user_inatomic(usermem, kmem, size + 1);
+   unused = __copy_to_user_inatomic(usermem, kmem, size + 1 + OOB_TAG_OFF);
 
pr_info("out-of-bounds in strn

[PATCH v3] kasan: fix KASAN unit tests for tag-based KASAN

2020-07-06 Thread Walter Wu
We use tag-based KASAN, then KASAN unit tests don't detect out-of-bounds
memory access. They need to be fixed.

With tag-based KASAN, the state of each 16 aligned bytes of memory is
encoded in one shadow byte and the shadow value is tag of pointer, so
we need to read next shadow byte, the shadow value is not equal to tag
value of pointer, so that tag-based KASAN will detect out-of-bounds
memory access.

Signed-off-by: Walter Wu 
Suggested-by: Dmitry Vyukov 
Cc: Andrey Ryabinin 
Cc: Dmitry Vyukov 
Cc: Alexander Potapenko 
Cc: Matthias Brugger 
Cc: Andrey Konovalov 
Cc: Andrew Morton 
---

changes since v1:
- Reduce amount of non-compiled code.
- KUnit-KASAN Integration patchset is not merged yet. My patch should
  have conflict with it, if needed, we can continue to wait it.

changes since v2:
- Add one marco to make unit tests more readability.

---
 lib/test_kasan.c | 47 ++-
 1 file changed, 30 insertions(+), 17 deletions(-)

diff --git a/lib/test_kasan.c b/lib/test_kasan.c
index e3087d90e00d..b5049a807e25 100644
--- a/lib/test_kasan.c
+++ b/lib/test_kasan.c
@@ -23,6 +23,8 @@
 
 #include 
 
+#define OOB_TAG_OFF (IS_ENABLED(CONFIG_KASAN_GENERIC) ? 0 : 13)
+
 /*
  * Note: test functions are marked noinline so that their names appear in
  * reports.
@@ -40,7 +42,8 @@ static noinline void __init kmalloc_oob_right(void)
return;
}
 
-   ptr[size] = 'x';
+   ptr[size + OOB_TAG_OFF] = 'x';
+
kfree(ptr);
 }
 
@@ -92,7 +95,8 @@ static noinline void __init kmalloc_pagealloc_oob_right(void)
return;
}
 
-   ptr[size] = 0;
+   ptr[size + OOB_TAG_OFF] = 0;
+
kfree(ptr);
 }
 
@@ -162,7 +166,8 @@ static noinline void __init kmalloc_oob_krealloc_more(void)
return;
}
 
-   ptr2[size2] = 'x';
+   ptr2[size2 + OOB_TAG_OFF] = 'x';
+
kfree(ptr2);
 }
 
@@ -180,7 +185,9 @@ static noinline void __init kmalloc_oob_krealloc_less(void)
kfree(ptr1);
return;
}
-   ptr2[size2] = 'x';
+
+   ptr2[size2 + OOB_TAG_OFF] = 'x';
+
kfree(ptr2);
 }
 
@@ -216,7 +223,8 @@ static noinline void __init kmalloc_oob_memset_2(void)
return;
}
 
-   memset(ptr+7, 0, 2);
+   memset(ptr + 7 + OOB_TAG_OFF, 0, 2);
+
kfree(ptr);
 }
 
@@ -232,7 +240,8 @@ static noinline void __init kmalloc_oob_memset_4(void)
return;
}
 
-   memset(ptr+5, 0, 4);
+   memset(ptr + 5 + OOB_TAG_OFF, 0, 4);
+
kfree(ptr);
 }
 
@@ -249,7 +258,8 @@ static noinline void __init kmalloc_oob_memset_8(void)
return;
}
 
-   memset(ptr+1, 0, 8);
+   memset(ptr + 1 + OOB_TAG_OFF, 0, 8);
+
kfree(ptr);
 }
 
@@ -265,7 +275,8 @@ static noinline void __init kmalloc_oob_memset_16(void)
return;
}
 
-   memset(ptr+1, 0, 16);
+   memset(ptr + 1 + OOB_TAG_OFF, 0, 16);
+
kfree(ptr);
 }
 
@@ -281,7 +292,8 @@ static noinline void __init kmalloc_oob_in_memset(void)
return;
}
 
-   memset(ptr, 0, size+5);
+   memset(ptr, 0, size + 5 + OOB_TAG_OFF);
+
kfree(ptr);
 }
 
@@ -415,7 +427,8 @@ static noinline void __init kmem_cache_oob(void)
return;
}
 
-   *p = p[size];
+   *p = p[size + OOB_TAG_OFF];
+
kmem_cache_free(cache, p);
kmem_cache_destroy(cache);
 }
@@ -512,25 +525,25 @@ static noinline void __init copy_user_test(void)
}
 
pr_info("out-of-bounds in copy_from_user()\n");
-   unused = copy_from_user(kmem, usermem, size + 1);
+   unused = copy_from_user(kmem, usermem, size + 1 + OOB_TAG_OFF);
 
pr_info("out-of-bounds in copy_to_user()\n");
-   unused = copy_to_user(usermem, kmem, size + 1);
+   unused = copy_to_user(usermem, kmem, size + 1 + OOB_TAG_OFF);
 
pr_info("out-of-bounds in __copy_from_user()\n");
-   unused = __copy_from_user(kmem, usermem, size + 1);
+   unused = __copy_from_user(kmem, usermem, size + 1 + OOB_TAG_OFF);
 
pr_info("out-of-bounds in __copy_to_user()\n");
-   unused = __copy_to_user(usermem, kmem, size + 1);
+   unused = __copy_to_user(usermem, kmem, size + 1 + OOB_TAG_OFF);
 
pr_info("out-of-bounds in __copy_from_user_inatomic()\n");
-   unused = __copy_from_user_inatomic(kmem, usermem, size + 1);
+   unused = __copy_from_user_inatomic(kmem, usermem, size + 1 + 
OOB_TAG_OFF);
 
pr_info("out-of-bounds in __copy_to_user_inatomic()\n");
-   unused = __copy_to_user_inatomic(usermem, kmem, size + 1);
+   unused = __copy_to_user_inatomic(usermem, kmem, size + 1 + OOB_TAG_OFF);
 
pr_info("out-of-bounds in strncpy_from_user()\n");
-   unused = strncpy_from_user(kmem, usermem, size + 1);
+   unused = strncpy_from_user(kmem, usermem, size + 1

Re: [PATCH v2] kasan: fix KASAN unit tests for tag-based KASAN

2020-07-06 Thread Walter Wu
On Mon, 2020-07-06 at 08:19 +0200, Dmitry Vyukov wrote:
> On Mon, Jul 6, 2020 at 4:21 AM Walter Wu  wrote:
> >
> > We use tag-based KASAN, then KASAN unit tests don't detect out-of-bounds
> > memory access. They need to be fixed.
> >
> > With tag-based KASAN, the state of each 16 aligned bytes of memory is
> > encoded in one shadow byte and the shadow value is tag of pointer, so
> > we need to read next shadow byte, the shadow value is not equal to tag
> > value of pointer, so that tag-based KASAN will detect out-of-bounds
> > memory access.
> >
> > Signed-off-by: Walter Wu 
> > Cc: Andrey Ryabinin 
> > Cc: Dmitry Vyukov 
> > Cc: Alexander Potapenko 
> > Cc: Matthias Brugger 
> > Cc: Andrey Konovalov 
> > Cc: Andrew Morton 
> > ---
> >
> > changes since v1:
> > - Reduce amount of non-compiled code.
> > - KUnit-KASAN Integration patchset are not merged yet. My patch should
> >   have conflict with it, if needed, we can continue to wait it.
> >
> > ---
> >
> >  lib/test_kasan.c | 81 ++--
> >  1 file changed, 64 insertions(+), 17 deletions(-)
> >
> > diff --git a/lib/test_kasan.c b/lib/test_kasan.c
> > index e3087d90e00d..660664439d52 100644
> > --- a/lib/test_kasan.c
> > +++ b/lib/test_kasan.c
> > @@ -40,7 +40,11 @@ static noinline void __init kmalloc_oob_right(void)
> > return;
> > }
> >
> > -   ptr[size] = 'x';
> > +   if (IS_ENABLED(CONFIG_KASAN_GENERIC))
> > +   ptr[size] = 'x';
> > +   else
> > +   ptr[size + 5] = 'x';
> > +
> 
> Hi Walter,
> 
> Would if be possible to introduce something like:
> 
> #define OOB_TAG_OFF (IS_ENABLED(CONFIG_KASAN_GENERIC) ? 0 : 8)
> 

It is good suggestion. Thanks.

> and then add it throughout as
> 
> ptr[size + OOB_TAG_OFF] = 'x';
> 
> ?
> The current version results in quite some amount of additional code
> that needs to be read, extended  and maintained in the future. So I am
> thinking if it's possible to minimize it somehow...
> 

Ok, I will send next patch by your suggestion.

Thanks.

> > kfree(ptr);
> >  }
> >
> > @@ -92,7 +96,11 @@ static noinline void __init 
> > kmalloc_pagealloc_oob_right(void)
> > return;
> > }
> >
> > -   ptr[size] = 0;
> > +   if (IS_ENABLED(CONFIG_KASAN_GENERIC))
> > +   ptr[size] = 0;
> > +   else
> > +   ptr[size + 6] = 0;
> > +
> > kfree(ptr);
> >  }
> >
> > @@ -162,7 +170,11 @@ static noinline void __init 
> > kmalloc_oob_krealloc_more(void)
> > return;
> > }
> >
> > -   ptr2[size2] = 'x';
> > +   if (IS_ENABLED(CONFIG_KASAN_GENERIC))
> > +   ptr2[size2] = 'x';
> > +   else
> > +   ptr2[size2 + 13] = 'x';
> > +
> > kfree(ptr2);
> >  }
> >
> > @@ -180,7 +192,12 @@ static noinline void __init 
> > kmalloc_oob_krealloc_less(void)
> > kfree(ptr1);
> > return;
> > }
> > -   ptr2[size2] = 'x';
> > +
> > +   if (IS_ENABLED(CONFIG_KASAN_GENERIC))
> > +   ptr2[size2] = 'x';
> > +   else
> > +   ptr2[size2 + 2] = 'x';
> > +
> > kfree(ptr2);
> >  }
> >
> > @@ -216,7 +233,11 @@ static noinline void __init kmalloc_oob_memset_2(void)
> > return;
> > }
> >
> > -   memset(ptr+7, 0, 2);
> > +   if (IS_ENABLED(CONFIG_KASAN_GENERIC))
> > +   memset(ptr+7, 0, 2);
> > +   else
> > +   memset(ptr+15, 0, 2);
> > +
> > kfree(ptr);
> >  }
> >
> > @@ -232,7 +253,11 @@ static noinline void __init kmalloc_oob_memset_4(void)
> > return;
> > }
> >
> > -   memset(ptr+5, 0, 4);
> > +   if (IS_ENABLED(CONFIG_KASAN_GENERIC))
> > +   memset(ptr+5, 0, 4);
> > +   else
> > +   memset(ptr+15, 0, 4);
> > +
> > kfree(ptr);
> >  }
> >
> > @@ -249,7 +274,11 @@ static noinline void __init kmalloc_oob_memset_8(void)
> > return;
> > }
> >
> > -   memset(ptr+1, 0, 8);
> > +   if (IS_ENABLED(CONFIG_KASAN_GENERIC))
> > +   memset(ptr+1, 0, 8);
> > +   else
> > +   memset(ptr+1

[PATCH v2] kasan: fix KASAN unit tests for tag-based KASAN

2020-07-05 Thread Walter Wu
We use tag-based KASAN, then KASAN unit tests don't detect out-of-bounds
memory access. They need to be fixed.

With tag-based KASAN, the state of each 16 aligned bytes of memory is
encoded in one shadow byte and the shadow value is tag of pointer, so
we need to read next shadow byte, the shadow value is not equal to tag
value of pointer, so that tag-based KASAN will detect out-of-bounds
memory access.

Signed-off-by: Walter Wu 
Cc: Andrey Ryabinin 
Cc: Dmitry Vyukov 
Cc: Alexander Potapenko 
Cc: Matthias Brugger 
Cc: Andrey Konovalov 
Cc: Andrew Morton 
---

changes since v1:
- Reduce amount of non-compiled code.
- KUnit-KASAN Integration patchset are not merged yet. My patch should
  have conflict with it, if needed, we can continue to wait it.

---

 lib/test_kasan.c | 81 ++--
 1 file changed, 64 insertions(+), 17 deletions(-)

diff --git a/lib/test_kasan.c b/lib/test_kasan.c
index e3087d90e00d..660664439d52 100644
--- a/lib/test_kasan.c
+++ b/lib/test_kasan.c
@@ -40,7 +40,11 @@ static noinline void __init kmalloc_oob_right(void)
return;
}
 
-   ptr[size] = 'x';
+   if (IS_ENABLED(CONFIG_KASAN_GENERIC))
+   ptr[size] = 'x';
+   else
+   ptr[size + 5] = 'x';
+
kfree(ptr);
 }
 
@@ -92,7 +96,11 @@ static noinline void __init kmalloc_pagealloc_oob_right(void)
return;
}
 
-   ptr[size] = 0;
+   if (IS_ENABLED(CONFIG_KASAN_GENERIC))
+   ptr[size] = 0;
+   else
+   ptr[size + 6] = 0;
+
kfree(ptr);
 }
 
@@ -162,7 +170,11 @@ static noinline void __init kmalloc_oob_krealloc_more(void)
return;
}
 
-   ptr2[size2] = 'x';
+   if (IS_ENABLED(CONFIG_KASAN_GENERIC))
+   ptr2[size2] = 'x';
+   else
+   ptr2[size2 + 13] = 'x';
+
kfree(ptr2);
 }
 
@@ -180,7 +192,12 @@ static noinline void __init kmalloc_oob_krealloc_less(void)
kfree(ptr1);
return;
}
-   ptr2[size2] = 'x';
+
+   if (IS_ENABLED(CONFIG_KASAN_GENERIC))
+   ptr2[size2] = 'x';
+   else
+   ptr2[size2 + 2] = 'x';
+
kfree(ptr2);
 }
 
@@ -216,7 +233,11 @@ static noinline void __init kmalloc_oob_memset_2(void)
return;
}
 
-   memset(ptr+7, 0, 2);
+   if (IS_ENABLED(CONFIG_KASAN_GENERIC))
+   memset(ptr+7, 0, 2);
+   else
+   memset(ptr+15, 0, 2);
+
kfree(ptr);
 }
 
@@ -232,7 +253,11 @@ static noinline void __init kmalloc_oob_memset_4(void)
return;
}
 
-   memset(ptr+5, 0, 4);
+   if (IS_ENABLED(CONFIG_KASAN_GENERIC))
+   memset(ptr+5, 0, 4);
+   else
+   memset(ptr+15, 0, 4);
+
kfree(ptr);
 }
 
@@ -249,7 +274,11 @@ static noinline void __init kmalloc_oob_memset_8(void)
return;
}
 
-   memset(ptr+1, 0, 8);
+   if (IS_ENABLED(CONFIG_KASAN_GENERIC))
+   memset(ptr+1, 0, 8);
+   else
+   memset(ptr+15, 0, 8);
+
kfree(ptr);
 }
 
@@ -265,7 +294,11 @@ static noinline void __init kmalloc_oob_memset_16(void)
return;
}
 
-   memset(ptr+1, 0, 16);
+   if (IS_ENABLED(CONFIG_KASAN_GENERIC))
+   memset(ptr+1, 0, 16);
+   else
+   memset(ptr+15, 0, 16);
+
kfree(ptr);
 }
 
@@ -281,7 +314,11 @@ static noinline void __init kmalloc_oob_in_memset(void)
return;
}
 
-   memset(ptr, 0, size+5);
+   if (IS_ENABLED(CONFIG_KASAN_GENERIC))
+   memset(ptr, 0, size+5);
+   else
+   memset(ptr, 0, size+7);
+
kfree(ptr);
 }
 
@@ -415,7 +452,11 @@ static noinline void __init kmem_cache_oob(void)
return;
}
 
-   *p = p[size];
+   if (IS_ENABLED(CONFIG_KASAN_GENERIC))
+   *p = p[size];
+   else
+   *p = p[size + 8];
+
kmem_cache_free(cache, p);
kmem_cache_destroy(cache);
 }
@@ -497,6 +538,7 @@ static noinline void __init copy_user_test(void)
char __user *usermem;
size_t size = 10;
int unused;
+   size_t oob_size;
 
kmem = kmalloc(size, GFP_KERNEL);
if (!kmem)
@@ -511,26 +553,31 @@ static noinline void __init copy_user_test(void)
return;
}
 
+   if (IS_ENABLED(CONFIG_KASAN_GENERIC))
+   oob_size = 1;
+   else
+   oob_size = 7;
+
pr_info("out-of-bounds in copy_from_user()\n");
-   unused = copy_from_user(kmem, usermem, size + 1);
+   unused = copy_from_user(kmem, usermem, size + oob_size);
 
pr_info("out-of-bounds in copy_to_user()\n");
-   unused = copy_to_user(usermem, kmem, size + 1);
+   unused = copy_to_user(usermem, kmem, size + oob_size);
 
pr_info("out-of-bounds in __copy_from_u

Re: [PATCH v7 0/4] kasan: memorize and print call_rcu stack

2020-06-23 Thread Walter Wu
On Mon, 2020-06-01 at 13:08 +0800, Walter Wu wrote:
> This patchset improves KASAN reports by making them to have
> call_rcu() call stack information. It is useful for programmers
> to solve use-after-free or double-free memory issue.
> 
> The KASAN report was as follows(cleaned up slightly):
> 
> BUG: KASAN: use-after-free in kasan_rcu_reclaim+0x58/0x60
> 
> Freed by task 0:
>  kasan_save_stack+0x24/0x50
>  kasan_set_track+0x24/0x38
>  kasan_set_free_info+0x18/0x20
>  __kasan_slab_free+0x10c/0x170
>  kasan_slab_free+0x10/0x18
>  kfree+0x98/0x270
>  kasan_rcu_reclaim+0x1c/0x60
> 
> Last call_rcu():
>  kasan_save_stack+0x24/0x50
>  kasan_record_aux_stack+0xbc/0xd0
>  call_rcu+0x8c/0x580
>  kasan_rcu_uaf+0xf4/0xf8
> 
> Generic KASAN will record the last two call_rcu() call stacks and
> print up to 2 call_rcu() call stacks in KASAN report. it is only
> suitable for generic KASAN.
> 
> This feature considers the size of struct kasan_alloc_meta and
> kasan_free_meta, we try to optimize the structure layout and size
> , lets it get better memory consumption.
> 
> [1]https://bugzilla.kernel.org/show_bug.cgi?id=198437
> [2]https://groups.google.com/forum/#!searchin/kasan-dev/better$20stack$20traces$20for$20rcu%7Csort:date/kasan-dev/KQsjT_88hDE/7rNUZprRBgAJ
> 
> Changes since v1:
> - remove new config option, default enable it in generic KASAN
> - test this feature in SLAB/SLUB, it is pass.
> - modify macro to be more clearly
> - modify documentation
> 
> Changes since v2:
> - change recording from first/last to the last two call stacks
> - move free track into kasan free meta
> - init slab_free_meta on object slot creation
> - modify documentation
> 
> Changes since v3:
> - change variable name to be more clearly
> - remove the redundant condition
> - remove init free meta-data and increasing object condition
> 
> Changes since v4:
> - add a macro KASAN_KMALLOC_FREETRACK in order to check whether
>   print free stack
> - change printing message
> - remove descriptions in Kocong.kasan
> 
> Changes since v5:
> - reuse print_stack() in print_track()
> 
> Changes since v6:
> - fix typo
> - renamed the variable name in testcase
> 
> Walter Wu (4):
> rcu: kasan: record and print call_rcu() call stack
> kasan: record and print the free track
> kasan: add tests for call_rcu stack recording
> kasan: update documentation for generic kasan
> 

Hi Andrew,

Would you tell me why don't pick up this patches?
Do I miss something?

I will want to implement another new patches, but it need to depend on
this patches.


Thanks for your helps.

Walter

> Documentation/dev-tools/kasan.rst |  3 +++
> include/linux/kasan.h |  2 ++
> kernel/rcu/tree.c |  2 ++
> lib/test_kasan.c  | 30 ++
> mm/kasan/common.c | 26 --
> mm/kasan/generic.c| 43 
> +++
> mm/kasan/generic_report.c |  1 +
> mm/kasan/kasan.h  | 23 +--
> mm/kasan/quarantine.c |  1 +
> mm/kasan/report.c | 54 
> +++---
> mm/kasan/tags.c   | 37 +
> 11 files changed, 171 insertions(+), 51 deletions(-)



[PATCH v7 4/4] kasan: update documentation for generic kasan

2020-05-31 Thread Walter Wu
Generic KASAN will support to record the last two call_rcu() call stacks
and print them in KASAN report. So that need to update documentation.

Signed-off-by: Walter Wu 
Reviewed-and-tested-by: Dmitry Vyukov 
Reviewed-by: Andrey Konovalov 
Cc: Andrey Ryabinin 
Cc: Alexander Potapenko 
Cc: Jonathan Corbet 
---
 Documentation/dev-tools/kasan.rst | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/Documentation/dev-tools/kasan.rst 
b/Documentation/dev-tools/kasan.rst
index c652d740735d..fede42e6536b 100644
--- a/Documentation/dev-tools/kasan.rst
+++ b/Documentation/dev-tools/kasan.rst
@@ -193,6 +193,9 @@ function calls GCC directly inserts the code to check the 
shadow memory.
 This option significantly enlarges kernel but it gives x1.1-x2 performance
 boost over outline instrumented kernel.
 
+Generic KASAN prints up to 2 call_rcu() call stacks in reports, the last one
+and the second to last.
+
 Software tag-based KASAN
 
 
-- 
2.18.0


[PATCH v7 3/4] kasan: add tests for call_rcu stack recording

2020-05-31 Thread Walter Wu
Test call_rcu() call stack recording and verify whether it correctly
is printed in KASAN report.

Signed-off-by: Walter Wu 
Reviewed-and-tested-by: Dmitry Vyukov 
Reviewed-by: Andrey Konovalov 
Cc: Andrey Ryabinin 
Cc: Alexander Potapenko 
Cc: Matthias Brugger 
---

Changes since v6:
- renamed the variable name in testcase

---
 lib/test_kasan.c | 30 ++
 1 file changed, 30 insertions(+)

diff --git a/lib/test_kasan.c b/lib/test_kasan.c
index e3087d90e00d..19c72c1501ef 100644
--- a/lib/test_kasan.c
+++ b/lib/test_kasan.c
@@ -792,6 +792,35 @@ static noinline void __init vmalloc_oob(void)
 static void __init vmalloc_oob(void) {}
 #endif
 
+static struct kasan_rcu_info {
+   int i;
+   struct rcu_head rcu;
+} *global_rcu_ptr;
+
+static noinline void __init kasan_rcu_reclaim(struct rcu_head *rp)
+{
+   struct kasan_rcu_info *fp = container_of(rp,
+   struct kasan_rcu_info, rcu);
+
+   kfree(fp);
+   fp->i = 1;
+}
+
+static noinline void __init kasan_rcu_uaf(void)
+{
+   struct kasan_rcu_info *ptr;
+
+   pr_info("use-after-free in kasan_rcu_reclaim\n");
+   ptr = kmalloc(sizeof(struct kasan_rcu_info), GFP_KERNEL);
+   if (!ptr) {
+   pr_err("Allocation failed\n");
+   return;
+   }
+
+   global_rcu_ptr = rcu_dereference_protected(ptr, NULL);
+   call_rcu(_rcu_ptr->rcu, kasan_rcu_reclaim);
+}
+
 static int __init kmalloc_tests_init(void)
 {
/*
@@ -839,6 +868,7 @@ static int __init kmalloc_tests_init(void)
kasan_bitops();
kmalloc_double_kzfree();
vmalloc_oob();
+   kasan_rcu_uaf();
 
kasan_restore_multi_shot(multishot);
 
-- 
2.18.0


[PATCH v7 2/4] kasan: record and print the free track

2020-05-31 Thread Walter Wu
Move free track from kasan_alloc_meta to kasan_free_meta in order
to make struct kasan_alloc_meta and kasan_free_meta size are both
16 bytes. It is a good size because it is the minimal redzone size
and a good number of alignment.

For free track, we make some modifications as shown below:
1) Remove the free_track from struct kasan_alloc_meta.
2) Add the free_track into struct kasan_free_meta.
3) Add a macro KASAN_KMALLOC_FREETRACK in order to check whether
   it can print free stack in KASAN report.

[1]https://bugzilla.kernel.org/show_bug.cgi?id=198437

Signed-off-by: Walter Wu 
Suggested-by: Dmitry Vyukov 
Co-developed-by: Dmitry Vyukov 
Reviewed-and-tested-by: Dmitry Vyukov 
Reviewed-by: Andrey Konovalov 
Cc: Andrey Ryabinin 
Cc: Alexander Potapenko 
---
 mm/kasan/common.c | 22 ++
 mm/kasan/generic.c| 22 ++
 mm/kasan/generic_report.c |  1 +
 mm/kasan/kasan.h  | 13 +++--
 mm/kasan/quarantine.c |  1 +
 mm/kasan/report.c | 26 --
 mm/kasan/tags.c   | 37 +
 7 files changed, 78 insertions(+), 44 deletions(-)

diff --git a/mm/kasan/common.c b/mm/kasan/common.c
index 8bc618289bb1..47b53912f322 100644
--- a/mm/kasan/common.c
+++ b/mm/kasan/common.c
@@ -51,7 +51,7 @@ depot_stack_handle_t kasan_save_stack(gfp_t flags)
return stack_depot_save(entries, nr_entries, flags);
 }
 
-static inline void set_track(struct kasan_track *track, gfp_t flags)
+void kasan_set_track(struct kasan_track *track, gfp_t flags)
 {
track->pid = current->pid;
track->stack = kasan_save_stack(flags);
@@ -299,24 +299,6 @@ struct kasan_free_meta *get_free_info(struct kmem_cache 
*cache,
return (void *)object + cache->kasan_info.free_meta_offset;
 }
 
-
-static void kasan_set_free_info(struct kmem_cache *cache,
-   void *object, u8 tag)
-{
-   struct kasan_alloc_meta *alloc_meta;
-   u8 idx = 0;
-
-   alloc_meta = get_alloc_info(cache, object);
-
-#ifdef CONFIG_KASAN_SW_TAGS_IDENTIFY
-   idx = alloc_meta->free_track_idx;
-   alloc_meta->free_pointer_tag[idx] = tag;
-   alloc_meta->free_track_idx = (idx + 1) % KASAN_NR_FREE_STACKS;
-#endif
-
-   set_track(_meta->free_track[idx], GFP_NOWAIT);
-}
-
 void kasan_poison_slab(struct page *page)
 {
unsigned long i;
@@ -492,7 +474,7 @@ static void *__kasan_kmalloc(struct kmem_cache *cache, 
const void *object,
KASAN_KMALLOC_REDZONE);
 
if (cache->flags & SLAB_KASAN)
-   set_track(_alloc_info(cache, object)->alloc_track, flags);
+   kasan_set_track(_alloc_info(cache, object)->alloc_track, 
flags);
 
return set_tag(object, tag);
 }
diff --git a/mm/kasan/generic.c b/mm/kasan/generic.c
index 8acf48882ba2..4b3cbad7431b 100644
--- a/mm/kasan/generic.c
+++ b/mm/kasan/generic.c
@@ -346,3 +346,25 @@ void kasan_record_aux_stack(void *addr)
alloc_info->aux_stack[1] = alloc_info->aux_stack[0];
alloc_info->aux_stack[0] = kasan_save_stack(GFP_NOWAIT);
 }
+
+void kasan_set_free_info(struct kmem_cache *cache,
+   void *object, u8 tag)
+{
+   struct kasan_free_meta *free_meta;
+
+   free_meta = get_free_info(cache, object);
+   kasan_set_track(_meta->free_track, GFP_NOWAIT);
+
+   /*
+*  the object was freed and has free track set
+*/
+   *(u8 *)kasan_mem_to_shadow(object) = KASAN_KMALLOC_FREETRACK;
+}
+
+struct kasan_track *kasan_get_free_track(struct kmem_cache *cache,
+   void *object, u8 tag)
+{
+   if (*(u8 *)kasan_mem_to_shadow(object) != KASAN_KMALLOC_FREETRACK)
+   return NULL;
+   return _free_info(cache, object)->free_track;
+}
diff --git a/mm/kasan/generic_report.c b/mm/kasan/generic_report.c
index e200acb2d292..a38c7a9e192a 100644
--- a/mm/kasan/generic_report.c
+++ b/mm/kasan/generic_report.c
@@ -80,6 +80,7 @@ static const char *get_shadow_bug_type(struct 
kasan_access_info *info)
break;
case KASAN_FREE_PAGE:
case KASAN_KMALLOC_FREE:
+   case KASAN_KMALLOC_FREETRACK:
bug_type = "use-after-free";
break;
case KASAN_ALLOCA_LEFT:
diff --git a/mm/kasan/kasan.h b/mm/kasan/kasan.h
index a7391bc83070..ef655a1c6e15 100644
--- a/mm/kasan/kasan.h
+++ b/mm/kasan/kasan.h
@@ -17,15 +17,17 @@
 #define KASAN_PAGE_REDZONE  0xFE  /* redzone for kmalloc_large allocations 
*/
 #define KASAN_KMALLOC_REDZONE   0xFC  /* redzone inside slub object */
 #define KASAN_KMALLOC_FREE  0xFB  /* object was freed 
(kmem_cache_free/kfree) */
+#define KASAN_KMALLOC_FREETRACK 0xFA  /* object was freed and has free track 
set */
 #else
 #define KASAN_FREE_PAGE KASAN_TAG_INVALID
 #define KASAN_PAGE_REDZONE  KASAN_TAG_INVALID
 #define KASAN_KMALLOC_REDZONE   KASAN_TAG_INVAL

[PATCH v7 1/4] rcu: kasan: record and print call_rcu() call stack

2020-05-31 Thread Walter Wu
This feature will record the last two call_rcu() call stacks and
prints up to 2 call_rcu() call stacks in KASAN report.

When call_rcu() is called, we store the call_rcu() call stack into
slub alloc meta-data, so that the KASAN report can print rcu stack.

[1]https://bugzilla.kernel.org/show_bug.cgi?id=198437
[2]https://groups.google.com/forum/#!searchin/kasan-dev/better$20stack$20traces$20for$20rcu%7Csort:date/kasan-dev/KQsjT_88hDE/7rNUZprRBgAJ

Signed-off-by: Walter Wu 
Suggested-by: Dmitry Vyukov 
Acked-by: Paul E. McKenney 
Reviewed-and-tested-by: Dmitry Vyukov 
Reviewed-by: Andrey Konovalov 
Cc: Andrey Ryabinin 
Cc: Alexander Potapenko 
Cc: Andrew Morton 
Cc: Josh Triplett 
Cc: Mathieu Desnoyers 
Cc: Lai Jiangshan 
Cc: Joel Fernandes 
---

Changes since v6:
- fix typo

---
 include/linux/kasan.h |  2 ++
 kernel/rcu/tree.c |  2 ++
 mm/kasan/common.c |  4 ++--
 mm/kasan/generic.c| 21 +
 mm/kasan/kasan.h  | 10 ++
 mm/kasan/report.c | 28 +++-
 6 files changed, 60 insertions(+), 7 deletions(-)

diff --git a/include/linux/kasan.h b/include/linux/kasan.h
index 31314ca7c635..23b7ee00572d 100644
--- a/include/linux/kasan.h
+++ b/include/linux/kasan.h
@@ -174,11 +174,13 @@ static inline size_t kasan_metadata_size(struct 
kmem_cache *cache) { return 0; }
 
 void kasan_cache_shrink(struct kmem_cache *cache);
 void kasan_cache_shutdown(struct kmem_cache *cache);
+void kasan_record_aux_stack(void *ptr);
 
 #else /* CONFIG_KASAN_GENERIC */
 
 static inline void kasan_cache_shrink(struct kmem_cache *cache) {}
 static inline void kasan_cache_shutdown(struct kmem_cache *cache) {}
+static inline void kasan_record_aux_stack(void *ptr) {}
 
 #endif /* CONFIG_KASAN_GENERIC */
 
diff --git a/kernel/rcu/tree.c b/kernel/rcu/tree.c
index 06548e2ebb72..36a4ff7f320b 100644
--- a/kernel/rcu/tree.c
+++ b/kernel/rcu/tree.c
@@ -57,6 +57,7 @@
 #include 
 #include 
 #include 
+#include 
 #include "../time/tick-internal.h"
 
 #include "tree.h"
@@ -2668,6 +2669,7 @@ __call_rcu(struct rcu_head *head, rcu_callback_t func)
head->func = func;
head->next = NULL;
local_irq_save(flags);
+   kasan_record_aux_stack(head);
rdp = this_cpu_ptr(_data);
 
/* Add the callback to our list. */
diff --git a/mm/kasan/common.c b/mm/kasan/common.c
index 2906358e42f0..8bc618289bb1 100644
--- a/mm/kasan/common.c
+++ b/mm/kasan/common.c
@@ -41,7 +41,7 @@
 #include "kasan.h"
 #include "../slab.h"
 
-static inline depot_stack_handle_t save_stack(gfp_t flags)
+depot_stack_handle_t kasan_save_stack(gfp_t flags)
 {
unsigned long entries[KASAN_STACK_DEPTH];
unsigned int nr_entries;
@@ -54,7 +54,7 @@ static inline depot_stack_handle_t save_stack(gfp_t flags)
 static inline void set_track(struct kasan_track *track, gfp_t flags)
 {
track->pid = current->pid;
-   track->stack = save_stack(flags);
+   track->stack = kasan_save_stack(flags);
 }
 
 void kasan_enable_current(void)
diff --git a/mm/kasan/generic.c b/mm/kasan/generic.c
index 56ff8885fe2e..8acf48882ba2 100644
--- a/mm/kasan/generic.c
+++ b/mm/kasan/generic.c
@@ -325,3 +325,24 @@ DEFINE_ASAN_SET_SHADOW(f2);
 DEFINE_ASAN_SET_SHADOW(f3);
 DEFINE_ASAN_SET_SHADOW(f5);
 DEFINE_ASAN_SET_SHADOW(f8);
+
+void kasan_record_aux_stack(void *addr)
+{
+   struct page *page = kasan_addr_to_page(addr);
+   struct kmem_cache *cache;
+   struct kasan_alloc_meta *alloc_info;
+   void *object;
+
+   if (!(page && PageSlab(page)))
+   return;
+
+   cache = page->slab_cache;
+   object = nearest_obj(cache, page, addr);
+   alloc_info = get_alloc_info(cache, object);
+
+   /*
+* record the last two call_rcu() call stacks.
+*/
+   alloc_info->aux_stack[1] = alloc_info->aux_stack[0];
+   alloc_info->aux_stack[0] = kasan_save_stack(GFP_NOWAIT);
+}
diff --git a/mm/kasan/kasan.h b/mm/kasan/kasan.h
index e8f37199d885..a7391bc83070 100644
--- a/mm/kasan/kasan.h
+++ b/mm/kasan/kasan.h
@@ -104,7 +104,15 @@ struct kasan_track {
 
 struct kasan_alloc_meta {
struct kasan_track alloc_track;
+#ifdef CONFIG_KASAN_GENERIC
+   /*
+* call_rcu() call stack is stored into struct kasan_alloc_meta.
+* The free stack is stored into struct kasan_free_meta.
+*/
+   depot_stack_handle_t aux_stack[2];
+#else
struct kasan_track free_track[KASAN_NR_FREE_STACKS];
+#endif
 #ifdef CONFIG_KASAN_SW_TAGS_IDENTIFY
u8 free_pointer_tag[KASAN_NR_FREE_STACKS];
u8 free_track_idx;
@@ -159,6 +167,8 @@ void kasan_report_invalid_free(void *object, unsigned long 
ip);
 
 struct page *kasan_addr_to_page(const void *addr);
 
+depot_stack_handle_t kasan_save_stack(gfp_t flags);
+
 #if defined(CONFIG_KASAN_GENERIC) && \
(defined(CONFIG_SLAB) || defined(CONFIG_SLUB))
 void quarantine_put(struct kasan_free_met

[PATCH v7 0/4] kasan: memorize and print call_rcu stack

2020-05-31 Thread Walter Wu
This patchset improves KASAN reports by making them to have
call_rcu() call stack information. It is useful for programmers
to solve use-after-free or double-free memory issue.

The KASAN report was as follows(cleaned up slightly):

BUG: KASAN: use-after-free in kasan_rcu_reclaim+0x58/0x60

Freed by task 0:
 kasan_save_stack+0x24/0x50
 kasan_set_track+0x24/0x38
 kasan_set_free_info+0x18/0x20
 __kasan_slab_free+0x10c/0x170
 kasan_slab_free+0x10/0x18
 kfree+0x98/0x270
 kasan_rcu_reclaim+0x1c/0x60

Last call_rcu():
 kasan_save_stack+0x24/0x50
 kasan_record_aux_stack+0xbc/0xd0
 call_rcu+0x8c/0x580
 kasan_rcu_uaf+0xf4/0xf8

Generic KASAN will record the last two call_rcu() call stacks and
print up to 2 call_rcu() call stacks in KASAN report. it is only
suitable for generic KASAN.

This feature considers the size of struct kasan_alloc_meta and
kasan_free_meta, we try to optimize the structure layout and size
, lets it get better memory consumption.

[1]https://bugzilla.kernel.org/show_bug.cgi?id=198437
[2]https://groups.google.com/forum/#!searchin/kasan-dev/better$20stack$20traces$20for$20rcu%7Csort:date/kasan-dev/KQsjT_88hDE/7rNUZprRBgAJ

Changes since v1:
- remove new config option, default enable it in generic KASAN
- test this feature in SLAB/SLUB, it is pass.
- modify macro to be more clearly
- modify documentation

Changes since v2:
- change recording from first/last to the last two call stacks
- move free track into kasan free meta
- init slab_free_meta on object slot creation
- modify documentation

Changes since v3:
- change variable name to be more clearly
- remove the redundant condition
- remove init free meta-data and increasing object condition

Changes since v4:
- add a macro KASAN_KMALLOC_FREETRACK in order to check whether
  print free stack
- change printing message
- remove descriptions in Kocong.kasan

Changes since v5:
- reuse print_stack() in print_track()

Changes since v6:
- fix typo
- renamed the variable name in testcase

Walter Wu (4):
rcu: kasan: record and print call_rcu() call stack
kasan: record and print the free track
kasan: add tests for call_rcu stack recording
kasan: update documentation for generic kasan

Documentation/dev-tools/kasan.rst |  3 +++
include/linux/kasan.h |  2 ++
kernel/rcu/tree.c |  2 ++
lib/test_kasan.c  | 30 ++
mm/kasan/common.c | 26 --
mm/kasan/generic.c| 43 
+++
mm/kasan/generic_report.c |  1 +
mm/kasan/kasan.h  | 23 +--
mm/kasan/quarantine.c |  1 +
mm/kasan/report.c | 54 
+++---
mm/kasan/tags.c   | 37 +
11 files changed, 171 insertions(+), 51 deletions(-)

Re: [PATCH v6 1/4] rcu/kasan: record and print call_rcu() call stack

2020-05-25 Thread Walter Wu
On Mon, 2020-05-25 at 11:56 +0200, Dmitry Vyukov wrote:
> On Fri, May 22, 2020 at 4:01 AM Walter Wu  wrote:
> >
> > This feature will record the last two call_rcu() call stacks and
> > prints up to 2 call_rcu() call stacks in KASAN report.
> >
> > When call_rcu() is called, we store the call_rcu() call stack into
> > slub alloc meta-data, so that the KASAN report can print rcu stack.
> >
> > [1]https://bugzilla.kernel.org/show_bug.cgi?id=198437
> > [2]https://groups.google.com/forum/#!searchin/kasan-dev/better$20stack$20traces$20for$20rcu%7Csort:date/kasan-dev/KQsjT_88hDE/7rNUZprRBgAJ
> 
> Hi Walter,
> 
> The series look good to me. Thanks for bearing with me. I am eager to
> see this in syzbot reports.
> 
> Reviewed-and-tested-by: Dmitry Vyukov 
> 

Hi Dmitry,

I appreciate for your response. This patches make KASAN report more
better and let me learn a lot. Thank you for good suggestion and
detailed explanation.

Walter

> > Signed-off-by: Walter Wu 
> > Suggested-by: Dmitry Vyukov 
> > Acked-by: Paul E. McKenney 
> > Cc: Andrey Ryabinin 
> > Cc: Dmitry Vyukov 
> > Cc: Alexander Potapenko 
> > Cc: Andrew Morton 
> > Cc: Josh Triplett 
> > Cc: Mathieu Desnoyers 
> > Cc: Lai Jiangshan 
> > Cc: Joel Fernandes 
> > Cc: Andrey Konovalov 
> > ---
> >  include/linux/kasan.h |  2 ++
> >  kernel/rcu/tree.c |  2 ++
> >  mm/kasan/common.c |  4 ++--
> >  mm/kasan/generic.c| 21 +
> >  mm/kasan/kasan.h  | 10 ++
> >  mm/kasan/report.c | 28 +++-
> >  6 files changed, 60 insertions(+), 7 deletions(-)
> >
> > diff --git a/include/linux/kasan.h b/include/linux/kasan.h
> > index 31314ca7c635..23b7ee00572d 100644
> > --- a/include/linux/kasan.h
> > +++ b/include/linux/kasan.h
> > @@ -174,11 +174,13 @@ static inline size_t kasan_metadata_size(struct 
> > kmem_cache *cache) { return 0; }
> >
> >  void kasan_cache_shrink(struct kmem_cache *cache);
> >  void kasan_cache_shutdown(struct kmem_cache *cache);
> > +void kasan_record_aux_stack(void *ptr);
> >
> >  #else /* CONFIG_KASAN_GENERIC */
> >
> >  static inline void kasan_cache_shrink(struct kmem_cache *cache) {}
> >  static inline void kasan_cache_shutdown(struct kmem_cache *cache) {}
> > +static inline void kasan_record_aux_stack(void *ptr) {}
> >
> >  #endif /* CONFIG_KASAN_GENERIC */
> >
> > diff --git a/kernel/rcu/tree.c b/kernel/rcu/tree.c
> > index 06548e2ebb72..36a4ff7f320b 100644
> > --- a/kernel/rcu/tree.c
> > +++ b/kernel/rcu/tree.c
> > @@ -57,6 +57,7 @@
> >  #include 
> >  #include 
> >  #include 
> > +#include 
> >  #include "../time/tick-internal.h"
> >
> >  #include "tree.h"
> > @@ -2668,6 +2669,7 @@ __call_rcu(struct rcu_head *head, rcu_callback_t func)
> > head->func = func;
> > head->next = NULL;
> > local_irq_save(flags);
> > +   kasan_record_aux_stack(head);
> > rdp = this_cpu_ptr(_data);
> >
> > /* Add the callback to our list. */
> > diff --git a/mm/kasan/common.c b/mm/kasan/common.c
> > index 2906358e42f0..8bc618289bb1 100644
> > --- a/mm/kasan/common.c
> > +++ b/mm/kasan/common.c
> > @@ -41,7 +41,7 @@
> >  #include "kasan.h"
> >  #include "../slab.h"
> >
> > -static inline depot_stack_handle_t save_stack(gfp_t flags)
> > +depot_stack_handle_t kasan_save_stack(gfp_t flags)
> >  {
> > unsigned long entries[KASAN_STACK_DEPTH];
> > unsigned int nr_entries;
> > @@ -54,7 +54,7 @@ static inline depot_stack_handle_t save_stack(gfp_t flags)
> >  static inline void set_track(struct kasan_track *track, gfp_t flags)
> >  {
> > track->pid = current->pid;
> > -   track->stack = save_stack(flags);
> > +   track->stack = kasan_save_stack(flags);
> >  }
> >
> >  void kasan_enable_current(void)
> > diff --git a/mm/kasan/generic.c b/mm/kasan/generic.c
> > index 56ff8885fe2e..8acf48882ba2 100644
> > --- a/mm/kasan/generic.c
> > +++ b/mm/kasan/generic.c
> > @@ -325,3 +325,24 @@ DEFINE_ASAN_SET_SHADOW(f2);
> >  DEFINE_ASAN_SET_SHADOW(f3);
> >  DEFINE_ASAN_SET_SHADOW(f5);
> >  DEFINE_ASAN_SET_SHADOW(f8);
> > +
> > +void kasan_record_aux_stack(void *addr)
> > +{
> > +   struct page *page = kasan_addr_to_page(addr);
> > +   struct kmem_cache *cache;
> > +   struct kasan_alloc_meta *alloc_info;
> &g

[PATCH v6 3/4] kasan: add tests for call_rcu stack recording

2020-05-21 Thread Walter Wu
Test call_rcu() call stack recording and verify whether it correctly
is printed in KASAN report.

Signed-off-by: Walter Wu 
Cc: Andrey Ryabinin 
Cc: Dmitry Vyukov 
Cc: Alexander Potapenko 
Cc: Matthias Brugger 
---
 lib/test_kasan.c | 30 ++
 1 file changed, 30 insertions(+)

diff --git a/lib/test_kasan.c b/lib/test_kasan.c
index e3087d90e00d..6e5fb05d42d8 100644
--- a/lib/test_kasan.c
+++ b/lib/test_kasan.c
@@ -792,6 +792,35 @@ static noinline void __init vmalloc_oob(void)
 static void __init vmalloc_oob(void) {}
 #endif
 
+static struct kasan_rcu_info {
+   int i;
+   struct rcu_head rcu;
+} *global_ptr;
+
+static noinline void __init kasan_rcu_reclaim(struct rcu_head *rp)
+{
+   struct kasan_rcu_info *fp = container_of(rp,
+   struct kasan_rcu_info, rcu);
+
+   kfree(fp);
+   fp->i = 1;
+}
+
+static noinline void __init kasan_rcu_uaf(void)
+{
+   struct kasan_rcu_info *ptr;
+
+   pr_info("use-after-free in kasan_rcu_reclaim\n");
+   ptr = kmalloc(sizeof(struct kasan_rcu_info), GFP_KERNEL);
+   if (!ptr) {
+   pr_err("Allocation failed\n");
+   return;
+   }
+
+   global_ptr = rcu_dereference_protected(ptr, NULL);
+   call_rcu(_ptr->rcu, kasan_rcu_reclaim);
+}
+
 static int __init kmalloc_tests_init(void)
 {
/*
@@ -839,6 +868,7 @@ static int __init kmalloc_tests_init(void)
kasan_bitops();
kmalloc_double_kzfree();
vmalloc_oob();
+   kasan_rcu_uaf();
 
kasan_restore_multi_shot(multishot);
 
-- 
2.18.0


[PATCH v6 2/4] kasan: record and print the free track

2020-05-21 Thread Walter Wu
Move free track from kasan_alloc_meta to kasan_free_meta in order
to make struct kasan_alloc_meta and kasan_free_meta size are both
16 bytes. It is a good size because it is the minimal redzone size
and a good number of alignment.

For free track, we make some modifications as shown below:
1) Remove the free_track from struct kasan_alloc_meta.
2) Add the free_track into struct kasan_free_meta.
3) Add a macro KASAN_KMALLOC_FREETRACK in order to check whether
   it can print free stack in KASAN report.

[1]https://bugzilla.kernel.org/show_bug.cgi?id=198437

Signed-off-by: Walter Wu 
Suggested-by: Dmitry Vyukov 
Co-developed-by: Dmitry Vyukov 
Cc: Andrey Ryabinin 
Cc: Dmitry Vyukov 
Cc: Alexander Potapenko 
---
 mm/kasan/common.c | 22 ++
 mm/kasan/generic.c| 22 ++
 mm/kasan/generic_report.c |  1 +
 mm/kasan/kasan.h  | 13 +++--
 mm/kasan/quarantine.c |  1 +
 mm/kasan/report.c | 26 --
 mm/kasan/tags.c   | 37 +
 7 files changed, 78 insertions(+), 44 deletions(-)

diff --git a/mm/kasan/common.c b/mm/kasan/common.c
index 8bc618289bb1..47b53912f322 100644
--- a/mm/kasan/common.c
+++ b/mm/kasan/common.c
@@ -51,7 +51,7 @@ depot_stack_handle_t kasan_save_stack(gfp_t flags)
return stack_depot_save(entries, nr_entries, flags);
 }
 
-static inline void set_track(struct kasan_track *track, gfp_t flags)
+void kasan_set_track(struct kasan_track *track, gfp_t flags)
 {
track->pid = current->pid;
track->stack = kasan_save_stack(flags);
@@ -299,24 +299,6 @@ struct kasan_free_meta *get_free_info(struct kmem_cache 
*cache,
return (void *)object + cache->kasan_info.free_meta_offset;
 }
 
-
-static void kasan_set_free_info(struct kmem_cache *cache,
-   void *object, u8 tag)
-{
-   struct kasan_alloc_meta *alloc_meta;
-   u8 idx = 0;
-
-   alloc_meta = get_alloc_info(cache, object);
-
-#ifdef CONFIG_KASAN_SW_TAGS_IDENTIFY
-   idx = alloc_meta->free_track_idx;
-   alloc_meta->free_pointer_tag[idx] = tag;
-   alloc_meta->free_track_idx = (idx + 1) % KASAN_NR_FREE_STACKS;
-#endif
-
-   set_track(_meta->free_track[idx], GFP_NOWAIT);
-}
-
 void kasan_poison_slab(struct page *page)
 {
unsigned long i;
@@ -492,7 +474,7 @@ static void *__kasan_kmalloc(struct kmem_cache *cache, 
const void *object,
KASAN_KMALLOC_REDZONE);
 
if (cache->flags & SLAB_KASAN)
-   set_track(_alloc_info(cache, object)->alloc_track, flags);
+   kasan_set_track(_alloc_info(cache, object)->alloc_track, 
flags);
 
return set_tag(object, tag);
 }
diff --git a/mm/kasan/generic.c b/mm/kasan/generic.c
index 8acf48882ba2..4b3cbad7431b 100644
--- a/mm/kasan/generic.c
+++ b/mm/kasan/generic.c
@@ -346,3 +346,25 @@ void kasan_record_aux_stack(void *addr)
alloc_info->aux_stack[1] = alloc_info->aux_stack[0];
alloc_info->aux_stack[0] = kasan_save_stack(GFP_NOWAIT);
 }
+
+void kasan_set_free_info(struct kmem_cache *cache,
+   void *object, u8 tag)
+{
+   struct kasan_free_meta *free_meta;
+
+   free_meta = get_free_info(cache, object);
+   kasan_set_track(_meta->free_track, GFP_NOWAIT);
+
+   /*
+*  the object was freed and has free track set
+*/
+   *(u8 *)kasan_mem_to_shadow(object) = KASAN_KMALLOC_FREETRACK;
+}
+
+struct kasan_track *kasan_get_free_track(struct kmem_cache *cache,
+   void *object, u8 tag)
+{
+   if (*(u8 *)kasan_mem_to_shadow(object) != KASAN_KMALLOC_FREETRACK)
+   return NULL;
+   return _free_info(cache, object)->free_track;
+}
diff --git a/mm/kasan/generic_report.c b/mm/kasan/generic_report.c
index e200acb2d292..a38c7a9e192a 100644
--- a/mm/kasan/generic_report.c
+++ b/mm/kasan/generic_report.c
@@ -80,6 +80,7 @@ static const char *get_shadow_bug_type(struct 
kasan_access_info *info)
break;
case KASAN_FREE_PAGE:
case KASAN_KMALLOC_FREE:
+   case KASAN_KMALLOC_FREETRACK:
bug_type = "use-after-free";
break;
case KASAN_ALLOCA_LEFT:
diff --git a/mm/kasan/kasan.h b/mm/kasan/kasan.h
index a7391bc83070..ef655a1c6e15 100644
--- a/mm/kasan/kasan.h
+++ b/mm/kasan/kasan.h
@@ -17,15 +17,17 @@
 #define KASAN_PAGE_REDZONE  0xFE  /* redzone for kmalloc_large allocations 
*/
 #define KASAN_KMALLOC_REDZONE   0xFC  /* redzone inside slub object */
 #define KASAN_KMALLOC_FREE  0xFB  /* object was freed 
(kmem_cache_free/kfree) */
+#define KASAN_KMALLOC_FREETRACK 0xFA  /* object was freed and has free track 
set */
 #else
 #define KASAN_FREE_PAGE KASAN_TAG_INVALID
 #define KASAN_PAGE_REDZONE  KASAN_TAG_INVALID
 #define KASAN_KMALLOC_REDZONE   KASAN_TAG_INVALID
 #define KASAN_KMALLOC_FREE  KASAN_TAG_INVA

[PATCH v6 4/4] kasan: update documentation for generic kasan

2020-05-21 Thread Walter Wu
Generic KASAN will support to record the last two call_rcu() call stacks
and print them in KASAN report. So that need to update documentation.

Signed-off-by: Walter Wu 
Cc: Andrey Ryabinin 
Cc: Dmitry Vyukov 
Cc: Alexander Potapenko 
Cc: Jonathan Corbet 
---
 Documentation/dev-tools/kasan.rst | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/Documentation/dev-tools/kasan.rst 
b/Documentation/dev-tools/kasan.rst
index c652d740735d..fede42e6536b 100644
--- a/Documentation/dev-tools/kasan.rst
+++ b/Documentation/dev-tools/kasan.rst
@@ -193,6 +193,9 @@ function calls GCC directly inserts the code to check the 
shadow memory.
 This option significantly enlarges kernel but it gives x1.1-x2 performance
 boost over outline instrumented kernel.
 
+Generic KASAN prints up to 2 call_rcu() call stacks in reports, the last one
+and the second to last.
+
 Software tag-based KASAN
 
 
-- 
2.18.0


[PATCH v6 1/4] rcu/kasan: record and print call_rcu() call stack

2020-05-21 Thread Walter Wu
This feature will record the last two call_rcu() call stacks and
prints up to 2 call_rcu() call stacks in KASAN report.

When call_rcu() is called, we store the call_rcu() call stack into
slub alloc meta-data, so that the KASAN report can print rcu stack.

[1]https://bugzilla.kernel.org/show_bug.cgi?id=198437
[2]https://groups.google.com/forum/#!searchin/kasan-dev/better$20stack$20traces$20for$20rcu%7Csort:date/kasan-dev/KQsjT_88hDE/7rNUZprRBgAJ

Signed-off-by: Walter Wu 
Suggested-by: Dmitry Vyukov 
Acked-by: Paul E. McKenney 
Cc: Andrey Ryabinin 
Cc: Dmitry Vyukov 
Cc: Alexander Potapenko 
Cc: Andrew Morton 
Cc: Josh Triplett 
Cc: Mathieu Desnoyers 
Cc: Lai Jiangshan 
Cc: Joel Fernandes 
Cc: Andrey Konovalov 
---
 include/linux/kasan.h |  2 ++
 kernel/rcu/tree.c |  2 ++
 mm/kasan/common.c |  4 ++--
 mm/kasan/generic.c| 21 +
 mm/kasan/kasan.h  | 10 ++
 mm/kasan/report.c | 28 +++-
 6 files changed, 60 insertions(+), 7 deletions(-)

diff --git a/include/linux/kasan.h b/include/linux/kasan.h
index 31314ca7c635..23b7ee00572d 100644
--- a/include/linux/kasan.h
+++ b/include/linux/kasan.h
@@ -174,11 +174,13 @@ static inline size_t kasan_metadata_size(struct 
kmem_cache *cache) { return 0; }
 
 void kasan_cache_shrink(struct kmem_cache *cache);
 void kasan_cache_shutdown(struct kmem_cache *cache);
+void kasan_record_aux_stack(void *ptr);
 
 #else /* CONFIG_KASAN_GENERIC */
 
 static inline void kasan_cache_shrink(struct kmem_cache *cache) {}
 static inline void kasan_cache_shutdown(struct kmem_cache *cache) {}
+static inline void kasan_record_aux_stack(void *ptr) {}
 
 #endif /* CONFIG_KASAN_GENERIC */
 
diff --git a/kernel/rcu/tree.c b/kernel/rcu/tree.c
index 06548e2ebb72..36a4ff7f320b 100644
--- a/kernel/rcu/tree.c
+++ b/kernel/rcu/tree.c
@@ -57,6 +57,7 @@
 #include 
 #include 
 #include 
+#include 
 #include "../time/tick-internal.h"
 
 #include "tree.h"
@@ -2668,6 +2669,7 @@ __call_rcu(struct rcu_head *head, rcu_callback_t func)
head->func = func;
head->next = NULL;
local_irq_save(flags);
+   kasan_record_aux_stack(head);
rdp = this_cpu_ptr(_data);
 
/* Add the callback to our list. */
diff --git a/mm/kasan/common.c b/mm/kasan/common.c
index 2906358e42f0..8bc618289bb1 100644
--- a/mm/kasan/common.c
+++ b/mm/kasan/common.c
@@ -41,7 +41,7 @@
 #include "kasan.h"
 #include "../slab.h"
 
-static inline depot_stack_handle_t save_stack(gfp_t flags)
+depot_stack_handle_t kasan_save_stack(gfp_t flags)
 {
unsigned long entries[KASAN_STACK_DEPTH];
unsigned int nr_entries;
@@ -54,7 +54,7 @@ static inline depot_stack_handle_t save_stack(gfp_t flags)
 static inline void set_track(struct kasan_track *track, gfp_t flags)
 {
track->pid = current->pid;
-   track->stack = save_stack(flags);
+   track->stack = kasan_save_stack(flags);
 }
 
 void kasan_enable_current(void)
diff --git a/mm/kasan/generic.c b/mm/kasan/generic.c
index 56ff8885fe2e..8acf48882ba2 100644
--- a/mm/kasan/generic.c
+++ b/mm/kasan/generic.c
@@ -325,3 +325,24 @@ DEFINE_ASAN_SET_SHADOW(f2);
 DEFINE_ASAN_SET_SHADOW(f3);
 DEFINE_ASAN_SET_SHADOW(f5);
 DEFINE_ASAN_SET_SHADOW(f8);
+
+void kasan_record_aux_stack(void *addr)
+{
+   struct page *page = kasan_addr_to_page(addr);
+   struct kmem_cache *cache;
+   struct kasan_alloc_meta *alloc_info;
+   void *object;
+
+   if (!(page && PageSlab(page)))
+   return;
+
+   cache = page->slab_cache;
+   object = nearest_obj(cache, page, addr);
+   alloc_info = get_alloc_info(cache, object);
+
+   /*
+* record the last two call_rcu() call stacks.
+*/
+   alloc_info->aux_stack[1] = alloc_info->aux_stack[0];
+   alloc_info->aux_stack[0] = kasan_save_stack(GFP_NOWAIT);
+}
diff --git a/mm/kasan/kasan.h b/mm/kasan/kasan.h
index e8f37199d885..a7391bc83070 100644
--- a/mm/kasan/kasan.h
+++ b/mm/kasan/kasan.h
@@ -104,7 +104,15 @@ struct kasan_track {
 
 struct kasan_alloc_meta {
struct kasan_track alloc_track;
+#ifdef CONFIG_KASAN_GENERIC
+   /*
+* call_rcu() call stack is stored into struct kasan_alloc_meta.
+* The free stack is stored into struct kasan_free_meta.
+*/
+   depot_stack_handle_t aux_stack[2];
+#else
struct kasan_track free_track[KASAN_NR_FREE_STACKS];
+#endif
 #ifdef CONFIG_KASAN_SW_TAGS_IDENTIFY
u8 free_pointer_tag[KASAN_NR_FREE_STACKS];
u8 free_track_idx;
@@ -159,6 +167,8 @@ void kasan_report_invalid_free(void *object, unsigned long 
ip);
 
 struct page *kasan_addr_to_page(const void *addr);
 
+depot_stack_handle_t kasan_save_stack(gfp_t flags);
+
 #if defined(CONFIG_KASAN_GENERIC) && \
(defined(CONFIG_SLAB) || defined(CONFIG_SLUB))
 void quarantine_put(struct kasan_free_meta *info, struct kmem_cache *cache);
diff --git a/mm/kasan/report

[PATCH v6 0/4] kasan: memorize and print call_rcu stack

2020-05-21 Thread Walter Wu
This patchset improves KASAN reports by making them to have
call_rcu() call stack information. It is useful for programmers
to solve use-after-free or double-free memory issue.

The KASAN report was as follows(cleaned up slightly):

BUG: KASAN: use-after-free in kasan_rcu_reclaim+0x58/0x60

Freed by task 0:
 kasan_save_stack+0x24/0x50
 kasan_set_track+0x24/0x38
 kasan_set_free_info+0x18/0x20
 __kasan_slab_free+0x10c/0x170
 kasan_slab_free+0x10/0x18
 kfree+0x98/0x270
 kasan_rcu_reclaim+0x1c/0x60

Last call_rcu():
 kasan_save_stack+0x24/0x50
 kasan_record_aux_stack+0xbc/0xd0
 call_rcu+0x8c/0x580
 kasan_rcu_uaf+0xf4/0xf8

Generic KASAN will record the last two call_rcu() call stacks and
print up to 2 call_rcu() call stacks in KASAN report. it is only
suitable for generic KASAN.

This feature considers the size of struct kasan_alloc_meta and
kasan_free_meta, we try to optimize the structure layout and size
, let it get better memory consumption.

[1]https://bugzilla.kernel.org/show_bug.cgi?id=198437
[2]https://groups.google.com/forum/#!searchin/kasan-dev/better$20stack$20traces$20for$20rcu%7Csort:date/kasan-dev/KQsjT_88hDE/7rNUZprRBgAJ

Changes since v2:
- remove new config option, default enable it in generic KASAN
- test this feature in SLAB/SLUB, it is pass.
- modify macro to be more clearly
- modify documentation

Changes since v3:
- change recording from first/last to the last two call stacks
- move free track into kasan free meta
- init slab_free_meta on object slot creation
- modify documentation

Changes since v4:
- change variable name to be more clearly
- remove the redundant condition
- remove init free meta-data and increasing object condition

Changes since v5:
- add a macro KASAN_KMALLOC_FREETRACK in order to check whether
  print free stack
- change printing message
- remove descriptions in Kocong.kasan

Changes since v6:
- reuse print_stack() in print_track()

Walter Wu (4):
rcu/kasan: record and print call_rcu() call stack
kasan: record and print the free track
kasan: add tests for call_rcu stack recording
kasan: update documentation for generic kasan

Documentation/dev-tools/kasan.rst |  3 +++
include/linux/kasan.h |  2 ++
kernel/rcu/tree.c |  2 ++
lib/test_kasan.c  | 30 ++
mm/kasan/common.c | 26 --
mm/kasan/generic.c| 43 
+++
mm/kasan/generic_report.c |  1 +
mm/kasan/kasan.h  | 23 +--
mm/kasan/quarantine.c |  1 +
mm/kasan/report.c | 54 
+++---
mm/kasan/tags.c   | 37 +
11 files changed, 171 insertions(+), 51 deletions(-)

Re: [PATCH v5 1/4] rcu/kasan: record and print call_rcu() call stack

2020-05-20 Thread Walter Wu
> On Wed, May 20, 2020 at 2:34 PM Walter Wu  wrote:
> >
> > This feature will record the last two call_rcu() call stacks and
> > prints up to 2 call_rcu() call stacks in KASAN report.
> >
> > When call_rcu() is called, we store the call_rcu() call stack into
> > slub alloc meta-data, so that the KASAN report can print rcu stack.
> >
> > [1]https://bugzilla.kernel.org/show_bug.cgi?id=198437
> > [2]https://groups.google.com/forum/#!searchin/kasan-dev/better$20stack$20traces$20for$20rcu%7Csort:date/kasan-dev/KQsjT_88hDE/7rNUZprRBgAJ
> >
> > Signed-off-by: Walter Wu 
> > Suggested-by: Dmitry Vyukov 
> > Acked-by: Paul E. McKenney 
> > Cc: Andrey Ryabinin 
> > Cc: Dmitry Vyukov 
> > Cc: Alexander Potapenko 
> > Cc: Andrew Morton 
> > Cc: Josh Triplett 
> > Cc: Mathieu Desnoyers 
> > Cc: Lai Jiangshan 
> > Cc: Joel Fernandes 
> > Cc: Andrey Konovalov 
> > ---
> >  include/linux/kasan.h |  2 ++
> >  kernel/rcu/tree.c |  2 ++
> >  mm/kasan/common.c |  4 ++--
> >  mm/kasan/generic.c| 21 +
> >  mm/kasan/kasan.h  | 10 ++
> >  mm/kasan/report.c | 24 
> >  6 files changed, 61 insertions(+), 2 deletions(-)
> >
> > diff --git a/include/linux/kasan.h b/include/linux/kasan.h
> > index 31314ca7c635..23b7ee00572d 100644
> > --- a/include/linux/kasan.h
> > +++ b/include/linux/kasan.h
> > @@ -174,11 +174,13 @@ static inline size_t kasan_metadata_size(struct 
> > kmem_cache *cache) { return 0; }
> >
> >  void kasan_cache_shrink(struct kmem_cache *cache);
> >  void kasan_cache_shutdown(struct kmem_cache *cache);
> > +void kasan_record_aux_stack(void *ptr);
> >
> >  #else /* CONFIG_KASAN_GENERIC */
> >
> >  static inline void kasan_cache_shrink(struct kmem_cache *cache) {}
> >  static inline void kasan_cache_shutdown(struct kmem_cache *cache) {}
> > +static inline void kasan_record_aux_stack(void *ptr) {}
> >
> >  #endif /* CONFIG_KASAN_GENERIC */
> >
> > diff --git a/kernel/rcu/tree.c b/kernel/rcu/tree.c
> > index 06548e2ebb72..36a4ff7f320b 100644
> > --- a/kernel/rcu/tree.c
> > +++ b/kernel/rcu/tree.c
> > @@ -57,6 +57,7 @@
> >  #include 
> >  #include 
> >  #include 
> > +#include 
> >  #include "../time/tick-internal.h"
> >
> >  #include "tree.h"
> > @@ -2668,6 +2669,7 @@ __call_rcu(struct rcu_head *head, rcu_callback_t func)
> > head->func = func;
> > head->next = NULL;
> > local_irq_save(flags);
> > +   kasan_record_aux_stack(head);
> > rdp = this_cpu_ptr(_data);
> >
> > /* Add the callback to our list. */
> > diff --git a/mm/kasan/common.c b/mm/kasan/common.c
> > index 2906358e42f0..8bc618289bb1 100644
> > --- a/mm/kasan/common.c
> > +++ b/mm/kasan/common.c
> > @@ -41,7 +41,7 @@
> >  #include "kasan.h"
> >  #include "../slab.h"
> >
> > -static inline depot_stack_handle_t save_stack(gfp_t flags)
> > +depot_stack_handle_t kasan_save_stack(gfp_t flags)
> >  {
> > unsigned long entries[KASAN_STACK_DEPTH];
> > unsigned int nr_entries;
> > @@ -54,7 +54,7 @@ static inline depot_stack_handle_t save_stack(gfp_t flags)
> >  static inline void set_track(struct kasan_track *track, gfp_t flags)
> >  {
> > track->pid = current->pid;
> > -   track->stack = save_stack(flags);
> > +   track->stack = kasan_save_stack(flags);
> >  }
> >
> >  void kasan_enable_current(void)
> > diff --git a/mm/kasan/generic.c b/mm/kasan/generic.c
> > index 56ff8885fe2e..8acf48882ba2 100644
> > --- a/mm/kasan/generic.c
> > +++ b/mm/kasan/generic.c
> > @@ -325,3 +325,24 @@ DEFINE_ASAN_SET_SHADOW(f2);
> >  DEFINE_ASAN_SET_SHADOW(f3);
> >  DEFINE_ASAN_SET_SHADOW(f5);
> >  DEFINE_ASAN_SET_SHADOW(f8);
> > +
> > +void kasan_record_aux_stack(void *addr)
> > +{
> > +   struct page *page = kasan_addr_to_page(addr);
> > +   struct kmem_cache *cache;
> > +   struct kasan_alloc_meta *alloc_info;
> > +   void *object;
> > +
> > +   if (!(page && PageSlab(page)))
> > +   return;
> > +
> > +   cache = page->slab_cache;
> > +   object = nearest_obj(cache, page, addr);
> > +   alloc_info = get_alloc_info(cache, object);
> > +
> > +   /*
> > +* record the last two call_rcu() call stacks.
> > +

[PATCH v5 4/4] kasan: update documentation for generic kasan

2020-05-20 Thread Walter Wu
Generic KASAN will support to record the last two call_rcu() call stacks
and print them in KASAN report. So that need to update documentation.

Signed-off-by: Walter Wu 
Cc: Andrey Ryabinin 
Cc: Dmitry Vyukov 
Cc: Alexander Potapenko 
Cc: Jonathan Corbet 
---
 Documentation/dev-tools/kasan.rst | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/Documentation/dev-tools/kasan.rst 
b/Documentation/dev-tools/kasan.rst
index c652d740735d..fede42e6536b 100644
--- a/Documentation/dev-tools/kasan.rst
+++ b/Documentation/dev-tools/kasan.rst
@@ -193,6 +193,9 @@ function calls GCC directly inserts the code to check the 
shadow memory.
 This option significantly enlarges kernel but it gives x1.1-x2 performance
 boost over outline instrumented kernel.
 
+Generic KASAN prints up to 2 call_rcu() call stacks in reports, the last one
+and the second to last.
+
 Software tag-based KASAN
 
 
-- 
2.18.0


[PATCH v5 3/4] kasan: add tests for call_rcu stack recording

2020-05-20 Thread Walter Wu
Test call_rcu() call stack recording and verify whether it correctly
is printed in KASAN report.

Signed-off-by: Walter Wu 
Cc: Andrey Ryabinin 
Cc: Dmitry Vyukov 
Cc: Alexander Potapenko 
Cc: Matthias Brugger 
---
 lib/test_kasan.c | 30 ++
 1 file changed, 30 insertions(+)

diff --git a/lib/test_kasan.c b/lib/test_kasan.c
index e3087d90e00d..6e5fb05d42d8 100644
--- a/lib/test_kasan.c
+++ b/lib/test_kasan.c
@@ -792,6 +792,35 @@ static noinline void __init vmalloc_oob(void)
 static void __init vmalloc_oob(void) {}
 #endif
 
+static struct kasan_rcu_info {
+   int i;
+   struct rcu_head rcu;
+} *global_ptr;
+
+static noinline void __init kasan_rcu_reclaim(struct rcu_head *rp)
+{
+   struct kasan_rcu_info *fp = container_of(rp,
+   struct kasan_rcu_info, rcu);
+
+   kfree(fp);
+   fp->i = 1;
+}
+
+static noinline void __init kasan_rcu_uaf(void)
+{
+   struct kasan_rcu_info *ptr;
+
+   pr_info("use-after-free in kasan_rcu_reclaim\n");
+   ptr = kmalloc(sizeof(struct kasan_rcu_info), GFP_KERNEL);
+   if (!ptr) {
+   pr_err("Allocation failed\n");
+   return;
+   }
+
+   global_ptr = rcu_dereference_protected(ptr, NULL);
+   call_rcu(_ptr->rcu, kasan_rcu_reclaim);
+}
+
 static int __init kmalloc_tests_init(void)
 {
/*
@@ -839,6 +868,7 @@ static int __init kmalloc_tests_init(void)
kasan_bitops();
kmalloc_double_kzfree();
vmalloc_oob();
+   kasan_rcu_uaf();
 
kasan_restore_multi_shot(multishot);
 
-- 
2.18.0


[PATCH v5 2/4] kasan: record and print the free track

2020-05-20 Thread Walter Wu
Move free track from kasan_alloc_meta to kasan_free_meta in order
to make struct kasan_alloc_meta and kasan_free_meta size are both
16 bytes. It is a good size because it is the minimal redzone size
and a good number of alignment.

For free track, we make some modifications as shown below:
1) Remove the free_track from struct kasan_alloc_meta.
2) Add the free_track into struct kasan_free_meta.
3) Add a macro KASAN_KMALLOC_FREETRACK in order to check whether
   print free stack in KASAN report.

[1]https://bugzilla.kernel.org/show_bug.cgi?id=198437

Signed-off-by: Walter Wu 
Suggested-by: Dmitry Vyukov 
Co-developed-by: Dmitry Vyukov 
Cc: Andrey Ryabinin 
Cc: Dmitry Vyukov 
Cc: Alexander Potapenko 
---
 mm/kasan/common.c | 22 ++
 mm/kasan/generic.c| 22 ++
 mm/kasan/generic_report.c |  1 +
 mm/kasan/kasan.h  | 13 +++--
 mm/kasan/quarantine.c |  1 +
 mm/kasan/report.c | 26 --
 mm/kasan/tags.c   | 37 +
 7 files changed, 78 insertions(+), 44 deletions(-)

diff --git a/mm/kasan/common.c b/mm/kasan/common.c
index 8bc618289bb1..47b53912f322 100644
--- a/mm/kasan/common.c
+++ b/mm/kasan/common.c
@@ -51,7 +51,7 @@ depot_stack_handle_t kasan_save_stack(gfp_t flags)
return stack_depot_save(entries, nr_entries, flags);
 }
 
-static inline void set_track(struct kasan_track *track, gfp_t flags)
+void kasan_set_track(struct kasan_track *track, gfp_t flags)
 {
track->pid = current->pid;
track->stack = kasan_save_stack(flags);
@@ -299,24 +299,6 @@ struct kasan_free_meta *get_free_info(struct kmem_cache 
*cache,
return (void *)object + cache->kasan_info.free_meta_offset;
 }
 
-
-static void kasan_set_free_info(struct kmem_cache *cache,
-   void *object, u8 tag)
-{
-   struct kasan_alloc_meta *alloc_meta;
-   u8 idx = 0;
-
-   alloc_meta = get_alloc_info(cache, object);
-
-#ifdef CONFIG_KASAN_SW_TAGS_IDENTIFY
-   idx = alloc_meta->free_track_idx;
-   alloc_meta->free_pointer_tag[idx] = tag;
-   alloc_meta->free_track_idx = (idx + 1) % KASAN_NR_FREE_STACKS;
-#endif
-
-   set_track(_meta->free_track[idx], GFP_NOWAIT);
-}
-
 void kasan_poison_slab(struct page *page)
 {
unsigned long i;
@@ -492,7 +474,7 @@ static void *__kasan_kmalloc(struct kmem_cache *cache, 
const void *object,
KASAN_KMALLOC_REDZONE);
 
if (cache->flags & SLAB_KASAN)
-   set_track(_alloc_info(cache, object)->alloc_track, flags);
+   kasan_set_track(_alloc_info(cache, object)->alloc_track, 
flags);
 
return set_tag(object, tag);
 }
diff --git a/mm/kasan/generic.c b/mm/kasan/generic.c
index 8acf48882ba2..4b3cbad7431b 100644
--- a/mm/kasan/generic.c
+++ b/mm/kasan/generic.c
@@ -346,3 +346,25 @@ void kasan_record_aux_stack(void *addr)
alloc_info->aux_stack[1] = alloc_info->aux_stack[0];
alloc_info->aux_stack[0] = kasan_save_stack(GFP_NOWAIT);
 }
+
+void kasan_set_free_info(struct kmem_cache *cache,
+   void *object, u8 tag)
+{
+   struct kasan_free_meta *free_meta;
+
+   free_meta = get_free_info(cache, object);
+   kasan_set_track(_meta->free_track, GFP_NOWAIT);
+
+   /*
+*  the object was freed and has free track set
+*/
+   *(u8 *)kasan_mem_to_shadow(object) = KASAN_KMALLOC_FREETRACK;
+}
+
+struct kasan_track *kasan_get_free_track(struct kmem_cache *cache,
+   void *object, u8 tag)
+{
+   if (*(u8 *)kasan_mem_to_shadow(object) != KASAN_KMALLOC_FREETRACK)
+   return NULL;
+   return _free_info(cache, object)->free_track;
+}
diff --git a/mm/kasan/generic_report.c b/mm/kasan/generic_report.c
index e200acb2d292..a38c7a9e192a 100644
--- a/mm/kasan/generic_report.c
+++ b/mm/kasan/generic_report.c
@@ -80,6 +80,7 @@ static const char *get_shadow_bug_type(struct 
kasan_access_info *info)
break;
case KASAN_FREE_PAGE:
case KASAN_KMALLOC_FREE:
+   case KASAN_KMALLOC_FREETRACK:
bug_type = "use-after-free";
break;
case KASAN_ALLOCA_LEFT:
diff --git a/mm/kasan/kasan.h b/mm/kasan/kasan.h
index a7391bc83070..ef655a1c6e15 100644
--- a/mm/kasan/kasan.h
+++ b/mm/kasan/kasan.h
@@ -17,15 +17,17 @@
 #define KASAN_PAGE_REDZONE  0xFE  /* redzone for kmalloc_large allocations 
*/
 #define KASAN_KMALLOC_REDZONE   0xFC  /* redzone inside slub object */
 #define KASAN_KMALLOC_FREE  0xFB  /* object was freed 
(kmem_cache_free/kfree) */
+#define KASAN_KMALLOC_FREETRACK 0xFA  /* object was freed and has free track 
set */
 #else
 #define KASAN_FREE_PAGE KASAN_TAG_INVALID
 #define KASAN_PAGE_REDZONE  KASAN_TAG_INVALID
 #define KASAN_KMALLOC_REDZONE   KASAN_TAG_INVALID
 #define KASAN_KMALLOC_FREE  KASAN_TAG_INVALID
+#defin

[PATCH v5 1/4] rcu/kasan: record and print call_rcu() call stack

2020-05-20 Thread Walter Wu
This feature will record the last two call_rcu() call stacks and
prints up to 2 call_rcu() call stacks in KASAN report.

When call_rcu() is called, we store the call_rcu() call stack into
slub alloc meta-data, so that the KASAN report can print rcu stack.

[1]https://bugzilla.kernel.org/show_bug.cgi?id=198437
[2]https://groups.google.com/forum/#!searchin/kasan-dev/better$20stack$20traces$20for$20rcu%7Csort:date/kasan-dev/KQsjT_88hDE/7rNUZprRBgAJ

Signed-off-by: Walter Wu 
Suggested-by: Dmitry Vyukov 
Acked-by: Paul E. McKenney 
Cc: Andrey Ryabinin 
Cc: Dmitry Vyukov 
Cc: Alexander Potapenko 
Cc: Andrew Morton 
Cc: Josh Triplett 
Cc: Mathieu Desnoyers 
Cc: Lai Jiangshan 
Cc: Joel Fernandes 
Cc: Andrey Konovalov 
---
 include/linux/kasan.h |  2 ++
 kernel/rcu/tree.c |  2 ++
 mm/kasan/common.c |  4 ++--
 mm/kasan/generic.c| 21 +
 mm/kasan/kasan.h  | 10 ++
 mm/kasan/report.c | 24 
 6 files changed, 61 insertions(+), 2 deletions(-)

diff --git a/include/linux/kasan.h b/include/linux/kasan.h
index 31314ca7c635..23b7ee00572d 100644
--- a/include/linux/kasan.h
+++ b/include/linux/kasan.h
@@ -174,11 +174,13 @@ static inline size_t kasan_metadata_size(struct 
kmem_cache *cache) { return 0; }
 
 void kasan_cache_shrink(struct kmem_cache *cache);
 void kasan_cache_shutdown(struct kmem_cache *cache);
+void kasan_record_aux_stack(void *ptr);
 
 #else /* CONFIG_KASAN_GENERIC */
 
 static inline void kasan_cache_shrink(struct kmem_cache *cache) {}
 static inline void kasan_cache_shutdown(struct kmem_cache *cache) {}
+static inline void kasan_record_aux_stack(void *ptr) {}
 
 #endif /* CONFIG_KASAN_GENERIC */
 
diff --git a/kernel/rcu/tree.c b/kernel/rcu/tree.c
index 06548e2ebb72..36a4ff7f320b 100644
--- a/kernel/rcu/tree.c
+++ b/kernel/rcu/tree.c
@@ -57,6 +57,7 @@
 #include 
 #include 
 #include 
+#include 
 #include "../time/tick-internal.h"
 
 #include "tree.h"
@@ -2668,6 +2669,7 @@ __call_rcu(struct rcu_head *head, rcu_callback_t func)
head->func = func;
head->next = NULL;
local_irq_save(flags);
+   kasan_record_aux_stack(head);
rdp = this_cpu_ptr(_data);
 
/* Add the callback to our list. */
diff --git a/mm/kasan/common.c b/mm/kasan/common.c
index 2906358e42f0..8bc618289bb1 100644
--- a/mm/kasan/common.c
+++ b/mm/kasan/common.c
@@ -41,7 +41,7 @@
 #include "kasan.h"
 #include "../slab.h"
 
-static inline depot_stack_handle_t save_stack(gfp_t flags)
+depot_stack_handle_t kasan_save_stack(gfp_t flags)
 {
unsigned long entries[KASAN_STACK_DEPTH];
unsigned int nr_entries;
@@ -54,7 +54,7 @@ static inline depot_stack_handle_t save_stack(gfp_t flags)
 static inline void set_track(struct kasan_track *track, gfp_t flags)
 {
track->pid = current->pid;
-   track->stack = save_stack(flags);
+   track->stack = kasan_save_stack(flags);
 }
 
 void kasan_enable_current(void)
diff --git a/mm/kasan/generic.c b/mm/kasan/generic.c
index 56ff8885fe2e..8acf48882ba2 100644
--- a/mm/kasan/generic.c
+++ b/mm/kasan/generic.c
@@ -325,3 +325,24 @@ DEFINE_ASAN_SET_SHADOW(f2);
 DEFINE_ASAN_SET_SHADOW(f3);
 DEFINE_ASAN_SET_SHADOW(f5);
 DEFINE_ASAN_SET_SHADOW(f8);
+
+void kasan_record_aux_stack(void *addr)
+{
+   struct page *page = kasan_addr_to_page(addr);
+   struct kmem_cache *cache;
+   struct kasan_alloc_meta *alloc_info;
+   void *object;
+
+   if (!(page && PageSlab(page)))
+   return;
+
+   cache = page->slab_cache;
+   object = nearest_obj(cache, page, addr);
+   alloc_info = get_alloc_info(cache, object);
+
+   /*
+* record the last two call_rcu() call stacks.
+*/
+   alloc_info->aux_stack[1] = alloc_info->aux_stack[0];
+   alloc_info->aux_stack[0] = kasan_save_stack(GFP_NOWAIT);
+}
diff --git a/mm/kasan/kasan.h b/mm/kasan/kasan.h
index e8f37199d885..a7391bc83070 100644
--- a/mm/kasan/kasan.h
+++ b/mm/kasan/kasan.h
@@ -104,7 +104,15 @@ struct kasan_track {
 
 struct kasan_alloc_meta {
struct kasan_track alloc_track;
+#ifdef CONFIG_KASAN_GENERIC
+   /*
+* call_rcu() call stack is stored into struct kasan_alloc_meta.
+* The free stack is stored into struct kasan_free_meta.
+*/
+   depot_stack_handle_t aux_stack[2];
+#else
struct kasan_track free_track[KASAN_NR_FREE_STACKS];
+#endif
 #ifdef CONFIG_KASAN_SW_TAGS_IDENTIFY
u8 free_pointer_tag[KASAN_NR_FREE_STACKS];
u8 free_track_idx;
@@ -159,6 +167,8 @@ void kasan_report_invalid_free(void *object, unsigned long 
ip);
 
 struct page *kasan_addr_to_page(const void *addr);
 
+depot_stack_handle_t kasan_save_stack(gfp_t flags);
+
 #if defined(CONFIG_KASAN_GENERIC) && \
(defined(CONFIG_SLAB) || defined(CONFIG_SLUB))
 void quarantine_put(struct kasan_free_meta *info, struct kmem_cache *cache);
diff --git a/mm/kasan/report.c b/m

[PATCH v5 0/4] kasan: memorize and print call_rcu stack

2020-05-20 Thread Walter Wu
This patchset improves KASAN reports by making them to have
call_rcu() call stack information. It is useful for programmers
to solve use-after-free or double-free memory issue.

The KASAN report was as follows(cleaned up slightly):

BUG: KASAN: use-after-free in kasan_rcu_reclaim+0x58/0x60

Freed by task 0:
 kasan_save_stack+0x24/0x50
 kasan_set_track+0x24/0x38
 kasan_set_free_info+0x18/0x20
 __kasan_slab_free+0x10c/0x170
 kasan_slab_free+0x10/0x18
 kfree+0x98/0x270
 kasan_rcu_reclaim+0x1c/0x60

Last one call_rcu() call stack:
 kasan_save_stack+0x24/0x50
 kasan_record_aux_stack+0xbc/0xd0
 call_rcu+0x8c/0x580
 kasan_rcu_uaf+0xf4/0xf8

Generic KASAN will record the last two call_rcu() call stacks and
print up to 2 call_rcu() call stacks in KASAN report. it is only
suitable for generic KASAN.

This feature considers the size of struct kasan_alloc_meta and
kasan_free_meta, we try to optimize the structure layout and size
, let it get better memory consumption.

[1]https://bugzilla.kernel.org/show_bug.cgi?id=198437
[2]https://groups.google.com/forum/#!searchin/kasan-dev/better$20stack$20traces$20for$20rcu%7Csort:date/kasan-dev/KQsjT_88hDE/7rNUZprRBgAJ

Changes since v2:
- remove new config option, default enable it in generic KASAN
- test this feature in SLAB/SLUB, it is pass.
- modify macro to be more clearly
- modify documentation

Changes since v3:
- change recording from first/last to the last two call stacks
- move free track into kasan free meta
- init slab_free_meta on object slot creation
- modify documentation

Changes since v4:
- change variable name to be more clearly
- remove the redundant condition
- remove init free meta-data and increasing object condition

Changes since v5:
- add a macro KASAN_KMALLOC_FREETRACK in order to check whether
  print free stack
- change printing message
- remove descriptions in Kocong.kasan

Walter Wu (4):
rcu/kasan: record and print call_rcu() call stack
kasan: record and print the free track
kasan: add tests for call_rcu stack recording
kasan: update documentation for generic kasan

Documentation/dev-tools/kasan.rst |  3 +++
include/linux/kasan.h |  2 ++
kernel/rcu/tree.c |  2 ++
lib/test_kasan.c  | 30 ++
mm/kasan/common.c | 26 --
mm/kasan/generic.c| 43 
+++
mm/kasan/generic_report.c |  1 +
mm/kasan/kasan.h  | 23 +--
mm/kasan/quarantine.c |  1 +
mm/kasan/report.c | 50 
--
mm/kasan/tags.c   | 37 +
11 files changed, 172 insertions(+), 46 deletions(-)


Re: [PATCH v4 2/4] kasan: record and print the free track

2020-05-20 Thread Walter Wu
On Wed, 2020-05-20 at 13:15 +0200, 'Dmitry Vyukov' via kasan-dev wrote:
> On Wed, May 20, 2020 at 12:15 PM Walter Wu  wrote:
> >
> > On Wed, 2020-05-20 at 11:44 +0200, 'Dmitry Vyukov' via kasan-dev wrote:
> > > On Wed, May 20, 2020 at 11:17 AM Walter Wu  
> > > wrote:
> > > > > > On Wed, 2020-05-20 at 13:14 +0800, Walter Wu wrote:
> > > > > > > > On Wed, May 20, 2020 at 6:03 AM Walter Wu 
> > > > > > > >  wrote:
> > > > > > > > >
> > > > > > > > > > On Tue, May 19, 2020 at 4:25 AM Walter Wu 
> > > > > > > > > >  wrote:
> > > > > > > > > > >
> > > > > > > > > > > Move free track from slub alloc meta-data to slub free 
> > > > > > > > > > > meta-data in
> > > > > > > > > > > order to make struct kasan_free_meta size is 16 bytes. It 
> > > > > > > > > > > is a good
> > > > > > > > > > > size because it is the minimal redzone size and a good 
> > > > > > > > > > > number of
> > > > > > > > > > > alignment.
> > > > > > > > > > >
> > > > > > > > > > > For free track in generic KASAN, we do the modification 
> > > > > > > > > > > in struct
> > > > > > > > > > > kasan_alloc_meta and kasan_free_meta:
> > > > > > > > > > > - remove free track from kasan_alloc_meta.
> > > > > > > > > > > - add free track into kasan_free_meta.
> > > > > > > > > > >
> > > > > > > > > > > [1]https://bugzilla.kernel.org/show_bug.cgi?id=198437
> > > > > > > > > > >
> > > > > > > > > > > Signed-off-by: Walter Wu 
> > > > > > > > > > > Suggested-by: Dmitry Vyukov 
> > > > > > > > > > > Cc: Andrey Ryabinin 
> > > > > > > > > > > Cc: Dmitry Vyukov 
> > > > > > > > > > > Cc: Alexander Potapenko 
> > > > > > > > > > > ---
> > > > > > > > > > >  mm/kasan/common.c  | 22 ++
> > > > > > > > > > >  mm/kasan/generic.c | 18 ++
> > > > > > > > > > >  mm/kasan/kasan.h   |  7 +++
> > > > > > > > > > >  mm/kasan/report.c  | 20 
> > > > > > > > > > >  mm/kasan/tags.c| 37 
> > > > > > > > > > > +
> > > > > > > > > > >  5 files changed, 64 insertions(+), 40 deletions(-)
> > > > > > > > > > >
> > > > > > > > > > > diff --git a/mm/kasan/common.c b/mm/kasan/common.c
> > > > > > > > > > > index 8bc618289bb1..47b53912f322 100644
> > > > > > > > > > > --- a/mm/kasan/common.c
> > > > > > > > > > > +++ b/mm/kasan/common.c
> > > > > > > > > > > @@ -51,7 +51,7 @@ depot_stack_handle_t 
> > > > > > > > > > > kasan_save_stack(gfp_t flags)
> > > > > > > > > > > return stack_depot_save(entries, nr_entries, 
> > > > > > > > > > > flags);
> > > > > > > > > > >  }
> > > > > > > > > > >
> > > > > > > > > > > -static inline void set_track(struct kasan_track *track, 
> > > > > > > > > > > gfp_t flags)
> > > > > > > > > > > +void kasan_set_track(struct kasan_track *track, gfp_t 
> > > > > > > > > > > flags)
> > > > > > > > > > >  {
> > > > > > > > > > > track->pid = current->pid;
> > > > > > > > > > > track->stack = kasan_save_stack(flags);
> > > > > > > > > > > @@ -299,24 +299,6 @@ struct kasan_free_meta 
> > > > > > > > > > > *get_free_info(struct kmem_cache *cache,
> > > > > > > > > > > return (void *)o

Re: [PATCH v4 2/4] kasan: record and print the free track

2020-05-20 Thread Walter Wu
On Wed, 2020-05-20 at 11:44 +0200, 'Dmitry Vyukov' via kasan-dev wrote:
> On Wed, May 20, 2020 at 11:17 AM Walter Wu  wrote:
> > > > On Wed, 2020-05-20 at 13:14 +0800, Walter Wu wrote:
> > > > > > On Wed, May 20, 2020 at 6:03 AM Walter Wu 
> > > > > >  wrote:
> > > > > > >
> > > > > > > > On Tue, May 19, 2020 at 4:25 AM Walter Wu 
> > > > > > > >  wrote:
> > > > > > > > >
> > > > > > > > > Move free track from slub alloc meta-data to slub free 
> > > > > > > > > meta-data in
> > > > > > > > > order to make struct kasan_free_meta size is 16 bytes. It is 
> > > > > > > > > a good
> > > > > > > > > size because it is the minimal redzone size and a good number 
> > > > > > > > > of
> > > > > > > > > alignment.
> > > > > > > > >
> > > > > > > > > For free track in generic KASAN, we do the modification in 
> > > > > > > > > struct
> > > > > > > > > kasan_alloc_meta and kasan_free_meta:
> > > > > > > > > - remove free track from kasan_alloc_meta.
> > > > > > > > > - add free track into kasan_free_meta.
> > > > > > > > >
> > > > > > > > > [1]https://bugzilla.kernel.org/show_bug.cgi?id=198437
> > > > > > > > >
> > > > > > > > > Signed-off-by: Walter Wu 
> > > > > > > > > Suggested-by: Dmitry Vyukov 
> > > > > > > > > Cc: Andrey Ryabinin 
> > > > > > > > > Cc: Dmitry Vyukov 
> > > > > > > > > Cc: Alexander Potapenko 
> > > > > > > > > ---
> > > > > > > > >  mm/kasan/common.c  | 22 ++
> > > > > > > > >  mm/kasan/generic.c | 18 ++
> > > > > > > > >  mm/kasan/kasan.h   |  7 +++
> > > > > > > > >  mm/kasan/report.c  | 20 
> > > > > > > > >  mm/kasan/tags.c| 37 +
> > > > > > > > >  5 files changed, 64 insertions(+), 40 deletions(-)
> > > > > > > > >
> > > > > > > > > diff --git a/mm/kasan/common.c b/mm/kasan/common.c
> > > > > > > > > index 8bc618289bb1..47b53912f322 100644
> > > > > > > > > --- a/mm/kasan/common.c
> > > > > > > > > +++ b/mm/kasan/common.c
> > > > > > > > > @@ -51,7 +51,7 @@ depot_stack_handle_t kasan_save_stack(gfp_t 
> > > > > > > > > flags)
> > > > > > > > > return stack_depot_save(entries, nr_entries, flags);
> > > > > > > > >  }
> > > > > > > > >
> > > > > > > > > -static inline void set_track(struct kasan_track *track, 
> > > > > > > > > gfp_t flags)
> > > > > > > > > +void kasan_set_track(struct kasan_track *track, gfp_t flags)
> > > > > > > > >  {
> > > > > > > > > track->pid = current->pid;
> > > > > > > > > track->stack = kasan_save_stack(flags);
> > > > > > > > > @@ -299,24 +299,6 @@ struct kasan_free_meta 
> > > > > > > > > *get_free_info(struct kmem_cache *cache,
> > > > > > > > > return (void *)object + 
> > > > > > > > > cache->kasan_info.free_meta_offset;
> > > > > > > > >  }
> > > > > > > > >
> > > > > > > > > -
> > > > > > > > > -static void kasan_set_free_info(struct kmem_cache *cache,
> > > > > > > > > -   void *object, u8 tag)
> > > > > > > > > -{
> > > > > > > > > -   struct kasan_alloc_meta *alloc_meta;
> > > > > > > > > -   u8 idx = 0;
> > > > > > > > > -
> > > > > > > > > -   alloc_meta = get_alloc_info(cache, object);
> > > > > > > > > -
> > > > > > > > > -#ifdef CONFIG_KASAN_SW_

Re: [PATCH v4 2/4] kasan: record and print the free track

2020-05-20 Thread Walter Wu
> On Wed, May 20, 2020 at 8:18 AM Walter Wu  wrote:
> >
> > On Wed, 2020-05-20 at 13:14 +0800, Walter Wu wrote:
> > > > On Wed, May 20, 2020 at 6:03 AM Walter Wu  
> > > > wrote:
> > > > >
> > > > > > On Tue, May 19, 2020 at 4:25 AM Walter Wu 
> > > > > >  wrote:
> > > > > > >
> > > > > > > Move free track from slub alloc meta-data to slub free meta-data 
> > > > > > > in
> > > > > > > order to make struct kasan_free_meta size is 16 bytes. It is a 
> > > > > > > good
> > > > > > > size because it is the minimal redzone size and a good number of
> > > > > > > alignment.
> > > > > > >
> > > > > > > For free track in generic KASAN, we do the modification in struct
> > > > > > > kasan_alloc_meta and kasan_free_meta:
> > > > > > > - remove free track from kasan_alloc_meta.
> > > > > > > - add free track into kasan_free_meta.
> > > > > > >
> > > > > > > [1]https://bugzilla.kernel.org/show_bug.cgi?id=198437
> > > > > > >
> > > > > > > Signed-off-by: Walter Wu 
> > > > > > > Suggested-by: Dmitry Vyukov 
> > > > > > > Cc: Andrey Ryabinin 
> > > > > > > Cc: Dmitry Vyukov 
> > > > > > > Cc: Alexander Potapenko 
> > > > > > > ---
> > > > > > >  mm/kasan/common.c  | 22 ++
> > > > > > >  mm/kasan/generic.c | 18 ++
> > > > > > >  mm/kasan/kasan.h   |  7 +++
> > > > > > >  mm/kasan/report.c  | 20 
> > > > > > >  mm/kasan/tags.c| 37 +
> > > > > > >  5 files changed, 64 insertions(+), 40 deletions(-)
> > > > > > >
> > > > > > > diff --git a/mm/kasan/common.c b/mm/kasan/common.c
> > > > > > > index 8bc618289bb1..47b53912f322 100644
> > > > > > > --- a/mm/kasan/common.c
> > > > > > > +++ b/mm/kasan/common.c
> > > > > > > @@ -51,7 +51,7 @@ depot_stack_handle_t kasan_save_stack(gfp_t 
> > > > > > > flags)
> > > > > > > return stack_depot_save(entries, nr_entries, flags);
> > > > > > >  }
> > > > > > >
> > > > > > > -static inline void set_track(struct kasan_track *track, gfp_t 
> > > > > > > flags)
> > > > > > > +void kasan_set_track(struct kasan_track *track, gfp_t flags)
> > > > > > >  {
> > > > > > > track->pid = current->pid;
> > > > > > > track->stack = kasan_save_stack(flags);
> > > > > > > @@ -299,24 +299,6 @@ struct kasan_free_meta *get_free_info(struct 
> > > > > > > kmem_cache *cache,
> > > > > > > return (void *)object + 
> > > > > > > cache->kasan_info.free_meta_offset;
> > > > > > >  }
> > > > > > >
> > > > > > > -
> > > > > > > -static void kasan_set_free_info(struct kmem_cache *cache,
> > > > > > > -   void *object, u8 tag)
> > > > > > > -{
> > > > > > > -   struct kasan_alloc_meta *alloc_meta;
> > > > > > > -   u8 idx = 0;
> > > > > > > -
> > > > > > > -   alloc_meta = get_alloc_info(cache, object);
> > > > > > > -
> > > > > > > -#ifdef CONFIG_KASAN_SW_TAGS_IDENTIFY
> > > > > > > -   idx = alloc_meta->free_track_idx;
> > > > > > > -   alloc_meta->free_pointer_tag[idx] = tag;
> > > > > > > -   alloc_meta->free_track_idx = (idx + 1) % 
> > > > > > > KASAN_NR_FREE_STACKS;
> > > > > > > -#endif
> > > > > > > -
> > > > > > > -   set_track(_meta->free_track[idx], GFP_NOWAIT);
> > > > > > > -}
> > > > > > > -
> > > > > > >  void kasan_poison_slab(struct page *page)
> > > > > > >  {
> > > > > > > unsigned long i;
> > > > > 

Re: [PATCH v4 2/4] kasan: record and print the free track

2020-05-20 Thread Walter Wu
On Wed, 2020-05-20 at 13:14 +0800, Walter Wu wrote:
> > On Wed, May 20, 2020 at 6:03 AM Walter Wu  wrote:
> > >
> > > > On Tue, May 19, 2020 at 4:25 AM Walter Wu  
> > > > wrote:
> > > > >
> > > > > Move free track from slub alloc meta-data to slub free meta-data in
> > > > > order to make struct kasan_free_meta size is 16 bytes. It is a good
> > > > > size because it is the minimal redzone size and a good number of
> > > > > alignment.
> > > > >
> > > > > For free track in generic KASAN, we do the modification in struct
> > > > > kasan_alloc_meta and kasan_free_meta:
> > > > > - remove free track from kasan_alloc_meta.
> > > > > - add free track into kasan_free_meta.
> > > > >
> > > > > [1]https://bugzilla.kernel.org/show_bug.cgi?id=198437
> > > > >
> > > > > Signed-off-by: Walter Wu 
> > > > > Suggested-by: Dmitry Vyukov 
> > > > > Cc: Andrey Ryabinin 
> > > > > Cc: Dmitry Vyukov 
> > > > > Cc: Alexander Potapenko 
> > > > > ---
> > > > >  mm/kasan/common.c  | 22 ++
> > > > >  mm/kasan/generic.c | 18 ++
> > > > >  mm/kasan/kasan.h   |  7 +++
> > > > >  mm/kasan/report.c  | 20 
> > > > >  mm/kasan/tags.c| 37 +
> > > > >  5 files changed, 64 insertions(+), 40 deletions(-)
> > > > >
> > > > > diff --git a/mm/kasan/common.c b/mm/kasan/common.c
> > > > > index 8bc618289bb1..47b53912f322 100644
> > > > > --- a/mm/kasan/common.c
> > > > > +++ b/mm/kasan/common.c
> > > > > @@ -51,7 +51,7 @@ depot_stack_handle_t kasan_save_stack(gfp_t flags)
> > > > > return stack_depot_save(entries, nr_entries, flags);
> > > > >  }
> > > > >
> > > > > -static inline void set_track(struct kasan_track *track, gfp_t flags)
> > > > > +void kasan_set_track(struct kasan_track *track, gfp_t flags)
> > > > >  {
> > > > > track->pid = current->pid;
> > > > > track->stack = kasan_save_stack(flags);
> > > > > @@ -299,24 +299,6 @@ struct kasan_free_meta *get_free_info(struct 
> > > > > kmem_cache *cache,
> > > > > return (void *)object + cache->kasan_info.free_meta_offset;
> > > > >  }
> > > > >
> > > > > -
> > > > > -static void kasan_set_free_info(struct kmem_cache *cache,
> > > > > -   void *object, u8 tag)
> > > > > -{
> > > > > -   struct kasan_alloc_meta *alloc_meta;
> > > > > -   u8 idx = 0;
> > > > > -
> > > > > -   alloc_meta = get_alloc_info(cache, object);
> > > > > -
> > > > > -#ifdef CONFIG_KASAN_SW_TAGS_IDENTIFY
> > > > > -   idx = alloc_meta->free_track_idx;
> > > > > -   alloc_meta->free_pointer_tag[idx] = tag;
> > > > > -   alloc_meta->free_track_idx = (idx + 1) % KASAN_NR_FREE_STACKS;
> > > > > -#endif
> > > > > -
> > > > > -   set_track(_meta->free_track[idx], GFP_NOWAIT);
> > > > > -}
> > > > > -
> > > > >  void kasan_poison_slab(struct page *page)
> > > > >  {
> > > > > unsigned long i;
> > > > > @@ -492,7 +474,7 @@ static void *__kasan_kmalloc(struct kmem_cache 
> > > > > *cache, const void *object,
> > > > > KASAN_KMALLOC_REDZONE);
> > > > >
> > > > > if (cache->flags & SLAB_KASAN)
> > > > > -   set_track(_alloc_info(cache, 
> > > > > object)->alloc_track, flags);
> > > > > +   kasan_set_track(_alloc_info(cache, 
> > > > > object)->alloc_track, flags);
> > > > >
> > > > > return set_tag(object, tag);
> > > > >  }
> > > > > diff --git a/mm/kasan/generic.c b/mm/kasan/generic.c
> > > > > index 3372bdcaf92a..763d8a13e0ac 100644
> > > > > --- a/mm/kasan/generic.c
> > > > > +++ b/mm/kasan/generic.c
> > > > > @@ -344,3 +344,21 @@ void kasan_record_aux_stack(void *addr)
> > > > > alloc_info

Re: [PATCH v4 2/4] kasan: record and print the free track

2020-05-19 Thread Walter Wu
> On Wed, May 20, 2020 at 6:03 AM Walter Wu  wrote:
> >
> > > On Tue, May 19, 2020 at 4:25 AM Walter Wu  
> > > wrote:
> > > >
> > > > Move free track from slub alloc meta-data to slub free meta-data in
> > > > order to make struct kasan_free_meta size is 16 bytes. It is a good
> > > > size because it is the minimal redzone size and a good number of
> > > > alignment.
> > > >
> > > > For free track in generic KASAN, we do the modification in struct
> > > > kasan_alloc_meta and kasan_free_meta:
> > > > - remove free track from kasan_alloc_meta.
> > > > - add free track into kasan_free_meta.
> > > >
> > > > [1]https://bugzilla.kernel.org/show_bug.cgi?id=198437
> > > >
> > > > Signed-off-by: Walter Wu 
> > > > Suggested-by: Dmitry Vyukov 
> > > > Cc: Andrey Ryabinin 
> > > > Cc: Dmitry Vyukov 
> > > > Cc: Alexander Potapenko 
> > > > ---
> > > >  mm/kasan/common.c  | 22 ++
> > > >  mm/kasan/generic.c | 18 ++
> > > >  mm/kasan/kasan.h   |  7 +++
> > > >  mm/kasan/report.c  | 20 
> > > >  mm/kasan/tags.c| 37 +
> > > >  5 files changed, 64 insertions(+), 40 deletions(-)
> > > >
> > > > diff --git a/mm/kasan/common.c b/mm/kasan/common.c
> > > > index 8bc618289bb1..47b53912f322 100644
> > > > --- a/mm/kasan/common.c
> > > > +++ b/mm/kasan/common.c
> > > > @@ -51,7 +51,7 @@ depot_stack_handle_t kasan_save_stack(gfp_t flags)
> > > > return stack_depot_save(entries, nr_entries, flags);
> > > >  }
> > > >
> > > > -static inline void set_track(struct kasan_track *track, gfp_t flags)
> > > > +void kasan_set_track(struct kasan_track *track, gfp_t flags)
> > > >  {
> > > > track->pid = current->pid;
> > > > track->stack = kasan_save_stack(flags);
> > > > @@ -299,24 +299,6 @@ struct kasan_free_meta *get_free_info(struct 
> > > > kmem_cache *cache,
> > > > return (void *)object + cache->kasan_info.free_meta_offset;
> > > >  }
> > > >
> > > > -
> > > > -static void kasan_set_free_info(struct kmem_cache *cache,
> > > > -   void *object, u8 tag)
> > > > -{
> > > > -   struct kasan_alloc_meta *alloc_meta;
> > > > -   u8 idx = 0;
> > > > -
> > > > -   alloc_meta = get_alloc_info(cache, object);
> > > > -
> > > > -#ifdef CONFIG_KASAN_SW_TAGS_IDENTIFY
> > > > -   idx = alloc_meta->free_track_idx;
> > > > -   alloc_meta->free_pointer_tag[idx] = tag;
> > > > -   alloc_meta->free_track_idx = (idx + 1) % KASAN_NR_FREE_STACKS;
> > > > -#endif
> > > > -
> > > > -   set_track(_meta->free_track[idx], GFP_NOWAIT);
> > > > -}
> > > > -
> > > >  void kasan_poison_slab(struct page *page)
> > > >  {
> > > > unsigned long i;
> > > > @@ -492,7 +474,7 @@ static void *__kasan_kmalloc(struct kmem_cache 
> > > > *cache, const void *object,
> > > > KASAN_KMALLOC_REDZONE);
> > > >
> > > > if (cache->flags & SLAB_KASAN)
> > > > -   set_track(_alloc_info(cache, object)->alloc_track, 
> > > > flags);
> > > > +   kasan_set_track(_alloc_info(cache, 
> > > > object)->alloc_track, flags);
> > > >
> > > > return set_tag(object, tag);
> > > >  }
> > > > diff --git a/mm/kasan/generic.c b/mm/kasan/generic.c
> > > > index 3372bdcaf92a..763d8a13e0ac 100644
> > > > --- a/mm/kasan/generic.c
> > > > +++ b/mm/kasan/generic.c
> > > > @@ -344,3 +344,21 @@ void kasan_record_aux_stack(void *addr)
> > > > alloc_info->aux_stack[1] = alloc_info->aux_stack[0];
> > > > alloc_info->aux_stack[0] = kasan_save_stack(GFP_NOWAIT);
> > > >  }
> > > > +
> > > > +void kasan_set_free_info(struct kmem_cache *cache,
> > > > +   void *object, u8 tag)
> > > > +{
> > > > +   struct kasan_free_meta *free_meta;
> > > > +
> > > >

Re: [PATCH v4 2/4] kasan: record and print the free track

2020-05-19 Thread Walter Wu
> On Wed, May 20, 2020 at 6:03 AM Walter Wu  wrote:
> >
> > > On Tue, May 19, 2020 at 4:25 AM Walter Wu  
> > > wrote:
> > > >
> > > > Move free track from slub alloc meta-data to slub free meta-data in
> > > > order to make struct kasan_free_meta size is 16 bytes. It is a good
> > > > size because it is the minimal redzone size and a good number of
> > > > alignment.
> > > >
> > > > For free track in generic KASAN, we do the modification in struct
> > > > kasan_alloc_meta and kasan_free_meta:
> > > > - remove free track from kasan_alloc_meta.
> > > > - add free track into kasan_free_meta.
> > > >
> > > > [1]https://bugzilla.kernel.org/show_bug.cgi?id=198437
> > > >
> > > > Signed-off-by: Walter Wu 
> > > > Suggested-by: Dmitry Vyukov 
> > > > Cc: Andrey Ryabinin 
> > > > Cc: Dmitry Vyukov 
> > > > Cc: Alexander Potapenko 
> > > > ---
> > > >  mm/kasan/common.c  | 22 ++
> > > >  mm/kasan/generic.c | 18 ++
> > > >  mm/kasan/kasan.h   |  7 +++
> > > >  mm/kasan/report.c  | 20 
> > > >  mm/kasan/tags.c| 37 +
> > > >  5 files changed, 64 insertions(+), 40 deletions(-)
> > > >
> > > > diff --git a/mm/kasan/common.c b/mm/kasan/common.c
> > > > index 8bc618289bb1..47b53912f322 100644
> > > > --- a/mm/kasan/common.c
> > > > +++ b/mm/kasan/common.c
> > > > @@ -51,7 +51,7 @@ depot_stack_handle_t kasan_save_stack(gfp_t flags)
> > > > return stack_depot_save(entries, nr_entries, flags);
> > > >  }
> > > >
> > > > -static inline void set_track(struct kasan_track *track, gfp_t flags)
> > > > +void kasan_set_track(struct kasan_track *track, gfp_t flags)
> > > >  {
> > > > track->pid = current->pid;
> > > > track->stack = kasan_save_stack(flags);
> > > > @@ -299,24 +299,6 @@ struct kasan_free_meta *get_free_info(struct 
> > > > kmem_cache *cache,
> > > > return (void *)object + cache->kasan_info.free_meta_offset;
> > > >  }
> > > >
> > > > -
> > > > -static void kasan_set_free_info(struct kmem_cache *cache,
> > > > -   void *object, u8 tag)
> > > > -{
> > > > -   struct kasan_alloc_meta *alloc_meta;
> > > > -   u8 idx = 0;
> > > > -
> > > > -   alloc_meta = get_alloc_info(cache, object);
> > > > -
> > > > -#ifdef CONFIG_KASAN_SW_TAGS_IDENTIFY
> > > > -   idx = alloc_meta->free_track_idx;
> > > > -   alloc_meta->free_pointer_tag[idx] = tag;
> > > > -   alloc_meta->free_track_idx = (idx + 1) % KASAN_NR_FREE_STACKS;
> > > > -#endif
> > > > -
> > > > -   set_track(_meta->free_track[idx], GFP_NOWAIT);
> > > > -}
> > > > -
> > > >  void kasan_poison_slab(struct page *page)
> > > >  {
> > > > unsigned long i;
> > > > @@ -492,7 +474,7 @@ static void *__kasan_kmalloc(struct kmem_cache 
> > > > *cache, const void *object,
> > > > KASAN_KMALLOC_REDZONE);
> > > >
> > > > if (cache->flags & SLAB_KASAN)
> > > > -   set_track(_alloc_info(cache, object)->alloc_track, 
> > > > flags);
> > > > +   kasan_set_track(_alloc_info(cache, 
> > > > object)->alloc_track, flags);
> > > >
> > > > return set_tag(object, tag);
> > > >  }
> > > > diff --git a/mm/kasan/generic.c b/mm/kasan/generic.c
> > > > index 3372bdcaf92a..763d8a13e0ac 100644
> > > > --- a/mm/kasan/generic.c
> > > > +++ b/mm/kasan/generic.c
> > > > @@ -344,3 +344,21 @@ void kasan_record_aux_stack(void *addr)
> > > > alloc_info->aux_stack[1] = alloc_info->aux_stack[0];
> > > > alloc_info->aux_stack[0] = kasan_save_stack(GFP_NOWAIT);
> > > >  }
> > > > +
> > > > +void kasan_set_free_info(struct kmem_cache *cache,
> > > > +   void *object, u8 tag)
> > > > +{
> > > > +   struct kasan_free_meta *free_meta;
> > > > +
> > > >

Re: [PATCH v4 2/4] kasan: record and print the free track

2020-05-19 Thread Walter Wu
> On Tue, May 19, 2020 at 4:25 AM Walter Wu  wrote:
> >
> > Move free track from slub alloc meta-data to slub free meta-data in
> > order to make struct kasan_free_meta size is 16 bytes. It is a good
> > size because it is the minimal redzone size and a good number of
> > alignment.
> >
> > For free track in generic KASAN, we do the modification in struct
> > kasan_alloc_meta and kasan_free_meta:
> > - remove free track from kasan_alloc_meta.
> > - add free track into kasan_free_meta.
> >
> > [1]https://bugzilla.kernel.org/show_bug.cgi?id=198437
> >
> > Signed-off-by: Walter Wu 
> > Suggested-by: Dmitry Vyukov 
> > Cc: Andrey Ryabinin 
> > Cc: Dmitry Vyukov 
> > Cc: Alexander Potapenko 
> > ---
> >  mm/kasan/common.c  | 22 ++
> >  mm/kasan/generic.c | 18 ++
> >  mm/kasan/kasan.h   |  7 +++
> >  mm/kasan/report.c  | 20 
> >  mm/kasan/tags.c| 37 +
> >  5 files changed, 64 insertions(+), 40 deletions(-)
> >
> > diff --git a/mm/kasan/common.c b/mm/kasan/common.c
> > index 8bc618289bb1..47b53912f322 100644
> > --- a/mm/kasan/common.c
> > +++ b/mm/kasan/common.c
> > @@ -51,7 +51,7 @@ depot_stack_handle_t kasan_save_stack(gfp_t flags)
> > return stack_depot_save(entries, nr_entries, flags);
> >  }
> >
> > -static inline void set_track(struct kasan_track *track, gfp_t flags)
> > +void kasan_set_track(struct kasan_track *track, gfp_t flags)
> >  {
> > track->pid = current->pid;
> > track->stack = kasan_save_stack(flags);
> > @@ -299,24 +299,6 @@ struct kasan_free_meta *get_free_info(struct 
> > kmem_cache *cache,
> > return (void *)object + cache->kasan_info.free_meta_offset;
> >  }
> >
> > -
> > -static void kasan_set_free_info(struct kmem_cache *cache,
> > -   void *object, u8 tag)
> > -{
> > -   struct kasan_alloc_meta *alloc_meta;
> > -   u8 idx = 0;
> > -
> > -   alloc_meta = get_alloc_info(cache, object);
> > -
> > -#ifdef CONFIG_KASAN_SW_TAGS_IDENTIFY
> > -   idx = alloc_meta->free_track_idx;
> > -   alloc_meta->free_pointer_tag[idx] = tag;
> > -   alloc_meta->free_track_idx = (idx + 1) % KASAN_NR_FREE_STACKS;
> > -#endif
> > -
> > -   set_track(_meta->free_track[idx], GFP_NOWAIT);
> > -}
> > -
> >  void kasan_poison_slab(struct page *page)
> >  {
> > unsigned long i;
> > @@ -492,7 +474,7 @@ static void *__kasan_kmalloc(struct kmem_cache *cache, 
> > const void *object,
> > KASAN_KMALLOC_REDZONE);
> >
> > if (cache->flags & SLAB_KASAN)
> > -   set_track(_alloc_info(cache, object)->alloc_track, 
> > flags);
> > +   kasan_set_track(_alloc_info(cache, 
> > object)->alloc_track, flags);
> >
> > return set_tag(object, tag);
> >  }
> > diff --git a/mm/kasan/generic.c b/mm/kasan/generic.c
> > index 3372bdcaf92a..763d8a13e0ac 100644
> > --- a/mm/kasan/generic.c
> > +++ b/mm/kasan/generic.c
> > @@ -344,3 +344,21 @@ void kasan_record_aux_stack(void *addr)
> > alloc_info->aux_stack[1] = alloc_info->aux_stack[0];
> > alloc_info->aux_stack[0] = kasan_save_stack(GFP_NOWAIT);
> >  }
> > +
> > +void kasan_set_free_info(struct kmem_cache *cache,
> > +   void *object, u8 tag)
> > +{
> > +   struct kasan_free_meta *free_meta;
> > +
> > +   free_meta = get_free_info(cache, object);
> > +   kasan_set_track(_meta->free_track, GFP_NOWAIT);
> > +}
> > +
> > +struct kasan_track *kasan_get_free_track(struct kmem_cache *cache,
> > +   void *object, u8 tag)
> > +{
> > +   struct kasan_free_meta *free_meta;
> > +
> > +   free_meta = get_free_info(cache, object);
> > +   return _meta->free_track;
> > +}
> > diff --git a/mm/kasan/kasan.h b/mm/kasan/kasan.h
> > index a7391bc83070..ad897ec36545 100644
> > --- a/mm/kasan/kasan.h
> > +++ b/mm/kasan/kasan.h
> > @@ -127,6 +127,9 @@ struct kasan_free_meta {
> >  * Otherwise it might be used for the allocator freelist.
> >  */
> > struct qlist_node quarantine_link;
> > +#ifdef CONFIG_KASAN_GENERIC
> > +   struct kasan_track free_track;
> > +#endif
> >  };
> >
> >  struct kasan_alloc_meta *get_a

Re: [PATCH v4 1/4] rcu/kasan: record and print call_rcu() call stack

2020-05-19 Thread Walter Wu
On Tue, 2020-05-19 at 08:48 -0700, Paul E. McKenney wrote:
> On Tue, May 19, 2020 at 10:23:59AM +0800, Walter Wu wrote:
> > This feature will record the last two call_rcu() call stacks and
> > prints up to 2 call_rcu() call stacks in KASAN report.
> > 
> > When call_rcu() is called, we store the call_rcu() call stack into
> > slub alloc meta-data, so that the KASAN report can print rcu stack.
> > 
> > [1]https://bugzilla.kernel.org/show_bug.cgi?id=198437
> > [2]https://groups.google.com/forum/#!searchin/kasan-dev/better$20stack$20traces$20for$20rcu%7Csort:date/kasan-dev/KQsjT_88hDE/7rNUZprRBgAJ
> > 
> > Signed-off-by: Walter Wu 
> > Suggested-by: Dmitry Vyukov 
> > Cc: Andrey Ryabinin 
> > Cc: Dmitry Vyukov 
> > Cc: Alexander Potapenko 
> > Cc: Andrew Morton 
> > Cc: Paul E. McKenney 
> > Cc: Josh Triplett 
> > Cc: Mathieu Desnoyers 
> > Cc: Lai Jiangshan 
> > Cc: Joel Fernandes 
> 
> From an RCU perspective:
> 
> Acked-by: Paul E. McKenney 
> 

Hi Paul,

Thank you for your suggestion and review.


Walter

> > ---
> >  include/linux/kasan.h |  2 ++
> >  kernel/rcu/tree.c |  2 ++
> >  lib/Kconfig.kasan |  2 ++
> >  mm/kasan/common.c |  4 ++--
> >  mm/kasan/generic.c| 19 +++
> >  mm/kasan/kasan.h  | 10 ++
> >  mm/kasan/report.c | 24 
> >  7 files changed, 61 insertions(+), 2 deletions(-)
> > 
> > diff --git a/include/linux/kasan.h b/include/linux/kasan.h
> > index 31314ca7c635..23b7ee00572d 100644
> > --- a/include/linux/kasan.h
> > +++ b/include/linux/kasan.h
> > @@ -174,11 +174,13 @@ static inline size_t kasan_metadata_size(struct 
> > kmem_cache *cache) { return 0; }
> >  
> >  void kasan_cache_shrink(struct kmem_cache *cache);
> >  void kasan_cache_shutdown(struct kmem_cache *cache);
> > +void kasan_record_aux_stack(void *ptr);
> >  
> >  #else /* CONFIG_KASAN_GENERIC */
> >  
> >  static inline void kasan_cache_shrink(struct kmem_cache *cache) {}
> >  static inline void kasan_cache_shutdown(struct kmem_cache *cache) {}
> > +static inline void kasan_record_aux_stack(void *ptr) {}
> >  
> >  #endif /* CONFIG_KASAN_GENERIC */
> >  
> > diff --git a/kernel/rcu/tree.c b/kernel/rcu/tree.c
> > index 06548e2ebb72..36a4ff7f320b 100644
> > --- a/kernel/rcu/tree.c
> > +++ b/kernel/rcu/tree.c
> > @@ -57,6 +57,7 @@
> >  #include 
> >  #include 
> >  #include 
> > +#include 
> >  #include "../time/tick-internal.h"
> >  
> >  #include "tree.h"
> > @@ -2668,6 +2669,7 @@ __call_rcu(struct rcu_head *head, rcu_callback_t func)
> > head->func = func;
> > head->next = NULL;
> > local_irq_save(flags);
> > +   kasan_record_aux_stack(head);
> > rdp = this_cpu_ptr(_data);
> >  
> > /* Add the callback to our list. */
> > diff --git a/lib/Kconfig.kasan b/lib/Kconfig.kasan
> > index 81f5464ea9e1..4e83cf6e3caa 100644
> > --- a/lib/Kconfig.kasan
> > +++ b/lib/Kconfig.kasan
> > @@ -58,6 +58,8 @@ config KASAN_GENERIC
> >   For better error detection enable CONFIG_STACKTRACE.
> >   Currently CONFIG_KASAN_GENERIC doesn't work with CONFIG_DEBUG_SLAB
> >   (the resulting kernel does not boot).
> > + In generic mode KASAN prints the last two call_rcu() call stacks in
> > + reports.
> >  
> >  config KASAN_SW_TAGS
> > bool "Software tag-based mode"
> > diff --git a/mm/kasan/common.c b/mm/kasan/common.c
> > index 2906358e42f0..8bc618289bb1 100644
> > --- a/mm/kasan/common.c
> > +++ b/mm/kasan/common.c
> > @@ -41,7 +41,7 @@
> >  #include "kasan.h"
> >  #include "../slab.h"
> >  
> > -static inline depot_stack_handle_t save_stack(gfp_t flags)
> > +depot_stack_handle_t kasan_save_stack(gfp_t flags)
> >  {
> > unsigned long entries[KASAN_STACK_DEPTH];
> > unsigned int nr_entries;
> > @@ -54,7 +54,7 @@ static inline depot_stack_handle_t save_stack(gfp_t flags)
> >  static inline void set_track(struct kasan_track *track, gfp_t flags)
> >  {
> > track->pid = current->pid;
> > -   track->stack = save_stack(flags);
> > +   track->stack = kasan_save_stack(flags);
> >  }
> >  
> >  void kasan_enable_current(void)
> > diff --git a/mm/kasan/generic.c b/mm/kasan/generic.c
> > index 56ff8885fe2e..3372bdcaf92a 100644
> > --- a/mm/kasan/generic.c
> > +++ b/mm/kasan/generic.c
> > @@ -325,3 +325,22

Re: [PATCH v4 1/4] rcu/kasan: record and print call_rcu() call stack

2020-05-19 Thread Walter Wu
Hi Andrey,

On Tue, 2020-05-19 at 16:52 +0200, 'Andrey Konovalov' via kasan-dev
wrote:
> On Tue, May 19, 2020 at 4:24 AM Walter Wu  wrote:
> >
> > This feature will record the last two call_rcu() call stacks and
> > prints up to 2 call_rcu() call stacks in KASAN report.
> >
> > When call_rcu() is called, we store the call_rcu() call stack into
> > slub alloc meta-data, so that the KASAN report can print rcu stack.
> >
> > [1]https://bugzilla.kernel.org/show_bug.cgi?id=198437
> > [2]https://groups.google.com/forum/#!searchin/kasan-dev/better$20stack$20traces$20for$20rcu%7Csort:date/kasan-dev/KQsjT_88hDE/7rNUZprRBgAJ
> >
> > Signed-off-by: Walter Wu 
> > Suggested-by: Dmitry Vyukov 
> > Cc: Andrey Ryabinin 
> > Cc: Dmitry Vyukov 
> > Cc: Alexander Potapenko 
> > Cc: Andrew Morton 
> > Cc: Paul E. McKenney 
> > Cc: Josh Triplett 
> > Cc: Mathieu Desnoyers 
> > Cc: Lai Jiangshan 
> > Cc: Joel Fernandes 
> > ---
> >  include/linux/kasan.h |  2 ++
> >  kernel/rcu/tree.c |  2 ++
> >  lib/Kconfig.kasan |  2 ++
> >  mm/kasan/common.c |  4 ++--
> >  mm/kasan/generic.c| 19 +++
> >  mm/kasan/kasan.h  | 10 ++
> >  mm/kasan/report.c | 24 
> >  7 files changed, 61 insertions(+), 2 deletions(-)
> >
> > diff --git a/include/linux/kasan.h b/include/linux/kasan.h
> > index 31314ca7c635..23b7ee00572d 100644
> > --- a/include/linux/kasan.h
> > +++ b/include/linux/kasan.h
> > @@ -174,11 +174,13 @@ static inline size_t kasan_metadata_size(struct 
> > kmem_cache *cache) { return 0; }
> >
> >  void kasan_cache_shrink(struct kmem_cache *cache);
> >  void kasan_cache_shutdown(struct kmem_cache *cache);
> > +void kasan_record_aux_stack(void *ptr);
> >
> >  #else /* CONFIG_KASAN_GENERIC */
> >
> >  static inline void kasan_cache_shrink(struct kmem_cache *cache) {}
> >  static inline void kasan_cache_shutdown(struct kmem_cache *cache) {}
> > +static inline void kasan_record_aux_stack(void *ptr) {}
> >
> >  #endif /* CONFIG_KASAN_GENERIC */
> >
> > diff --git a/kernel/rcu/tree.c b/kernel/rcu/tree.c
> > index 06548e2ebb72..36a4ff7f320b 100644
> > --- a/kernel/rcu/tree.c
> > +++ b/kernel/rcu/tree.c
> > @@ -57,6 +57,7 @@
> >  #include 
> >  #include 
> >  #include 
> > +#include 
> >  #include "../time/tick-internal.h"
> >
> >  #include "tree.h"
> > @@ -2668,6 +2669,7 @@ __call_rcu(struct rcu_head *head, rcu_callback_t func)
> > head->func = func;
> > head->next = NULL;
> > local_irq_save(flags);
> > +   kasan_record_aux_stack(head);
> > rdp = this_cpu_ptr(_data);
> >
> > /* Add the callback to our list. */
> > diff --git a/lib/Kconfig.kasan b/lib/Kconfig.kasan
> > index 81f5464ea9e1..4e83cf6e3caa 100644
> > --- a/lib/Kconfig.kasan
> > +++ b/lib/Kconfig.kasan
> > @@ -58,6 +58,8 @@ config KASAN_GENERIC
> >   For better error detection enable CONFIG_STACKTRACE.
> >   Currently CONFIG_KASAN_GENERIC doesn't work with CONFIG_DEBUG_SLAB
> >   (the resulting kernel does not boot).
> > + In generic mode KASAN prints the last two call_rcu() call stacks 
> > in
> > + reports.
> 
> I don't think we need this here, mentioning this in the documentation is fine.
> 

Ok, we will remove it. Only mention it in the documentation.

> 
> >
> >  config KASAN_SW_TAGS
> > bool "Software tag-based mode"
> > diff --git a/mm/kasan/common.c b/mm/kasan/common.c
> > index 2906358e42f0..8bc618289bb1 100644
> > --- a/mm/kasan/common.c
> > +++ b/mm/kasan/common.c
> > @@ -41,7 +41,7 @@
> >  #include "kasan.h"
> >  #include "../slab.h"
> >
> > -static inline depot_stack_handle_t save_stack(gfp_t flags)
> > +depot_stack_handle_t kasan_save_stack(gfp_t flags)
> >  {
> > unsigned long entries[KASAN_STACK_DEPTH];
> > unsigned int nr_entries;
> > @@ -54,7 +54,7 @@ static inline depot_stack_handle_t save_stack(gfp_t flags)
> >  static inline void set_track(struct kasan_track *track, gfp_t flags)
> >  {
> > track->pid = current->pid;
> > -   track->stack = save_stack(flags);
> > +   track->stack = kasan_save_stack(flags);
> >  }
> >
> >  void kasan_enable_current(void)
> > diff --git a/mm/kasan/generic.c b/mm/kasan/generic.c
> > index 56ff8885fe2e..3372bdcaf92a 100644
&

[PATCH v4 3/4] kasan: add tests for call_rcu stack recording

2020-05-18 Thread Walter Wu
Test call_rcu() call stack recording and verify whether it correctly
is printed in KASAN report.

Signed-off-by: Walter Wu 
Cc: Andrey Ryabinin 
Cc: Dmitry Vyukov 
Cc: Alexander Potapenko 
Cc: Matthias Brugger 
---
 lib/test_kasan.c | 30 ++
 1 file changed, 30 insertions(+)

diff --git a/lib/test_kasan.c b/lib/test_kasan.c
index e3087d90e00d..6e5fb05d42d8 100644
--- a/lib/test_kasan.c
+++ b/lib/test_kasan.c
@@ -792,6 +792,35 @@ static noinline void __init vmalloc_oob(void)
 static void __init vmalloc_oob(void) {}
 #endif
 
+static struct kasan_rcu_info {
+   int i;
+   struct rcu_head rcu;
+} *global_ptr;
+
+static noinline void __init kasan_rcu_reclaim(struct rcu_head *rp)
+{
+   struct kasan_rcu_info *fp = container_of(rp,
+   struct kasan_rcu_info, rcu);
+
+   kfree(fp);
+   fp->i = 1;
+}
+
+static noinline void __init kasan_rcu_uaf(void)
+{
+   struct kasan_rcu_info *ptr;
+
+   pr_info("use-after-free in kasan_rcu_reclaim\n");
+   ptr = kmalloc(sizeof(struct kasan_rcu_info), GFP_KERNEL);
+   if (!ptr) {
+   pr_err("Allocation failed\n");
+   return;
+   }
+
+   global_ptr = rcu_dereference_protected(ptr, NULL);
+   call_rcu(_ptr->rcu, kasan_rcu_reclaim);
+}
+
 static int __init kmalloc_tests_init(void)
 {
/*
@@ -839,6 +868,7 @@ static int __init kmalloc_tests_init(void)
kasan_bitops();
kmalloc_double_kzfree();
vmalloc_oob();
+   kasan_rcu_uaf();
 
kasan_restore_multi_shot(multishot);
 
-- 
2.18.0


[PATCH v4 4/4] kasan: update documentation for generic kasan

2020-05-18 Thread Walter Wu
Generic KASAN will support to record the last two call_rcu() call
stacks and print them in KASAN report. So need to update documentation.

Signed-off-by: Walter Wu 
Cc: Andrey Ryabinin 
Cc: Dmitry Vyukov 
Cc: Alexander Potapenko 
Cc: Jonathan Corbet 
---
 Documentation/dev-tools/kasan.rst | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/Documentation/dev-tools/kasan.rst 
b/Documentation/dev-tools/kasan.rst
index c652d740735d..fede42e6536b 100644
--- a/Documentation/dev-tools/kasan.rst
+++ b/Documentation/dev-tools/kasan.rst
@@ -193,6 +193,9 @@ function calls GCC directly inserts the code to check the 
shadow memory.
 This option significantly enlarges kernel but it gives x1.1-x2 performance
 boost over outline instrumented kernel.
 
+Generic KASAN prints up to 2 call_rcu() call stacks in reports, the last one
+and the second to last.
+
 Software tag-based KASAN
 
 
-- 
2.18.0


[PATCH v4 2/4] kasan: record and print the free track

2020-05-18 Thread Walter Wu
Move free track from slub alloc meta-data to slub free meta-data in
order to make struct kasan_free_meta size is 16 bytes. It is a good
size because it is the minimal redzone size and a good number of
alignment.

For free track in generic KASAN, we do the modification in struct
kasan_alloc_meta and kasan_free_meta:
- remove free track from kasan_alloc_meta.
- add free track into kasan_free_meta.

[1]https://bugzilla.kernel.org/show_bug.cgi?id=198437

Signed-off-by: Walter Wu 
Suggested-by: Dmitry Vyukov 
Cc: Andrey Ryabinin 
Cc: Dmitry Vyukov 
Cc: Alexander Potapenko 
---
 mm/kasan/common.c  | 22 ++
 mm/kasan/generic.c | 18 ++
 mm/kasan/kasan.h   |  7 +++
 mm/kasan/report.c  | 20 
 mm/kasan/tags.c| 37 +
 5 files changed, 64 insertions(+), 40 deletions(-)

diff --git a/mm/kasan/common.c b/mm/kasan/common.c
index 8bc618289bb1..47b53912f322 100644
--- a/mm/kasan/common.c
+++ b/mm/kasan/common.c
@@ -51,7 +51,7 @@ depot_stack_handle_t kasan_save_stack(gfp_t flags)
return stack_depot_save(entries, nr_entries, flags);
 }
 
-static inline void set_track(struct kasan_track *track, gfp_t flags)
+void kasan_set_track(struct kasan_track *track, gfp_t flags)
 {
track->pid = current->pid;
track->stack = kasan_save_stack(flags);
@@ -299,24 +299,6 @@ struct kasan_free_meta *get_free_info(struct kmem_cache 
*cache,
return (void *)object + cache->kasan_info.free_meta_offset;
 }
 
-
-static void kasan_set_free_info(struct kmem_cache *cache,
-   void *object, u8 tag)
-{
-   struct kasan_alloc_meta *alloc_meta;
-   u8 idx = 0;
-
-   alloc_meta = get_alloc_info(cache, object);
-
-#ifdef CONFIG_KASAN_SW_TAGS_IDENTIFY
-   idx = alloc_meta->free_track_idx;
-   alloc_meta->free_pointer_tag[idx] = tag;
-   alloc_meta->free_track_idx = (idx + 1) % KASAN_NR_FREE_STACKS;
-#endif
-
-   set_track(_meta->free_track[idx], GFP_NOWAIT);
-}
-
 void kasan_poison_slab(struct page *page)
 {
unsigned long i;
@@ -492,7 +474,7 @@ static void *__kasan_kmalloc(struct kmem_cache *cache, 
const void *object,
KASAN_KMALLOC_REDZONE);
 
if (cache->flags & SLAB_KASAN)
-   set_track(_alloc_info(cache, object)->alloc_track, flags);
+   kasan_set_track(_alloc_info(cache, object)->alloc_track, 
flags);
 
return set_tag(object, tag);
 }
diff --git a/mm/kasan/generic.c b/mm/kasan/generic.c
index 3372bdcaf92a..763d8a13e0ac 100644
--- a/mm/kasan/generic.c
+++ b/mm/kasan/generic.c
@@ -344,3 +344,21 @@ void kasan_record_aux_stack(void *addr)
alloc_info->aux_stack[1] = alloc_info->aux_stack[0];
alloc_info->aux_stack[0] = kasan_save_stack(GFP_NOWAIT);
 }
+
+void kasan_set_free_info(struct kmem_cache *cache,
+   void *object, u8 tag)
+{
+   struct kasan_free_meta *free_meta;
+
+   free_meta = get_free_info(cache, object);
+   kasan_set_track(_meta->free_track, GFP_NOWAIT);
+}
+
+struct kasan_track *kasan_get_free_track(struct kmem_cache *cache,
+   void *object, u8 tag)
+{
+   struct kasan_free_meta *free_meta;
+
+   free_meta = get_free_info(cache, object);
+   return _meta->free_track;
+}
diff --git a/mm/kasan/kasan.h b/mm/kasan/kasan.h
index a7391bc83070..ad897ec36545 100644
--- a/mm/kasan/kasan.h
+++ b/mm/kasan/kasan.h
@@ -127,6 +127,9 @@ struct kasan_free_meta {
 * Otherwise it might be used for the allocator freelist.
 */
struct qlist_node quarantine_link;
+#ifdef CONFIG_KASAN_GENERIC
+   struct kasan_track free_track;
+#endif
 };
 
 struct kasan_alloc_meta *get_alloc_info(struct kmem_cache *cache,
@@ -168,6 +171,10 @@ void kasan_report_invalid_free(void *object, unsigned long 
ip);
 struct page *kasan_addr_to_page(const void *addr);
 
 depot_stack_handle_t kasan_save_stack(gfp_t flags);
+void kasan_set_track(struct kasan_track *track, gfp_t flags);
+void kasan_set_free_info(struct kmem_cache *cache, void *object, u8 tag);
+struct kasan_track *kasan_get_free_track(struct kmem_cache *cache,
+   void *object, u8 tag);
 
 #if defined(CONFIG_KASAN_GENERIC) && \
(defined(CONFIG_SLAB) || defined(CONFIG_SLUB))
diff --git a/mm/kasan/report.c b/mm/kasan/report.c
index 6f8f2bf8f53b..96d2657fe70f 100644
--- a/mm/kasan/report.c
+++ b/mm/kasan/report.c
@@ -159,26 +159,6 @@ static void describe_object_addr(struct kmem_cache *cache, 
void *object,
(void *)(object_addr + cache->object_size));
 }
 
-static struct kasan_track *kasan_get_free_track(struct kmem_cache *cache,
-   void *object, u8 tag)
-{
-   struct kasan_alloc_meta *alloc_meta;
-   int i = 0;
-
-   alloc_meta = get_alloc_info(cache, object);
-
-#ifdef CONFIG_KASAN_SW_TAGS_IDENTIFY
-   for (i = 0; i < KASAN_NR_FREE

[PATCH v4 1/4] rcu/kasan: record and print call_rcu() call stack

2020-05-18 Thread Walter Wu
This feature will record the last two call_rcu() call stacks and
prints up to 2 call_rcu() call stacks in KASAN report.

When call_rcu() is called, we store the call_rcu() call stack into
slub alloc meta-data, so that the KASAN report can print rcu stack.

[1]https://bugzilla.kernel.org/show_bug.cgi?id=198437
[2]https://groups.google.com/forum/#!searchin/kasan-dev/better$20stack$20traces$20for$20rcu%7Csort:date/kasan-dev/KQsjT_88hDE/7rNUZprRBgAJ

Signed-off-by: Walter Wu 
Suggested-by: Dmitry Vyukov 
Cc: Andrey Ryabinin 
Cc: Dmitry Vyukov 
Cc: Alexander Potapenko 
Cc: Andrew Morton 
Cc: Paul E. McKenney 
Cc: Josh Triplett 
Cc: Mathieu Desnoyers 
Cc: Lai Jiangshan 
Cc: Joel Fernandes 
---
 include/linux/kasan.h |  2 ++
 kernel/rcu/tree.c |  2 ++
 lib/Kconfig.kasan |  2 ++
 mm/kasan/common.c |  4 ++--
 mm/kasan/generic.c| 19 +++
 mm/kasan/kasan.h  | 10 ++
 mm/kasan/report.c | 24 
 7 files changed, 61 insertions(+), 2 deletions(-)

diff --git a/include/linux/kasan.h b/include/linux/kasan.h
index 31314ca7c635..23b7ee00572d 100644
--- a/include/linux/kasan.h
+++ b/include/linux/kasan.h
@@ -174,11 +174,13 @@ static inline size_t kasan_metadata_size(struct 
kmem_cache *cache) { return 0; }
 
 void kasan_cache_shrink(struct kmem_cache *cache);
 void kasan_cache_shutdown(struct kmem_cache *cache);
+void kasan_record_aux_stack(void *ptr);
 
 #else /* CONFIG_KASAN_GENERIC */
 
 static inline void kasan_cache_shrink(struct kmem_cache *cache) {}
 static inline void kasan_cache_shutdown(struct kmem_cache *cache) {}
+static inline void kasan_record_aux_stack(void *ptr) {}
 
 #endif /* CONFIG_KASAN_GENERIC */
 
diff --git a/kernel/rcu/tree.c b/kernel/rcu/tree.c
index 06548e2ebb72..36a4ff7f320b 100644
--- a/kernel/rcu/tree.c
+++ b/kernel/rcu/tree.c
@@ -57,6 +57,7 @@
 #include 
 #include 
 #include 
+#include 
 #include "../time/tick-internal.h"
 
 #include "tree.h"
@@ -2668,6 +2669,7 @@ __call_rcu(struct rcu_head *head, rcu_callback_t func)
head->func = func;
head->next = NULL;
local_irq_save(flags);
+   kasan_record_aux_stack(head);
rdp = this_cpu_ptr(_data);
 
/* Add the callback to our list. */
diff --git a/lib/Kconfig.kasan b/lib/Kconfig.kasan
index 81f5464ea9e1..4e83cf6e3caa 100644
--- a/lib/Kconfig.kasan
+++ b/lib/Kconfig.kasan
@@ -58,6 +58,8 @@ config KASAN_GENERIC
  For better error detection enable CONFIG_STACKTRACE.
  Currently CONFIG_KASAN_GENERIC doesn't work with CONFIG_DEBUG_SLAB
  (the resulting kernel does not boot).
+ In generic mode KASAN prints the last two call_rcu() call stacks in
+ reports.
 
 config KASAN_SW_TAGS
bool "Software tag-based mode"
diff --git a/mm/kasan/common.c b/mm/kasan/common.c
index 2906358e42f0..8bc618289bb1 100644
--- a/mm/kasan/common.c
+++ b/mm/kasan/common.c
@@ -41,7 +41,7 @@
 #include "kasan.h"
 #include "../slab.h"
 
-static inline depot_stack_handle_t save_stack(gfp_t flags)
+depot_stack_handle_t kasan_save_stack(gfp_t flags)
 {
unsigned long entries[KASAN_STACK_DEPTH];
unsigned int nr_entries;
@@ -54,7 +54,7 @@ static inline depot_stack_handle_t save_stack(gfp_t flags)
 static inline void set_track(struct kasan_track *track, gfp_t flags)
 {
track->pid = current->pid;
-   track->stack = save_stack(flags);
+   track->stack = kasan_save_stack(flags);
 }
 
 void kasan_enable_current(void)
diff --git a/mm/kasan/generic.c b/mm/kasan/generic.c
index 56ff8885fe2e..3372bdcaf92a 100644
--- a/mm/kasan/generic.c
+++ b/mm/kasan/generic.c
@@ -325,3 +325,22 @@ DEFINE_ASAN_SET_SHADOW(f2);
 DEFINE_ASAN_SET_SHADOW(f3);
 DEFINE_ASAN_SET_SHADOW(f5);
 DEFINE_ASAN_SET_SHADOW(f8);
+
+void kasan_record_aux_stack(void *addr)
+{
+   struct page *page = kasan_addr_to_page(addr);
+   struct kmem_cache *cache;
+   struct kasan_alloc_meta *alloc_info;
+   void *object;
+
+   if (!(page && PageSlab(page)))
+   return;
+
+   cache = page->slab_cache;
+   object = nearest_obj(cache, page, addr);
+   alloc_info = get_alloc_info(cache, object);
+
+   /* record the last two call_rcu() call stacks */
+   alloc_info->aux_stack[1] = alloc_info->aux_stack[0];
+   alloc_info->aux_stack[0] = kasan_save_stack(GFP_NOWAIT);
+}
diff --git a/mm/kasan/kasan.h b/mm/kasan/kasan.h
index e8f37199d885..a7391bc83070 100644
--- a/mm/kasan/kasan.h
+++ b/mm/kasan/kasan.h
@@ -104,7 +104,15 @@ struct kasan_track {
 
 struct kasan_alloc_meta {
struct kasan_track alloc_track;
+#ifdef CONFIG_KASAN_GENERIC
+   /*
+* call_rcu() call stack is stored into struct kasan_alloc_meta.
+* The free stack is stored into struct kasan_free_meta.
+*/
+   depot_stack_handle_t aux_stack[2];
+#else
struct kasan_track free_track[KASAN_NR_FREE_STACKS];
+#endif
 #ifdef CON

  1   2   3   >