diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2026-10-22 10:02:37 -1000 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2026-10-22 10:02:37 -1000 |
| commit | 14785eff402944f56466ef0058408334cfc2f91d (patch) | |
| tree | b61a8af6aa38f266bb7ee6a34de837a295a1853a /include/linux | |
| parent | 3815f7d55ae18564f4eac57557479f8b3548af95 (diff) | |
| parent | 722658cac48a6ba49f5506fd74d010ad9dbb2f05 (diff) | |
| download | linux-14785eff402944f56466ef0058408334cfc2f91d.tar.gz linux-14785eff402944f56466ef0058408334cfc2f91d.zip | |
Merge tag 'keys-v7.4-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/jarkko/linux-tpmdd
Pull keys updates from Jarkko Sakkinen:
"Highlight:
- Don't leak local kernel addresses (and complement the ongoing
rhashtable migration) (Kyle Zeng)
The index value for the associative array has been calculated with
the following formula:
mult_64x32_and_fold(description + type address + domain address)
By creating a sequence of dummy keys (e.g., "A", "B", "C", ...), it
is trivial to form a group of equations with a predictable hash
function, and ultimately break KASLR.
Kyle's solution is based on an ephemeral SipHash key and an atomic
64-bit counter, which is encapsulated to a key_index_id(). This
function is then used to assign identifiers for types and domains,
and since the IDs are unique for each power on, they are as unique
as memory addresses are.
With these ingredients the index value calculation can be changed
into form, which is not leaking any kernel addresses:
SipHash(description + type id + domain id)
Features and improvements:
- TPM fields were moved from trusted_key_options to the TPM backend.
They cost memory for non-TPM backends.
- A TPM trusted key now caches tpm_is_tpm2() at the root of each call
chain, and passes the result as a parameter. This decreases the
amount of I/O traffic given that tpm_is_tpm2() starts and stops the
chip via tpm_try_get_ops() and tpm_put_ops().
Bugfixes:
- A TPM trusted key corrupted the return value of a failed key
unsealing operation if the pcrlock feature was used.
- A TPM 2 trusted key allocated an off-by-four too large buffer for
the decoded ASN.1 blob coming from keyctl add trusted.
- Sometimes a TPM 2 trusted key rejected created keys based on the
TPM2_Create response size, treating them as too large. Now it
correctly checks the extracted TPM2 key blob size.
- The keyctl reject operation raced with keyctl restrict_keyring
because keyring->sem was not held in key_reject_and_link() before
accessing keyring->restrict_link.
- keyctl_describe_key() was not holding key->sem while accessing its
fields, which can lead to use-after-free of a retired key type.
- find_keyring_by_name() and procfs code were reading the UID from
key->user->uid instead of key->uid. The latter is the cached value
and is meant to protect against a use-after-free caused by keyctl
chown.
- search_process_keyrings_rcu() did not properly RCU-dereference the
authorization key payload, which could cause a null dereference if
the payload was revoked.
- keyctl_read_key() checked key->type->read without holding key->sem,
which can lead to use-after-free if the type is retired. Based on
my suggestion, this was addressed in __keyctl_read_key(), which
already did take key->sem"
* tag 'keys-v7.4-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/jarkko/linux-tpmdd:
keys/trusted_keys: reuse TPM version in option handling
security: keys: Fix comment of search_process_keyrings_rcu()
keys/trusted/tpm2: Validate TPM2_Create object sizes separately
keys/trusted_keys: move TPM-specific fields into struct trusted_key_tpm
keys: Protect the read method check against type removal
keys: Avoid owner account dereferences in /proc/keys
keys: make keyring indexes independent of kernel addresses
keys: Check the authorization payload in process keyring searches
keys: Avoid the owner account dereference in named keyring lookup
keys: Protect the type name while describing a key
KEYS: Fix key_reject_and_link() race with keyring restriction
KEYS: trusted: Fix blob allocation size in tpm2_key_decode()
keys/trusted_keys: return immediately after TPM unseal failure
Diffstat (limited to 'include/linux')
| -rw-r--r-- | include/linux/key-type.h | 1 | ||||
| -rw-r--r-- | include/linux/key.h | 5 |
2 files changed, 6 insertions, 0 deletions
diff --git a/include/linux/key-type.h b/include/linux/key-type.h index bb97bd3e5af4..c4f329b6ae3f 100644 --- a/include/linux/key-type.h +++ b/include/linux/key-type.h @@ -161,6 +161,7 @@ struct key_type { const void *in, const void *in2); /* internal fields */ + atomic64_t index_id; /* Opaque keyring index ID */ struct list_head link; /* link in types list */ struct lock_class_key lock_class; /* key->sem lock class */ } __randomize_layout; diff --git a/include/linux/key.h b/include/linux/key.h index 81b8f05c6898..e40b5267658f 100644 --- a/include/linux/key.h +++ b/include/linux/key.h @@ -107,6 +107,7 @@ struct keyring_name; struct key_tag { struct rcu_head rcu; + atomic64_t index_id; /* Opaque keyring index ID */ refcount_t usage; bool removed; /* T when subject removed */ }; @@ -129,6 +130,8 @@ struct keyring_index_key { struct key_type *type; struct key_tag *domain_tag; /* Domain of operation */ const char *description; + u64 type_id; /* Cached index IDs */ + u64 domain_id; }; union key_payload { @@ -251,6 +254,8 @@ struct key { struct key_type *type; /* type of key */ struct key_tag *domain_tag; /* Domain of operation */ char *description; + u64 type_id; + u64 domain_id; }; }; |
