From ffe3a0a07e949f44404f430057fe82d8e73b2b61 Mon Sep 17 00:00:00 2001 From: Suraj Sonawane Date: Tue, 19 Nov 2024 02:47:47 +0530 Subject: [PATCH] fix slab-after-free read syz test Signed-off-by: Suraj Sonawane --- security/keys/gc.c | 2 ++ security/keys/key.c | 16 +++++++++++++--- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/security/keys/gc.c b/security/keys/gc.c index 7d687b096..9b19a972d 100644 --- a/security/keys/gc.c +++ b/security/keys/gc.c @@ -143,6 +143,7 @@ static noinline void key_gc_unused_keys(struct list_head *keys) kdebug("- %u", key->serial); key_check(key); + WRITE_ONCE(key->state, KEY_IS_DEAD); #ifdef CONFIG_KEY_NOTIFICATIONS remove_watch_list(key->watchers, key->serial); @@ -159,6 +160,7 @@ static noinline void key_gc_unused_keys(struct list_head *keys) if (state != KEY_IS_UNINSTANTIATED) atomic_dec(&key->user->nikeys); + smp_wmb(); key_user_put(key->user); key_put_tag(key->domain_tag); kfree(key->description); diff --git a/security/keys/key.c b/security/keys/key.c index 3d7d18501..5356da9d9 100644 --- a/security/keys/key.c +++ b/security/keys/key.c @@ -274,14 +274,22 @@ struct key *key_alloc(struct key_type *type, const char *desc, } /* allocate and initialise the key and its description */ - key = kmem_cache_zalloc(key_jar, GFP_KERNEL); + key = kmem_cache_zalloc(key_jar, GFP_KERNEL | __GFP_ZERO); if (!key) goto no_memory_2; key->index_key.desc_len = desclen; key->index_key.description = kmemdup(desc, desclen + 1, GFP_KERNEL); - if (!key->index_key.description) - goto no_memory_3; + + if (!key->index_key.description) { + kmem_cache_free(key_jar, key); + return ERR_PTR(-ENOMEM); + } else { + /* Ensure memory is correctly associated */ + smp_wmb(); /* Memory barrier to ensure key is set before use */ + key->state = KEY_IS_UNINSTANTIATED; + } + key->index_key.type = type; key_set_index_key(&key->index_key); @@ -651,6 +659,8 @@ void key_put(struct key *key) if (refcount_dec_and_test(&key->usage)) { unsigned long flags; + WRITE_ONCE(key->state, KEY_IS_DEAD); + /* deal with the user's key tracking and quota */ if (test_bit(KEY_FLAG_IN_QUOTA, &key->flags)) { spin_lock_irqsave(&key->user->lock, flags); -- 2.34.1