Index: mm/kasan/report.c |
diff --git a/mm/kasan/report.c b/mm/kasan/report.c |
index beee0e980e2dd3385b007fbcb119f599207dacc0..7831d58c6c3775b302d5b446cbb7968d47527cba 100644 |
--- a/mm/kasan/report.c |
+++ b/mm/kasan/report.c |
@@ -39,6 +39,26 @@ |
#define SHADOW_BYTES_PER_ROW (SHADOW_BLOCKS_PER_ROW * SHADOW_BYTES_PER_BLOCK) |
#define SHADOW_ROWS_AROUND_ADDR 2 |
+static bool bad_in_pshadow(const void *addr, size_t size) |
+{ |
+ u8 shadow_val; |
+ const void *end = addr + size; |
+ |
+ if (!kasan_pshadow_inited()) |
+ return false; |
+ |
+ shadow_val = *(u8 *)kasan_mem_to_pshadow(addr); |
+ if (shadow_val == KASAN_PER_PAGE_FREE) |
+ return true; |
+ |
+ for (; addr < end; addr += PAGE_SIZE) { |
+ if (shadow_val != *(u8 *)kasan_mem_to_pshadow(addr)) |
+ return true; |
+ } |
+ |
+ return false; |
+} |
+ |
static const void *find_first_bad_addr(const void *addr, size_t size) |
{ |
u8 shadow_val = *(u8 *)kasan_mem_to_shadow(addr); |
@@ -62,6 +82,11 @@ static const char *get_shadow_bug_type(struct kasan_access_info *info) |
const char *bug_type = "unknown-crash"; |
u8 *shadow_addr; |
+ if (bad_in_pshadow(info->access_addr, info->access_size)) { |
+ info->first_bad_addr = NULL; |
+ bug_type = "use-after-free"; |
+ return bug_type; |
+ } |
info->first_bad_addr = find_first_bad_addr(info->access_addr, |
info->access_size); |
@@ -290,6 +315,9 @@ static void print_shadow_for_address(const void *addr) |
const void *shadow = kasan_mem_to_shadow(addr); |
const void *shadow_row; |
+ if (!addr) |
+ return; |
+ |
shadow_row = (void *)round_down((unsigned long)shadow, |
SHADOW_BYTES_PER_ROW) |
- SHADOW_ROWS_AROUND_ADDR * SHADOW_BYTES_PER_ROW; |
@@ -390,7 +418,7 @@ static inline bool kasan_report_enabled(void) |
return !test_and_set_bit(KASAN_BIT_REPORTED, &kasan_flags); |
} |
-void kasan_report(unsigned long addr, size_t size, |
+void __kasan_report(unsigned long addr, size_t size, |
bool is_write, unsigned long ip) |
{ |
struct kasan_access_info info; |