Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > linux.kernel > #1566774 > unrolled thread
| Started by | Borislav Petkov <bp@alien8.de> |
|---|---|
| First post | 2017-01-25 18:30 +0100 |
| Last post | 2017-01-30 10:00 +0100 |
| Articles | 7 — 3 participants |
Back to article view | Back to linux.kernel
This discussion starts older than the indexed window; earlier articles aren't shown. The article labeled Started by
below is the oldest one visible, not the original post.
Re: x86/microcode: use-after-free after cpu offline/online Borislav Petkov <bp@alien8.de> - 2017-01-25 18:30 +0100
Re: x86/microcode: use-after-free after cpu offline/online Borislav Petkov <bp@alien8.de> - 2017-01-25 20:30 +0100
[PATCH] x86/microcode: Do not access the initrd after it has been freed Borislav Petkov <bp@alien8.de> - 2017-01-26 18:00 +0100
Re: [PATCH] x86/microcode: Do not access the initrd after it has been freed Borislav Petkov <bp@alien8.de> - 2017-01-27 10:20 +0100
Re: [PATCH] x86/microcode: Do not access the initrd after it has been freed Ingo Molnar <mingo@kernel.org> - 2017-01-30 10:00 +0100
Re: [PATCH] x86/microcode: Do not access the initrd after it has been freed Borislav Petkov <bp@alien8.de> - 2017-01-30 10:50 +0100
[tip:x86/microcode] x86/microcode: Do not access the initrd after it has been freed tip-bot for Borislav Petkov <tipbot@zytor.com> - 2017-01-30 10:00 +0100
| From | Borislav Petkov <bp@alien8.de> |
|---|---|
| Date | 2017-01-25 18:30 +0100 |
| Subject | Re: x86/microcode: use-after-free after cpu offline/online |
| Message-ID | <t3zyr-4DC-39@gated-at.bofh.it> |
On Wed, Jan 25, 2017 at 07:58:39PM +0300, Andrey Ryabinin wrote:
> On 4.10-rc5
> # echo 0 > /sys/devices/system/cpu/cpu1/online
> # echo 1 > /sys/devices/system/cpu/cpu1/online
>
> triggers use-after-free (probably caused by 06b8534cb72 "x86/microcode: Rework microcode loading").
>
> __load_ucode_intel() accesses initrd which is obviously gone at this point:
Does that help?
---
diff --git a/arch/x86/kernel/cpu/microcode/core.c b/arch/x86/kernel/cpu/microcode/core.c
index 2af69d27da62..fdbf8d29ffcf 100644
--- a/arch/x86/kernel/cpu/microcode/core.c
+++ b/arch/x86/kernel/cpu/microcode/core.c
@@ -248,8 +248,12 @@ struct cpio_data find_microcode_in_initrd(const char *path, bool use_pa)
* possibly relocates the ramdisk. In either case, initrd_start contains
* the updated address so use that instead.
*/
- if (!use_pa && initrd_start)
- start = initrd_start;
+ if (!use_pa) {
+ if (initrd_start)
+ start = initrd_start;
+ else
+ return (struct cpio_data){ NULL, 0, "" };
+ }
return find_cpio_data(path, (void *)start, size, NULL);
#else /* !CONFIG_BLK_DEV_INITRD */
--
Regards/Gruss,
Boris.
Good mailing practices for 400: avoid top-posting and trim the reply.
[toc] | [next] | [standalone]
| From | Borislav Petkov <bp@alien8.de> |
|---|---|
| Date | 2017-01-25 20:30 +0100 |
| Message-ID | <t3Bqx-5Sh-1@gated-at.bofh.it> |
| In reply to | #1566774 |
On Wed, Jan 25, 2017 at 10:14:50PM +0300, Andrey Ryabinin wrote:
> > Does that help?
>
> Yup.
> Tested-by: Andrey Ryabinin <aryabinin@virtuozzo.com>
Thanks, I'll run it through the test boxes here too.
--
Regards/Gruss,
Boris.
Good mailing practices for 400: avoid top-posting and trim the reply.
[toc] | [prev] | [next] | [standalone]
| From | Borislav Petkov <bp@alien8.de> |
|---|---|
| Date | 2017-01-26 18:00 +0100 |
| Subject | [PATCH] x86/microcode: Do not access the initrd after it has been freed |
| Message-ID | <t3VyW-1k9-25@gated-at.bofh.it> |
| In reply to | #1566876 |
On Wed, Jan 25, 2017 at 08:23:36PM +0100, Borislav Petkov wrote:
> On Wed, Jan 25, 2017 at 10:14:50PM +0300, Andrey Ryabinin wrote:
> > > Does that help?
> >
> > Yup.
> > Tested-by: Andrey Ryabinin <aryabinin@virtuozzo.com>
>
> Thanks, I'll run it through the test boxes here too.
Yeah, the fix isn't that simple, I had to do a bit more. Please test
that one instead.
Thanks.
---
From: Borislav Petkov <bp@suse.de>
Date: Wed, 25 Jan 2017 21:00:48 +0100
Subject: [PATCH] x86/microcode: Do not access the initrd after it has been freed
When we look for microcode blobs, we first try builtin and if that
doesn't succeed, we fallback to the initrd supplied to the kernel.
However, at some point doing boot, that initrd gets jettisoned and we
shouldn't access it anymore. But we do, as the below KASAN report shows.
That's because find_microcode_in_initrd() doesn't check whether the
initrd is still valid or not.
So do that.
==================================================================
BUG: KASAN: use-after-free in find_cpio_data
Read of size 1 by task swapper/1/0
page:ffffea0000db9d40 count:0 mapcount:0 mapping: (null) index:0x1
flags: 0x100000000000000()
raw: 0100000000000000 0000000000000000 0000000000000001 00000000ffffffff
raw: dead000000000100 dead000000000200 0000000000000000 0000000000000000
page dumped because: kasan: bad access detected
CPU: 1 PID: 0 Comm: swapper/1 Tainted: G W 4.10.0-rc5-debug-00075-g2dbde22 #3
Hardware name: Dell Inc. XPS 13 9360/0839Y6, BIOS 1.2.3 12/01/2016
Call Trace:
dump_stack
? _atomic_dec_and_lock
? __dump_page
kasan_report_error
? pointer
? find_cpio_data
__asan_report_load1_noabort
? find_cpio_data
find_cpio_data
? vsprintf
? dump_stack
? get_ucode_user
? print_usage_bug
find_microcode_in_initrd
__load_ucode_intel
? collect_cpu_info_early
? debug_check_no_locks_freed
load_ucode_intel_ap
? collect_cpu_info
? trace_hardirqs_on
? flat_send_IPI_mask_allbutself
load_ucode_ap
? get_builtin_firmware
? flush_tlb_func
? do_raw_spin_trylock
? cpumask_weight
cpu_init
? trace_hardirqs_off
? play_dead_common
? native_play_dead
? hlt_play_dead
? syscall_init
? arch_cpu_idle_dead
? do_idle
start_secondary
start_cpu
Memory state around the buggy address:
ffff880036e74f00: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
ffff880036e74f80: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
>ffff880036e75000: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
^
ffff880036e75080: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
ffff880036e75100: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
==================================================================
Reported-by: Andrey Ryabinin <aryabinin@virtuozzo.com>
Signed-off-by: Borislav Petkov <bp@suse.de>
---
arch/x86/include/asm/microcode.h | 1 +
arch/x86/kernel/cpu/microcode/amd.c | 5 +++--
arch/x86/kernel/cpu/microcode/core.c | 22 +++++++++++++++++-----
3 files changed, 21 insertions(+), 7 deletions(-)
diff --git a/arch/x86/include/asm/microcode.h b/arch/x86/include/asm/microcode.h
index 38711df3bcb5..2266f864b747 100644
--- a/arch/x86/include/asm/microcode.h
+++ b/arch/x86/include/asm/microcode.h
@@ -140,6 +140,7 @@ extern void __init load_ucode_bsp(void);
extern void load_ucode_ap(void);
void reload_early_microcode(void);
extern bool get_builtin_firmware(struct cpio_data *cd, const char *name);
+extern bool initrd_gone;
#else
static inline int __init microcode_init(void) { return 0; };
static inline void __init load_ucode_bsp(void) { }
diff --git a/arch/x86/kernel/cpu/microcode/amd.c b/arch/x86/kernel/cpu/microcode/amd.c
index 6a31e2691f3a..079e81733a58 100644
--- a/arch/x86/kernel/cpu/microcode/amd.c
+++ b/arch/x86/kernel/cpu/microcode/amd.c
@@ -384,8 +384,9 @@ void load_ucode_amd_ap(unsigned int family)
reget:
if (!get_builtin_microcode(&cp, family)) {
#ifdef CONFIG_BLK_DEV_INITRD
- cp = find_cpio_data(ucode_path, (void *)initrd_start,
- initrd_end - initrd_start, NULL);
+ if (!initrd_gone)
+ cp = find_cpio_data(ucode_path, (void *)initrd_start,
+ initrd_end - initrd_start, NULL);
#endif
if (!(cp.data && cp.size)) {
/*
diff --git a/arch/x86/kernel/cpu/microcode/core.c b/arch/x86/kernel/cpu/microcode/core.c
index 2af69d27da62..73102d932760 100644
--- a/arch/x86/kernel/cpu/microcode/core.c
+++ b/arch/x86/kernel/cpu/microcode/core.c
@@ -46,6 +46,8 @@
static struct microcode_ops *microcode_ops;
static bool dis_ucode_ldr = true;
+bool initrd_gone;
+
LIST_HEAD(microcode_cache);
/*
@@ -190,21 +192,24 @@ void load_ucode_ap(void)
static int __init save_microcode_in_initrd(void)
{
struct cpuinfo_x86 *c = &boot_cpu_data;
+ int ret = -EINVAL;
switch (c->x86_vendor) {
case X86_VENDOR_INTEL:
if (c->x86 >= 6)
- return save_microcode_in_initrd_intel();
+ ret = save_microcode_in_initrd_intel();
break;
case X86_VENDOR_AMD:
if (c->x86 >= 0x10)
- return save_microcode_in_initrd_amd(c->x86);
+ ret = save_microcode_in_initrd_amd(c->x86);
break;
default:
break;
}
- return -EINVAL;
+ initrd_gone = true;
+
+ return ret;
}
struct cpio_data find_microcode_in_initrd(const char *path, bool use_pa)
@@ -247,9 +252,16 @@ struct cpio_data find_microcode_in_initrd(const char *path, bool use_pa)
* has the virtual address of the beginning of the initrd. It also
* possibly relocates the ramdisk. In either case, initrd_start contains
* the updated address so use that instead.
+ *
+ * initrd_gone is for the hotplug case where we've thrown out initrd
+ * already.
*/
- if (!use_pa && initrd_start)
- start = initrd_start;
+ if (!use_pa) {
+ if (initrd_gone)
+ return (struct cpio_data){ NULL, 0, "" };
+ if (initrd_start)
+ start = initrd_start;
+ }
return find_cpio_data(path, (void *)start, size, NULL);
#else /* !CONFIG_BLK_DEV_INITRD */
--
2.11.0
--
Regards/Gruss,
Boris.
Good mailing practices for 400: avoid top-posting and trim the reply.
[toc] | [prev] | [next] | [standalone]
| From | Borislav Petkov <bp@alien8.de> |
|---|---|
| Date | 2017-01-27 10:20 +0100 |
| Subject | Re: [PATCH] x86/microcode: Do not access the initrd after it has been freed |
| Message-ID | <t4aRk-2ha-19@gated-at.bofh.it> |
| In reply to | #1567596 |
On Fri, Jan 27, 2017 at 11:14:06AM +0300, Andrey Ryabinin wrote:
> Works for me as well.
> Tested-by: Andrey Ryabinin <aryabinin@virtuozzo.com>
Thanks!
--
Regards/Gruss,
Boris.
Good mailing practices for 400: avoid top-posting and trim the reply.
[toc] | [prev] | [next] | [standalone]
| From | Ingo Molnar <mingo@kernel.org> |
|---|---|
| Date | 2017-01-30 10:00 +0100 |
| Subject | Re: [PATCH] x86/microcode: Do not access the initrd after it has been freed |
| Message-ID | <t5fYC-1PU-21@gated-at.bofh.it> |
| In reply to | #1567976 |
* Borislav Petkov <bp@alien8.de> wrote: > On Fri, Jan 27, 2017 at 11:14:06AM +0300, Andrey Ryabinin wrote: > > Works for me as well. > > Tested-by: Andrey Ryabinin <aryabinin@virtuozzo.com> > > Thanks! Ok, I have applied this to tip:x86/urgent. Note that there are new conflicts with your pending work in tip:x86/microcode, and I fixed them up in: 7c5b4112040e Merge branch 'x86/urgent' into x86/microcode, to resolve conflicts Could you please double-check my conflict resolution? Thanks, Ingo
[toc] | [prev] | [next] | [standalone]
| From | Borislav Petkov <bp@alien8.de> |
|---|---|
| Date | 2017-01-30 10:50 +0100 |
| Subject | Re: [PATCH] x86/microcode: Do not access the initrd after it has been freed |
| Message-ID | <t5gL0-2ll-9@gated-at.bofh.it> |
| In reply to | #1569474 |
On Mon, Jan 30, 2017 at 09:46:32AM +0100, Ingo Molnar wrote:
> Ok, I have applied this to tip:x86/urgent.
>
> Note that there are new conflicts with your pending work in tip:x86/microcode, and
> I fixed them up in:
>
> 7c5b4112040e Merge branch 'x86/urgent' into x86/microcode, to resolve conflicts
>
> Could you please double-check my conflict resolution?
Almost, this part is wrong:
--------------------- arch/x86/kernel/cpu/microcode/amd.c ---------------------
index 7889ae492af0,079e81733a58..73082365ed1c
@@@ -268,20 -316,43 +268,20 @@@ void __load_ucode_amd(unsigned int cpui
use_pa = false;
}
- if (!get_builtin_microcode(&cp, x86_family(cpuid_1_eax)))
- if (!get_builtin_microcode(&cp, family))
++ if (!get_builtin_microcode(&cp, x86_family(cpuid_1_eax)) && !initrd_gone)
cp = find_microcode_in_initrd(path, use_pa);
--
Btw, I did experiment with the merging because I knew it'll cause
trouble due to the urgent fix and here's what I did:
You're merging tip/x86/urgent into tip/x86/microcode so I checked out
the microcode branch and did:
$ git checkout -b tip-microcode tip/x86/microcode
$ git merge -s recursive -X ours tip/x86/urgent
This way I'm favouring our changes in the conflicting files. It merges
cleanly and the resulting diff is below.
The logic behind it is is that tip/x86/microcode does away with a bunch
of code and the urgent change touches some of that code but that's only
for 4.10.
It goes away in 4.11 and that's why we should prefer "ours" as the merge
option.
[ Btw, I'll send a patch for 4.11 later to make initrd_gone static as
it is going to be used only in microcode/core.c after the cleanup. ]
However, I still haven't figured out how to say "prefer ours but only
for specific files or subtree" because the diff has that hunk in
arch/x86/kernel/fpu/core.c too which should definitely not be "ours" as
it is a fix and there the urgent version should be the one going in.
Hmmm.
---
$ git diff HEAD~1..
diff --git a/arch/x86/include/asm/microcode.h b/arch/x86/include/asm/microcode.h
index 90b22bbdfce9..daadeeea00b1 100644
--- a/arch/x86/include/asm/microcode.h
+++ b/arch/x86/include/asm/microcode.h
@@ -139,6 +139,7 @@ extern void __init load_ucode_bsp(void);
extern void load_ucode_ap(void);
void reload_early_microcode(void);
extern bool get_builtin_firmware(struct cpio_data *cd, const char *name);
+extern bool initrd_gone;
#else
static inline int __init microcode_init(void) { return 0; };
static inline void __init load_ucode_bsp(void) { }
diff --git a/arch/x86/kernel/cpu/microcode/core.c b/arch/x86/kernel/cpu/microcode/core.c
index 3b74d2f315d3..b4a4cd39b358 100644
--- a/arch/x86/kernel/cpu/microcode/core.c
+++ b/arch/x86/kernel/cpu/microcode/core.c
@@ -46,6 +46,8 @@
static struct microcode_ops *microcode_ops;
static bool dis_ucode_ldr = true;
+bool initrd_gone;
+
LIST_HEAD(microcode_cache);
/*
@@ -219,11 +221,12 @@ void load_ucode_ap(void)
static int __init save_microcode_in_initrd(void)
{
struct cpuinfo_x86 *c = &boot_cpu_data;
+ int ret = -EINVAL;
switch (c->x86_vendor) {
case X86_VENDOR_INTEL:
if (c->x86 >= 6)
- return save_microcode_in_initrd_intel();
+ ret = save_microcode_in_initrd_intel();
break;
case X86_VENDOR_AMD:
if (c->x86 >= 0x10)
@@ -233,7 +236,9 @@ static int __init save_microcode_in_initrd(void)
break;
}
- return -EINVAL;
+ initrd_gone = true;
+
+ return ret;
}
struct cpio_data find_microcode_in_initrd(const char *path, bool use_pa)
@@ -276,9 +281,16 @@ struct cpio_data find_microcode_in_initrd(const char *path, bool use_pa)
* has the virtual address of the beginning of the initrd. It also
* possibly relocates the ramdisk. In either case, initrd_start contains
* the updated address so use that instead.
+ *
+ * initrd_gone is for the hotplug case where we've thrown out initrd
+ * already.
*/
- if (!use_pa && initrd_start)
- start = initrd_start;
+ if (!use_pa) {
+ if (initrd_gone)
+ return (struct cpio_data){ NULL, 0, "" };
+ if (initrd_start)
+ start = initrd_start;
+ }
return find_cpio_data(path, (void *)start, size, NULL);
#else /* !CONFIG_BLK_DEV_INITRD */
diff --git a/arch/x86/kernel/fpu/core.c b/arch/x86/kernel/fpu/core.c
index e4e97a5355ce..de7234401275 100644
--- a/arch/x86/kernel/fpu/core.c
+++ b/arch/x86/kernel/fpu/core.c
@@ -9,6 +9,7 @@
#include <asm/fpu/regset.h>
#include <asm/fpu/signal.h>
#include <asm/fpu/types.h>
+#include <asm/fpu/xstate.h>
#include <asm/traps.h>
#include <linux/hardirq.h>
@@ -183,7 +184,8 @@ void fpstate_init(union fpregs_state *state)
* it will #GP. Make sure it is replaced after the memset().
*/
if (static_cpu_has(X86_FEATURE_XSAVES))
- state->xsave.header.xcomp_bv = XCOMP_BV_COMPACTED_FORMAT;
+ state->xsave.header.xcomp_bv = XCOMP_BV_COMPACTED_FORMAT |
+ xfeatures_mask;
if (static_cpu_has(X86_FEATURE_FXSR))
fpstate_init_fxstate(&state->fxsave);
--
Regards/Gruss,
Boris.
Good mailing practices for 400: avoid top-posting and trim the reply.
[toc] | [prev] | [next] | [standalone]
| From | tip-bot for Borislav Petkov <tipbot@zytor.com> |
|---|---|
| Date | 2017-01-30 10:00 +0100 |
| Subject | [tip:x86/microcode] x86/microcode: Do not access the initrd after it has been freed |
| Message-ID | <t5fYC-1PU-7@gated-at.bofh.it> |
| In reply to | #1567596 |
Commit-ID: 24c2503255d35c269b67162c397a1a1c1e02f6ce
Gitweb: http://git.kernel.org/tip/24c2503255d35c269b67162c397a1a1c1e02f6ce
Author: Borislav Petkov <bp@suse.de>
AuthorDate: Wed, 25 Jan 2017 21:00:48 +0100
Committer: Ingo Molnar <mingo@kernel.org>
CommitDate: Mon, 30 Jan 2017 09:32:42 +0100
x86/microcode: Do not access the initrd after it has been freed
When we look for microcode blobs, we first try builtin and if that
doesn't succeed, we fallback to the initrd supplied to the kernel.
However, at some point doing boot, that initrd gets jettisoned and we
shouldn't access it anymore. But we do, as the below KASAN report shows.
That's because find_microcode_in_initrd() doesn't check whether the
initrd is still valid or not.
So do that.
==================================================================
BUG: KASAN: use-after-free in find_cpio_data
Read of size 1 by task swapper/1/0
page:ffffea0000db9d40 count:0 mapcount:0 mapping: (null) index:0x1
flags: 0x100000000000000()
raw: 0100000000000000 0000000000000000 0000000000000001 00000000ffffffff
raw: dead000000000100 dead000000000200 0000000000000000 0000000000000000
page dumped because: kasan: bad access detected
CPU: 1 PID: 0 Comm: swapper/1 Tainted: G W 4.10.0-rc5-debug-00075-g2dbde22 #3
Hardware name: Dell Inc. XPS 13 9360/0839Y6, BIOS 1.2.3 12/01/2016
Call Trace:
dump_stack
? _atomic_dec_and_lock
? __dump_page
kasan_report_error
? pointer
? find_cpio_data
__asan_report_load1_noabort
? find_cpio_data
find_cpio_data
? vsprintf
? dump_stack
? get_ucode_user
? print_usage_bug
find_microcode_in_initrd
__load_ucode_intel
? collect_cpu_info_early
? debug_check_no_locks_freed
load_ucode_intel_ap
? collect_cpu_info
? trace_hardirqs_on
? flat_send_IPI_mask_allbutself
load_ucode_ap
? get_builtin_firmware
? flush_tlb_func
? do_raw_spin_trylock
? cpumask_weight
cpu_init
? trace_hardirqs_off
? play_dead_common
? native_play_dead
? hlt_play_dead
? syscall_init
? arch_cpu_idle_dead
? do_idle
start_secondary
start_cpu
Memory state around the buggy address:
ffff880036e74f00: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
ffff880036e74f80: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
>ffff880036e75000: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
^
ffff880036e75080: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
ffff880036e75100: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
==================================================================
Reported-by: Andrey Ryabinin <aryabinin@virtuozzo.com>
Tested-by: Andrey Ryabinin <aryabinin@virtuozzo.com>
Signed-off-by: Borislav Petkov <bp@suse.de>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Link: http://lkml.kernel.org/r/20170126165833.evjemhbqzaepirxo@pd.tnic
Signed-off-by: Ingo Molnar <mingo@kernel.org>
---
arch/x86/include/asm/microcode.h | 1 +
arch/x86/kernel/cpu/microcode/amd.c | 5 +++--
arch/x86/kernel/cpu/microcode/core.c | 22 +++++++++++++++++-----
3 files changed, 21 insertions(+), 7 deletions(-)
diff --git a/arch/x86/include/asm/microcode.h b/arch/x86/include/asm/microcode.h
index 38711df..2266f86 100644
--- a/arch/x86/include/asm/microcode.h
+++ b/arch/x86/include/asm/microcode.h
@@ -140,6 +140,7 @@ extern void __init load_ucode_bsp(void);
extern void load_ucode_ap(void);
void reload_early_microcode(void);
extern bool get_builtin_firmware(struct cpio_data *cd, const char *name);
+extern bool initrd_gone;
#else
static inline int __init microcode_init(void) { return 0; };
static inline void __init load_ucode_bsp(void) { }
diff --git a/arch/x86/kernel/cpu/microcode/amd.c b/arch/x86/kernel/cpu/microcode/amd.c
index 6a31e26..079e817 100644
--- a/arch/x86/kernel/cpu/microcode/amd.c
+++ b/arch/x86/kernel/cpu/microcode/amd.c
@@ -384,8 +384,9 @@ void load_ucode_amd_ap(unsigned int family)
reget:
if (!get_builtin_microcode(&cp, family)) {
#ifdef CONFIG_BLK_DEV_INITRD
- cp = find_cpio_data(ucode_path, (void *)initrd_start,
- initrd_end - initrd_start, NULL);
+ if (!initrd_gone)
+ cp = find_cpio_data(ucode_path, (void *)initrd_start,
+ initrd_end - initrd_start, NULL);
#endif
if (!(cp.data && cp.size)) {
/*
diff --git a/arch/x86/kernel/cpu/microcode/core.c b/arch/x86/kernel/cpu/microcode/core.c
index 2af69d2..73102d9 100644
--- a/arch/x86/kernel/cpu/microcode/core.c
+++ b/arch/x86/kernel/cpu/microcode/core.c
@@ -46,6 +46,8 @@
static struct microcode_ops *microcode_ops;
static bool dis_ucode_ldr = true;
+bool initrd_gone;
+
LIST_HEAD(microcode_cache);
/*
@@ -190,21 +192,24 @@ void load_ucode_ap(void)
static int __init save_microcode_in_initrd(void)
{
struct cpuinfo_x86 *c = &boot_cpu_data;
+ int ret = -EINVAL;
switch (c->x86_vendor) {
case X86_VENDOR_INTEL:
if (c->x86 >= 6)
- return save_microcode_in_initrd_intel();
+ ret = save_microcode_in_initrd_intel();
break;
case X86_VENDOR_AMD:
if (c->x86 >= 0x10)
- return save_microcode_in_initrd_amd(c->x86);
+ ret = save_microcode_in_initrd_amd(c->x86);
break;
default:
break;
}
- return -EINVAL;
+ initrd_gone = true;
+
+ return ret;
}
struct cpio_data find_microcode_in_initrd(const char *path, bool use_pa)
@@ -247,9 +252,16 @@ struct cpio_data find_microcode_in_initrd(const char *path, bool use_pa)
* has the virtual address of the beginning of the initrd. It also
* possibly relocates the ramdisk. In either case, initrd_start contains
* the updated address so use that instead.
+ *
+ * initrd_gone is for the hotplug case where we've thrown out initrd
+ * already.
*/
- if (!use_pa && initrd_start)
- start = initrd_start;
+ if (!use_pa) {
+ if (initrd_gone)
+ return (struct cpio_data){ NULL, 0, "" };
+ if (initrd_start)
+ start = initrd_start;
+ }
return find_cpio_data(path, (void *)start, size, NULL);
#else /* !CONFIG_BLK_DEV_INITRD */
[toc] | [prev] | [standalone]
Back to top | Article view | linux.kernel
csiph-web