* [PATCH] kasan: separate double free case from invalid free
@ 2022-06-15 6:22 Kuan-Ying Lee
2022-07-03 23:15 ` Andrew Morton
2022-07-12 20:36 ` Andrey Konovalov
0 siblings, 2 replies; 4+ messages in thread
From: Kuan-Ying Lee @ 2022-06-15 6:22 UTC (permalink / raw)
To: Andrey Ryabinin, Alexander Potapenko, Andrey Konovalov,
Dmitry Vyukov, Vincenzo Frascino, Andrew Morton,
Matthias Brugger
Cc: chinwen.chang, yee.lee, casper.li, andrew.yang, Kuan-Ying Lee,
kasan-dev, linux-mm, linux-kernel, linux-arm-kernel,
linux-mediatek
Currently, KASAN describes all invalid-free/double-free bugs as
"double-free or invalid-free". This is ambiguous.
KASAN should report "double-free" when a double-free is a more
likely cause (the address points to the start of an object) and
report "invalid-free" otherwise [1].
[1] https://bugzilla.kernel.org/show_bug.cgi?id=212193
Signed-off-by: Kuan-Ying Lee <Kuan-Ying.Lee@mediatek.com>
---
mm/kasan/common.c | 8 ++++----
mm/kasan/kasan.h | 3 ++-
mm/kasan/report.c | 12 ++++++++----
3 files changed, 14 insertions(+), 9 deletions(-)
diff --git a/mm/kasan/common.c b/mm/kasan/common.c
index c40c0e7b3b5f..707c3a527fcb 100644
--- a/mm/kasan/common.c
+++ b/mm/kasan/common.c
@@ -343,7 +343,7 @@ static inline bool ____kasan_slab_free(struct kmem_cache *cache, void *object,
if (unlikely(nearest_obj(cache, virt_to_slab(object), object) !=
object)) {
- kasan_report_invalid_free(tagged_object, ip);
+ kasan_report_invalid_free(tagged_object, ip, KASAN_REPORT_INVALID_FREE);
return true;
}
@@ -352,7 +352,7 @@ static inline bool ____kasan_slab_free(struct kmem_cache *cache, void *object,
return false;
if (!kasan_byte_accessible(tagged_object)) {
- kasan_report_invalid_free(tagged_object, ip);
+ kasan_report_invalid_free(tagged_object, ip, KASAN_REPORT_DOUBLE_FREE);
return true;
}
@@ -377,12 +377,12 @@ bool __kasan_slab_free(struct kmem_cache *cache, void *object,
static inline bool ____kasan_kfree_large(void *ptr, unsigned long ip)
{
if (ptr != page_address(virt_to_head_page(ptr))) {
- kasan_report_invalid_free(ptr, ip);
+ kasan_report_invalid_free(ptr, ip, KASAN_REPORT_INVALID_FREE);
return true;
}
if (!kasan_byte_accessible(ptr)) {
- kasan_report_invalid_free(ptr, ip);
+ kasan_report_invalid_free(ptr, ip, KASAN_REPORT_DOUBLE_FREE);
return true;
}
diff --git a/mm/kasan/kasan.h b/mm/kasan/kasan.h
index 610d60d6e5b8..01c03e45acd4 100644
--- a/mm/kasan/kasan.h
+++ b/mm/kasan/kasan.h
@@ -125,6 +125,7 @@ static inline bool kasan_sync_fault_possible(void)
enum kasan_report_type {
KASAN_REPORT_ACCESS,
KASAN_REPORT_INVALID_FREE,
+ KASAN_REPORT_DOUBLE_FREE,
};
struct kasan_report_info {
@@ -277,7 +278,7 @@ static inline void kasan_print_address_stack_frame(const void *addr) { }
bool kasan_report(unsigned long addr, size_t size,
bool is_write, unsigned long ip);
-void kasan_report_invalid_free(void *object, unsigned long ip);
+void kasan_report_invalid_free(void *object, unsigned long ip, enum kasan_report_type type);
struct page *kasan_addr_to_page(const void *addr);
struct slab *kasan_addr_to_slab(const void *addr);
diff --git a/mm/kasan/report.c b/mm/kasan/report.c
index b341a191651d..fe3f606b3a98 100644
--- a/mm/kasan/report.c
+++ b/mm/kasan/report.c
@@ -176,8 +176,12 @@ static void end_report(unsigned long *flags, void *addr)
static void print_error_description(struct kasan_report_info *info)
{
if (info->type == KASAN_REPORT_INVALID_FREE) {
- pr_err("BUG: KASAN: double-free or invalid-free in %pS\n",
- (void *)info->ip);
+ pr_err("BUG: KASAN: invalid-free in %pS\n", (void *)info->ip);
+ return;
+ }
+
+ if (info->type == KASAN_REPORT_DOUBLE_FREE) {
+ pr_err("BUG: KASAN: double-free in %pS\n", (void *)info->ip);
return;
}
@@ -433,7 +437,7 @@ static void print_report(struct kasan_report_info *info)
}
}
-void kasan_report_invalid_free(void *ptr, unsigned long ip)
+void kasan_report_invalid_free(void *ptr, unsigned long ip, enum kasan_report_type type)
{
unsigned long flags;
struct kasan_report_info info;
@@ -448,7 +452,7 @@ void kasan_report_invalid_free(void *ptr, unsigned long ip)
start_report(&flags, true);
- info.type = KASAN_REPORT_INVALID_FREE;
+ info.type = type;
info.access_addr = ptr;
info.first_bad_addr = kasan_reset_tag(ptr);
info.access_size = 0;
--
2.18.0
_______________________________________________
Linux-mediatek mailing list
Linux-mediatek@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-mediatek
^ permalink raw reply related [flat|nested] 4+ messages in thread
* Re: [PATCH] kasan: separate double free case from invalid free
2022-06-15 6:22 [PATCH] kasan: separate double free case from invalid free Kuan-Ying Lee
@ 2022-07-03 23:15 ` Andrew Morton
2022-07-04 7:46 ` Dmitry Vyukov
2022-07-12 20:36 ` Andrey Konovalov
1 sibling, 1 reply; 4+ messages in thread
From: Andrew Morton @ 2022-07-03 23:15 UTC (permalink / raw)
To: Kuan-Ying Lee
Cc: Andrey Ryabinin, Alexander Potapenko, Andrey Konovalov,
Dmitry Vyukov, Vincenzo Frascino, Matthias Brugger,
chinwen.chang, yee.lee, casper.li, andrew.yang, kasan-dev,
linux-mm, linux-kernel, linux-arm-kernel, linux-mediatek
On Wed, 15 Jun 2022 14:22:18 +0800 Kuan-Ying Lee <Kuan-Ying.Lee@mediatek.com> wrote:
> Currently, KASAN describes all invalid-free/double-free bugs as
> "double-free or invalid-free". This is ambiguous.
>
> KASAN should report "double-free" when a double-free is a more
> likely cause (the address points to the start of an object) and
> report "invalid-free" otherwise [1].
>
> [1] https://bugzilla.kernel.org/show_bug.cgi?id=212193
>
> ...
Could we please have some review of this?
Thanks.
>
> diff --git a/mm/kasan/common.c b/mm/kasan/common.c
> index c40c0e7b3b5f..707c3a527fcb 100644
> --- a/mm/kasan/common.c
> +++ b/mm/kasan/common.c
> @@ -343,7 +343,7 @@ static inline bool ____kasan_slab_free(struct kmem_cache *cache, void *object,
>
> if (unlikely(nearest_obj(cache, virt_to_slab(object), object) !=
> object)) {
> - kasan_report_invalid_free(tagged_object, ip);
> + kasan_report_invalid_free(tagged_object, ip, KASAN_REPORT_INVALID_FREE);
> return true;
> }
>
> @@ -352,7 +352,7 @@ static inline bool ____kasan_slab_free(struct kmem_cache *cache, void *object,
> return false;
>
> if (!kasan_byte_accessible(tagged_object)) {
> - kasan_report_invalid_free(tagged_object, ip);
> + kasan_report_invalid_free(tagged_object, ip, KASAN_REPORT_DOUBLE_FREE);
> return true;
> }
>
> @@ -377,12 +377,12 @@ bool __kasan_slab_free(struct kmem_cache *cache, void *object,
> static inline bool ____kasan_kfree_large(void *ptr, unsigned long ip)
> {
> if (ptr != page_address(virt_to_head_page(ptr))) {
> - kasan_report_invalid_free(ptr, ip);
> + kasan_report_invalid_free(ptr, ip, KASAN_REPORT_INVALID_FREE);
> return true;
> }
>
> if (!kasan_byte_accessible(ptr)) {
> - kasan_report_invalid_free(ptr, ip);
> + kasan_report_invalid_free(ptr, ip, KASAN_REPORT_DOUBLE_FREE);
> return true;
> }
>
> diff --git a/mm/kasan/kasan.h b/mm/kasan/kasan.h
> index 610d60d6e5b8..01c03e45acd4 100644
> --- a/mm/kasan/kasan.h
> +++ b/mm/kasan/kasan.h
> @@ -125,6 +125,7 @@ static inline bool kasan_sync_fault_possible(void)
> enum kasan_report_type {
> KASAN_REPORT_ACCESS,
> KASAN_REPORT_INVALID_FREE,
> + KASAN_REPORT_DOUBLE_FREE,
> };
>
> struct kasan_report_info {
> @@ -277,7 +278,7 @@ static inline void kasan_print_address_stack_frame(const void *addr) { }
>
> bool kasan_report(unsigned long addr, size_t size,
> bool is_write, unsigned long ip);
> -void kasan_report_invalid_free(void *object, unsigned long ip);
> +void kasan_report_invalid_free(void *object, unsigned long ip, enum kasan_report_type type);
>
> struct page *kasan_addr_to_page(const void *addr);
> struct slab *kasan_addr_to_slab(const void *addr);
> diff --git a/mm/kasan/report.c b/mm/kasan/report.c
> index b341a191651d..fe3f606b3a98 100644
> --- a/mm/kasan/report.c
> +++ b/mm/kasan/report.c
> @@ -176,8 +176,12 @@ static void end_report(unsigned long *flags, void *addr)
> static void print_error_description(struct kasan_report_info *info)
> {
> if (info->type == KASAN_REPORT_INVALID_FREE) {
> - pr_err("BUG: KASAN: double-free or invalid-free in %pS\n",
> - (void *)info->ip);
> + pr_err("BUG: KASAN: invalid-free in %pS\n", (void *)info->ip);
> + return;
> + }
> +
> + if (info->type == KASAN_REPORT_DOUBLE_FREE) {
> + pr_err("BUG: KASAN: double-free in %pS\n", (void *)info->ip);
> return;
> }
>
> @@ -433,7 +437,7 @@ static void print_report(struct kasan_report_info *info)
> }
> }
>
> -void kasan_report_invalid_free(void *ptr, unsigned long ip)
> +void kasan_report_invalid_free(void *ptr, unsigned long ip, enum kasan_report_type type)
> {
> unsigned long flags;
> struct kasan_report_info info;
> @@ -448,7 +452,7 @@ void kasan_report_invalid_free(void *ptr, unsigned long ip)
>
> start_report(&flags, true);
>
> - info.type = KASAN_REPORT_INVALID_FREE;
> + info.type = type;
> info.access_addr = ptr;
> info.first_bad_addr = kasan_reset_tag(ptr);
> info.access_size = 0;
> --
> 2.18.0
>
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH] kasan: separate double free case from invalid free
2022-07-03 23:15 ` Andrew Morton
@ 2022-07-04 7:46 ` Dmitry Vyukov
0 siblings, 0 replies; 4+ messages in thread
From: Dmitry Vyukov @ 2022-07-04 7:46 UTC (permalink / raw)
To: Andrew Morton
Cc: Kuan-Ying Lee, Andrey Ryabinin, Alexander Potapenko,
Andrey Konovalov, Vincenzo Frascino, Matthias Brugger,
chinwen.chang, yee.lee, casper.li, andrew.yang, kasan-dev,
linux-mm, linux-kernel, linux-arm-kernel, linux-mediatek
On Mon, 4 Jul 2022 at 01:15, Andrew Morton <akpm@linux-foundation.org> wrote:
>
> On Wed, 15 Jun 2022 14:22:18 +0800 Kuan-Ying Lee <Kuan-Ying.Lee@mediatek.com> wrote:
>
> > Currently, KASAN describes all invalid-free/double-free bugs as
> > "double-free or invalid-free". This is ambiguous.
> >
> > KASAN should report "double-free" when a double-free is a more
> > likely cause (the address points to the start of an object) and
> > report "invalid-free" otherwise [1].
> >
> > [1] https://bugzilla.kernel.org/show_bug.cgi?id=212193
> >
> > ...
>
> Could we please have some review of this?
Looks reasonable to me.
Looking through git log it seems the only reason to combine them was
laziness/didn't seem important enough.
Reviewed-by: Dmitry Vyukov <dvyukov@google.com>
I will update syzkaller parsing of bug messages to not produce
duplicates for existing double-frees.
Not sure if anything needs to be done for other kernel testing systems.
> > diff --git a/mm/kasan/common.c b/mm/kasan/common.c
> > index c40c0e7b3b5f..707c3a527fcb 100644
> > --- a/mm/kasan/common.c
> > +++ b/mm/kasan/common.c
> > @@ -343,7 +343,7 @@ static inline bool ____kasan_slab_free(struct kmem_cache *cache, void *object,
> >
> > if (unlikely(nearest_obj(cache, virt_to_slab(object), object) !=
> > object)) {
> > - kasan_report_invalid_free(tagged_object, ip);
> > + kasan_report_invalid_free(tagged_object, ip, KASAN_REPORT_INVALID_FREE);
> > return true;
> > }
> >
> > @@ -352,7 +352,7 @@ static inline bool ____kasan_slab_free(struct kmem_cache *cache, void *object,
> > return false;
> >
> > if (!kasan_byte_accessible(tagged_object)) {
> > - kasan_report_invalid_free(tagged_object, ip);
> > + kasan_report_invalid_free(tagged_object, ip, KASAN_REPORT_DOUBLE_FREE);
> > return true;
> > }
> >
> > @@ -377,12 +377,12 @@ bool __kasan_slab_free(struct kmem_cache *cache, void *object,
> > static inline bool ____kasan_kfree_large(void *ptr, unsigned long ip)
> > {
> > if (ptr != page_address(virt_to_head_page(ptr))) {
> > - kasan_report_invalid_free(ptr, ip);
> > + kasan_report_invalid_free(ptr, ip, KASAN_REPORT_INVALID_FREE);
> > return true;
> > }
> >
> > if (!kasan_byte_accessible(ptr)) {
> > - kasan_report_invalid_free(ptr, ip);
> > + kasan_report_invalid_free(ptr, ip, KASAN_REPORT_DOUBLE_FREE);
> > return true;
> > }
> >
> > diff --git a/mm/kasan/kasan.h b/mm/kasan/kasan.h
> > index 610d60d6e5b8..01c03e45acd4 100644
> > --- a/mm/kasan/kasan.h
> > +++ b/mm/kasan/kasan.h
> > @@ -125,6 +125,7 @@ static inline bool kasan_sync_fault_possible(void)
> > enum kasan_report_type {
> > KASAN_REPORT_ACCESS,
> > KASAN_REPORT_INVALID_FREE,
> > + KASAN_REPORT_DOUBLE_FREE,
> > };
> >
> > struct kasan_report_info {
> > @@ -277,7 +278,7 @@ static inline void kasan_print_address_stack_frame(const void *addr) { }
> >
> > bool kasan_report(unsigned long addr, size_t size,
> > bool is_write, unsigned long ip);
> > -void kasan_report_invalid_free(void *object, unsigned long ip);
> > +void kasan_report_invalid_free(void *object, unsigned long ip, enum kasan_report_type type);
> >
> > struct page *kasan_addr_to_page(const void *addr);
> > struct slab *kasan_addr_to_slab(const void *addr);
> > diff --git a/mm/kasan/report.c b/mm/kasan/report.c
> > index b341a191651d..fe3f606b3a98 100644
> > --- a/mm/kasan/report.c
> > +++ b/mm/kasan/report.c
> > @@ -176,8 +176,12 @@ static void end_report(unsigned long *flags, void *addr)
> > static void print_error_description(struct kasan_report_info *info)
> > {
> > if (info->type == KASAN_REPORT_INVALID_FREE) {
> > - pr_err("BUG: KASAN: double-free or invalid-free in %pS\n",
> > - (void *)info->ip);
> > + pr_err("BUG: KASAN: invalid-free in %pS\n", (void *)info->ip);
> > + return;
> > + }
> > +
> > + if (info->type == KASAN_REPORT_DOUBLE_FREE) {
> > + pr_err("BUG: KASAN: double-free in %pS\n", (void *)info->ip);
> > return;
> > }
> >
> > @@ -433,7 +437,7 @@ static void print_report(struct kasan_report_info *info)
> > }
> > }
> >
> > -void kasan_report_invalid_free(void *ptr, unsigned long ip)
> > +void kasan_report_invalid_free(void *ptr, unsigned long ip, enum kasan_report_type type)
> > {
> > unsigned long flags;
> > struct kasan_report_info info;
> > @@ -448,7 +452,7 @@ void kasan_report_invalid_free(void *ptr, unsigned long ip)
> >
> > start_report(&flags, true);
> >
> > - info.type = KASAN_REPORT_INVALID_FREE;
> > + info.type = type;
> > info.access_addr = ptr;
> > info.first_bad_addr = kasan_reset_tag(ptr);
> > info.access_size = 0;
> > --
> > 2.18.0
> >
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH] kasan: separate double free case from invalid free
2022-06-15 6:22 [PATCH] kasan: separate double free case from invalid free Kuan-Ying Lee
2022-07-03 23:15 ` Andrew Morton
@ 2022-07-12 20:36 ` Andrey Konovalov
1 sibling, 0 replies; 4+ messages in thread
From: Andrey Konovalov @ 2022-07-12 20:36 UTC (permalink / raw)
To: Kuan-Ying Lee
Cc: Andrey Ryabinin, Alexander Potapenko, Dmitry Vyukov,
Vincenzo Frascino, Andrew Morton, Matthias Brugger,
Chinwen Chang, Yee Lee (李建誼),
casper.li, Andrew Yang, kasan-dev, Linux Memory Management List,
LKML, Linux ARM, moderated list:ARM/Mediatek SoC support
On Wed, Jun 15, 2022 at 8:22 AM 'Kuan-Ying Lee' via kasan-dev
<kasan-dev@googlegroups.com> wrote:
>
> Currently, KASAN describes all invalid-free/double-free bugs as
> "double-free or invalid-free". This is ambiguous.
>
> KASAN should report "double-free" when a double-free is a more
> likely cause (the address points to the start of an object) and
> report "invalid-free" otherwise [1].
>
> [1] https://bugzilla.kernel.org/show_bug.cgi?id=212193
>
> Signed-off-by: Kuan-Ying Lee <Kuan-Ying.Lee@mediatek.com>
> ---
> mm/kasan/common.c | 8 ++++----
> mm/kasan/kasan.h | 3 ++-
> mm/kasan/report.c | 12 ++++++++----
> 3 files changed, 14 insertions(+), 9 deletions(-)
>
> diff --git a/mm/kasan/common.c b/mm/kasan/common.c
> index c40c0e7b3b5f..707c3a527fcb 100644
> --- a/mm/kasan/common.c
> +++ b/mm/kasan/common.c
> @@ -343,7 +343,7 @@ static inline bool ____kasan_slab_free(struct kmem_cache *cache, void *object,
>
> if (unlikely(nearest_obj(cache, virt_to_slab(object), object) !=
> object)) {
> - kasan_report_invalid_free(tagged_object, ip);
> + kasan_report_invalid_free(tagged_object, ip, KASAN_REPORT_INVALID_FREE);
> return true;
> }
>
> @@ -352,7 +352,7 @@ static inline bool ____kasan_slab_free(struct kmem_cache *cache, void *object,
> return false;
>
> if (!kasan_byte_accessible(tagged_object)) {
> - kasan_report_invalid_free(tagged_object, ip);
> + kasan_report_invalid_free(tagged_object, ip, KASAN_REPORT_DOUBLE_FREE);
> return true;
> }
>
> @@ -377,12 +377,12 @@ bool __kasan_slab_free(struct kmem_cache *cache, void *object,
> static inline bool ____kasan_kfree_large(void *ptr, unsigned long ip)
> {
> if (ptr != page_address(virt_to_head_page(ptr))) {
> - kasan_report_invalid_free(ptr, ip);
> + kasan_report_invalid_free(ptr, ip, KASAN_REPORT_INVALID_FREE);
> return true;
> }
>
> if (!kasan_byte_accessible(ptr)) {
> - kasan_report_invalid_free(ptr, ip);
> + kasan_report_invalid_free(ptr, ip, KASAN_REPORT_DOUBLE_FREE);
> return true;
> }
>
> diff --git a/mm/kasan/kasan.h b/mm/kasan/kasan.h
> index 610d60d6e5b8..01c03e45acd4 100644
> --- a/mm/kasan/kasan.h
> +++ b/mm/kasan/kasan.h
> @@ -125,6 +125,7 @@ static inline bool kasan_sync_fault_possible(void)
> enum kasan_report_type {
> KASAN_REPORT_ACCESS,
> KASAN_REPORT_INVALID_FREE,
> + KASAN_REPORT_DOUBLE_FREE,
> };
>
> struct kasan_report_info {
> @@ -277,7 +278,7 @@ static inline void kasan_print_address_stack_frame(const void *addr) { }
>
> bool kasan_report(unsigned long addr, size_t size,
> bool is_write, unsigned long ip);
> -void kasan_report_invalid_free(void *object, unsigned long ip);
> +void kasan_report_invalid_free(void *object, unsigned long ip, enum kasan_report_type type);
>
> struct page *kasan_addr_to_page(const void *addr);
> struct slab *kasan_addr_to_slab(const void *addr);
> diff --git a/mm/kasan/report.c b/mm/kasan/report.c
> index b341a191651d..fe3f606b3a98 100644
> --- a/mm/kasan/report.c
> +++ b/mm/kasan/report.c
> @@ -176,8 +176,12 @@ static void end_report(unsigned long *flags, void *addr)
> static void print_error_description(struct kasan_report_info *info)
> {
> if (info->type == KASAN_REPORT_INVALID_FREE) {
> - pr_err("BUG: KASAN: double-free or invalid-free in %pS\n",
> - (void *)info->ip);
> + pr_err("BUG: KASAN: invalid-free in %pS\n", (void *)info->ip);
> + return;
> + }
> +
> + if (info->type == KASAN_REPORT_DOUBLE_FREE) {
> + pr_err("BUG: KASAN: double-free in %pS\n", (void *)info->ip);
> return;
> }
>
> @@ -433,7 +437,7 @@ static void print_report(struct kasan_report_info *info)
> }
> }
>
> -void kasan_report_invalid_free(void *ptr, unsigned long ip)
> +void kasan_report_invalid_free(void *ptr, unsigned long ip, enum kasan_report_type type)
> {
> unsigned long flags;
> struct kasan_report_info info;
> @@ -448,7 +452,7 @@ void kasan_report_invalid_free(void *ptr, unsigned long ip)
>
> start_report(&flags, true);
>
> - info.type = KASAN_REPORT_INVALID_FREE;
> + info.type = type;
> info.access_addr = ptr;
> info.first_bad_addr = kasan_reset_tag(ptr);
> info.access_size = 0;
> --
> 2.18.0
Reviewed-by: Andrey Konovalov <andreyknvl@gmail.com>
Thanks for the patch!
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2022-07-12 20:37 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-06-15 6:22 [PATCH] kasan: separate double free case from invalid free Kuan-Ying Lee
2022-07-03 23:15 ` Andrew Morton
2022-07-04 7:46 ` Dmitry Vyukov
2022-07-12 20:36 ` Andrey Konovalov
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).