summaryrefslogtreecommitdiffstats
path: root/mm/kasan/quarantine.c
diff options
context:
space:
mode:
authorAndrey Konovalov <andreyknvl@google.com>2023-11-20 18:47:19 +0100
committerAndrew Morton <akpm@linux-foundation.org>2023-12-10 16:51:48 -0800
commit773688a6cb24b0b3c2ba40354d883348a2befa38 (patch)
tree7777e7a212937ca49769a84c64e90a77de9c1a74 /mm/kasan/quarantine.c
parent2d5524635b00fc90016577e1a18c21682b1bb913 (diff)
downloadlinux-stable-773688a6cb24b0b3c2ba40354d883348a2befa38.tar.gz
linux-stable-773688a6cb24b0b3c2ba40354d883348a2befa38.tar.bz2
linux-stable-773688a6cb24b0b3c2ba40354d883348a2befa38.zip
kasan: use stack_depot_put for Generic mode
Evict alloc/free stack traces from the stack depot for Generic KASAN once they are evicted from the quaratine. For auxiliary stack traces, evict the oldest stack trace once a new one is saved (KASAN only keeps references to the last two). Also evict all saved stack traces on krealloc. To avoid double-evicting and mis-evicting stack traces (in case KASAN's metadata was corrupted), reset KASAN's per-object metadata that stores stack depot handles when the object is initialized and when it's evicted from the quarantine. Note that stack_depot_put is no-op if the handle is 0. Link: https://lkml.kernel.org/r/5cef104d9b842899489b4054fe8d1339a71acee0.1700502145.git.andreyknvl@google.com Signed-off-by: Andrey Konovalov <andreyknvl@google.com> Reviewed-by: Marco Elver <elver@google.com> Cc: Alexander Potapenko <glider@google.com> Cc: Dmitry Vyukov <dvyukov@google.com> Cc: Evgenii Stepanov <eugenis@google.com> Cc: Oscar Salvador <osalvador@suse.de> Cc: Vlastimil Babka <vbabka@suse.cz> Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Diffstat (limited to 'mm/kasan/quarantine.c')
-rw-r--r--mm/kasan/quarantine.c26
1 files changed, 20 insertions, 6 deletions
diff --git a/mm/kasan/quarantine.c b/mm/kasan/quarantine.c
index ca4529156735..265ca2bbe2dd 100644
--- a/mm/kasan/quarantine.c
+++ b/mm/kasan/quarantine.c
@@ -143,11 +143,22 @@ static void *qlink_to_object(struct qlist_node *qlink, struct kmem_cache *cache)
static void qlink_free(struct qlist_node *qlink, struct kmem_cache *cache)
{
void *object = qlink_to_object(qlink, cache);
- struct kasan_free_meta *meta = kasan_get_free_meta(cache, object);
+ struct kasan_alloc_meta *alloc_meta = kasan_get_alloc_meta(cache, object);
+ struct kasan_free_meta *free_meta = kasan_get_free_meta(cache, object);
unsigned long flags;
- if (IS_ENABLED(CONFIG_SLAB))
- local_irq_save(flags);
+ if (alloc_meta) {
+ stack_depot_put(alloc_meta->alloc_track.stack);
+ stack_depot_put(alloc_meta->aux_stack[0]);
+ stack_depot_put(alloc_meta->aux_stack[1]);
+ __memset(alloc_meta, 0, sizeof(*alloc_meta));
+ }
+
+ if (free_meta &&
+ *(u8 *)kasan_mem_to_shadow(object) == KASAN_SLAB_FREETRACK) {
+ stack_depot_put(free_meta->free_track.stack);
+ free_meta->free_track.stack = 0;
+ }
/*
* If init_on_free is enabled and KASAN's free metadata is stored in
@@ -157,14 +168,17 @@ static void qlink_free(struct qlist_node *qlink, struct kmem_cache *cache)
*/
if (slab_want_init_on_free(cache) &&
cache->kasan_info.free_meta_offset == 0)
- memzero_explicit(meta, sizeof(*meta));
+ memzero_explicit(free_meta, sizeof(*free_meta));
/*
- * As the object now gets freed from the quarantine, assume that its
- * free track is no longer valid.
+ * As the object now gets freed from the quarantine,
+ * take note that its free track is no longer exists.
*/
*(u8 *)kasan_mem_to_shadow(object) = KASAN_SLAB_FREE;
+ if (IS_ENABLED(CONFIG_SLAB))
+ local_irq_save(flags);
+
___cache_free(cache, object, _THIS_IP_);
if (IS_ENABLED(CONFIG_SLAB))