Merge tag 'clk-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/clk/linux
[linux-2.6-microblaze.git] / mm / slab_common.c
index 2f2b55c..adbace4 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/seq_file.h>
 #include <linux/proc_fs.h>
 #include <linux/debugfs.h>
+#include <linux/kasan.h>
 #include <asm/cacheflush.h>
 #include <asm/tlbflush.h>
 #include <asm/page.h>
@@ -53,7 +54,7 @@ static DECLARE_WORK(slab_caches_to_rcu_destroy_work,
  */
 #define SLAB_NEVER_MERGE (SLAB_RED_ZONE | SLAB_POISON | SLAB_STORE_USER | \
                SLAB_TRACE | SLAB_TYPESAFE_BY_RCU | SLAB_NOLEAKTRACE | \
-               SLAB_FAILSLAB | SLAB_KASAN)
+               SLAB_FAILSLAB | kasan_never_merge())
 
 #define SLAB_MERGE_SAME (SLAB_RECLAIM_ACCOUNT | SLAB_CACHE_DMA | \
                         SLAB_CACHE_DMA32 | SLAB_ACCOUNT)
@@ -536,6 +537,81 @@ bool slab_is_available(void)
        return slab_state >= UP;
 }
 
+/**
+ * kmem_valid_obj - does the pointer reference a valid slab object?
+ * @object: pointer to query.
+ *
+ * Return: %true if the pointer is to a not-yet-freed object from
+ * kmalloc() or kmem_cache_alloc(), either %true or %false if the pointer
+ * is to an already-freed object, and %false otherwise.
+ */
+bool kmem_valid_obj(void *object)
+{
+       struct page *page;
+
+       /* Some arches consider ZERO_SIZE_PTR to be a valid address. */
+       if (object < (void *)PAGE_SIZE || !virt_addr_valid(object))
+               return false;
+       page = virt_to_head_page(object);
+       return PageSlab(page);
+}
+
+/**
+ * kmem_dump_obj - Print available slab provenance information
+ * @object: slab object for which to find provenance information.
+ *
+ * This function uses pr_cont(), so that the caller is expected to have
+ * printed out whatever preamble is appropriate.  The provenance information
+ * depends on the type of object and on how much debugging is enabled.
+ * For a slab-cache object, the fact that it is a slab object is printed,
+ * and, if available, the slab name, return address, and stack trace from
+ * the allocation of that object.
+ *
+ * This function will splat if passed a pointer to a non-slab object.
+ * If you are not sure what type of object you have, you should instead
+ * use mem_dump_obj().
+ */
+void kmem_dump_obj(void *object)
+{
+       char *cp = IS_ENABLED(CONFIG_MMU) ? "" : "/vmalloc";
+       int i;
+       struct page *page;
+       unsigned long ptroffset;
+       struct kmem_obj_info kp = { };
+
+       if (WARN_ON_ONCE(!virt_addr_valid(object)))
+               return;
+       page = virt_to_head_page(object);
+       if (WARN_ON_ONCE(!PageSlab(page))) {
+               pr_cont(" non-slab memory.\n");
+               return;
+       }
+       kmem_obj_info(&kp, object, page);
+       if (kp.kp_slab_cache)
+               pr_cont(" slab%s %s", cp, kp.kp_slab_cache->name);
+       else
+               pr_cont(" slab%s", cp);
+       if (kp.kp_objp)
+               pr_cont(" start %px", kp.kp_objp);
+       if (kp.kp_data_offset)
+               pr_cont(" data offset %lu", kp.kp_data_offset);
+       if (kp.kp_objp) {
+               ptroffset = ((char *)object - (char *)kp.kp_objp) - kp.kp_data_offset;
+               pr_cont(" pointer offset %lu", ptroffset);
+       }
+       if (kp.kp_slab_cache && kp.kp_slab_cache->usersize)
+               pr_cont(" size %u", kp.kp_slab_cache->usersize);
+       if (kp.kp_ret)
+               pr_cont(" allocated at %pS\n", kp.kp_ret);
+       else
+               pr_cont("\n");
+       for (i = 0; i < ARRAY_SIZE(kp.kp_stack); i++) {
+               if (!kp.kp_stack[i])
+                       break;
+               pr_info("    %pS\n", kp.kp_stack[i]);
+       }
+}
+
 #ifndef CONFIG_SLOB
 /* Create a cache during boot when no slab services are available yet */
 void __init create_boot_cache(struct kmem_cache *s, const char *name,
@@ -1176,7 +1252,7 @@ size_t ksize(const void *objp)
         * We assume that ksize callers could use whole allocated area,
         * so we need to unpoison this area.
         */
-       kasan_unpoison_shadow(objp, size);
+       kasan_unpoison_range(objp, size);
        return size;
 }
 EXPORT_SYMBOL(ksize);