All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] x86/boot/compressed: Correct relocation destination on old linkers
@ 2020-01-11 19:00 Arvind Sankar
  2020-02-07 21:49 ` [PATCH v2] x86/boot: " Arvind Sankar
  0 siblings, 1 reply; 5+ messages in thread
From: Arvind Sankar @ 2020-01-11 19:00 UTC (permalink / raw)
  To: Thomas Gleixner, Ingo Molnar, Borislav Petkov, H. Peter Anvin
  Cc: x86, linux-kernel

As described in commit 6d92bc9d483a ("x86/build: Build compressed x86
kernels as PIE"), pre-2.26 binutils generates R_386_32 relocations in
PIE mode.  Since the startup code does not perform relocation, any reloc
entry with R_386_32 will remain as 0 in the executing code.

Commit 974f221c84b0 ("x86/boot: Move compressed kernel to the end of the
decompression buffer") added a new symbol _end but did not mark it
hidden, which doesn't give the correct offset on older linkers. This
doesn't cause a crash, but means the compressed kernel is actually
relocated starting from the end of the decompression buffer, rather than
ending there.

Mark _end as hidden to fix.

Fixes: 974f221c84b0 ("x86/boot: Move compressed kernel to the end of the decompression buffer")
Signed-off-by: Arvind Sankar <nivedita@alum.mit.edu>
---
 arch/x86/boot/compressed/head_32.S | 5 +++--
 arch/x86/boot/compressed/head_64.S | 1 +
 2 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/arch/x86/boot/compressed/head_32.S b/arch/x86/boot/compressed/head_32.S
index f2dfd6d083ef..e4d1142f9f65 100644
--- a/arch/x86/boot/compressed/head_32.S
+++ b/arch/x86/boot/compressed/head_32.S
@@ -49,16 +49,17 @@
  * Position Independent Executable (PIE) so that linker won't optimize
  * R_386_GOT32X relocation to its fixed symbol address.  Older
  * linkers generate R_386_32 relocations against locally defined symbols,
- * _bss, _ebss, _got and _egot, in PIE.  It isn't wrong, just less
+ * _bss, _ebss, _got, _egot and _end, in PIE.  It isn't wrong, just less
  * optimal than R_386_RELATIVE.  But the x86 kernel fails to properly handle
  * R_386_32 relocations when relocating the kernel.  To generate
- * R_386_RELATIVE relocations, we mark _bss, _ebss, _got and _egot as
+ * R_386_RELATIVE relocations, we mark _bss, _ebss, _got, _egot and _end as
  * hidden:
  */
 	.hidden _bss
 	.hidden _ebss
 	.hidden _got
 	.hidden _egot
+	.hidden _end
 
 	__HEAD
 SYM_FUNC_START(startup_32)
diff --git a/arch/x86/boot/compressed/head_64.S b/arch/x86/boot/compressed/head_64.S
index 6eb30f8a3ce7..206fb95e827c 100644
--- a/arch/x86/boot/compressed/head_64.S
+++ b/arch/x86/boot/compressed/head_64.S
@@ -42,6 +42,7 @@
 	.hidden _ebss
 	.hidden _got
 	.hidden _egot
+	.hidden _end
 
 	__HEAD
 	.code32
-- 
2.24.1


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

* [PATCH v2] x86/boot: Correct relocation destination on old linkers
  2020-01-11 19:00 [PATCH] x86/boot/compressed: Correct relocation destination on old linkers Arvind Sankar
@ 2020-02-07 21:49 ` Arvind Sankar
  2020-03-13 18:33   ` Arvind Sankar
  2020-05-19 12:35   ` [tip: x86/boot] " tip-bot2 for Arvind Sankar
  0 siblings, 2 replies; 5+ messages in thread
From: Arvind Sankar @ 2020-02-07 21:49 UTC (permalink / raw)
  To: Thomas Gleixner, Ingo Molnar, Borislav Petkov, H. Peter Anvin
  Cc: x86, linux-kernel, H.J. Lu

For the 32-bit kernel, as described in commit 6d92bc9d483a ("x86/build:
Build compressed x86 kernels as PIE"), pre-2.26 binutils generates
R_386_32 relocations in PIE mode.  Since the startup code does not
perform relocation, any reloc entry with R_386_32 will remain as 0 in
the executing code.

Commit 974f221c84b0 ("x86/boot: Move compressed kernel to the end of the
decompression buffer") added a new symbol _end but did not mark it
hidden, which doesn't give the correct offset on older linkers. This
causes the compressed kernel to be copied beyond the end of the
decompression buffer, rather than flush against it. This region of
memory may be reserved or already allocated for other purposes by the
bootloader.

Mark _end as hidden to fix. This changes the relocation from R_386_32 to
R_386_RELATIVE even on the pre-2.26 binutils.

For 64-bit, this is not strictly necessary, as the 64-bit kernel is only
built as PIE if the linker supports -z noreloc-overflow, which implies
binutils-2.27+, but for consistency, mark _end as hidden here too.

The below illustrates the before/after impact of the patch using
binutils-2.25 and gcc-4.6.4 (locally compiled from source) and QEMU.

Disassembly before patch:
  48:   8b 86 60 02 00 00       mov    0x260(%esi),%eax
  4e:   2d 00 00 00 00          sub    $0x0,%eax
                        4f: R_386_32    _end
Disassembly after patch:
  48:   8b 86 60 02 00 00       mov    0x260(%esi),%eax
  4e:   2d 00 f0 76 00          sub    $0x76f000,%eax
                        4f: R_386_RELATIVE      *ABS*

Dump from extract_kernel before patch:
	early console in extract_kernel
	input_data: 0x0207c098 <--- this is at output + init_size
	input_len: 0x0074fef1
	output: 0x01000000
	output_len: 0x00fa63d0
	kernel_total_size: 0x0107c000
	needed_size: 0x0107c000

Dump from extract_kernel after patch:
	early console in extract_kernel
	input_data: 0x0190d098 <--- this is at output + init_size - _end
	input_len: 0x0074fef1
	output: 0x01000000
	output_len: 0x00fa63d0
	kernel_total_size: 0x0107c000
	needed_size: 0x0107c000

Fixes: 974f221c84b0 ("x86/boot: Move compressed kernel to the end of the decompression buffer")
Signed-off-by: Arvind Sankar <nivedita@alum.mit.edu>
---
Changes from v1: more extensive commit message illustrating the issue

 arch/x86/boot/compressed/head_32.S | 5 +++--
 arch/x86/boot/compressed/head_64.S | 1 +
 2 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/arch/x86/boot/compressed/head_32.S b/arch/x86/boot/compressed/head_32.S
index 73f17d0544dd..bf707c989236 100644
--- a/arch/x86/boot/compressed/head_32.S
+++ b/arch/x86/boot/compressed/head_32.S
@@ -49,16 +49,17 @@
  * Position Independent Executable (PIE) so that linker won't optimize
  * R_386_GOT32X relocation to its fixed symbol address.  Older
  * linkers generate R_386_32 relocations against locally defined symbols,
- * _bss, _ebss, _got and _egot, in PIE.  It isn't wrong, just less
+ * _bss, _ebss, _got, _egot and _end, in PIE.  It isn't wrong, just less
  * optimal than R_386_RELATIVE.  But the x86 kernel fails to properly handle
  * R_386_32 relocations when relocating the kernel.  To generate
- * R_386_RELATIVE relocations, we mark _bss, _ebss, _got and _egot as
+ * R_386_RELATIVE relocations, we mark _bss, _ebss, _got, _egot and _end as
  * hidden:
  */
 	.hidden _bss
 	.hidden _ebss
 	.hidden _got
 	.hidden _egot
+	.hidden _end
 
 	__HEAD
 SYM_FUNC_START(startup_32)
diff --git a/arch/x86/boot/compressed/head_64.S b/arch/x86/boot/compressed/head_64.S
index 1f1f6c8139b3..949909548b86 100644
--- a/arch/x86/boot/compressed/head_64.S
+++ b/arch/x86/boot/compressed/head_64.S
@@ -42,6 +42,7 @@
 	.hidden _ebss
 	.hidden _got
 	.hidden _egot
+	.hidden _end
 
 	__HEAD
 	.code32
-- 
2.24.1


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

* Re: [PATCH v2] x86/boot: Correct relocation destination on old linkers
  2020-02-07 21:49 ` [PATCH v2] x86/boot: " Arvind Sankar
@ 2020-03-13 18:33   ` Arvind Sankar
  2020-05-16 23:12     ` Arvind Sankar
  2020-05-19 12:35   ` [tip: x86/boot] " tip-bot2 for Arvind Sankar
  1 sibling, 1 reply; 5+ messages in thread
From: Arvind Sankar @ 2020-03-13 18:33 UTC (permalink / raw)
  To: Arvind Sankar
  Cc: Thomas Gleixner, Ingo Molnar, Borislav Petkov, H. Peter Anvin,
	x86, linux-kernel, H.J. Lu

On Fri, Feb 07, 2020 at 04:49:26PM -0500, Arvind Sankar wrote:
> For the 32-bit kernel, as described in commit 6d92bc9d483a ("x86/build:
> Build compressed x86 kernels as PIE"), pre-2.26 binutils generates
> R_386_32 relocations in PIE mode.  Since the startup code does not
> perform relocation, any reloc entry with R_386_32 will remain as 0 in
> the executing code.
> 
> Commit 974f221c84b0 ("x86/boot: Move compressed kernel to the end of the
> decompression buffer") added a new symbol _end but did not mark it
> hidden, which doesn't give the correct offset on older linkers. This
> causes the compressed kernel to be copied beyond the end of the
> decompression buffer, rather than flush against it. This region of
> memory may be reserved or already allocated for other purposes by the
> bootloader.
> 
> Mark _end as hidden to fix. This changes the relocation from R_386_32 to
> R_386_RELATIVE even on the pre-2.26 binutils.
> 
> For 64-bit, this is not strictly necessary, as the 64-bit kernel is only
> built as PIE if the linker supports -z noreloc-overflow, which implies
> binutils-2.27+, but for consistency, mark _end as hidden here too.
> 

Gentle reminder.

https://lore.kernel.org/lkml/20200207214926.3564079-1-nivedita@alum.mit.edu/

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

* Re: [PATCH v2] x86/boot: Correct relocation destination on old linkers
  2020-03-13 18:33   ` Arvind Sankar
@ 2020-05-16 23:12     ` Arvind Sankar
  0 siblings, 0 replies; 5+ messages in thread
From: Arvind Sankar @ 2020-05-16 23:12 UTC (permalink / raw)
  To: Arvind Sankar
  Cc: Thomas Gleixner, Ingo Molnar, Borislav Petkov, H. Peter Anvin,
	x86, linux-kernel, H.J. Lu

On Fri, Mar 13, 2020 at 02:33:50PM -0400, Arvind Sankar wrote:
> On Fri, Feb 07, 2020 at 04:49:26PM -0500, Arvind Sankar wrote:
> > For the 32-bit kernel, as described in commit 6d92bc9d483a ("x86/build:
> > Build compressed x86 kernels as PIE"), pre-2.26 binutils generates
> > R_386_32 relocations in PIE mode.  Since the startup code does not
> > perform relocation, any reloc entry with R_386_32 will remain as 0 in
> > the executing code.
> > 
> > Commit 974f221c84b0 ("x86/boot: Move compressed kernel to the end of the
> > decompression buffer") added a new symbol _end but did not mark it
> > hidden, which doesn't give the correct offset on older linkers. This
> > causes the compressed kernel to be copied beyond the end of the
> > decompression buffer, rather than flush against it. This region of
> > memory may be reserved or already allocated for other purposes by the
> > bootloader.
> > 
> > Mark _end as hidden to fix. This changes the relocation from R_386_32 to
> > R_386_RELATIVE even on the pre-2.26 binutils.
> > 
> > For 64-bit, this is not strictly necessary, as the 64-bit kernel is only
> > built as PIE if the linker supports -z noreloc-overflow, which implies
> > binutils-2.27+, but for consistency, mark _end as hidden here too.
> > 
> 
> Gentle reminder.
> 
> https://lore.kernel.org/lkml/20200207214926.3564079-1-nivedita@alum.mit.edu/

Ping.

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

* [tip: x86/boot] x86/boot: Correct relocation destination on old linkers
  2020-02-07 21:49 ` [PATCH v2] x86/boot: " Arvind Sankar
  2020-03-13 18:33   ` Arvind Sankar
@ 2020-05-19 12:35   ` tip-bot2 for Arvind Sankar
  1 sibling, 0 replies; 5+ messages in thread
From: tip-bot2 for Arvind Sankar @ 2020-05-19 12:35 UTC (permalink / raw)
  To: linux-tip-commits; +Cc: Arvind Sankar, Borislav Petkov, x86, LKML

The following commit has been merged into the x86/boot branch of tip:

Commit-ID:     5214028dd89e49ba27007c3ee475279e584261f0
Gitweb:        https://git.kernel.org/tip/5214028dd89e49ba27007c3ee475279e584261f0
Author:        Arvind Sankar <nivedita@alum.mit.edu>
AuthorDate:    Fri, 07 Feb 2020 16:49:26 -05:00
Committer:     Borislav Petkov <bp@suse.de>
CommitterDate: Tue, 19 May 2020 14:11:22 +02:00

x86/boot: Correct relocation destination on old linkers

For the 32-bit kernel, as described in

  6d92bc9d483a ("x86/build: Build compressed x86 kernels as PIE"),

pre-2.26 binutils generates R_386_32 relocations in PIE mode. Since the
startup code does not perform relocation, any reloc entry with R_386_32
will remain as 0 in the executing code.

Commit

  974f221c84b0 ("x86/boot: Move compressed kernel to the end of the
                 decompression buffer")

added a new symbol _end but did not mark it hidden, which doesn't give
the correct offset on older linkers. This causes the compressed kernel
to be copied beyond the end of the decompression buffer, rather than
flush against it. This region of memory may be reserved or already
allocated for other purposes by the bootloader.

Mark _end as hidden to fix. This changes the relocation from R_386_32 to
R_386_RELATIVE even on the pre-2.26 binutils.

For 64-bit, this is not strictly necessary, as the 64-bit kernel is only
built as PIE if the linker supports -z noreloc-overflow, which implies
binutils-2.27+, but for consistency, mark _end as hidden here too.

The below illustrates the before/after impact of the patch using
binutils-2.25 and gcc-4.6.4 (locally compiled from source) and QEMU.

  Disassembly before patch:
    48:   8b 86 60 02 00 00       mov    0x260(%esi),%eax
    4e:   2d 00 00 00 00          sub    $0x0,%eax
                          4f: R_386_32    _end
  Disassembly after patch:
    48:   8b 86 60 02 00 00       mov    0x260(%esi),%eax
    4e:   2d 00 f0 76 00          sub    $0x76f000,%eax
                          4f: R_386_RELATIVE      *ABS*

Dump from extract_kernel before patch:
	early console in extract_kernel
	input_data: 0x0207c098 <--- this is at output + init_size
	input_len: 0x0074fef1
	output: 0x01000000
	output_len: 0x00fa63d0
	kernel_total_size: 0x0107c000
	needed_size: 0x0107c000

Dump from extract_kernel after patch:
	early console in extract_kernel
	input_data: 0x0190d098 <--- this is at output + init_size - _end
	input_len: 0x0074fef1
	output: 0x01000000
	output_len: 0x00fa63d0
	kernel_total_size: 0x0107c000
	needed_size: 0x0107c000

Fixes: 974f221c84b0 ("x86/boot: Move compressed kernel to the end of the decompression buffer")
Signed-off-by: Arvind Sankar <nivedita@alum.mit.edu>
Signed-off-by: Borislav Petkov <bp@suse.de>
Link: https://lkml.kernel.org/r/20200207214926.3564079-1-nivedita@alum.mit.edu
---
 arch/x86/boot/compressed/head_32.S | 5 +++--
 arch/x86/boot/compressed/head_64.S | 1 +
 2 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/arch/x86/boot/compressed/head_32.S b/arch/x86/boot/compressed/head_32.S
index ab33070..03557f2 100644
--- a/arch/x86/boot/compressed/head_32.S
+++ b/arch/x86/boot/compressed/head_32.S
@@ -49,16 +49,17 @@
  * Position Independent Executable (PIE) so that linker won't optimize
  * R_386_GOT32X relocation to its fixed symbol address.  Older
  * linkers generate R_386_32 relocations against locally defined symbols,
- * _bss, _ebss, _got and _egot, in PIE.  It isn't wrong, just less
+ * _bss, _ebss, _got, _egot and _end, in PIE.  It isn't wrong, just less
  * optimal than R_386_RELATIVE.  But the x86 kernel fails to properly handle
  * R_386_32 relocations when relocating the kernel.  To generate
- * R_386_RELATIVE relocations, we mark _bss, _ebss, _got and _egot as
+ * R_386_RELATIVE relocations, we mark _bss, _ebss, _got, _egot and _end as
  * hidden:
  */
 	.hidden _bss
 	.hidden _ebss
 	.hidden _got
 	.hidden _egot
+	.hidden _end
 
 	__HEAD
 SYM_FUNC_START(startup_32)
diff --git a/arch/x86/boot/compressed/head_64.S b/arch/x86/boot/compressed/head_64.S
index 6b11060..e821a7d 100644
--- a/arch/x86/boot/compressed/head_64.S
+++ b/arch/x86/boot/compressed/head_64.S
@@ -42,6 +42,7 @@
 	.hidden _ebss
 	.hidden _got
 	.hidden _egot
+	.hidden _end
 
 	__HEAD
 	.code32

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

end of thread, other threads:[~2020-05-19 12:35 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-01-11 19:00 [PATCH] x86/boot/compressed: Correct relocation destination on old linkers Arvind Sankar
2020-02-07 21:49 ` [PATCH v2] x86/boot: " Arvind Sankar
2020-03-13 18:33   ` Arvind Sankar
2020-05-16 23:12     ` Arvind Sankar
2020-05-19 12:35   ` [tip: x86/boot] " tip-bot2 for Arvind Sankar

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.