All of lore.kernel.org
 help / color / mirror / Atom feed
From: sashiko-bot@kernel.org
To: "Eduard Zateev" <hackerowskiy@gmail.com>,
	dhowells@redhat.com, jarkko@kernel.org, paul@paul-moore.com,
	jmorris@namei.org, serge@hallyn.com
Cc: keyrings@vger.kernel.org, linux-security-module@vger.kernel.org,
	syzbot+c15de43f1e7fffbb7b9b@syzkaller.appspotmail.com,
	syzkaller-bugs@googlegroups.com
Subject: Re: [PATCH] keys: use long workqueue for garbage collection
Date: Sat, 24 Oct 2026 04:36:11 +0000	[thread overview]
Message-ID: <sashiko-outbox-183546@kernel.org> (raw)
In-Reply-To: <20261024042944.52493-1-hackerowskiy@gmail.com>

Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Critical] keys: concurrent key_garbage_collector() via schedule_work() in key_put()
--

commit 49fec25be24d41f55255824b44e92e9f57128440
Author: Eduard Zateev <hackerowskiy@gmail.com>

keys: use long workqueue for garbage collection

This commit switches the key garbage collector work item (key_gc_work) in
security/keys/gc.c from system_percpu_wq to system_long_wq because key
garbage collection can block waiting for RCU grace periods.

Link: https://syzkaller.appspot.com/bug?extid=c15de43f1e7fffbb7b9b

> diff --git a/security/keys/gc.c b/security/keys/gc.c
> index eda445f815d47..b174b8c511b4b 100644
> --- a/security/keys/gc.c
> +++ b/security/keys/gc.c
> @@ -19,6 +19,7 @@ unsigned key_gc_delay = 5 * 60;
>   * Reaper for unused keys.
>   */
>  static void key_garbage_collector(struct work_struct *work);
> +/* Key GC may wait for RCU grace periods, so queue it on system_long_wq. */
>  DECLARE_WORK(key_gc_work, key_garbage_collector);
>  
>  /*
> @@ -57,7 +58,7 @@ void key_schedule_gc(time64_t gc_at)
>  
>  	if (gc_at <= now || test_bit(KEY_GC_REAP_KEYTYPE, &key_gc_flags)) {
>  		kdebug("IMMEDIATE");
> -		schedule_work(&key_gc_work);
> +		queue_work(system_long_wq, &key_gc_work);

[Severity: Critical]
Does this allow key_garbage_collector() to run concurrently with itself across
two CPUs because key_put() still queues key_gc_work on system_percpu_wq?

While this patch updates the four schedule_work(&key_gc_work) call sites in
security/keys/gc.c to use system_long_wq, key_put() in security/keys/key.c
still calls schedule_work(&key_gc_work):

security/keys/key.c:key_put() {
	if (key) {
		key_check(key);

		if (refcount_dec_and_test(&key->usage)) {
			/* Mark key as safe for GC after key->user done. */
			clear_bit_unlock(KEY_FLAG_USER_ALIVE, &key->flags);
			schedule_work(&key_gc_work);
		}
	}
}

First, since key_put() is the path that clears KEY_FLAG_USER_ALIVE to trigger
reaping of unreferenced keys and the resulting synchronize_rcu() call, normal
system_percpu_wq workers will still execute key_garbage_collector() and block
on RCU grace periods.

Second, in __queue_work(), cross-CPU non-reentrancy for a work_struct that is
already executing relies on matching the target workqueue against the running
worker's workqueue:

kernel/workqueue.c:__queue_work() {
	...
	last_pool = get_work_pool(work);
	if (last_pool && last_pool != pool) {
		worker = find_worker_executing_work(last_pool, work);

		if (worker && worker->current_pwq->wq == wq) {
			pwq = worker->current_pwq;\
			pool = pwq->pool;
			WARN_ON_ONCE(pool != last_pool);
		} else {
			/* meh... not running there, queue here */
			raw_spin_unlock(&last_pool->lock);
			raw_spin_lock(&pool->lock);
		}
	}
	...
}

Once process_one_work() clears WORK_STRUCT_PENDING_BIT and begins executing
key_garbage_collector() on one CPU under system_long_wq, a concurrent
key_put() -> schedule_work(&key_gc_work) on another CPU passes wq ==
system_percpu_wq (or vice versa). Because worker->current_pwq->wq == wq is
false, __queue_work() queues key_gc_work on the second CPU's pool and runs a
second instance of key_garbage_collector() in parallel while the first is
sleeping in synchronize_rcu(), cond_resched(), or down_write(&key->sem).

key_garbage_collector() assumes only a single instance can run at a time:

security/keys/gc.c:key_garbage_collector() {
	static LIST_HEAD(graveyard);
	static u8 gc_state;		/* Internal persistent state */
	...
	/* As only this function is permitted to remove things from the key
	 * serial tree, if cursor is non-NULL then it will always point to a
	 * valid node in the tree - even if lock got dropped.
	 */
	spin_lock(&key_serial_lock);
	cursor = rb_first(&key_serial_tree);
	...
}

Can concurrent execution of key_garbage_collector() corrupt the static
graveyard list and gc_state, free keys in key_gc_unused_keys() before the
other worker's synchronize_rcu() completes, or rb_erase() and free the key
pointed to by the other worker's cursor while key_serial_lock is dropped?

Should key_put() in security/keys/key.c also be updated to call
queue_work(system_long_wq, &key_gc_work)?

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20261024042944.52493-1-hackerowskiy@gmail.com?part=1

  reply	other threads:[~2026-10-24  4:36 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-10-24  4:29 [PATCH] keys: use long workqueue for garbage collection Eduard Zateev
2026-10-24  4:36 ` sashiko-bot [this message]
2026-10-24  5:20 ` Jarkko Sakkinen
2026-10-24  5:37   ` Jarkko Sakkinen
2026-10-24  5:43     ` 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=sashiko-outbox-183546@kernel.org \
    --to=sashiko-bot@kernel.org \
    --cc=dhowells@redhat.com \
    --cc=hackerowskiy@gmail.com \
    --cc=jarkko@kernel.org \
    --cc=jmorris@namei.org \
    --cc=keyrings@vger.kernel.org \
    --cc=linux-security-module@vger.kernel.org \
    --cc=paul@paul-moore.com \
    --cc=sashiko-reviews@lists.linux.dev \
    --cc=serge@hallyn.com \
    --cc=syzbot+c15de43f1e7fffbb7b9b@syzkaller.appspotmail.com \
    --cc=syzkaller-bugs@googlegroups.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.