All of lore.kernel.org
 help / color / mirror / Atom feed
From: Mihai Carabas <mihai.carabas@oracle.com>
To: linux-kernel@vger.kernel.org
Cc: Mihai Carabas <mihai.carabas@oracle.com>,
	Thomas Gleixner <tglx@linutronix.de>,
	Ingo Molnar <mingo@redhat.com>, Borislav Petkov <bp@alien8.de>,
	x86@kernel.org, "H. Peter Anvin" <hpa@zytor.com>,
	Jonathan Corbet <corbet@lwn.net>,
	linux-doc@vger.kernel.org
Subject: [PATCH RFC 2/3] x86: microcode: intel: process microcode metadata
Date: Mon, 27 Apr 2020 10:27:58 +0300	[thread overview]
Message-ID: <1587972479-10971-3-git-send-email-mihai.carabas@oracle.com> (raw)
In-Reply-To: <1587972479-10971-1-git-send-email-mihai.carabas@oracle.com>

Process the microcode metadata to see what changes are done on
CPU feature bits.

The default kernel policy imposed by is_microcode_allowed() is
to abort any microcode late loading if there will be removed a
feature and will continue the loading otherwise. Complex policies
can be created in the future.

Signed-off-by: Mihai Carabas <mihai.carabas@oracle.com>
---
 arch/x86/kernel/cpu/microcode/intel.c | 85 +++++++++++++++++++++++++++++++++++
 1 file changed, 85 insertions(+)

diff --git a/arch/x86/kernel/cpu/microcode/intel.c b/arch/x86/kernel/cpu/microcode/intel.c
index a54d5e6..2ef4338 100644
--- a/arch/x86/kernel/cpu/microcode/intel.c
+++ b/arch/x86/kernel/cpu/microcode/intel.c
@@ -23,6 +23,7 @@
 #include <linux/firmware.h>
 #include <linux/uaccess.h>
 #include <linux/vmalloc.h>
+#include <linux/string.h>
 #include <linux/initrd.h>
 #include <linux/kernel.h>
 #include <linux/slab.h>
@@ -965,6 +966,81 @@ static bool is_blacklisted(unsigned int cpu)
 
 	return false;
 }
+/**
+ * is_microcode_allowed - parse and enforce policies
+ * @firmware - metadata blob
+ *
+ * Parses the metadata file provided with the microcode in order to see the
+ * changes brought in by the new blob.
+ *
+ * Based on the type of changes, currently it enforces the following policy: if
+ * there is a feature being removed by the new microcode, reject the loading.
+ *
+ * RETURNS:
+ * false if it rejects the microcode or true if it accepts the microcode.
+ */
+static bool is_microcode_allowed(const struct firmware *firmware)
+{
+	int ret, index, leaf, eax, ebx, ecx, edx, line_nr = 0;
+	char *data = (char *) firmware->data;
+	char *line;
+	char op;
+
+	/*
+	 * Get each line and match it with regular expression:
+	 * {m|c} {+|-} u32 [u32]*
+	 *
+	 * See section Late loading metadata file from
+	 * Documentation/x86/microcode.rst
+	 */
+	while (data && (data - ((char *)(firmware->data)) < firmware->size)) {
+		line = strsep(&data, "\n");
+		line_nr++;
+
+		/*
+		 * For each line check the first letter to see the type of
+		 * operation done by the microcode and create a sscanf call
+		 * the would match the rest of the line of that operation.
+		 * If it is not a match, exist with parsing error. If it is
+		 * a match and is a remove action (-) do not allow microcode
+		 * to be loaded.
+		 */
+		switch (line[0]) {
+		case 'c':
+			ret = sscanf(&line[1], " %c %x %x %x %x %x %x", &op,
+			    &index, &leaf, &eax, &ebx, &ecx, &edx);
+			if (ret != 7)
+				goto out_error;
+			if (op == '-')
+				goto out_cpuid_rem_notsupp;
+			break;
+		case 'm':
+			ret = sscanf(&line[1], " %c %x", &op, &index);
+			if (ret != 2)
+				goto out_error;
+			if (op == '-')
+				goto out_msr_rem_notsupp;
+			break;
+		default:
+			goto out_error;
+		}
+	}
+
+	return true;
+
+out_error:
+	pr_warn("Microcode metadata failed parsing at line %d\n", line_nr);
+	return false;
+
+out_msr_rem_notsupp:
+	pr_warn("Kernel policy does not allow to remove MSR: %x\n", index);
+	return false;
+
+out_cpuid_rem_notsupp:
+	pr_warn("Kernel policy does not allow to remove CPUID: %x leaf: %x, eax: %x, ebx: %x, ecx: %x, edx: %x\n",
+	    index, leaf, eax, ebx, ecx, edx);
+	return false;
+}
 
 static enum ucode_state request_microcode_fw(int cpu, struct device *device,
 					     bool refresh_fw)
@@ -992,10 +1068,19 @@ static enum ucode_state request_microcode_fw(int cpu, struct device *device,
 		return UCODE_NFOUND;
 	}
 
+	/* Load the metadata file in memory. */
 	if (request_firmware_direct(&meta_firmware, meta_name, device)) {
 		pr_debug("metadata file %s load failed\n", name);
 		pr_debug("no feature check will be done pre-loading the microcode\n");
 	} else {
+		/* Check the policy based on the metadata file. */
+		if (!is_microcode_allowed(meta_firmware)) {
+			pr_warn("kernel does not support the new microcode: %s\n",
+			    name);
+			release_firmware(meta_firmware);
+			release_firmware(firmware);
+			return UCODE_ERROR;
+		}
 		release_firmware(meta_firmware);
 	}
 
-- 
1.8.3.1


  parent reply	other threads:[~2020-04-27  8:08 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-04-27  7:27 [PATCH RFC] Microcode late loading feature identification Mihai Carabas
2020-04-27  7:27 ` [PATCH RFC 1/3] x86: microcode: intel: read microcode metadata file Mihai Carabas
2020-05-04 14:12   ` Borislav Petkov
2020-04-27  7:27 ` Mihai Carabas [this message]
2020-04-27  7:27 ` [PATCH RFC 3/3] Documentation: x86: microcode: add description for " Mihai Carabas
2020-05-04 14:09   ` Borislav Petkov
2020-05-11 14:11 ` [PATCH RFC] Microcode late loading feature identification Mihai Carabas
2020-05-11 15:23   ` Raj, Ashok

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=1587972479-10971-3-git-send-email-mihai.carabas@oracle.com \
    --to=mihai.carabas@oracle.com \
    --cc=bp@alien8.de \
    --cc=corbet@lwn.net \
    --cc=hpa@zytor.com \
    --cc=linux-doc@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mingo@redhat.com \
    --cc=tglx@linutronix.de \
    --cc=x86@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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.