All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] x86/microcode: Refactor Intel microcode loading
@ 2019-04-04 11:11 Jann Horn
  2019-04-04 16:27 ` Borislav Petkov
  2019-04-10 20:49 ` [tip:x86/microcode] x86/microcode/intel: Refactor Intel microcode blob loading tip-bot for Jann Horn
  0 siblings, 2 replies; 7+ messages in thread
From: Jann Horn @ 2019-04-04 11:11 UTC (permalink / raw)
  To: Thomas Gleixner, Ingo Molnar, Borislav Petkov, H. Peter Anvin, jannh
  Cc: x86, linux-kernel, David Laight

This changes generic_load_microcode() to use the iov_iter API instead of
an open-coded version. This allows us to avoid explicitly casting between
user and kernel pointers.

Because the iov_iter API makes it hard to read the same location twice, as
a side effect, this also fixes a double-read of the microcode header (which
could e.g. lead to out-of-bounds reads in microcode_sanity_check()).
Not that it matters much, only root can do this anyway...

Signed-off-by: Jann Horn <jannh@google.com>
---
I have tested that with this patch applied, microcode loading still works
both via "iucode-tool -k" and via
/sys/devices/system/cpu/microcode/reload.

 arch/x86/kernel/cpu/microcode/intel.c | 64 +++++++++++++--------------
 1 file changed, 32 insertions(+), 32 deletions(-)

diff --git a/arch/x86/kernel/cpu/microcode/intel.c b/arch/x86/kernel/cpu/microcode/intel.c
index 16936a24795c..cb976e8ef94d 100644
--- a/arch/x86/kernel/cpu/microcode/intel.c
+++ b/arch/x86/kernel/cpu/microcode/intel.c
@@ -31,6 +31,7 @@
 #include <linux/kernel.h>
 #include <linux/slab.h>
 #include <linux/cpu.h>
+#include <linux/uio.h>
 #include <linux/mm.h>
 
 #include <asm/microcode_intel.h>
@@ -861,32 +862,33 @@ static enum ucode_state apply_microcode_intel(int cpu)
 	return ret;
 }
 
-static enum ucode_state generic_load_microcode(int cpu, void *data, size_t size,
-				int (*get_ucode_data)(void *, const void *, size_t))
+static enum ucode_state generic_load_microcode(int cpu, struct iov_iter *iter)
 {
 	struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
-	u8 *ucode_ptr = data, *new_mc = NULL, *mc = NULL;
+	u8 *new_mc = NULL, *mc = NULL;
 	int new_rev = uci->cpu_sig.rev;
-	unsigned int leftover = size;
 	unsigned int curr_mc_size = 0, new_mc_size = 0;
 	unsigned int csig, cpf;
 	enum ucode_state ret = UCODE_OK;
 
-	while (leftover) {
+	while (iov_iter_count(iter)) {
 		struct microcode_header_intel mc_header;
-		unsigned int mc_size;
+		unsigned int mc_size, data_size;
+		u8 *data;
 
-		if (leftover < sizeof(mc_header)) {
-			pr_err("error! Truncated header in microcode data file\n");
+		if (!copy_from_iter_full(&mc_header, sizeof(mc_header), iter)) {
+			pr_err("error! Truncated or inaccessible header in microcode data\n");
 			break;
 		}
 
-		if (get_ucode_data(&mc_header, ucode_ptr, sizeof(mc_header)))
-			break;
-
 		mc_size = get_totalsize(&mc_header);
-		if (!mc_size || mc_size > leftover) {
-			pr_err("error! Bad data in microcode data file\n");
+		if (mc_size < sizeof(mc_header)) {
+			pr_err("error! Bad data in microcode data file (totalsize too small)\n");
+			break;
+		}
+		data_size = mc_size - sizeof(mc_header);
+		if (data_size > iov_iter_count(iter)) {
+			pr_err("error! Bad data in microcode data file (truncated file?)\n");
 			break;
 		}
 
@@ -899,7 +901,9 @@ static enum ucode_state generic_load_microcode(int cpu, void *data, size_t size,
 			curr_mc_size = mc_size;
 		}
 
-		if (get_ucode_data(mc, ucode_ptr, mc_size) ||
+		memcpy(mc, &mc_header, sizeof(mc_header));
+		data = mc + sizeof(mc_header);
+		if (!copy_from_iter_full(data, data_size, iter) ||
 		    microcode_sanity_check(mc, 1) < 0) {
 			break;
 		}
@@ -914,14 +918,11 @@ static enum ucode_state generic_load_microcode(int cpu, void *data, size_t size,
 			mc = NULL;	/* trigger new vmalloc */
 			ret = UCODE_NEW;
 		}
-
-		ucode_ptr += mc_size;
-		leftover  -= mc_size;
 	}
 
 	vfree(mc);
 
-	if (leftover) {
+	if (iov_iter_count(iter)) {
 		vfree(new_mc);
 		return UCODE_ERROR;
 	}
@@ -945,12 +946,6 @@ static enum ucode_state generic_load_microcode(int cpu, void *data, size_t size,
 	return ret;
 }
 
-static int get_ucode_fw(void *to, const void *from, size_t n)
-{
-	memcpy(to, from, n);
-	return 0;
-}
-
 static bool is_blacklisted(unsigned int cpu)
 {
 	struct cpuinfo_x86 *c = &cpu_data(cpu);
@@ -981,6 +976,8 @@ static enum ucode_state request_microcode_fw(int cpu, struct device *device,
 	struct cpuinfo_x86 *c = &cpu_data(cpu);
 	const struct firmware *firmware;
 	enum ucode_state ret;
+	struct kvec kvec;
+	struct iov_iter iter;
 
 	if (is_blacklisted(cpu))
 		return UCODE_NFOUND;
@@ -993,26 +990,29 @@ static enum ucode_state request_microcode_fw(int cpu, struct device *device,
 		return UCODE_NFOUND;
 	}
 
-	ret = generic_load_microcode(cpu, (void *)firmware->data,
-				     firmware->size, &get_ucode_fw);
+	kvec.iov_base = (void *)firmware->data;
+	kvec.iov_len = firmware->size;
+	iov_iter_kvec(&iter, WRITE, &kvec, 1, firmware->size);
+	ret = generic_load_microcode(cpu, &iter);
 
 	release_firmware(firmware);
 
 	return ret;
 }
 
-static int get_ucode_user(void *to, const void *from, size_t n)
-{
-	return copy_from_user(to, from, n);
-}
-
 static enum ucode_state
 request_microcode_user(int cpu, const void __user *buf, size_t size)
 {
+	struct iovec iov;
+	struct iov_iter iter;
+
 	if (is_blacklisted(cpu))
 		return UCODE_NFOUND;
 
-	return generic_load_microcode(cpu, (void *)buf, size, &get_ucode_user);
+	iov.iov_base = (void __user *)buf;
+	iov.iov_len = size;
+	iov_iter_init(&iter, WRITE, &iov, 1, size);
+	return generic_load_microcode(cpu, &iter);
 }
 
 static struct microcode_ops microcode_intel_ops = {
-- 
2.21.0.392.gf8f6787159e-goog


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [PATCH] x86/microcode: Refactor Intel microcode loading
  2019-04-04 11:11 [PATCH] x86/microcode: Refactor Intel microcode loading Jann Horn
@ 2019-04-04 16:27 ` Borislav Petkov
  2019-04-04 16:31   ` Jann Horn
  2019-04-10 20:49 ` [tip:x86/microcode] x86/microcode/intel: Refactor Intel microcode blob loading tip-bot for Jann Horn
  1 sibling, 1 reply; 7+ messages in thread
From: Borislav Petkov @ 2019-04-04 16:27 UTC (permalink / raw)
  To: Jann Horn
  Cc: Thomas Gleixner, Ingo Molnar, H. Peter Anvin, x86, linux-kernel,
	David Laight

On Thu, Apr 04, 2019 at 01:11:28PM +0200, Jann Horn wrote:
> This changes generic_load_microcode() to use the iov_iter API instead of
> an open-coded version. This allows us to avoid explicitly casting between
> user and kernel pointers.
> 
> Because the iov_iter API makes it hard to read the same location twice, as
> a side effect, this also fixes a double-read of the microcode header (which
> could e.g. lead to out-of-bounds reads in microcode_sanity_check()).
> Not that it matters much, only root can do this anyway...
> 
> Signed-off-by: Jann Horn <jannh@google.com>
> ---
> I have tested that with this patch applied, microcode loading still works
> both via "iucode-tool -k" and via
> /sys/devices/system/cpu/microcode/reload.

Yeah, this cannot have worked because I think I broke it recently and
you'd need this:

---
diff --git a/arch/x86/kernel/cpu/microcode/core.c b/arch/x86/kernel/cpu/microcode/core.c
index 5260185cbf7b..8a4a7823451a 100644
--- a/arch/x86/kernel/cpu/microcode/core.c
+++ b/arch/x86/kernel/cpu/microcode/core.c
@@ -418,8 +418,9 @@ static int do_microcode_update(const void __user *buf, size_t size)
                if (ustate == UCODE_ERROR) {
                        error = -1;
                        break;
-               } else if (ustate == UCODE_OK)
+               } else if (ustate == UCODE_NEW) {
                        apply_microcode_on_target(cpu);
+               }
        }
 
        return error;
---

Regardless, I'll take care of it. Thanks a lot for doing this cleanup,
it looks really cool and nicely clean - exactly how I envisioned it. :-)

I'll test it more later with the above fix and apply it.

Thx.

-- 
Regards/Gruss,
    Boris.

Good mailing practices for 400: avoid top-posting and trim the reply.

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [PATCH] x86/microcode: Refactor Intel microcode loading
  2019-04-04 16:27 ` Borislav Petkov
@ 2019-04-04 16:31   ` Jann Horn
  2019-04-04 16:47     ` Borislav Petkov
  0 siblings, 1 reply; 7+ messages in thread
From: Jann Horn @ 2019-04-04 16:31 UTC (permalink / raw)
  To: Borislav Petkov
  Cc: Thomas Gleixner, Ingo Molnar, H. Peter Anvin,
	the arch/x86 maintainers, kernel list, David Laight

On Thu, Apr 4, 2019 at 6:28 PM Borislav Petkov <bp@alien8.de> wrote:
>
> On Thu, Apr 04, 2019 at 01:11:28PM +0200, Jann Horn wrote:
> > This changes generic_load_microcode() to use the iov_iter API instead of
> > an open-coded version. This allows us to avoid explicitly casting between
> > user and kernel pointers.
> >
> > Because the iov_iter API makes it hard to read the same location twice, as
> > a side effect, this also fixes a double-read of the microcode header (which
> > could e.g. lead to out-of-bounds reads in microcode_sanity_check()).
> > Not that it matters much, only root can do this anyway...
> >
> > Signed-off-by: Jann Horn <jannh@google.com>
> > ---
> > I have tested that with this patch applied, microcode loading still works
> > both via "iucode-tool -k" and via
> > /sys/devices/system/cpu/microcode/reload.
>
> Yeah, this cannot have worked because I think I broke it recently and
> you'd need this:

Uuuh. I *definitely* tested this. I ran this yesterday evening on my
home machine, on top of commit
14c741de93861749dfb60b4964028541f5c506ca from Linus' tree, plus two
cherry-picked fixes for drm/ttm. I specifically made sure that I had
the old microcode version before reloading these ways and I had the
new version after reloading. And the verbose dmesg logs also looked
okay.

> ---
> diff --git a/arch/x86/kernel/cpu/microcode/core.c b/arch/x86/kernel/cpu/microcode/core.c
> index 5260185cbf7b..8a4a7823451a 100644
> --- a/arch/x86/kernel/cpu/microcode/core.c
> +++ b/arch/x86/kernel/cpu/microcode/core.c
> @@ -418,8 +418,9 @@ static int do_microcode_update(const void __user *buf, size_t size)
>                 if (ustate == UCODE_ERROR) {
>                         error = -1;
>                         break;
> -               } else if (ustate == UCODE_OK)
> +               } else if (ustate == UCODE_NEW) {
>                         apply_microcode_on_target(cpu);
> +               }
>         }
>
>         return error;
> ---
>
> Regardless, I'll take care of it. Thanks a lot for doing this cleanup,
> it looks really cool and nicely clean - exactly how I envisioned it. :-)
>
> I'll test it more later with the above fix and apply it.
>
> Thx.
>
> --
> Regards/Gruss,
>     Boris.
>
> Good mailing practices for 400: avoid top-posting and trim the reply.

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH] x86/microcode: Refactor Intel microcode loading
  2019-04-04 16:31   ` Jann Horn
@ 2019-04-04 16:47     ` Borislav Petkov
  2019-04-04 22:54       ` Jann Horn
  0 siblings, 1 reply; 7+ messages in thread
From: Borislav Petkov @ 2019-04-04 16:47 UTC (permalink / raw)
  To: Jann Horn
  Cc: Thomas Gleixner, Ingo Molnar, H. Peter Anvin,
	the arch/x86 maintainers, kernel list, David Laight

On Thu, Apr 04, 2019 at 06:31:37PM +0200, Jann Horn wrote:
> Uuuh. I *definitely* tested this. I ran this yesterday evening on my
> home machine, on top of commit
> 14c741de93861749dfb60b4964028541f5c506ca from Linus' tree, plus two
> cherry-picked fixes for drm/ttm. I specifically made sure that I had
> the old microcode version before reloading these ways and I had the
> new version after reloading. And the verbose dmesg logs also looked
> okay.

How did you check the microcode revision before and after? /proc/cpuinfo?

Because that old method doesn't say anything in dmesg if there's no
debugging output, only the iucode_tool says something like the below if
you enable verbose output:

# iucode-tool -v --kernel=/dev/cpu/microcode /lib/firmware/intel-ucode/06-3a-09
iucode-tool: processed 1 valid microcode(s), 1 signature(s), 1 unique signature(s)
iucode-tool: selected 1 microcode(s), 1 signature(s)
iucode-tool: Uploading selected microcodes to: /dev/cpu/microcode
iucode-tool: /dev/cpu/microcode: 1 microcode entries uploaded, 13312 bytes

-- 
Regards/Gruss,
    Boris.

Good mailing practices for 400: avoid top-posting and trim the reply.

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH] x86/microcode: Refactor Intel microcode loading
  2019-04-04 16:47     ` Borislav Petkov
@ 2019-04-04 22:54       ` Jann Horn
  2019-04-05  4:10         ` Borislav Petkov
  0 siblings, 1 reply; 7+ messages in thread
From: Jann Horn @ 2019-04-04 22:54 UTC (permalink / raw)
  To: Borislav Petkov
  Cc: Thomas Gleixner, Ingo Molnar, H. Peter Anvin,
	the arch/x86 maintainers, kernel list, David Laight

On Thu, Apr 4, 2019 at 6:47 PM Borislav Petkov <bp@alien8.de> wrote:
> On Thu, Apr 04, 2019 at 06:31:37PM +0200, Jann Horn wrote:
> > Uuuh. I *definitely* tested this. I ran this yesterday evening on my
> > home machine, on top of commit
> > 14c741de93861749dfb60b4964028541f5c506ca from Linus' tree, plus two
> > cherry-picked fixes for drm/ttm. I specifically made sure that I had
> > the old microcode version before reloading these ways and I had the
> > new version after reloading. And the verbose dmesg logs also looked
> > okay.
>
> How did you check the microcode revision before and after? /proc/cpuinfo?
>
> Because that old method doesn't say anything in dmesg if there's no
> debugging output, only the iucode_tool says something like the below if
> you enable verbose output:
>
> # iucode-tool -v --kernel=/dev/cpu/microcode /lib/firmware/intel-ucode/06-3a-09
> iucode-tool: processed 1 valid microcode(s), 1 signature(s), 1 unique signature(s)
> iucode-tool: selected 1 microcode(s), 1 signature(s)
> iucode-tool: Uploading selected microcodes to: /dev/cpu/microcode
> iucode-tool: /dev/cpu/microcode: 1 microcode entries uploaded, 13312 bytes

Ah, dammit. I'm re-testing it now, and as you said, the microcode
isn't actually loading. I was testing with
arch/x86/kernel/cpu/{core,intel}.c added to
/sys/kernel/debug/dynamic_debug/control, I guess I must have decided
that it worked when I saw this:

[  159.485550] microcode: CPU0 found a matching microcode update with
version 0x25 (current=0x19)
[  159.485588] microcode: CPU1 found a matching microcode update with
version 0x25 (current=0x19)
[  159.485615] microcode: CPU2 found a matching microcode update with
version 0x25 (current=0x19)
[  159.485640] microcode: CPU3 found a matching microcode update with
version 0x25 (current=0x19)
[  159.485664] microcode: CPU4 found a matching microcode update with
version 0x25 (current=0x19)
[  159.485689] microcode: CPU5 found a matching microcode update with
version 0x25 (current=0x19)
[  159.485713] microcode: CPU6 found a matching microcode update with
version 0x25 (current=0x19)
[  159.485731] microcode: CPU7 found a matching microcode update with
version 0x25 (current=0x19)

I thought I had checked /sys/devices/system/cpu/cpu0/microcode/version
afterwards. But apparently I didn't. Bleh. Sorry about that.

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH] x86/microcode: Refactor Intel microcode loading
  2019-04-04 22:54       ` Jann Horn
@ 2019-04-05  4:10         ` Borislav Petkov
  0 siblings, 0 replies; 7+ messages in thread
From: Borislav Petkov @ 2019-04-05  4:10 UTC (permalink / raw)
  To: Jann Horn
  Cc: Thomas Gleixner, Ingo Molnar, H. Peter Anvin,
	the arch/x86 maintainers, kernel list, David Laight

On Fri, Apr 05, 2019 at 12:54:31AM +0200, Jann Horn wrote:
> [  159.485731] microcode: CPU7 found a matching microcode update with
> version 0x25 (current=0x19)

Yeah, that printk can be kinda misleading :)

> I thought I had checked /sys/devices/system/cpu/cpu0/microcode/version
> afterwards. But apparently I didn't. Bleh. Sorry about that.

No worries at all, now at least it is all clear what's happening. I was
beginning to recheck what I'm seeing here too.

And I can finally deprecate this ancient method which is just as
kaputtski because it is happening as late as the late loading method
when you do

echo 1 > /sys/devices/system/cpu/microcode/reload

---
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 5ad92419be19..5a0a752f3ddd 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -1330,8 +1330,16 @@ config MICROCODE_AMD
 	  processors will be enabled.
 
 config MICROCODE_OLD_INTERFACE
-	def_bool y
+	bool "Ancient loading interface (DEPRECATED)"
+	default n
 	depends on MICROCODE
+	---help---
+	  DO NOT USE THIS! This is the ancient /dev/cpu/microcode interface
+	  which was used by userspace tools like iucode_tool and microcode.ctl.
+	  It is inadequate because it runs too late to be able to properly
+	  load microcode on a machine and it needs special tools. Instead, you
+	  should've switched to the early loading method with the initrd or
+	  builtin microcode by now: Documentation/x86/microcode.txt
 
 config X86_MSR
 	tristate "/dev/cpu/*/msr - Model-specific register support"
---

I'll test some more and post later.

Thx!

-- 
Regards/Gruss,
    Boris.

Good mailing practices for 400: avoid top-posting and trim the reply.

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [tip:x86/microcode] x86/microcode/intel: Refactor Intel microcode blob loading
  2019-04-04 11:11 [PATCH] x86/microcode: Refactor Intel microcode loading Jann Horn
  2019-04-04 16:27 ` Borislav Petkov
@ 2019-04-10 20:49 ` tip-bot for Jann Horn
  1 sibling, 0 replies; 7+ messages in thread
From: tip-bot for Jann Horn @ 2019-04-10 20:49 UTC (permalink / raw)
  To: linux-tip-commits; +Cc: tglx, linux-kernel, jannh, mingo, bp, hpa, x86, mingo

Commit-ID:  7e94a7b659eefedda82cde97229a26f319fb1182
Gitweb:     https://git.kernel.org/tip/7e94a7b659eefedda82cde97229a26f319fb1182
Author:     Jann Horn <jannh@google.com>
AuthorDate: Thu, 4 Apr 2019 13:11:28 +0200
Committer:  Borislav Petkov <bp@suse.de>
CommitDate: Wed, 10 Apr 2019 22:40:25 +0200

x86/microcode/intel: Refactor Intel microcode blob loading

Change generic_load_microcode() to use the iov_iter API instead of a
clumsy open-coded version which has to pay attention to __user data
or kernel data, depending on the loading method. This allows to avoid
explicit casting between user and kernel pointers.

Because the iov_iter API makes it hard to read the same location twice,
as a side effect, also fix a double-read of the microcode header (which
could e.g. lead to out-of-bounds reads in microcode_sanity_check()).

Not that it matters much, only root is allowed to load microcode
anyway...

 [ bp: Massage a bit, sort function-local variables. ]

Signed-off-by: Jann Horn <jannh@google.com>
Signed-off-by: Borislav Petkov <bp@suse.de>
Reviewed-by: Thomas Gleixner <tglx@linutronix.de>
Cc: "H. Peter Anvin" <hpa@zytor.com>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: x86-ml <x86@kernel.org>
Link: https://lkml.kernel.org/r/20190404111128.131157-1-jannh@google.com
---
 arch/x86/kernel/cpu/microcode/intel.c | 71 ++++++++++++++++++-----------------
 1 file changed, 36 insertions(+), 35 deletions(-)

diff --git a/arch/x86/kernel/cpu/microcode/intel.c b/arch/x86/kernel/cpu/microcode/intel.c
index 16936a24795c..a44bdbe7c55e 100644
--- a/arch/x86/kernel/cpu/microcode/intel.c
+++ b/arch/x86/kernel/cpu/microcode/intel.c
@@ -31,6 +31,7 @@
 #include <linux/kernel.h>
 #include <linux/slab.h>
 #include <linux/cpu.h>
+#include <linux/uio.h>
 #include <linux/mm.h>
 
 #include <asm/microcode_intel.h>
@@ -861,32 +862,33 @@ out:
 	return ret;
 }
 
-static enum ucode_state generic_load_microcode(int cpu, void *data, size_t size,
-				int (*get_ucode_data)(void *, const void *, size_t))
+static enum ucode_state generic_load_microcode(int cpu, struct iov_iter *iter)
 {
 	struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
-	u8 *ucode_ptr = data, *new_mc = NULL, *mc = NULL;
-	int new_rev = uci->cpu_sig.rev;
-	unsigned int leftover = size;
 	unsigned int curr_mc_size = 0, new_mc_size = 0;
-	unsigned int csig, cpf;
 	enum ucode_state ret = UCODE_OK;
+	int new_rev = uci->cpu_sig.rev;
+	u8 *new_mc = NULL, *mc = NULL;
+	unsigned int csig, cpf;
 
-	while (leftover) {
+	while (iov_iter_count(iter)) {
 		struct microcode_header_intel mc_header;
-		unsigned int mc_size;
+		unsigned int mc_size, data_size;
+		u8 *data;
 
-		if (leftover < sizeof(mc_header)) {
-			pr_err("error! Truncated header in microcode data file\n");
+		if (!copy_from_iter_full(&mc_header, sizeof(mc_header), iter)) {
+			pr_err("error! Truncated or inaccessible header in microcode data file\n");
 			break;
 		}
 
-		if (get_ucode_data(&mc_header, ucode_ptr, sizeof(mc_header)))
-			break;
-
 		mc_size = get_totalsize(&mc_header);
-		if (!mc_size || mc_size > leftover) {
-			pr_err("error! Bad data in microcode data file\n");
+		if (mc_size < sizeof(mc_header)) {
+			pr_err("error! Bad data in microcode data file (totalsize too small)\n");
+			break;
+		}
+		data_size = mc_size - sizeof(mc_header);
+		if (data_size > iov_iter_count(iter)) {
+			pr_err("error! Bad data in microcode data file (truncated file?)\n");
 			break;
 		}
 
@@ -899,7 +901,9 @@ static enum ucode_state generic_load_microcode(int cpu, void *data, size_t size,
 			curr_mc_size = mc_size;
 		}
 
-		if (get_ucode_data(mc, ucode_ptr, mc_size) ||
+		memcpy(mc, &mc_header, sizeof(mc_header));
+		data = mc + sizeof(mc_header);
+		if (!copy_from_iter_full(data, data_size, iter) ||
 		    microcode_sanity_check(mc, 1) < 0) {
 			break;
 		}
@@ -914,14 +918,11 @@ static enum ucode_state generic_load_microcode(int cpu, void *data, size_t size,
 			mc = NULL;	/* trigger new vmalloc */
 			ret = UCODE_NEW;
 		}
-
-		ucode_ptr += mc_size;
-		leftover  -= mc_size;
 	}
 
 	vfree(mc);
 
-	if (leftover) {
+	if (iov_iter_count(iter)) {
 		vfree(new_mc);
 		return UCODE_ERROR;
 	}
@@ -945,12 +946,6 @@ static enum ucode_state generic_load_microcode(int cpu, void *data, size_t size,
 	return ret;
 }
 
-static int get_ucode_fw(void *to, const void *from, size_t n)
-{
-	memcpy(to, from, n);
-	return 0;
-}
-
 static bool is_blacklisted(unsigned int cpu)
 {
 	struct cpuinfo_x86 *c = &cpu_data(cpu);
@@ -977,10 +972,12 @@ static bool is_blacklisted(unsigned int cpu)
 static enum ucode_state request_microcode_fw(int cpu, struct device *device,
 					     bool refresh_fw)
 {
-	char name[30];
 	struct cpuinfo_x86 *c = &cpu_data(cpu);
 	const struct firmware *firmware;
+	struct iov_iter iter;
 	enum ucode_state ret;
+	struct kvec kvec;
+	char name[30];
 
 	if (is_blacklisted(cpu))
 		return UCODE_NFOUND;
@@ -993,26 +990,30 @@ static enum ucode_state request_microcode_fw(int cpu, struct device *device,
 		return UCODE_NFOUND;
 	}
 
-	ret = generic_load_microcode(cpu, (void *)firmware->data,
-				     firmware->size, &get_ucode_fw);
+	kvec.iov_base = (void *)firmware->data;
+	kvec.iov_len = firmware->size;
+	iov_iter_kvec(&iter, WRITE, &kvec, 1, firmware->size);
+	ret = generic_load_microcode(cpu, &iter);
 
 	release_firmware(firmware);
 
 	return ret;
 }
 
-static int get_ucode_user(void *to, const void *from, size_t n)
-{
-	return copy_from_user(to, from, n);
-}
-
 static enum ucode_state
 request_microcode_user(int cpu, const void __user *buf, size_t size)
 {
+	struct iov_iter iter;
+	struct iovec iov;
+
 	if (is_blacklisted(cpu))
 		return UCODE_NFOUND;
 
-	return generic_load_microcode(cpu, (void *)buf, size, &get_ucode_user);
+	iov.iov_base = (void __user *)buf;
+	iov.iov_len = size;
+	iov_iter_init(&iter, WRITE, &iov, 1, size);
+
+	return generic_load_microcode(cpu, &iter);
 }
 
 static struct microcode_ops microcode_intel_ops = {

^ permalink raw reply related	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2019-04-10 20:49 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-04-04 11:11 [PATCH] x86/microcode: Refactor Intel microcode loading Jann Horn
2019-04-04 16:27 ` Borislav Petkov
2019-04-04 16:31   ` Jann Horn
2019-04-04 16:47     ` Borislav Petkov
2019-04-04 22:54       ` Jann Horn
2019-04-05  4:10         ` Borislav Petkov
2019-04-10 20:49 ` [tip:x86/microcode] x86/microcode/intel: Refactor Intel microcode blob loading tip-bot for Jann Horn

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.