CVE-2022-49899
Severity CVSS v4.0:
Pending analysis
Type:
Unavailable / Other
Publication date:
01/05/2025
Last modified:
07/05/2025
Description
In the Linux kernel, the following vulnerability has been resolved:<br />
<br />
fscrypt: stop using keyrings subsystem for fscrypt_master_key<br />
<br />
The approach of fs/crypto/ internally managing the fscrypt_master_key<br />
structs as the payloads of "struct key" objects contained in a<br />
"struct key" keyring has outlived its usefulness. The original idea was<br />
to simplify the code by reusing code from the keyrings subsystem.<br />
However, several issues have arisen that can&#39;t easily be resolved:<br />
<br />
- When a master key struct is destroyed, blk_crypto_evict_key() must be<br />
called on any per-mode keys embedded in it. (This started being the<br />
case when inline encryption support was added.) Yet, the keyrings<br />
subsystem can arbitrarily delay the destruction of keys, even past the<br />
time the filesystem was unmounted. Therefore, currently there is no<br />
easy way to call blk_crypto_evict_key() when a master key is<br />
destroyed. Currently, this is worked around by holding an extra<br />
reference to the filesystem&#39;s request_queue(s). But it was overlooked<br />
that the request_queue reference is *not* guaranteed to pin the<br />
corresponding blk_crypto_profile too; for device-mapper devices that<br />
support inline crypto, it doesn&#39;t. This can cause a use-after-free.<br />
<br />
- When the last inode that was using an incompletely-removed master key<br />
is evicted, the master key removal is completed by removing the key<br />
struct from the keyring. Currently this is done via key_invalidate().<br />
Yet, key_invalidate() takes the key semaphore. This can deadlock when<br />
called from the shrinker, since in fscrypt_ioctl_add_key(), memory is<br />
allocated with GFP_KERNEL under the same semaphore.<br />
<br />
- More generally, the fact that the keyrings subsystem can arbitrarily<br />
delay the destruction of keys (via garbage collection delay, or via<br />
random processes getting temporary key references) is undesirable, as<br />
it means we can&#39;t strictly guarantee that all secrets are ever wiped.<br />
<br />
- Doing the master key lookups via the keyrings subsystem results in the<br />
key_permission LSM hook being called. fscrypt doesn&#39;t want this, as<br />
all access control for encrypted files is designed to happen via the<br />
files themselves, like any other files. The workaround which SELinux<br />
users are using is to change their SELinux policy to grant key search<br />
access to all domains. This works, but it is an odd extra step that<br />
shouldn&#39;t really have to be done.<br />
<br />
The fix for all these issues is to change the implementation to what I<br />
should have done originally: don&#39;t use the keyrings subsystem to keep<br />
track of the filesystem&#39;s fscrypt_master_key structs. Instead, just<br />
store them in a regular kernel data structure, and rework the reference<br />
counting, locking, and lifetime accordingly. Retain support for<br />
RCU-mode key lookups by using a hash table. Replace fscrypt_sb_free()<br />
with fscrypt_sb_delete(), which releases the keys synchronously and runs<br />
a bit earlier during unmount, so that block devices are still available.<br />
<br />
A side effect of this patch is that neither the master keys themselves<br />
nor the filesystem keyrings will be listed in /proc/keys anymore.<br />
("Master key users" and the master key users keyrings will still be<br />
listed.) However, this was mostly an implementation detail, and it was<br />
intended just for debugging purposes. I don&#39;t know of anyone using it.<br />
<br />
This patch does *not* change how "master key users" (->mk_users) works;<br />
that still uses the keyrings subsystem. That is still needed for key<br />
quotas, and changing that isn&#39;t necessary to solve the issues listed<br />
above. If we decide to change that too, it would be a separate patch.<br />
<br />
I&#39;ve marked this as fixing the original commit that added the fscrypt<br />
keyring, but as noted above the most important issue that this patch<br />
fixes wasn&#39;t introduced until the addition of inline encryption support.
Impact
Base Score 3.x
5.50
Severity 3.x
MEDIUM
Vulnerable products and versions
CPE | From | Up to |
---|---|---|
cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:* | 5.4 (including) | 5.10.154 (excluding) |
cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:* | 5.11 (including) | 5.15.78 (excluding) |
cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:* | 5.16 (including) | 6.0.8 (excluding) |
To consult the complete list of CPE names with products and versions, see this page