Linux Modules
 help / color / mirror / Atom feed
From: "Alessandro Carminati (Red Hat)" <alessandro.carminati@gmail.com>
To: linux-modules@vger.kernel.org
Cc: linux-kernel@vger.kernel.org,
	Luis Chamberlain <mcgrof@kernel.org>,
	Jonathan Corbet <corbet@lwn.net>,
	linux-doc@vger.kernel.org,
	Alessandro Carminati <alessandro.carminati@gmail.com>
Subject: [RFC PATCH 1/2] Modules: Introduce boot-time module signature flexibility
Date: Thu, 14 Sep 2023 11:27:38 +0000	[thread overview]
Message-ID: <20230914112739.112729-2-alessandro.carminati@gmail.com> (raw)
In-Reply-To: <20230914112739.112729-1-alessandro.carminati@gmail.com>

This commit introduces a novel boot argument parameter that provides an
advanced level of control over the verification of module signatures
during the initial stages of booting. With this enhancement, we gain the
capability to postpone the verification of module signatures to after
intrd stage is finished.

Given that bootloader-provided artifacts are commonly employed
post-verification, we can effectively capitalize on this verification
process and exempt the verification of modules within the initrd.
This strategic adjustment reduces the time needed in this stage to load
modules by temporarily enabling unsigned modules.
Before terminating the stage modules signature check can be re-enabled
keeping the system security level.

To activate this functionality, a fresh boot argument parameter has
been incorporated to disable verification during early boot.
Furthermore, a supplementary method is necessary to reactivate
verification subsequently.

This is executed by leveraging a switch within a /proc file, inspired
by the foundational principles of the Lockdown LSM levels. While this
mechanism permits the activation of the functionaliity, and it ensures
that the switch remains unalterable once engaged.

example usage:
```
$ qemu-system-aarch64 -M virt -cpu cortex-a53 -machine gic-version=3 \
               -m 512 -nographic -smp 2 -kernel arch/arm64/boot/Image \
               -initrd aarch64br.initrd \
               -append "rootwait init=/sbin/init module_sig_check_wait=1"

[    0.000000] Booting Linux on physical CPU 0x0000000000 [0x410fd034]
[...]
[    0.689441] Freeing unused kernel memory: 8576K
[    0.690536] Run /init as init process
Starting syslogd: OK
Starting klogd: OK
Running sysctl: OK
Saving 256 bits of non-creditable seed for next boot
Starting network: OK

Welcome to Buildroot
buildroot login: root
~ # cat /sys/module/module/parameters/sig_enforce
Y
~ # mount -t securityfs none  /sys/kernel/security
~ # cat /sys/kernel/security/module_sig_check_wait
1
~ # insmod usbserial.ko
~ # lsmod
Module                  Size  Used by    Not tainted
usbserial              36864  0
~ # rmmod usbserial
~ # echo 0 >/sys/kernel/security/module_sig_check_wait
[  226.114569] module_sig_check_wait disabled!
~ # insmod usbserial.ko
[  230.646980] Loading of unsigned module is rejected
[  230.648608] Loading of unsigned module is rejected
insmod: can't insert 'usbserial.ko': Key was rejected by service
~ # echo 1 > /sys/kernel/security/module_sig_check_wait
[  248.036518] module_sig_check_wait can be only disabled!
~ #
```

Signed-off-by: Alessandro Carminati (Red Hat) <alessandro.carminati@gmail.com>
---
 include/linux/module.h  |  4 +++
 kernel/module/main.c    | 14 ++++++-----
 kernel/module/signing.c | 56 +++++++++++++++++++++++++++++++++++++++++
 3 files changed, 68 insertions(+), 6 deletions(-)

diff --git a/include/linux/module.h b/include/linux/module.h
index a98e188cf37b..9899aeac43b0 100644
--- a/include/linux/module.h
+++ b/include/linux/module.h
@@ -34,6 +34,10 @@
 
 #define MODULE_NAME_LEN MAX_PARAM_PREFIX_LEN
 
+#ifdef CONFIG_MODULE_SIG
+extern int module_sig_check_wait;
+#endif
+
 struct modversion_info {
 	unsigned long crc;
 	char name[MODULE_NAME_LEN];
diff --git a/kernel/module/main.c b/kernel/module/main.c
index 59b1d067e528..d24dd1f728f2 100644
--- a/kernel/module/main.c
+++ b/kernel/module/main.c
@@ -2033,12 +2033,14 @@ static void module_augment_kernel_taints(struct module *mod, struct load_info *i
 		add_taint_module(mod, TAINT_TEST, LOCKDEP_STILL_OK);
 	}
 #ifdef CONFIG_MODULE_SIG
-	mod->sig_ok = info->sig_ok;
-	if (!mod->sig_ok) {
-		pr_notice_once("%s: module verification failed: signature "
-			       "and/or required key missing - tainting "
-			       "kernel\n", mod->name);
-		add_taint_module(mod, TAINT_UNSIGNED_MODULE, LOCKDEP_STILL_OK);
+	if (!module_sig_check_wait) {
+		mod->sig_ok = info->sig_ok;
+		if (!mod->sig_ok) {
+			pr_notice_once("%s: module verification failed: signature "
+				       "and/or required key missing - tainting "
+				       "kernel\n", mod->name);
+			add_taint_module(mod, TAINT_UNSIGNED_MODULE, LOCKDEP_STILL_OK);
+		}
 	}
 #endif
 
diff --git a/kernel/module/signing.c b/kernel/module/signing.c
index a2ff4242e623..2580ceed3cdb 100644
--- a/kernel/module/signing.c
+++ b/kernel/module/signing.c
@@ -19,6 +19,8 @@
 #undef MODULE_PARAM_PREFIX
 #define MODULE_PARAM_PREFIX "module."
 
+int module_sig_check_wait;
+
 static bool sig_enforce = IS_ENABLED(CONFIG_MODULE_SIG_FORCE);
 module_param(sig_enforce, bool_enable_only, 0644);
 
@@ -37,6 +39,58 @@ void set_module_sig_enforced(void)
 	sig_enforce = true;
 }
 
+/*
+ * test thing to enable sig enforcing later in boot sequence
+ */
+static int __init module_sig_check_wait_arg(char *str)
+{
+	return kstrtoint(str, 0, &module_sig_check_wait);
+}
+__setup("module_sig_check_wait=", module_sig_check_wait_arg);
+
+/*
+ * securityfs entry to disable module_sig_check_wait, and start enforcing modules signature check
+ */
+static ssize_t module_sig_check_wait_read(struct file *file, char __user *buf, size_t count,
+					  loff_t *ppos)
+{
+	return simple_read_from_buffer(buf, count, ppos,
+				       module_sig_check_wait == 1 ? "1\n" : "0\n", 2);
+}
+
+static ssize_t module_sig_check_wait_write(struct file *file, const char __user *buf,
+					   size_t n, loff_t *ppos)
+{
+	int tmp;
+
+	if (kstrtoint_from_user(buf, n, 10, &tmp))
+		return -EINVAL;
+	if (tmp != 0) {
+		pr_info("module_sig_check_wait can be only disabled!\n");
+		return -EINVAL;
+	}
+	pr_info("module_sig_check_wait disabled!\n");
+	module_sig_check_wait = tmp;
+
+	return n;
+}
+
+static const struct file_operations module_sig_check_wait_ops = {
+	.read  = module_sig_check_wait_read,
+	.write = module_sig_check_wait_write,
+};
+
+static int __init module_sig_check_wait_secfs_init(void)
+{
+	struct dentry *dentry;
+
+	dentry = securityfs_create_file("module_sig_check_wait", 0644, NULL, NULL,
+					&module_sig_check_wait_ops);
+	return PTR_ERR_OR_ZERO(dentry);
+}
+
+core_initcall(module_sig_check_wait_secfs_init);
+
 /*
  * Verify the signature on a module.
  */
@@ -69,6 +123,8 @@ int mod_verify_sig(const void *mod, struct load_info *info)
 
 int module_sig_check(struct load_info *info, int flags)
 {
+	if (module_sig_check_wait)
+		return 0;
 	int err = -ENODATA;
 	const unsigned long markerlen = sizeof(MODULE_SIG_STRING) - 1;
 	const char *reason;
-- 
2.34.1


  reply	other threads:[~2023-09-14 11:28 UTC|newest]

Thread overview: 12+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-09-14 11:27 [RFC PATCH 0/2] Enhancing Boot Speed and Security with Delayed Module Signature Verification Alessandro Carminati (Red Hat)
2023-09-14 11:27 ` Alessandro Carminati (Red Hat) [this message]
2023-11-16 17:35   ` [RFC PATCH 1/2] Modules: Introduce boot-time module signature flexibility Luis Chamberlain
2023-11-17 13:56     ` Alessandro Carminati
2023-11-17 18:33       ` Luis Chamberlain
2023-11-20 19:43         ` Luca Boccassi
2023-09-14 11:27 ` [RFC PATCH 2/2] docs: Update kernel-parameters.txt for signature verification enhancement Alessandro Carminati (Red Hat)
2023-09-15 15:59   ` Randy Dunlap
2023-11-08 15:33   ` Prarit Bhargava
2023-11-09 10:40     ` Alessandro Carminati
2023-11-08 15:32 ` [RFC PATCH 0/2] Enhancing Boot Speed and Security with Delayed Module Signature Verification Prarit Bhargava
2023-11-09 10:51 ` Alessandro Carminati

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20230914112739.112729-2-alessandro.carminati@gmail.com \
    --to=alessandro.carminati@gmail.com \
    --cc=corbet@lwn.net \
    --cc=linux-doc@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-modules@vger.kernel.org \
    --cc=mcgrof@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox