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