kasan: fix null pointer dereference in kasan_record_aux_stack
[linux-2.6-microblaze.git] / mm / kasan / generic.c
index 71ae070..5106b84 100644 (file)
@@ -9,8 +9,6 @@
  *        Andrey Konovalov <andreyknvl@gmail.com>
  */
 
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
 #include <linux/export.h>
 #include <linux/interrupt.h>
 #include <linux/init.h>
@@ -187,6 +185,13 @@ bool check_memory_region(unsigned long addr, size_t size, bool write,
        return check_memory_region_inline(addr, size, write, ret_ip);
 }
 
+bool check_invalid_free(void *addr)
+{
+       s8 shadow_byte = READ_ONCE(*(s8 *)kasan_mem_to_shadow(addr));
+
+       return shadow_byte < 0 || shadow_byte >= KASAN_GRANULE_SIZE;
+}
+
 void kasan_cache_shrink(struct kmem_cache *cache)
 {
        quarantine_remove_cache(cache);
@@ -323,7 +328,7 @@ void kasan_record_aux_stack(void *addr)
 {
        struct page *page = kasan_addr_to_page(addr);
        struct kmem_cache *cache;
-       struct kasan_alloc_meta *alloc_info;
+       struct kasan_alloc_meta *alloc_meta;
        void *object;
 
        if (!(page && PageSlab(page)))
@@ -331,10 +336,12 @@ void kasan_record_aux_stack(void *addr)
 
        cache = page->slab_cache;
        object = nearest_obj(cache, page, addr);
-       alloc_info = get_alloc_info(cache, object);
+       alloc_meta = kasan_get_alloc_meta(cache, object);
+       if (!alloc_meta)
+               return;
 
-       alloc_info->aux_stack[1] = alloc_info->aux_stack[0];
-       alloc_info->aux_stack[0] = kasan_save_stack(GFP_NOWAIT);
+       alloc_meta->aux_stack[1] = alloc_meta->aux_stack[0];
+       alloc_meta->aux_stack[0] = kasan_save_stack(GFP_NOWAIT);
 }
 
 void kasan_set_free_info(struct kmem_cache *cache,
@@ -342,12 +349,12 @@ void kasan_set_free_info(struct kmem_cache *cache,
 {
        struct kasan_free_meta *free_meta;
 
-       free_meta = get_free_info(cache, object);
-       kasan_set_track(&free_meta->free_track, GFP_NOWAIT);
+       free_meta = kasan_get_free_meta(cache, object);
+       if (!free_meta)
+               return;
 
-       /*
-        *  the object was freed and has free track set
-        */
+       kasan_set_track(&free_meta->free_track, GFP_NOWAIT);
+       /* The object was freed and has free track set. */
        *(u8 *)kasan_mem_to_shadow(object) = KASAN_KMALLOC_FREETRACK;
 }
 
@@ -356,5 +363,6 @@ struct kasan_track *kasan_get_free_track(struct kmem_cache *cache,
 {
        if (*(u8 *)kasan_mem_to_shadow(object) != KASAN_KMALLOC_FREETRACK)
                return NULL;
-       return &get_free_info(cache, object)->free_track;
+       /* Free meta must be present with KASAN_KMALLOC_FREETRACK. */
+       return &kasan_get_free_meta(cache, object)->free_track;
 }