[PATCH v10 19/25] integrity: Move integrity_kernel_module_request() to IMA

Roberto Sassu roberto.sassu at huaweicloud.com
Thu Feb 15 16:09:20 UTC 2024


On Thu, 2024-02-15 at 11:31 +0100, Roberto Sassu wrote:
> From: Roberto Sassu <roberto.sassu at huawei.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 at huawei.com>
> Acked-by: Paul Moore <paul at paul-moore.com>
> Reviewed-by: Stefan Berger <stefanb at linux.ibm.com>
> Reviewed-by: Mimi Zohar <zohar at linux.ibm.com>
> Acked-by: Mimi Zohar <zohar at linux.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);
>  }
>  
>  /**




More information about the Linux-security-module-archive mailing list