[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <09d6fa08e2d62720759f57237043a2dd9b5208ca.camel@huaweicloud.com>
Date: Thu, 15 Feb 2024 17:09:20 +0100
From: Roberto Sassu <roberto.sassu@...weicloud.com>
To: viro@...iv.linux.org.uk, brauner@...nel.org, jack@...e.cz,
chuck.lever@...cle.com, jlayton@...nel.org, neilb@...e.de,
kolga@...app.com, Dai.Ngo@...cle.com, tom@...pey.com, paul@...l-moore.com,
jmorris@...ei.org, serge@...lyn.com, zohar@...ux.ibm.com,
dmitry.kasatkin@...il.com, eric.snowberg@...cle.com, dhowells@...hat.com,
jarkko@...nel.org, stephen.smalley.work@...il.com, omosnace@...hat.com,
casey@...aufler-ca.com, shuah@...nel.org, mic@...ikod.net
Cc: linux-kernel@...r.kernel.org, linux-fsdevel@...r.kernel.org,
linux-nfs@...r.kernel.org, linux-security-module@...r.kernel.org,
linux-integrity@...r.kernel.org, keyrings@...r.kernel.org,
selinux@...r.kernel.org, linux-kselftest@...r.kernel.org, Roberto Sassu
<roberto.sassu@...wei.com>, Stefan Berger <stefanb@...ux.ibm.com>
Subject: Re: [PATCH v10 19/25] integrity: Move
integrity_kernel_module_request() to IMA
On Thu, 2024-02-15 at 11:31 +0100, Roberto Sassu wrote:
> From: Roberto Sassu <roberto.sassu@...wei.com>
>
> In preparation for removing the 'integrity' LSM, move
> integrity_kernel_module_request() to IMA, and rename it to
> ima_kernel_module_request(). Rewrite the function documentation, to explain
> better what the problem is.
>
> Compile it conditionally if CONFIG_INTEGRITY_ASYMMETRIC_KEYS is enabled,
> and call it from security.c (removed afterwards with the move of IMA to the
> LSM infrastructure).
>
> Adding this hook cannot be avoided, since IMA has no control on the flags
> passed to crypto_alloc_sig() in public_key_verify_signature(), and thus
> cannot pass CRYPTO_NOLOAD, which solved the problem for EVM hashing with
> commit e2861fa71641 ("evm: Don't deadlock if a crypto algorithm is
> unavailable").
>
> EVM alone does not need to implement this hook, first because there is no
> mutex to deadlock, and second because even if it had it, there should be a
> recursive call. However, since verification from EVM can be initiated only
> by setting inode metadata, deadlock would occur if modprobe would do the
> same while loading a kernel module (which is unlikely).
>
> Signed-off-by: Roberto Sassu <roberto.sassu@...wei.com>
> Acked-by: Paul Moore <paul@...l-moore.com>
> Reviewed-by: Stefan Berger <stefanb@...ux.ibm.com>
> Reviewed-by: Mimi Zohar <zohar@...ux.ibm.com>
> Acked-by: Mimi Zohar <zohar@...ux.ibm.com>
I hope the change of the ima_kernel_module_request() documentation is
fine for everyone.
If not, let me know.
Thanks
Roberto
> ---
> include/linux/ima.h | 10 ++++++++
> include/linux/integrity.h | 13 ----------
> security/integrity/digsig_asymmetric.c | 23 ------------------
> security/integrity/ima/ima_main.c | 33 ++++++++++++++++++++++++++
> security/security.c | 2 +-
> 5 files changed, 44 insertions(+), 37 deletions(-)
>
> diff --git a/include/linux/ima.h b/include/linux/ima.h
> index 31ef6c3c3207..0f9af283cbc8 100644
> --- a/include/linux/ima.h
> +++ b/include/linux/ima.h
> @@ -256,4 +256,14 @@ static inline bool ima_appraise_signature(enum kernel_read_file_id func)
> return false;
> }
> #endif /* CONFIG_IMA_APPRAISE && CONFIG_INTEGRITY_TRUSTED_KEYRING */
> +
> +#if defined(CONFIG_IMA) && defined(CONFIG_INTEGRITY_ASYMMETRIC_KEYS)
> +extern int ima_kernel_module_request(char *kmod_name);
> +#else
> +static inline int ima_kernel_module_request(char *kmod_name)
> +{
> + return 0;
> +}
> +
> +#endif
> #endif /* _LINUX_IMA_H */
> diff --git a/include/linux/integrity.h b/include/linux/integrity.h
> index 2ea0f2f65ab6..ef0f63ef5ebc 100644
> --- a/include/linux/integrity.h
> +++ b/include/linux/integrity.h
> @@ -42,17 +42,4 @@ static inline void integrity_load_keys(void)
> }
> #endif /* CONFIG_INTEGRITY */
>
> -#ifdef CONFIG_INTEGRITY_ASYMMETRIC_KEYS
> -
> -extern int integrity_kernel_module_request(char *kmod_name);
> -
> -#else
> -
> -static inline int integrity_kernel_module_request(char *kmod_name)
> -{
> - return 0;
> -}
> -
> -#endif /* CONFIG_INTEGRITY_ASYMMETRIC_KEYS */
> -
> #endif /* _LINUX_INTEGRITY_H */
> diff --git a/security/integrity/digsig_asymmetric.c b/security/integrity/digsig_asymmetric.c
> index 895f4b9ce8c6..de603cf42ac7 100644
> --- a/security/integrity/digsig_asymmetric.c
> +++ b/security/integrity/digsig_asymmetric.c
> @@ -132,26 +132,3 @@ int asymmetric_verify(struct key *keyring, const char *sig,
> pr_debug("%s() = %d\n", __func__, ret);
> return ret;
> }
> -
> -/**
> - * integrity_kernel_module_request - prevent crypto-pkcs1pad(rsa,*) requests
> - * @kmod_name: kernel module name
> - *
> - * We have situation, when public_key_verify_signature() in case of RSA
> - * algorithm use alg_name to store internal information in order to
> - * construct an algorithm on the fly, but crypto_larval_lookup() will try
> - * to use alg_name in order to load kernel module with same name.
> - * Since we don't have any real "crypto-pkcs1pad(rsa,*)" kernel modules,
> - * we are safe to fail such module request from crypto_larval_lookup().
> - *
> - * In this way we prevent modprobe execution during digsig verification
> - * and avoid possible deadlock if modprobe and/or it's dependencies
> - * also signed with digsig.
> - */
> -int integrity_kernel_module_request(char *kmod_name)
> -{
> - if (strncmp(kmod_name, "crypto-pkcs1pad(rsa,", 20) == 0)
> - return -EINVAL;
> -
> - return 0;
> -}
> diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c
> index 02021ee467d3..3891b83efdb3 100644
> --- a/security/integrity/ima/ima_main.c
> +++ b/security/integrity/ima/ima_main.c
> @@ -1091,6 +1091,39 @@ int ima_measure_critical_data(const char *event_label,
> }
> EXPORT_SYMBOL_GPL(ima_measure_critical_data);
>
> +#ifdef CONFIG_INTEGRITY_ASYMMETRIC_KEYS
> +
> +/**
> + * ima_kernel_module_request - Prevent crypto-pkcs1pad(rsa,*) requests
> + * @kmod_name: kernel module name
> + *
> + * Avoid a verification loop where verifying the signature of the modprobe
> + * binary requires executing modprobe itself. Since the modprobe iint->mutex
> + * is already held when the signature verification is performed, a deadlock
> + * occurs as soon as modprobe is executed within the critical region, since
> + * the same lock cannot be taken again.
> + *
> + * This happens when public_key_verify_signature(), in case of RSA algorithm,
> + * use alg_name to store internal information in order to construct an
> + * algorithm on the fly, but crypto_larval_lookup() will try to use alg_name
> + * in order to load a kernel module with same name.
> + *
> + * Since we don't have any real "crypto-pkcs1pad(rsa,*)" kernel modules,
> + * we are safe to fail such module request from crypto_larval_lookup(), and
> + * avoid the verification loop.
> + *
> + * Return: Zero if it is safe to load the kernel module, -EINVAL otherwise.
> + */
> +int ima_kernel_module_request(char *kmod_name)
> +{
> + if (strncmp(kmod_name, "crypto-pkcs1pad(rsa,", 20) == 0)
> + return -EINVAL;
> +
> + return 0;
> +}
> +
> +#endif /* CONFIG_INTEGRITY_ASYMMETRIC_KEYS */
> +
> static int __init init_ima(void)
> {
> int error;
> diff --git a/security/security.c b/security/security.c
> index f8d9ebeb4c31..48dc3db4c834 100644
> --- a/security/security.c
> +++ b/security/security.c
> @@ -3250,7 +3250,7 @@ int security_kernel_module_request(char *kmod_name)
> ret = call_int_hook(kernel_module_request, 0, kmod_name);
> if (ret)
> return ret;
> - return integrity_kernel_module_request(kmod_name);
> + return ima_kernel_module_request(kmod_name);
> }
>
> /**
Powered by blists - more mailing lists