forked from Minki/linux
5ab6d91ac9
Changes double-free report header from BUG: Double free or freeing an invalid pointer Unexpected shadow byte: 0xFB to BUG: KASAN: double-free or invalid-free in kmalloc_oob_left+0xe5/0xef This makes a bug uniquely identifiable by the first report line. To account for removing of the unexpected shadow value, print shadow bytes at the end of the report as in reports for other kinds of bugs. Link: http://lkml.kernel.org/r/20170302134851.101218-9-andreyknvl@google.com Signed-off-by: Andrey Konovalov <andreyknvl@google.com> Acked-by: Dmitry Vyukov <dvyukov@google.com> Cc: Andrey Ryabinin <aryabinin@virtuozzo.com> Cc: Alexander Potapenko <glider@google.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
116 lines
3.3 KiB
C
116 lines
3.3 KiB
C
#ifndef __MM_KASAN_KASAN_H
|
|
#define __MM_KASAN_KASAN_H
|
|
|
|
#include <linux/kasan.h>
|
|
#include <linux/stackdepot.h>
|
|
|
|
#define KASAN_SHADOW_SCALE_SIZE (1UL << KASAN_SHADOW_SCALE_SHIFT)
|
|
#define KASAN_SHADOW_MASK (KASAN_SHADOW_SCALE_SIZE - 1)
|
|
|
|
#define KASAN_FREE_PAGE 0xFF /* page was freed */
|
|
#define KASAN_PAGE_REDZONE 0xFE /* redzone for kmalloc_large allocations */
|
|
#define KASAN_KMALLOC_REDZONE 0xFC /* redzone inside slub object */
|
|
#define KASAN_KMALLOC_FREE 0xFB /* object was freed (kmem_cache_free/kfree) */
|
|
#define KASAN_GLOBAL_REDZONE 0xFA /* redzone for global variable */
|
|
|
|
/*
|
|
* Stack redzone shadow values
|
|
* (Those are compiler's ABI, don't change them)
|
|
*/
|
|
#define KASAN_STACK_LEFT 0xF1
|
|
#define KASAN_STACK_MID 0xF2
|
|
#define KASAN_STACK_RIGHT 0xF3
|
|
#define KASAN_STACK_PARTIAL 0xF4
|
|
#define KASAN_USE_AFTER_SCOPE 0xF8
|
|
|
|
/* Don't break randconfig/all*config builds */
|
|
#ifndef KASAN_ABI_VERSION
|
|
#define KASAN_ABI_VERSION 1
|
|
#endif
|
|
|
|
struct kasan_access_info {
|
|
const void *access_addr;
|
|
const void *first_bad_addr;
|
|
size_t access_size;
|
|
bool is_write;
|
|
unsigned long ip;
|
|
};
|
|
|
|
/* The layout of struct dictated by compiler */
|
|
struct kasan_source_location {
|
|
const char *filename;
|
|
int line_no;
|
|
int column_no;
|
|
};
|
|
|
|
/* The layout of struct dictated by compiler */
|
|
struct kasan_global {
|
|
const void *beg; /* Address of the beginning of the global variable. */
|
|
size_t size; /* Size of the global variable. */
|
|
size_t size_with_redzone; /* Size of the variable + size of the red zone. 32 bytes aligned */
|
|
const void *name;
|
|
const void *module_name; /* Name of the module where the global variable is declared. */
|
|
unsigned long has_dynamic_init; /* This needed for C++ */
|
|
#if KASAN_ABI_VERSION >= 4
|
|
struct kasan_source_location *location;
|
|
#endif
|
|
#if KASAN_ABI_VERSION >= 5
|
|
char *odr_indicator;
|
|
#endif
|
|
};
|
|
|
|
/**
|
|
* Structures to keep alloc and free tracks *
|
|
*/
|
|
|
|
#define KASAN_STACK_DEPTH 64
|
|
|
|
struct kasan_track {
|
|
u32 pid;
|
|
depot_stack_handle_t stack;
|
|
};
|
|
|
|
struct kasan_alloc_meta {
|
|
struct kasan_track alloc_track;
|
|
struct kasan_track free_track;
|
|
};
|
|
|
|
struct qlist_node {
|
|
struct qlist_node *next;
|
|
};
|
|
struct kasan_free_meta {
|
|
/* This field is used while the object is in the quarantine.
|
|
* Otherwise it might be used for the allocator freelist.
|
|
*/
|
|
struct qlist_node quarantine_link;
|
|
};
|
|
|
|
struct kasan_alloc_meta *get_alloc_info(struct kmem_cache *cache,
|
|
const void *object);
|
|
struct kasan_free_meta *get_free_info(struct kmem_cache *cache,
|
|
const void *object);
|
|
|
|
static inline const void *kasan_shadow_to_mem(const void *shadow_addr)
|
|
{
|
|
return (void *)(((unsigned long)shadow_addr - KASAN_SHADOW_OFFSET)
|
|
<< KASAN_SHADOW_SCALE_SHIFT);
|
|
}
|
|
|
|
void kasan_report(unsigned long addr, size_t size,
|
|
bool is_write, unsigned long ip);
|
|
void kasan_report_double_free(struct kmem_cache *cache, void *object,
|
|
void *ip);
|
|
|
|
#if defined(CONFIG_SLAB) || defined(CONFIG_SLUB)
|
|
void quarantine_put(struct kasan_free_meta *info, struct kmem_cache *cache);
|
|
void quarantine_reduce(void);
|
|
void quarantine_remove_cache(struct kmem_cache *cache);
|
|
#else
|
|
static inline void quarantine_put(struct kasan_free_meta *info,
|
|
struct kmem_cache *cache) { }
|
|
static inline void quarantine_reduce(void) { }
|
|
static inline void quarantine_remove_cache(struct kmem_cache *cache) { }
|
|
#endif
|
|
|
|
#endif
|