* [PATCH] x86/boot/compressed/64: Fix boot on machines with broken E820 table
@ 2019-08-13 13:16 Kirill A. Shutemov
2019-08-19 14:16 ` [tip:x86/urgent] " tip-bot for Kirill A. Shutemov
0 siblings, 1 reply; 5+ messages in thread
From: Kirill A. Shutemov @ 2019-08-13 13:16 UTC (permalink / raw)
To: Thomas Gleixner, Ingo Molnar, Borislav Petkov, H. Peter Anvin
Cc: x86, linux-kernel, Kirill A. Shutemov
BIOS on Samsung 500C Chromebook reports very rudimentary E820 table that
consists of 2 entries:
BIOS-e820: [mem 0x0000000000000000-0x0000000000000fff] usable
BIOS-e820: [mem 0x00000000fffff000-0x00000000ffffffff] reserved
It breaks logic in find_trampoline_placement(): bios_start lands on the
end of the first 4k page and trampoline start gets placed below 0.
Detect underflow and don't touch bios_start for such cases. It makes
kernel ignore E820 table on machines that doesn't have two usable pages
below BIOS_START_MAX.
Signed-off-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com>
Fixes: 1b3a62643660 ("x86/boot/compressed/64: Validate trampoline placement against E820")
Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=203463
---
arch/x86/boot/compressed/pgtable_64.c | 13 ++++++++++---
1 file changed, 10 insertions(+), 3 deletions(-)
diff --git a/arch/x86/boot/compressed/pgtable_64.c b/arch/x86/boot/compressed/pgtable_64.c
index 5f2d03067ae5..2faddeb0398a 100644
--- a/arch/x86/boot/compressed/pgtable_64.c
+++ b/arch/x86/boot/compressed/pgtable_64.c
@@ -72,6 +72,8 @@ static unsigned long find_trampoline_placement(void)
/* Find the first usable memory region under bios_start. */
for (i = boot_params->e820_entries - 1; i >= 0; i--) {
+ unsigned long new;
+
entry = &boot_params->e820_table[i];
/* Skip all entries above bios_start. */
@@ -84,15 +86,20 @@ static unsigned long find_trampoline_placement(void)
/* Adjust bios_start to the end of the entry if needed. */
if (bios_start > entry->addr + entry->size)
- bios_start = entry->addr + entry->size;
+ new = entry->addr + entry->size;
/* Keep bios_start page-aligned. */
- bios_start = round_down(bios_start, PAGE_SIZE);
+ new = round_down(new, PAGE_SIZE);
/* Skip the entry if it's too small. */
- if (bios_start - TRAMPOLINE_32BIT_SIZE < entry->addr)
+ if (new - TRAMPOLINE_32BIT_SIZE < entry->addr)
continue;
+ /* Protect against underflow. */
+ if (new - TRAMPOLINE_32BIT_SIZE > bios_start)
+ break;
+
+ bios_start = new;
break;
}
--
2.21.0
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [tip:x86/urgent] x86/boot/compressed/64: Fix boot on machines with broken E820 table
2019-08-13 13:16 [PATCH] x86/boot/compressed/64: Fix boot on machines with broken E820 table Kirill A. Shutemov
@ 2019-08-19 14:16 ` tip-bot for Kirill A. Shutemov
2019-08-26 3:33 ` Gustavo A. R. Silva
0 siblings, 1 reply; 5+ messages in thread
From: tip-bot for Kirill A. Shutemov @ 2019-08-19 14:16 UTC (permalink / raw)
To: linux-tip-commits
Cc: mingo, kirill.shutemov, x86, mingo, linux-kernel, bp, hpa, tglx, kirill
Commit-ID: 0a46fff2f9108c2c44218380a43a736cf4612541
Gitweb: https://git.kernel.org/tip/0a46fff2f9108c2c44218380a43a736cf4612541
Author: Kirill A. Shutemov <kirill@shutemov.name>
AuthorDate: Tue, 13 Aug 2019 16:16:54 +0300
Committer: Borislav Petkov <bp@suse.de>
CommitDate: Mon, 19 Aug 2019 15:59:13 +0200
x86/boot/compressed/64: Fix boot on machines with broken E820 table
BIOS on Samsung 500C Chromebook reports very rudimentary E820 table that
consists of 2 entries:
BIOS-e820: [mem 0x0000000000000000-0x0000000000000fff] usable
BIOS-e820: [mem 0x00000000fffff000-0x00000000ffffffff] reserved
It breaks logic in find_trampoline_placement(): bios_start lands on the
end of the first 4k page and trampoline start gets placed below 0.
Detect underflow and don't touch bios_start for such cases. It makes
kernel ignore E820 table on machines that doesn't have two usable pages
below BIOS_START_MAX.
Fixes: 1b3a62643660 ("x86/boot/compressed/64: Validate trampoline placement against E820")
Signed-off-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com>
Signed-off-by: Borislav Petkov <bp@suse.de>
Cc: "H. Peter Anvin" <hpa@zytor.com>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: x86-ml <x86@kernel.org>
Link: https://bugzilla.kernel.org/show_bug.cgi?id=203463
Link: https://lkml.kernel.org/r/20190813131654.24378-1-kirill.shutemov@linux.intel.com
---
arch/x86/boot/compressed/pgtable_64.c | 13 ++++++++++---
1 file changed, 10 insertions(+), 3 deletions(-)
diff --git a/arch/x86/boot/compressed/pgtable_64.c b/arch/x86/boot/compressed/pgtable_64.c
index 5f2d03067ae5..2faddeb0398a 100644
--- a/arch/x86/boot/compressed/pgtable_64.c
+++ b/arch/x86/boot/compressed/pgtable_64.c
@@ -72,6 +72,8 @@ static unsigned long find_trampoline_placement(void)
/* Find the first usable memory region under bios_start. */
for (i = boot_params->e820_entries - 1; i >= 0; i--) {
+ unsigned long new;
+
entry = &boot_params->e820_table[i];
/* Skip all entries above bios_start. */
@@ -84,15 +86,20 @@ static unsigned long find_trampoline_placement(void)
/* Adjust bios_start to the end of the entry if needed. */
if (bios_start > entry->addr + entry->size)
- bios_start = entry->addr + entry->size;
+ new = entry->addr + entry->size;
/* Keep bios_start page-aligned. */
- bios_start = round_down(bios_start, PAGE_SIZE);
+ new = round_down(new, PAGE_SIZE);
/* Skip the entry if it's too small. */
- if (bios_start - TRAMPOLINE_32BIT_SIZE < entry->addr)
+ if (new - TRAMPOLINE_32BIT_SIZE < entry->addr)
continue;
+ /* Protect against underflow. */
+ if (new - TRAMPOLINE_32BIT_SIZE > bios_start)
+ break;
+
+ bios_start = new;
break;
}
^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [tip:x86/urgent] x86/boot/compressed/64: Fix boot on machines with broken E820 table
2019-08-19 14:16 ` [tip:x86/urgent] " tip-bot for Kirill A. Shutemov
@ 2019-08-26 3:33 ` Gustavo A. R. Silva
2019-08-26 7:15 ` Borislav Petkov
0 siblings, 1 reply; 5+ messages in thread
From: Gustavo A. R. Silva @ 2019-08-26 3:33 UTC (permalink / raw)
To: tglx, bp, hpa, linux-kernel, mingo, x86, mingo, kirill.shutemov,
kirill, linux-tip-commits
Hi all,
On 8/19/19 9:16 AM, tip-bot for Kirill A. Shutemov wrote:
[..]
>
> diff --git a/arch/x86/boot/compressed/pgtable_64.c b/arch/x86/boot/compressed/pgtable_64.c
> index 5f2d03067ae5..2faddeb0398a 100644
> --- a/arch/x86/boot/compressed/pgtable_64.c
> +++ b/arch/x86/boot/compressed/pgtable_64.c
> @@ -72,6 +72,8 @@ static unsigned long find_trampoline_placement(void)
>
> /* Find the first usable memory region under bios_start. */
> for (i = boot_params->e820_entries - 1; i >= 0; i--) {
> + unsigned long new;
> +
> entry = &boot_params->e820_table[i];
>
> /* Skip all entries above bios_start. */
> @@ -84,15 +86,20 @@ static unsigned long find_trampoline_placement(void)
>
> /* Adjust bios_start to the end of the entry if needed. */
> if (bios_start > entry->addr + entry->size)
Notice that if this condition happens to be false, we end up with an
uninitialized variable *new*.
What would be the right value to assign to *new* at declaration under
this condition?
> - bios_start = entry->addr + entry->size;
> + new = entry->addr + entry->size;
>
> /* Keep bios_start page-aligned. */
> - bios_start = round_down(bios_start, PAGE_SIZE);
> + new = round_down(new, PAGE_SIZE);
>
> /* Skip the entry if it's too small. */
> - if (bios_start - TRAMPOLINE_32BIT_SIZE < entry->addr)
> + if (new - TRAMPOLINE_32BIT_SIZE < entry->addr)
> continue;
>
> + /* Protect against underflow. */
> + if (new - TRAMPOLINE_32BIT_SIZE > bios_start)
> + break;
> +
> + bios_start = new;
> break;
> }
>
>
--
Gustavo
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [tip:x86/urgent] x86/boot/compressed/64: Fix boot on machines with broken E820 table
2019-08-26 3:33 ` Gustavo A. R. Silva
@ 2019-08-26 7:15 ` Borislav Petkov
2019-08-26 13:33 ` Kirill A. Shutemov
0 siblings, 1 reply; 5+ messages in thread
From: Borislav Petkov @ 2019-08-26 7:15 UTC (permalink / raw)
To: Gustavo A. R. Silva
Cc: tglx, hpa, linux-kernel, mingo, x86, mingo, kirill.shutemov,
kirill, linux-tip-commits
On Sun, Aug 25, 2019 at 10:33:15PM -0500, Gustavo A. R. Silva wrote:
> Hi all,
>
> On 8/19/19 9:16 AM, tip-bot for Kirill A. Shutemov wrote:
> [..]
> >
> > diff --git a/arch/x86/boot/compressed/pgtable_64.c b/arch/x86/boot/compressed/pgtable_64.c
> > index 5f2d03067ae5..2faddeb0398a 100644
> > --- a/arch/x86/boot/compressed/pgtable_64.c
> > +++ b/arch/x86/boot/compressed/pgtable_64.c
> > @@ -72,6 +72,8 @@ static unsigned long find_trampoline_placement(void)
> >
> > /* Find the first usable memory region under bios_start. */
> > for (i = boot_params->e820_entries - 1; i >= 0; i--) {
> > + unsigned long new;
> > +
> > entry = &boot_params->e820_table[i];
> >
> > /* Skip all entries above bios_start. */
> > @@ -84,15 +86,20 @@ static unsigned long find_trampoline_placement(void)
> >
> > /* Adjust bios_start to the end of the entry if needed. */
> > if (bios_start > entry->addr + entry->size)
>
> Notice that if this condition happens to be false, we end up with an
> uninitialized variable *new*.
Yap, good catch.
> What would be the right value to assign to *new* at declaration under
> this condition?
Looking at the changed flow of the loop, how we use new instead of
bios_start and how we assign new back to bios_start, I think we should
do:
unsigned long new = bios_start;
at the beginning...
--
Regards/Gruss,
Boris.
Good mailing practices for 400: avoid top-posting and trim the reply.
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [tip:x86/urgent] x86/boot/compressed/64: Fix boot on machines with broken E820 table
2019-08-26 7:15 ` Borislav Petkov
@ 2019-08-26 13:33 ` Kirill A. Shutemov
0 siblings, 0 replies; 5+ messages in thread
From: Kirill A. Shutemov @ 2019-08-26 13:33 UTC (permalink / raw)
To: Borislav Petkov
Cc: Gustavo A. R. Silva, tglx, hpa, linux-kernel, mingo, x86, mingo,
kirill.shutemov, linux-tip-commits
On Mon, Aug 26, 2019 at 09:15:39AM +0200, Borislav Petkov wrote:
> On Sun, Aug 25, 2019 at 10:33:15PM -0500, Gustavo A. R. Silva wrote:
> > Hi all,
> >
> > On 8/19/19 9:16 AM, tip-bot for Kirill A. Shutemov wrote:
> > [..]
> > >
> > > diff --git a/arch/x86/boot/compressed/pgtable_64.c b/arch/x86/boot/compressed/pgtable_64.c
> > > index 5f2d03067ae5..2faddeb0398a 100644
> > > --- a/arch/x86/boot/compressed/pgtable_64.c
> > > +++ b/arch/x86/boot/compressed/pgtable_64.c
> > > @@ -72,6 +72,8 @@ static unsigned long find_trampoline_placement(void)
> > >
> > > /* Find the first usable memory region under bios_start. */
> > > for (i = boot_params->e820_entries - 1; i >= 0; i--) {
> > > + unsigned long new;
> > > +
> > > entry = &boot_params->e820_table[i];
> > >
> > > /* Skip all entries above bios_start. */
> > > @@ -84,15 +86,20 @@ static unsigned long find_trampoline_placement(void)
> > >
> > > /* Adjust bios_start to the end of the entry if needed. */
> > > if (bios_start > entry->addr + entry->size)
> >
> > Notice that if this condition happens to be false, we end up with an
> > uninitialized variable *new*.
>
> Yap, good catch.
:facepalm:
> > What would be the right value to assign to *new* at declaration under
> > this condition?
>
> Looking at the changed flow of the loop, how we use new instead of
> bios_start and how we assign new back to bios_start, I think we should
> do:
>
> unsigned long new = bios_start;
>
> at the beginning...
Right.
What about this:
From b613c675e6690ef5608a5abf71d90e15ced31b2b Mon Sep 17 00:00:00 2001
From: "Kirill A. Shutemov" <kirill.shutemov@linux.intel.com>
Date: Mon, 26 Aug 2019 16:26:01 +0300
Subject: [PATCH] x86/boot/compressed/64: Fix missining initialization in
find_trampoline_placement()
Gustavo noticed that 'new' can be left uninitialized if 'bios_start'
happens to be less or equal to 'entry->addr + entry->size'.
Initialize the variable at the start of the iteration to current value
of 'bios_start'.
Signed-off-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com>
Reported-by: "Gustavo A. R. Silva" <gustavo@embeddedor.com>
Fixes: 0a46fff2f910 ("x86/boot/compressed/64: Fix boot on machines with broken E820 table")
---
arch/x86/boot/compressed/pgtable_64.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/x86/boot/compressed/pgtable_64.c b/arch/x86/boot/compressed/pgtable_64.c
index 2faddeb0398a..c8862696a47b 100644
--- a/arch/x86/boot/compressed/pgtable_64.c
+++ b/arch/x86/boot/compressed/pgtable_64.c
@@ -72,7 +72,7 @@ static unsigned long find_trampoline_placement(void)
/* Find the first usable memory region under bios_start. */
for (i = boot_params->e820_entries - 1; i >= 0; i--) {
- unsigned long new;
+ unsigned long new = bios_start;
entry = &boot_params->e820_table[i];
--
Kirill A. Shutemov
^ permalink raw reply related [flat|nested] 5+ messages in thread
end of thread, other threads:[~2019-08-26 13:33 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-08-13 13:16 [PATCH] x86/boot/compressed/64: Fix boot on machines with broken E820 table Kirill A. Shutemov
2019-08-19 14:16 ` [tip:x86/urgent] " tip-bot for Kirill A. Shutemov
2019-08-26 3:33 ` Gustavo A. R. Silva
2019-08-26 7:15 ` Borislav Petkov
2019-08-26 13:33 ` Kirill A. Shutemov
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).