From: Jarkko Sakkinen <jarkko@kernel.org>
To: Karl Mehltretter <kmehltretter@gmail.com>
Cc: David Howells <dhowells@redhat.com>,
Paul Moore <paul@paul-moore.com>,
James Morris <jmorris@namei.org>,
"Serge E. Hallyn" <serge@hallyn.com>,
keyrings@vger.kernel.org, linux-security-module@vger.kernel.org,
linux-kernel@vger.kernel.org
Subject: Re: [PATCH v2] keys: fix lost wakeup when reaping a dead key type
Date: Tue, 25 Aug 2026 17:07:59 +0300 [thread overview]
Message-ID: <ao2hv-9TVbMe2bbm@kernel.org> (raw)
In-Reply-To: <20260821025327.61488-1-kmehltretter@gmail.com>
On Fri, Aug 21, 2026 at 04:53:27AM +0200, Karl Mehltretter wrote:
> clear_bit() is atomic with respect to the word it modifies, but it is
> an unordered operation: it implies no memory barrier on either side
> (Documentation/atomic_bitops.txt).
>
> key_garbage_collector() clears KEY_GC_REAPING_KEYTYPE with clear_bit()
> and calls wake_up_bit() after reaping a dead key type. wake_up_bit()
> uses a lockless waitqueue check and requires a full barrier after the
> clear.
>
> The existing smp_mb() is before clear_bit(), so nothing orders the clear
> against that check. The GC can see an empty waitqueue while
> unregister_key_type() still sees the bit set. The final wakeup is then
> lost, leaving module unload stuck in wait_on_bit().
>
> Use clear_and_wake_up_bit(). Its clear_bit_unlock() has RELEASE
> semantics, so the completed GC work stays ordered before the clear, and
> its smp_mb__after_atomic() orders the clear before the waitqueue check.
>
> Fixes: 0c061b5707ab ("KEYS: Correctly destroy key payloads when their keytype is removed")
> Assisted-by: Claude:claude-fable-5
> Signed-off-by: Karl Mehltretter <kmehltretter@gmail.com>
> ---
> v2: open with the ordering semantics of clear_bit(), as suggested by
> Jarkko. No code change.
> v1: https://lore.kernel.org/r/20260811173753.67616-1-kmehltretter@gmail.com/
>
> LKMM (herdtools7 7.58). LKMM has no clear_bit*() primitives, so these
> tests abstract the bit clear as a store while preserving the ordering
> relevant to this race. The fixed test models clear_bit_unlock() with
> smp_store_release() and smp_mb__after_atomic() with smp_mb().
>
> C keys-gc-buggy
> { flag=1; }
> P0(int *flag, int *wq)
> {
> int r0;
> smp_mb();
> WRITE_ONCE(*flag, 0);
> r0 = READ_ONCE(*wq);
> }
> P1(int *flag, int *wq)
> {
> int r1;
> WRITE_ONCE(*wq, 1);
> smp_mb();
> r1 = READ_ONCE(*flag);
> }
> exists (0:r0=0 /\ 1:r1=1)
>
> C keys-gc-fixed
> { flag=1; }
> P0(int *flag, int *wq)
> {
> int r0;
> smp_store_release(flag, 0);
> smp_mb();
> r0 = READ_ONCE(*wq);
> }
> P1(int *flag, int *wq)
> {
> int r1;
> WRITE_ONCE(*wq, 1);
> smp_mb();
> r1 = READ_ONCE(*flag);
> }
> exists (0:r0=0 /\ 1:r1=1)
>
> herd7 -conf linux-kernel.cfg keys-gc-buggy.litmus
> herd7 -conf linux-kernel.cfg keys-gc-fixed.litmus
>
> pre-fix: Sometimes
> fixed: Never
>
> security/keys/gc.c | 4 +---
> 1 file changed, 1 insertion(+), 3 deletions(-)
>
> diff --git a/security/keys/gc.c b/security/keys/gc.c
> index 748e83818a760..eda445f815d47 100644
> --- a/security/keys/gc.c
> +++ b/security/keys/gc.c
> @@ -318,9 +318,7 @@ static void key_garbage_collector(struct work_struct *work)
>
> if (unlikely(gc_state & KEY_GC_REAPING_DEAD_3)) {
> kdebug("dead wake");
> - smp_mb();
> - clear_bit(KEY_GC_REAPING_KEYTYPE, &key_gc_flags);
> - wake_up_bit(&key_gc_flags, KEY_GC_REAPING_KEYTYPE);
> + clear_and_wake_up_bit(KEY_GC_REAPING_KEYTYPE, &key_gc_flags);
> }
>
> if (gc_state & KEY_GC_REAP_AGAIN)
> --
> 2.53.0
Reviewed-by: Jarkko Sakkinen <jarkko@kernel.org>
I send this to -rc2 as I already sent keys PR and I have quite heavy
TPM PR to prepare.
BR, Jarkko
prev parent reply other threads:[~2026-08-25 14:08 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-21 2:53 [PATCH v2] keys: fix lost wakeup when reaping a dead key type Karl Mehltretter
2026-08-25 14:07 ` Jarkko Sakkinen [this message]
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=ao2hv-9TVbMe2bbm@kernel.org \
--to=jarkko@kernel.org \
--cc=dhowells@redhat.com \
--cc=jmorris@namei.org \
--cc=keyrings@vger.kernel.org \
--cc=kmehltretter@gmail.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-security-module@vger.kernel.org \
--cc=paul@paul-moore.com \
--cc=serge@hallyn.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.