]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
KEYS: fix overflow in keyctl_pkey_params_get_2()
authorJarkko Sakkinen <jarkko@kernel.org>
Mon, 1 Jun 2026 20:11:54 +0000 (23:11 +0300)
committerJarkko Sakkinen <jarkko@kernel.org>
Mon, 15 Jun 2026 12:19:12 +0000 (15:19 +0300)
The length for the internal output buffer is calculated incorrectly, which
can result overflow when a too small buffer is provided.

Fix the bug by allocating internal output with the size of the maximum
length of the cryptographic primitive instead of caller provided size.

Link: https://lore.kernel.org/keyrings/20260531024914.3712130-1-jarkko@kernel.org/
Cc: stable@vger.kernel.org # v4.20+
Fixes: 00d60fd3b932 ("KEYS: Provide keyctls to drive the new key type ops for asymmetric keys [ver #2]")
Reported-by: Alessandro Groppo <ale.grpp@gmail.com>
Tested-by: Alessandro Groppo <ale.grpp@gmail.com>
Signed-off-by: Jarkko Sakkinen <jarkko@kernel.org>
security/keys/keyctl_pkey.c

index 97bc27bbf079779f193d006ec89e4e2aad881fd1..ba150ee2d4a37d7cd7da85830f8fdc54ba2967cd 100644 (file)
@@ -138,28 +138,35 @@ static int keyctl_pkey_params_get_2(const struct keyctl_pkey_params __user *_par
                if (uparams.in_len  > info.max_dec_size ||
                    uparams.out_len > info.max_enc_size)
                        return -EINVAL;
+
+               params->out_len = info.max_enc_size;
                break;
        case KEYCTL_PKEY_DECRYPT:
                if (uparams.in_len  > info.max_enc_size ||
                    uparams.out_len > info.max_dec_size)
                        return -EINVAL;
+
+               params->out_len = info.max_dec_size;
                break;
        case KEYCTL_PKEY_SIGN:
                if (uparams.in_len  > info.max_data_size ||
                    uparams.out_len > info.max_sig_size)
                        return -EINVAL;
+
+               params->out_len = info.max_sig_size;
                break;
        case KEYCTL_PKEY_VERIFY:
                if (uparams.in_len  > info.max_data_size ||
                    uparams.in2_len > info.max_sig_size)
                        return -EINVAL;
+
+               params->out_len = info.max_sig_size;
                break;
        default:
                BUG();
        }
 
        params->in_len  = uparams.in_len;
-       params->out_len = uparams.out_len; /* Note: same as in2_len */
        return 0;
 }