At Mon, 29 Oct 2012 17:41:31 +0000,
Post by Matthew GarrettPost by Jiri KosinaThis is pretty much identical to the first patchset, but with the capability
renamed (CAP_COMPROMISE_KERNEL) and the kexec patch dropped. If anyone wants
to deploy these then they should disable kexec until support for signed
kexec payloads has been merged.
Apparently your patchset currently doesn't handle device firmware loading,
nor do you seem to mention in in the comments.
Correct.
Post by Jiri KosinaI believe signed firmware loading should be put on plate as well, right?
I think that's definitely something that should be covered. I hadn't
worried about it immediately as any attack would be limited to machines
with a specific piece of hardware, and the attacker would need to expend
a significant amount of reverse engineering work on the firmware - and
we'd probably benefit from them doing that in the long run...
request_firmware() is used for microcode loading, too, so it's fairly
a core part to cover, I'm afraid.
I played a bit about this yesterday. The patch below is a proof of
concept to (ab)use the module signing mechanism for firmware loading
too. Sign firmware files via scripts/sign-file, and put to
/lib/firmware/signed directory.
It's just a rough cut, and the module options are other pieces there
should be polished better, of course. Also another signature string
should be better for firmware files :)
Takashi
---
diff --git a/drivers/base/Kconfig b/drivers/base/Kconfig
index b34b5cd..2bc8415 100644
--- a/drivers/base/Kconfig
+++ b/drivers/base/Kconfig
@@ -145,6 +145,12 @@ config EXTRA_FIRMWARE_DIR
this option you can point it elsewhere, such as /lib/firmware/ or
some other directory containing the firmware files.
+config FIRMWARE_SIG
+ bool "Firmware signature check"
+ depends on FW_LOADER && MODULE_SIG
+ help
+ Check the embedded signature of firmware files like signed modules.
+
config DEBUG_DRIVER
bool "Driver Core verbose debug messages"
depends on DEBUG_KERNEL
diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c
index 8945f4e..81fc8a4 100644
--- a/drivers/base/firmware_class.c
+++ b/drivers/base/firmware_class.c
@@ -268,6 +268,12 @@ static void fw_free_buf(struct firmware_buf *buf)
/* direct firmware loading support */
static const char *fw_path[] = {
+#ifdef CONFIG_FIRMWARE_SIG
+ "/lib/firmware/updates/" UTS_RELEASE "/signed",
+ "/lib/firmware/updates/signed",
+ "/lib/firmware/" UTS_RELEASE "/signed",
+ "/lib/firmware/signed",
+#endif
"/lib/firmware/updates/" UTS_RELEASE,
"/lib/firmware/updates",
"/lib/firmware/" UTS_RELEASE,
@@ -844,6 +850,41 @@ exit:
return fw_priv;
}
+#ifdef CONFIG_FIRMWARE_SIG
+/* XXX */
+extern int mod_verify_sig(const void *mod, unsigned long *_modlen);
+
+static bool sig_enforce;
+module_param(sig_enforce, bool, 0444);
+
+static int firmware_sig_check(struct firmware_buf *buf)
+{
+ unsigned long markerlen = sizeof(MODULE_SIG_STRING) - 1;
+ long len;
+ int err;
+
+ len = buf->size - markerlen;
+ if (len <= 0 ||
+ memcmp(buf->data + len, MODULE_SIG_STRING, markerlen)) {
+ pr_debug("%s: no signature found\n", buf->fw_id);
+ return sig_enforce ? -ENOKEY : 0;
+ }
+ err = mod_verify_sig(buf->data, &len);
+ if (err < 0) {
+ pr_debug("%s: signature error: %d\n", buf->fw_id, err);
+ return err;
+ }
+ buf->size = len;
+ pr_debug("%s: signature OK!\n", buf->fw_id);
+ return 0;
+}
+#else
+static inline int firmware_sig_check(struct firmware_buf *buf)
+{
+ return 0;
+}
+#endif
+
static int _request_firmware_load(struct firmware_priv *fw_priv, bool uevent,
long timeout)
{
@@ -909,6 +950,9 @@ handle_fw:
if (!buf->size || test_bit(FW_STATUS_ABORT, &buf->status))
retval = -ENOENT;
+ if (!retval)
+ retval = firmware_sig_check(buf);
+
/*
* add firmware name into devres list so that we can auto cache
* and uncache firmware for device.
diff --git a/kernel/module_signing.c b/kernel/module_signing.c
index ea1b1df..c39f49b 100644
--- a/kernel/module_signing.c
+++ b/kernel/module_signing.c
@@ -11,6 +11,7 @@
#include <linux/kernel.h>
#include <linux/err.h>
+#include <linux/export.h>
#include <crypto/public_key.h>
#include <crypto/hash.h>
#include <keys/asymmetric-type.h>
@@ -247,3 +248,4 @@ error_put_key:
pr_devel("<==%s() = %d\n", __func__, ret);
return ret;
}
+EXPORT_SYMBOL_GPL(mod_verify_sig);
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to ***@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/