From 7fae3dd08e3e88491f06e22e648913e3f8cf30f0 Mon Sep 17 00:00:00 2001 From: Andrey Konovalov Date: Mon, 5 Sep 2022 23:05:42 +0200 Subject: [PATCH] kasan: fill in cache and object in complete_report_info Add cache and object fields to kasan_report_info and fill them in in complete_report_info() instead of fetching them in the middle of the report printing code. This allows the reporting code to get access to the object information before starting printing the report. One of the following patches uses this information to determine the bug type with the tag-based modes. Link: https://lkml.kernel.org/r/23264572cb2cbb8f0efbb51509b6757eb3cc1fc9.1662411799.git.andreyknvl@google.com Signed-off-by: Andrey Konovalov Reviewed-by: Marco Elver Cc: Alexander Potapenko Cc: Andrey Ryabinin Cc: Dmitry Vyukov Cc: Evgenii Stepanov Cc: Peter Collingbourne Signed-off-by: Andrew Morton --- mm/kasan/kasan.h | 2 ++ mm/kasan/report.c | 21 +++++++++++++-------- 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/mm/kasan/kasan.h b/mm/kasan/kasan.h index 7e07115..b8fa1e5 100644 --- a/mm/kasan/kasan.h +++ b/mm/kasan/kasan.h @@ -162,6 +162,8 @@ struct kasan_report_info { /* Filled in by the common reporting code. */ void *first_bad_addr; + struct kmem_cache *cache; + void *object; }; /* Do not change the struct layout: compiler ABI. */ diff --git a/mm/kasan/report.c b/mm/kasan/report.c index 0c2e7a5..763de8e 100644 --- a/mm/kasan/report.c +++ b/mm/kasan/report.c @@ -287,19 +287,16 @@ static inline bool init_task_stack_addr(const void *addr) sizeof(init_thread_union.stack)); } -static void print_address_description(void *addr, u8 tag) +static void print_address_description(void *addr, u8 tag, + struct kasan_report_info *info) { struct page *page = addr_to_page(addr); - struct slab *slab = kasan_addr_to_slab(addr); dump_stack_lvl(KERN_ERR); pr_err("\n"); - if (slab) { - struct kmem_cache *cache = slab->slab_cache; - void *object = nearest_obj(cache, slab, addr); - - describe_object(cache, object, addr, tag); + if (info->cache && info->object) { + describe_object(info->cache, info->object, addr, tag); pr_err("\n"); } @@ -406,7 +403,7 @@ static void print_report(struct kasan_report_info *info) pr_err("\n"); if (addr_has_metadata(addr)) { - print_address_description(addr, tag); + print_address_description(addr, tag, info); print_memory_metadata(info->first_bad_addr); } else { dump_stack_lvl(KERN_ERR); @@ -416,12 +413,20 @@ static void print_report(struct kasan_report_info *info) static void complete_report_info(struct kasan_report_info *info) { void *addr = kasan_reset_tag(info->access_addr); + struct slab *slab; if (info->type == KASAN_REPORT_ACCESS) info->first_bad_addr = kasan_find_first_bad_addr( info->access_addr, info->access_size); else info->first_bad_addr = addr; + + slab = kasan_addr_to_slab(addr); + if (slab) { + info->cache = slab->slab_cache; + info->object = nearest_obj(info->cache, slab, addr); + } else + info->cache = info->object = NULL; } void kasan_report_invalid_free(void *ptr, unsigned long ip, enum kasan_report_type type) -- 2.7.4