mm/kasan/common.c | 8 ++++---- mm/kasan/kasan.h | 3 ++- mm/kasan/report.c | 12 ++++++++---- 3 files changed, 14 insertions(+), 9 deletions(-)
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
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!
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 >
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 > >
© 2016 - 2024 Red Hat, Inc.