Commit 7fae3dd0 authored by Andrey Konovalov's avatar Andrey Konovalov Committed by Andrew Morton

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.comSigned-off-by: default avatarAndrey Konovalov <andreyknvl@google.com>
Reviewed-by: default avatarMarco Elver <elver@google.com>
Cc: Alexander Potapenko <glider@google.com>
Cc: Andrey Ryabinin <ryabinin.a.a@gmail.com>
Cc: Dmitry Vyukov <dvyukov@google.com>
Cc: Evgenii Stepanov <eugenis@google.com>
Cc: Peter Collingbourne <pcc@google.com>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
parent 015b109f
...@@ -162,6 +162,8 @@ struct kasan_report_info { ...@@ -162,6 +162,8 @@ struct kasan_report_info {
/* Filled in by the common reporting code. */ /* Filled in by the common reporting code. */
void *first_bad_addr; void *first_bad_addr;
struct kmem_cache *cache;
void *object;
}; };
/* Do not change the struct layout: compiler ABI. */ /* Do not change the struct layout: compiler ABI. */
......
...@@ -287,19 +287,16 @@ static inline bool init_task_stack_addr(const void *addr) ...@@ -287,19 +287,16 @@ static inline bool init_task_stack_addr(const void *addr)
sizeof(init_thread_union.stack)); 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 page *page = addr_to_page(addr);
struct slab *slab = kasan_addr_to_slab(addr);
dump_stack_lvl(KERN_ERR); dump_stack_lvl(KERN_ERR);
pr_err("\n"); pr_err("\n");
if (slab) { if (info->cache && info->object) {
struct kmem_cache *cache = slab->slab_cache; describe_object(info->cache, info->object, addr, tag);
void *object = nearest_obj(cache, slab, addr);
describe_object(cache, object, addr, tag);
pr_err("\n"); pr_err("\n");
} }
...@@ -406,7 +403,7 @@ static void print_report(struct kasan_report_info *info) ...@@ -406,7 +403,7 @@ static void print_report(struct kasan_report_info *info)
pr_err("\n"); pr_err("\n");
if (addr_has_metadata(addr)) { if (addr_has_metadata(addr)) {
print_address_description(addr, tag); print_address_description(addr, tag, info);
print_memory_metadata(info->first_bad_addr); print_memory_metadata(info->first_bad_addr);
} else { } else {
dump_stack_lvl(KERN_ERR); dump_stack_lvl(KERN_ERR);
...@@ -416,12 +413,20 @@ static void print_report(struct kasan_report_info *info) ...@@ -416,12 +413,20 @@ static void print_report(struct kasan_report_info *info)
static void complete_report_info(struct kasan_report_info *info) static void complete_report_info(struct kasan_report_info *info)
{ {
void *addr = kasan_reset_tag(info->access_addr); void *addr = kasan_reset_tag(info->access_addr);
struct slab *slab;
if (info->type == KASAN_REPORT_ACCESS) if (info->type == KASAN_REPORT_ACCESS)
info->first_bad_addr = kasan_find_first_bad_addr( info->first_bad_addr = kasan_find_first_bad_addr(
info->access_addr, info->access_size); info->access_addr, info->access_size);
else else
info->first_bad_addr = addr; 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) void kasan_report_invalid_free(void *ptr, unsigned long ip, enum kasan_report_type type)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment