[RFC PATCH 3/8] KEYS: Reject @desclen values over U16_MAX in key_alloc()

sashiko-bot at kernel.org sashiko-bot at kernel.org
Mon Oct 19 15:49:26 UTC 2026


Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [High] KEYS: desc_len truncation in __key_create_or_update() before key_alloc()
--

commit e49d7d031ada6f60dccb5c6e74d1e66145a0c3d4
Author: Jarkko Sakkinen <jarkko at kernel.org>

KEYS: Reject @desclen values over U16_MAX in key_alloc()

This commit adds a bounds check in key_alloc() to reject key descriptions
longer than U16_MAX with -EINVAL, preventing truncation when storing the
length in the 16-bit desc_len field of struct keyring_index_key.

> diff --git a/security/keys/key.c b/security/keys/key.c
> index b34a64d81d47a..a0f083339da8d 100644
> --- a/security/keys/key.c
> +++ b/security/keys/key.c
> @@ -245,6 +245,8 @@ struct key *key_alloc(struct key_type *type, const char *desc,
>  	}
>  
>  	desclen = strlen(desc);
> +	if (desclen > U16_MAX)
> +		goto error;
>  	quotalen = desclen + 1 + type->def_datalen;
>  
>  	/* get hold of the key tracking for this user */

[Severity: High]
Does __key_create_or_update() also need to validate the description length
before assigning index_key.desc_len?

In security/keys/key.c, __key_create_or_update() assigns strlen() to the
16-bit index_key.desc_len field and passes it into __key_link_begin() and
find_key_to_update() before key_alloc() is called:

security/keys/key.c:__key_create_or_update() {
	...
	index_key.desc_len = strlen(index_key.description);
	key_set_index_key(&index_key);

	ret = __key_link_lock(keyring, &index_key);
	if (ret < 0) {
		key_ref = ERR_PTR(ret);
		goto error_free_prep;
	}

	ret = __key_link_begin(keyring, &index_key, &edit);
	if (ret < 0) {
		key_ref = ERR_PTR(ret);
		goto error_link_end;
	}

	...
	if (allow_update) {
		if (index_key.type->update) {
			key_ref = find_key_to_update(keyring, &index_key);
			if (key_ref)
				goto found_matching_key;
		}
	}

	key = key_alloc(index_key.type, index_key.description,
			cred->fsuid, cred->fsgid, cred, perm, flags, NULL);
}

Although add_key() limits user-supplied _description strings to
KEY_MAX_DESC_SIZE, _description can be NULL when index_key.type->preparse
generates prep.description from the payload. For example, in
crypto/asymmetric_keys/x509_public_key.c, x509_key_preparse() constructs
prep->description from the X.509 certificate subject and hex-encoded
serial or skid:

	desc = kmalloc(sulen + 2 + srlen * 2 + 1, GFP_KERNEL);
	if (!desc)
		return -ENOMEM;
	p = memcpy(desc, cert->subject, sulen);
	p += sulen;
	*p++ = ':';
	*p++ = ' ';
	p = bin2hex(p, q, srlen);
	*p = 0;

Since the payload can be up to almost 1MB, strlen(index_key.description)
can exceed U16_MAX.

If strlen(index_key.description) is a multiple of 65536 (or 0),
index_key.desc_len truncates to 0 and triggers BUG_ON(index_key->desc_len == 0)
in __key_link_begin() in security/keys/keyring.c before key_alloc() is
reached.

If strlen(index_key.description) > U16_MAX is not a multiple of 65536,
index_key.desc_len truncates to strlen % 65536. Because
keyring_compare_object() in security/keys/keyring.c only compares
index_key->desc_len bytes:

	return key->index_key.type == index_key->type &&
		key->index_key.domain_tag == index_key->domain_tag &&
		key->index_key.desc_len == index_key->desc_len &&
		memcmp(key->index_key.description, index_key->description,
		       index_key->desc_len) == 0;

find_key_to_update() can match an existing key with a shorter description
sharing that prefix and update the wrong key via goto found_matching_key,
bypassing key_alloc() altogether (or fail with -EEXIST instead of -EINVAL).

In addition, keyring_search() in security/keys/keyring.c, as well as
request_key_and_link() and request_key_rcu() in security/keys/request_key.c,
also assign strlen(description) directly to .index_key.desc_len without
bounds checking.

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20261019142516.300040-1-jarkko@kernel.org?part=3



More information about the Linux-security-module-archive mailing list