]> www.infradead.org Git - users/dwmw2/linux.git/commitdiff
KEYS: trusted: dcp: fix improper sg use with CONFIG_VMAP_STACK=y
authorDavid Gstir <david@sigma-star.at>
Wed, 13 Nov 2024 21:27:54 +0000 (22:27 +0100)
committerJarkko Sakkinen <jarkko@kernel.org>
Tue, 21 Jan 2025 09:25:23 +0000 (11:25 +0200)
With vmalloc stack addresses enabled (CONFIG_VMAP_STACK=y) DCP trusted
keys can crash during en- and decryption of the blob encryption key via
the DCP crypto driver. This is caused by improperly using sg_init_one()
with vmalloc'd stack buffers (plain_key_blob).

Fix this by always using kmalloc() for buffers we give to the DCP crypto
driver.

Cc: stable@vger.kernel.org # v6.10+
Fixes: 0e28bf61a5f9 ("KEYS: trusted: dcp: fix leak of blob encryption key")
Signed-off-by: David Gstir <david@sigma-star.at>
Reviewed-by: Jarkko Sakkinen <jarkko@kernel.org>
Signed-off-by: Jarkko Sakkinen <jarkko@kernel.org>
security/keys/trusted-keys/trusted_dcp.c

index e908c53a803c4b39d55aed81e7fa43dd6533691d..7b6eb655df0cbf62ed3fdd4e6d054f249f674722 100644 (file)
@@ -201,12 +201,16 @@ static int trusted_dcp_seal(struct trusted_key_payload *p, char *datablob)
 {
        struct dcp_blob_fmt *b = (struct dcp_blob_fmt *)p->blob;
        int blen, ret;
-       u8 plain_blob_key[AES_KEYSIZE_128];
+       u8 *plain_blob_key;
 
        blen = calc_blob_len(p->key_len);
        if (blen > MAX_BLOB_SIZE)
                return -E2BIG;
 
+       plain_blob_key = kmalloc(AES_KEYSIZE_128, GFP_KERNEL);
+       if (!plain_blob_key)
+               return -ENOMEM;
+
        b->fmt_version = DCP_BLOB_VERSION;
        get_random_bytes(b->nonce, AES_KEYSIZE_128);
        get_random_bytes(plain_blob_key, AES_KEYSIZE_128);
@@ -229,7 +233,8 @@ static int trusted_dcp_seal(struct trusted_key_payload *p, char *datablob)
        ret = 0;
 
 out:
-       memzero_explicit(plain_blob_key, sizeof(plain_blob_key));
+       memzero_explicit(plain_blob_key, AES_KEYSIZE_128);
+       kfree(plain_blob_key);
 
        return ret;
 }
@@ -238,7 +243,7 @@ static int trusted_dcp_unseal(struct trusted_key_payload *p, char *datablob)
 {
        struct dcp_blob_fmt *b = (struct dcp_blob_fmt *)p->blob;
        int blen, ret;
-       u8 plain_blob_key[AES_KEYSIZE_128];
+       u8 *plain_blob_key = NULL;
 
        if (b->fmt_version != DCP_BLOB_VERSION) {
                pr_err("DCP blob has bad version: %i, expected %i\n",
@@ -256,6 +261,12 @@ static int trusted_dcp_unseal(struct trusted_key_payload *p, char *datablob)
                goto out;
        }
 
+       plain_blob_key = kmalloc(AES_KEYSIZE_128, GFP_KERNEL);
+       if (!plain_blob_key) {
+               ret = -ENOMEM;
+               goto out;
+       }
+
        ret = decrypt_blob_key(b->blob_key, plain_blob_key);
        if (ret) {
                pr_err("Unable to decrypt blob key: %i\n", ret);
@@ -271,7 +282,10 @@ static int trusted_dcp_unseal(struct trusted_key_payload *p, char *datablob)
 
        ret = 0;
 out:
-       memzero_explicit(plain_blob_key, sizeof(plain_blob_key));
+       if (plain_blob_key) {
+               memzero_explicit(plain_blob_key, AES_KEYSIZE_128);
+               kfree(plain_blob_key);
+       }
 
        return ret;
 }