mirror of
https://github.com/torvalds/linux.git
synced 2026-07-29 10:41:49 +02:00
keys: fix out-of-bounds read in keyring_get_key_chunk()
For description-level chunks keyring_get_key_chunk() advances the read
pointer by level * sizeof(long) past the inline prefix but only
bounds-checks the prefix, so a long enough key description is read past
its kmemdup(desc, desc_len + 1) allocation. Compute the full byte
offset and bounds-check the description against it before reading.
The walk only reaches a description-level chunk when two keys collide
through the hash, x, type and domain_tag chunks, so this is reached from
an unprivileged add_key(2) with a crafted pair of same-type keys whose
index hashes collide; KASAN reports a slab-out-of-bounds read.
Fixes: f771fde820 ("keys: Simplify key description management")
Assisted-by: Claude:claude-opus-4-8
Signed-off-by: Michael Bommarito <michael.bommarito@gmail.com>
Reviewed-by: Jarkko Sakkinen <jarkko@kernel.org>
Tested-by: Jarkko Sakkinen <jarkko@kernel.org>
Link: https://lore.kernel.org/r/20260719161505.2423935-2-michael.bommarito@gmail.com
Signed-off-by: Jarkko Sakkinen <jarkko@kernel.org>
This commit is contained in:
parent
35d661c98f
commit
63918731f9
|
|
@ -271,6 +271,7 @@ static unsigned long keyring_get_key_chunk(const void *data, int level)
|
|||
unsigned long chunk = 0;
|
||||
const u8 *d;
|
||||
int desc_len = index_key->desc_len, n = sizeof(chunk);
|
||||
unsigned int offset;
|
||||
|
||||
level /= ASSOC_ARRAY_KEY_CHUNK_SIZE;
|
||||
switch (level) {
|
||||
|
|
@ -284,12 +285,12 @@ static unsigned long keyring_get_key_chunk(const void *data, int level)
|
|||
return (unsigned long)index_key->domain_tag;
|
||||
default:
|
||||
level -= 4;
|
||||
if (desc_len <= sizeof(index_key->desc))
|
||||
offset = sizeof(index_key->desc) + level * sizeof(long);
|
||||
if (desc_len <= offset)
|
||||
return 0;
|
||||
|
||||
d = index_key->description + sizeof(index_key->desc);
|
||||
d += level * sizeof(long);
|
||||
desc_len -= sizeof(index_key->desc);
|
||||
d = index_key->description + offset;
|
||||
desc_len -= offset;
|
||||
if (desc_len > n)
|
||||
desc_len = n;
|
||||
do {
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user