All of lore.kernel.org
 help / color / mirror / Atom feed
From: Jarkko Sakkinen <jarkko@kernel.org>
To: David Howells <dhowells@redhat.com>
Cc: Kees Cook <kees@kernel.org>, Oleg Nesterov <oleg@redhat.com>,
	Greg KH <gregkh@linuxfoundation.org>,
	Josh Drake <josh@delphoslabs.com>,
	Suraj Sonawane <surajsonawane0215@gmail.com>,
	keyrings@vger.kernel.org, linux-security-module@vger.kernel.org,
	security@kernel.org, stable@vger.kernel.org,
	linux-kernel@vger.kernel.org
Subject: Re: [PATCH v2] keys: Fix UAF in key_put()
Date: Thu, 20 Mar 2025 18:14:15 +0200	[thread overview]
Message-ID: <Z9w-10St-WYpSnKC@kernel.org> (raw)
In-Reply-To: <2874581.1742399866@warthog.procyon.org.uk>

On Wed, Mar 19, 2025 at 03:57:46PM +0000, David Howells wrote:
>     
> Once a key's reference count has been reduced to 0, the garbage collector
> thread may destroy it at any time and so key_put() is not allowed to touch
> the key after that point.  The most key_put() is normally allowed to do is
> to touch key_gc_work as that's a static global variable.
> 
> However, in an effort to speed up the reclamation of quota, this is now
> done in key_put() once the key's usage is reduced to 0 - but now the code
> is looking at the key after the deadline, which is forbidden.
> 
> Fix this by using a flag to indicate that a key can be gc'd now rather than
> looking at the key's refcount in the garbage collector.
> 
> Fixes: 9578e327b2b4 ("keys: update key quotas in key_put()")
> Reported-by: syzbot+6105ffc1ded71d194d6d@syzkaller.appspotmail.com
> Signed-off-by: David Howells <dhowells@redhat.com>
> Tested-by: syzbot+6105ffc1ded71d194d6d@syzkaller.appspotmail.com
> cc: Jarkko Sakkinen <jarkko@kernel.org>
> cc: Oleg Nesterov <oleg@redhat.com>
> cc: Kees Cook <kees@kernel.org>
> cc: Hillf Danton <hdanton@sina.com>,
> cc: keyrings@vger.kernel.org
> Cc: stable@vger.kernel.org # v6.10+
> ---
>  include/linux/key.h |    1 +
>  security/keys/gc.c  |    4 +++-
>  security/keys/key.c |    2 ++
>  3 files changed, 6 insertions(+), 1 deletion(-)
> 
> diff --git a/include/linux/key.h b/include/linux/key.h
> index 074dca3222b9..ba05de8579ec 100644
> --- a/include/linux/key.h
> +++ b/include/linux/key.h
> @@ -236,6 +236,7 @@ struct key {
>  #define KEY_FLAG_ROOT_CAN_INVAL	7	/* set if key can be invalidated by root without permission */
>  #define KEY_FLAG_KEEP		8	/* set if key should not be removed */
>  #define KEY_FLAG_UID_KEYRING	9	/* set if key is a user or user session keyring */
> +#define KEY_FLAG_FINAL_PUT	10	/* set if final put has happened on key */
>  
>  	/* the key type and key description string
>  	 * - the desc is used to match a key against search criteria
> diff --git a/security/keys/gc.c b/security/keys/gc.c
> index 7d687b0962b1..f27223ea4578 100644
> --- a/security/keys/gc.c
> +++ b/security/keys/gc.c
> @@ -218,8 +218,10 @@ static void key_garbage_collector(struct work_struct *work)
>  		key = rb_entry(cursor, struct key, serial_node);
>  		cursor = rb_next(cursor);
>  
> -		if (refcount_read(&key->usage) == 0)
> +		if (test_bit(KEY_FLAG_FINAL_PUT, &key->flags)) {
> +			smp_mb(); /* Clobber key->user after FINAL_PUT seen. */

test_bit() is already atomic.

https://docs.kernel.org/core-api/wrappers/atomic_bitops.html

>  			goto found_unreferenced_key;
> +		}
>  
>  		if (unlikely(gc_state & KEY_GC_REAPING_DEAD_1)) {
>  			if (key->type == key_gc_dead_keytype) {
> diff --git a/security/keys/key.c b/security/keys/key.c
> index 3d7d185019d3..7198cd2ac3a3 100644
> --- a/security/keys/key.c
> +++ b/security/keys/key.c
> @@ -658,6 +658,8 @@ void key_put(struct key *key)
>  				key->user->qnbytes -= key->quotalen;
>  				spin_unlock_irqrestore(&key->user->lock, flags);
>  			}
> +			smp_mb(); /* key->user before FINAL_PUT set. */
> +			set_bit(KEY_FLAG_FINAL_PUT, &key->flags);

Ditto.

Nit: I'm just thinking should the name imply more like that "now
key_put() is actually done". E.g., even something like KEY_FLAG_PUT_DONE
would be more self-descriptive.

>  			schedule_work(&key_gc_work);
>  		}
>  	}
> 
> 

BR, Jarkko

  parent reply	other threads:[~2025-03-20 16:14 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-03-19 15:57 [PATCH v2] keys: Fix UAF in key_put() David Howells
2025-03-19 16:30 ` Oleg Nesterov
2025-03-19 18:11   ` Linus Torvalds
2025-03-19 18:47     ` David Howells
2025-03-20 16:14 ` Jarkko Sakkinen [this message]
2025-03-20 16:39   ` David Howells
2025-03-20 17:28     ` Jarkko Sakkinen
2025-03-20 18:46       ` Jarkko Sakkinen
2025-03-20 18:48         ` Jarkko Sakkinen

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=Z9w-10St-WYpSnKC@kernel.org \
    --to=jarkko@kernel.org \
    --cc=dhowells@redhat.com \
    --cc=gregkh@linuxfoundation.org \
    --cc=josh@delphoslabs.com \
    --cc=kees@kernel.org \
    --cc=keyrings@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-security-module@vger.kernel.org \
    --cc=oleg@redhat.com \
    --cc=security@kernel.org \
    --cc=stable@vger.kernel.org \
    --cc=surajsonawane0215@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.