Merge tag 'for-5.12-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux
[linux-2.6-microblaze.git] / mm / kasan / quarantine.c
index 0e3f849..5578312 100644 (file)
@@ -6,16 +6,6 @@
  * Copyright (C) 2016 Google, Inc.
  *
  * Based on code by Dmitry Chernenkov.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
  */
 
 #include <linux/gfp.h>
@@ -147,7 +137,12 @@ static void qlink_free(struct qlist_node *qlink, struct kmem_cache *cache)
        if (IS_ENABLED(CONFIG_SLAB))
                local_irq_save(flags);
 
+       /*
+        * As the object now gets freed from the quaratine, assume that its
+        * free track is no longer valid.
+        */
        *(u8 *)kasan_mem_to_shadow(object) = KASAN_KMALLOC_FREE;
+
        ___cache_free(cache, object, _THIS_IP_);
 
        if (IS_ENABLED(CONFIG_SLAB))
@@ -173,11 +168,19 @@ static void qlist_free_all(struct qlist_head *q, struct kmem_cache *cache)
        qlist_init(q);
 }
 
-void quarantine_put(struct kasan_free_meta *info, struct kmem_cache *cache)
+bool quarantine_put(struct kmem_cache *cache, void *object)
 {
        unsigned long flags;
        struct qlist_head *q;
        struct qlist_head temp = QLIST_INIT;
+       struct kasan_free_meta *meta = kasan_get_free_meta(cache, object);
+
+       /*
+        * If there's no metadata for this object, don't put it into
+        * quarantine.
+        */
+       if (!meta)
+               return false;
 
        /*
         * Note: irq must be disabled until after we move the batch to the
@@ -192,9 +195,9 @@ void quarantine_put(struct kasan_free_meta *info, struct kmem_cache *cache)
        q = this_cpu_ptr(&cpu_quarantine);
        if (q->offline) {
                local_irq_restore(flags);
-               return;
+               return false;
        }
-       qlist_put(q, &info->quarantine_link, cache->size);
+       qlist_put(q, &meta->quarantine_link, cache->size);
        if (unlikely(q->bytes > QUARANTINE_PERCPU_SIZE)) {
                qlist_move_all(q, &temp);
 
@@ -215,6 +218,8 @@ void quarantine_put(struct kasan_free_meta *info, struct kmem_cache *cache)
        }
 
        local_irq_restore(flags);
+
+       return true;
 }
 
 void quarantine_reduce(void)