mirror of
https://github.com/freebsd/freebsd-src.git
synced 2026-10-28 11:25:21 +01:00
zio_crypt: free the key unwrap uios when decryption fails
zio_crypt_key_unwrap() allocates a pair of iovec buffers through zio_crypt_uios_init_os() and releases them with zio_crypt_uios_fini_os() once the keys have been decrypted. When zio_decrypt_os() fails it jumps straight to the error label, which skips that release, so both buffers are leaked. The failure is reachable from userland: any key unwrap that does not authenticate leaks 64 bytes twice, so a loop of "zfs load-key" calls with the wrong passphrase grows kernel memory without bound. It is not Linux specific -- the FreeBSD implementation allocates these buffers as well. Release the uios as soon as the crypto operation returns and check the result afterwards, matching zio_crypt_key_wrap(), which already frees them unconditionally on both paths. The buffers are then released exactly once, and the error label continues to own nothing. Verified with kmemleak on Linux: 200 failed unwraps reported 204 leaked objects from zio_crypt_uios_init_os() before this change and none after, against one object on a control run that performed no unwraps. Reviewed-by: Rob Norris <[email protected]> Reviewed-by: Brian Behlendorf <[email protected]> Signed-off-by: Alexander Moch <[email protected]> Closes #19116
This commit is contained in:
1 parent
5b6906a5f5
commit
b6dde8a170
1 file changed
+3
-2
@@ -440,11 +440,12 @@ zio_crypt_key_unwrap(crypto_key_t *cwkey, uint64_t crypt, uint64_t version,
|
||||
ret = zio_decrypt_os(ci, cwkey, NULL,
|
||||
&cuio, &puio, ci->ci_keylen + SHA512_HMAC_KEYLEN,
|
||||
iv, (uint8_t *)aad, aad_len, mac);
|
||||
if (ret != 0)
|
||||
goto error;
|
||||
|
||||
zio_crypt_uios_fini_os(&cuio, &puio);
|
||||
|
||||
if (ret != 0)
|
||||
goto error;
|
||||
|
||||
/* generate a fresh salt */
|
||||
ret = random_get_bytes(key->zk_salt, ZIO_DATA_SALT_LEN);
|
||||
if (ret != 0)
|
||||
|
||||
Reference in new issue
Block a user