diff mbox

[03/27] Enforce module signatures if the kernel is locked down

Message ID 20240.1509643356@warthog.procyon.org.uk (mailing list archive)
State New, archived
Headers show

Commit Message

David Howells Nov. 2, 2017, 5:22 p.m. UTC
Hi Mimi,

I've altered this patch to allow for IMA appraisal on finit_module().  See the
attached.

David
---
commit c0d5336356004e7543314e388755a00e725521da
Author: David Howells <dhowells@redhat.com>
Date:   Wed May 24 14:56:01 2017 +0100

    Enforce module signatures if the kernel is locked down
    
    If the kernel is locked down, require that all modules have valid
    signatures that we can verify or that IMA can validate the file.
    
    Signed-off-by: David Howells <dhowells@redhat.com>
    Reviewed-by: "Lee, Chun-Yi" <jlee@suse.com>
    Reviewed-by: James Morris <james.l.morris@oracle.com>

--
To unsubscribe from this list: send the line "unsubscribe linux-security-module" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Comments

Mimi Zohar Nov. 2, 2017, 7:13 p.m. UTC | #1
On Thu, 2017-11-02 at 17:22 +0000, David Howells wrote:

>  #ifdef CONFIG_MODULE_SIG
> -static int module_sig_check(struct load_info *info, int flags)
> +static int module_sig_check(struct load_info *info, int flags,
> +			    bool can_do_ima_check)
>  {
>  	int err = -ENOKEY;
>  	const unsigned long markerlen = sizeof(MODULE_SIG_STRING) - 1;
> @@ -2781,13 +2783,16 @@ 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 && !sig_enforce)
> +	if (err == -ENOKEY && !sig_enforce &&
> +	    (!can_do_ima_check || !is_ima_appraise_enabled()) &&
> +	    !kernel_is_locked_down("Loading of unsigned modules"))

By this point, IMA-appraisal has already verified the kernel module
signature back in kernel_read_file_from_fd(), if it was required.
 Having a key with which to verify the appended signature or requiring
an appended signature, should not be required as well.

Mimi

--
To unsubscribe from this list: send the line "unsubscribe linux-security-module" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
David Howells Nov. 2, 2017, 9:30 p.m. UTC | #2
Mimi Zohar <zohar@linux.vnet.ibm.com> wrote:

> By this point, IMA-appraisal has already verified the kernel module
> signature back in kernel_read_file_from_fd(), if it was required.
>  Having a key with which to verify the appended signature or requiring
> an appended signature, should not be required as well.

I guess I don't need to put in any support for IMA here, then, and you've
taken care of it in your patchset such that it won't actually go into
module_sig_check() in that case (or will at least return immediately).

David
--
To unsubscribe from this list: send the line "unsubscribe linux-security-module" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Mimi Zohar Nov. 2, 2017, 9:41 p.m. UTC | #3
On Thu, 2017-11-02 at 21:30 +0000, David Howells wrote:
> Mimi Zohar <zohar@linux.vnet.ibm.com> wrote:
> 
> > By this point, IMA-appraisal has already verified the kernel module
> > signature back in kernel_read_file_from_fd(), if it was required.
> >  Having a key with which to verify the appended signature or requiring
> > an appended signature, should not be required as well.
> 
> I guess I don't need to put in any support for IMA here, then, and you've
> taken care of it in your patchset such that it won't actually go into
> module_sig_check() in that case (or will at least return immediately).

Right, it would never get here if the IMA signature verification
fails.  If sig_enforce is not enabled, then it will also work.  So the
only case is if sig_enforced is enabled and there is no key.

eg.
         else if (can_do_ima_check && is_ima_appraise_enabled())
                err = 0;

Mimi 

--
To unsubscribe from this list: send the line "unsubscribe linux-security-module" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
David Howells Nov. 2, 2017, 10:01 p.m. UTC | #4
Mimi Zohar <zohar@linux.vnet.ibm.com> wrote:

> Right, it would never get here if the IMA signature verification
> fails.  If sig_enforce is not enabled, then it will also work.  So the
> only case is if sig_enforced is enabled and there is no key.
> 
> eg.
>          else if (can_do_ima_check && is_ima_appraise_enabled())
>                 err = 0;

I'm not sure where you want to put that, but I can't just do this:

	/* Not having a signature is only an error if we're strict. */
	if (err == -ENOKEY && !sig_enforce &&
	    (!can_do_ima_check || !is_ima_appraise_enabled()) &&
	    !kernel_is_locked_down("Loading of unsigned modules"))
		err = 0;
	else if (can_do_ima_check && is_ima_appraise_enabled())
		err = 0;

because that'll print out a message in lockdown mode saying that you're not
allowed to do that and then maybe do it anyway.

David
--
To unsubscribe from this list: send the line "unsubscribe linux-security-module" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Mimi Zohar Nov. 2, 2017, 10:18 p.m. UTC | #5
On Thu, 2017-11-02 at 22:01 +0000, David Howells wrote:
> Mimi Zohar <zohar@linux.vnet.ibm.com> wrote:
> 
> > Right, it would never get here if the IMA signature verification
> > fails.  If sig_enforce is not enabled, then it will also work.  So the
> > only case is if sig_enforced is enabled and there is no key.
> > 
> > eg.
> >          else if (can_do_ima_check && is_ima_appraise_enabled())
> >                 err = 0;
> 
> I'm not sure where you want to put that, but I can't just do this:
> 
> 	/* Not having a signature is only an error if we're strict. */
> 	if (err == -ENOKEY && !sig_enforce &&
> 	    (!can_do_ima_check || !is_ima_appraise_enabled()) &&

The above IMA checks aren't needed here.

> 	    !kernel_is_locked_down("Loading of unsigned modules"))
> 		err = 0;
> 	else if (can_do_ima_check && is_ima_appraise_enabled())
> 		err = 0;
> 
> because that'll print out a message in lockdown mode saying that you're not
> allowed to do that and then maybe do it anyway.

Then at least for now, document that even though kernel modules might
be signed and verified by IMA-appraisal, that in lockdown mode they
also require an appended signature.

Mimi

--
To unsubscribe from this list: send the line "unsubscribe linux-security-module" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

diff --git a/kernel/module.c b/kernel/module.c
index de66ec825992..0ce29c8aa75a 100644
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -64,6 +64,7 @@ 
 #include <linux/bsearch.h>
 #include <linux/dynamic_debug.h>
 #include <linux/audit.h>
+#include <linux/ima.h>
 #include <uapi/linux/module.h>
 #include "module-internal.h"
 
@@ -2757,7 +2758,8 @@  static inline void kmemleak_load_module(const struct module *mod,
 #endif
 
 #ifdef CONFIG_MODULE_SIG
-static int module_sig_check(struct load_info *info, int flags)
+static int module_sig_check(struct load_info *info, int flags,
+			    bool can_do_ima_check)
 {
 	int err = -ENOKEY;
 	const unsigned long markerlen = sizeof(MODULE_SIG_STRING) - 1;
@@ -2781,13 +2783,16 @@  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 && !sig_enforce)
+	if (err == -ENOKEY && !sig_enforce &&
+	    (!can_do_ima_check || !is_ima_appraise_enabled()) &&
+	    !kernel_is_locked_down("Loading of unsigned modules"))
 		err = 0;
 
 	return err;
 }
 #else /* !CONFIG_MODULE_SIG */
-static int module_sig_check(struct load_info *info, int flags)
+static int module_sig_check(struct load_info *info, int flags,
+			    bool can_do_ima_check)
 {
 	return 0;
 }
@@ -3630,13 +3635,13 @@  static int unknown_module_param_cb(char *param, char *val, const char *modname,
 /* Allocate and load the module: note that size of section 0 is always
    zero, and we rely on this for optional sections. */
 static int load_module(struct load_info *info, const char __user *uargs,
-		       int flags)
+		       int flags, bool can_do_ima_check)
 {
 	struct module *mod;
 	long err;
 	char *after_dashes;
 
-	err = module_sig_check(info, flags);
+	err = module_sig_check(info, flags, can_do_ima_check);
 	if (err)
 		goto free_copy;
 
@@ -3830,7 +3835,7 @@  SYSCALL_DEFINE3(init_module, void __user *, umod,
 	if (err)
 		return err;
 
-	return load_module(&info, uargs, 0);
+	return load_module(&info, uargs, 0, false);
 }
 
 SYSCALL_DEFINE3(finit_module, int, fd, const char __user *, uargs, int, flags)
@@ -3857,7 +3862,7 @@  SYSCALL_DEFINE3(finit_module, int, fd, const char __user *, uargs, int, flags)
 	info.hdr = hdr;
 	info.len = size;
 
-	return load_module(&info, uargs, flags);
+	return load_module(&info, uargs, flags, true);
 }
 
 static inline int within(unsigned long addr, void *start, unsigned long size)