Re: [PATCH] x86/ima: require signed kernel modules

From: Mimi Zohar
Date: Mon Feb 11 2019 - 11:19:29 EST


On Mon, 2019-02-11 at 16:56 +0100, Jessica Yu wrote:
> +++ Mimi Zohar [31/01/19 14:18 -0500]:
> >Require signed kernel modules on systems with secure boot mode enabled.
> >
> >To coordinate between appended kernel module signatures and IMA
> >signatures, only define an IMA MODULE_CHECK policy rule if
> >CONFIG_MODULE_SIG is not enabled.
> >
> >This patch defines a function named set_module_sig_required() and renames
> >is_module_sig_enforced() to is_module_sig_enforced_or_required(). The
> >call to set_module_sig_required() is dependent on CONFIG_IMA_ARCH_POLICY
> >being enabled.
> >
> >Signed-off-by: Mimi Zohar <zohar@xxxxxxxxxxxxx>
> >---
> > arch/x86/kernel/ima_arch.c | 9 ++++++++-
> > include/linux/module.h | 7 ++++++-
> > kernel/module.c | 15 +++++++++++----
> > security/integrity/ima/ima_main.c | 2 +-
> > 4 files changed, 26 insertions(+), 7 deletions(-)
> >
> >diff --git a/arch/x86/kernel/ima_arch.c b/arch/x86/kernel/ima_arch.c
> >index e47cd9390ab4..96a023238a83 100644
> >--- a/arch/x86/kernel/ima_arch.c
> >+++ b/arch/x86/kernel/ima_arch.c
> >@@ -64,12 +64,19 @@ static const char * const sb_arch_rules[] = {
> > "appraise func=KEXEC_KERNEL_CHECK appraise_type=imasig",
> > #endif /* CONFIG_KEXEC_VERIFY_SIG */
> > "measure func=KEXEC_KERNEL_CHECK",
> >+#if !IS_ENABLED(CONFIG_MODULE_SIG)
> >+ "appraise func=MODULE_CHECK appraise_type=imasig",
> >+#endif
> >+ "measure func=MODULE_CHECK",
> > NULL
> > };
> >
> > const char * const *arch_get_ima_policy(void)
> > {
> >- if (IS_ENABLED(CONFIG_IMA_ARCH_POLICY) && arch_ima_get_secureboot())
> >+ if (IS_ENABLED(CONFIG_IMA_ARCH_POLICY) && arch_ima_get_secureboot()) {
> >+ if (IS_ENABLED(CONFIG_MODULE_SIG))
> >+ set_module_sig_required();
> > return sb_arch_rules;
> >+ }
> > return NULL;
> > }
> >diff --git a/include/linux/module.h b/include/linux/module.h
> >index 8fa38d3e7538..af51c8ec755f 100644
> >--- a/include/linux/module.h
> >+++ b/include/linux/module.h
> >@@ -659,7 +659,8 @@ static inline bool is_livepatch_module(struct module *mod)
> > }
> > #endif /* CONFIG_LIVEPATCH */
> >
> >-bool is_module_sig_enforced(void);
> >+bool is_module_sig_enforced_or_required(void);
> >+void set_module_sig_required(void);
> >
> > #else /* !CONFIG_MODULES... */
> >
> >@@ -780,6 +781,10 @@ static inline bool is_module_sig_enforced(void)
> > return false;
> > }
> >
> >+static inline void set_module_sig_required(void)
> >+{
> >+}
> >+
> > /* Dereference module function descriptor */
> > static inline
> > void *dereference_module_function_descriptor(struct module *mod, void *ptr)
> >diff --git a/kernel/module.c b/kernel/module.c
> >index 2ad1b5239910..70a9709d19eb 100644
> >--- a/kernel/module.c
> >+++ b/kernel/module.c
> >@@ -275,16 +275,23 @@ static void module_assert_mutex_or_preempt(void)
> >
> > static bool sig_enforce = IS_ENABLED(CONFIG_MODULE_SIG_FORCE);
> > module_param(sig_enforce, bool_enable_only, 0644);
> >+static bool sig_required;
> >
> > /*
> > * Export sig_enforce kernel cmdline parameter to allow other subsystems rely
> > * on that instead of directly to CONFIG_MODULE_SIG_FORCE config.
> > */
> >-bool is_module_sig_enforced(void)
> >+bool is_module_sig_enforced_or_required(void)
> > {
> >- return sig_enforce;
> >+ return sig_enforce || sig_required;
> > }
>
> Hi Mimi,
>
> Just wondering, is there any particular reason why a distinction is
> made between sig_enforce and sig_required? Doesn't sig_enforce imply
> that signed modules are required? In other words, why introduce
> another variable instead of just using sig_enforce? It may be
> confusing in the case of a user looking at /sys/module/module/parameters/sig_enforce
> and it having a value of 0 yet module signatures are being required by ima.

Hi Jessica,

It would definitely be a lot better not having to differentiate
between the builtin CONFIG/module parm enforced and runtime enforced.
ÂFor some reason the "lockdown" patch doesn't directly modify
sig_enforce.

Mimi

>
> >-EXPORT_SYMBOL(is_module_sig_enforced);
> >+EXPORT_SYMBOL(is_module_sig_enforced_or_required);
> >+
> >+void set_module_sig_required(void)
> >+{
> >+ sig_required = true;
> >+}
> >+EXPORT_SYMBOL(set_module_sig_required);
> >
> > /* Block module loading/unloading? */
> > int modules_disabled = 0;
> >@@ -2789,7 +2796,7 @@ static int module_sig_check(struct load_info *info, int flags)
> > }
> >
> > /* Not having a signature is only an error if we're strict. */
> >- if (err == -ENOKEY && !is_module_sig_enforced())
> >+ if (err == -ENOKEY && !is_module_sig_enforced_or_required())
> > err = 0;
> >
> > return err;
> >diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c
> >index 357edd140c09..bbaf87f688be 100644
> >--- a/security/integrity/ima/ima_main.c
> >+++ b/security/integrity/ima/ima_main.c
> >@@ -563,7 +563,7 @@ int ima_load_data(enum kernel_load_data_id id)
> > }
> > break;
> > case LOADING_MODULE:
> >- sig_enforce = is_module_sig_enforced();
> >+ sig_enforce = is_module_sig_enforced_or_required();
> >
> > if (ima_enforce && (!sig_enforce
> > && (ima_appraise & IMA_APPRAISE_MODULES))) {
> >--
> >2.7.5
> >
>