[PATCH v2] KEYS: Fix key_reject_and_link() race with keyring restriction

From: adrimg3196

Date: Thu Oct 08 2026 - 14:22:18 EST


Jarkko, you're right — v1 arrived without the diff. Here's v2 with the
full patch.

The restrict_link check in key_reject_and_link() is done before taking
the keyring semaphore, racing with a concurrent keyring_restrict()
that installs the restriction while holding the semaphore in write
mode.

This is the same pattern that commit dd3ea3fc ("KEYS: Fix add_key()
race with keyring restriction") just fixed in __key_create_or_update()
by moving the restrict_link snapshot to after the semaphore is taken.

Move the check under __key_link_lock() so a restriction installed
concurrently cannot be bypassed when linking a negative key.

Signed-off-by: Adrian Martinez <adrimg3196@xxxxxxxxx>
---
security/keys/key.c | 17 +++++++++++------
1 file changed, 11 insertions(+), 6 deletions(-)

--- a/security/keys/key.c
+++ b/security/keys/key.c
@@ -588,10 +588,17 @@ int key_reject_and_link(struct key *key,
ret = -EBUSY;

if (keyring) {
- if (keyring->restrict_link)
- return -EPERM;
-
link_ret = __key_link_lock(keyring, &key->index_key);
if (link_ret == 0) {
+ /*
+ * Check the restriction under the keyring semaphore.
+ * keyring_restrict() installs it while holding the
+ * semaphore, so testing it beforehand races with a
+ * concurrent restriction install (cf. the fix for
+ * __key_create_or_update()).
+ */
+ if (keyring->restrict_link) {
+ __key_link_end(keyring, &key->index_key, edit);
+ return -EPERM;
+ }
link_ret = __key_link_begin(keyring, &key->index_key, &edit);
if (link_ret < 0)
__key_link_end(keyring, &key->index_key, edit);