2020-01-08 12:43:41

by Ard Biesheuvel

[permalink] [raw]
Subject: [RFC PATCH 2/3] x86/boot/compressed: force hidden visibility for all symbol references

Eliminate all GOT entries in the decompressor binary, by forcing hidden
visibility for all symbol references, which informs the compiler that
such references will be resolved at link time without the need for
allocating GOT entries.

To ensure that no GOT entries will creep back in, add an assertion to
the decompressor linker script that will fire if the .got section has
a non-zero size.

Signed-off-by: Ard Biesheuvel <[email protected]>
---
arch/x86/boot/compressed/Makefile | 1 +
arch/x86/boot/compressed/hidden.h | 19 +++++++++++++++++++
arch/x86/boot/compressed/vmlinux.lds.S | 1 +
3 files changed, 21 insertions(+)

diff --git a/arch/x86/boot/compressed/Makefile b/arch/x86/boot/compressed/Makefile
index 56aa5fa0a66b..361df91b2288 100644
--- a/arch/x86/boot/compressed/Makefile
+++ b/arch/x86/boot/compressed/Makefile
@@ -39,6 +39,7 @@ KBUILD_CFLAGS += $(call cc-disable-warning, address-of-packed-member)
KBUILD_CFLAGS += $(call cc-disable-warning, gnu)
KBUILD_CFLAGS += -Wno-pointer-sign
KBUILD_CFLAGS += $(call cc-option,-fmacro-prefix-map=$(srctree)/=)
+KBUILD_CFLAGS += -include hidden.h

KBUILD_AFLAGS := $(KBUILD_CFLAGS) -D__ASSEMBLY__
GCOV_PROFILE := n
diff --git a/arch/x86/boot/compressed/hidden.h b/arch/x86/boot/compressed/hidden.h
new file mode 100644
index 000000000000..2a1693373cc7
--- /dev/null
+++ b/arch/x86/boot/compressed/hidden.h
@@ -0,0 +1,19 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * When building position independent code with GCC using the -fPIC option,
+ * (or even the -fPIE one on older versions), it will assume that we are
+ * building a dynamic object (either a shared library or an executable) that
+ * may have symbol references that can only be resolved at load time. For a
+ * variety of reasons (ELF symbol preemption, the CoW footprint of the section
+ * that is modified by the loader), this results in all references to symbols
+ * with external linkage to go via entries in the Global Offset Table (GOT),
+ * which carries absolute addresses which need to be fixed up when the
+ * executable image is loaded at an offset which is different from its link
+ * time offset.
+ *
+ * Fortunately, there is a way to inform the compiler that such symbol
+ * references will be satisfied at link time rather than at load time, by
+ * giving them 'hidden' visibility.
+ */
+
+#pragma GCC visibility push(hidden)
diff --git a/arch/x86/boot/compressed/vmlinux.lds.S b/arch/x86/boot/compressed/vmlinux.lds.S
index 51ca654e43a9..955496ff2fcd 100644
--- a/arch/x86/boot/compressed/vmlinux.lds.S
+++ b/arch/x86/boot/compressed/vmlinux.lds.S
@@ -78,6 +78,7 @@ SECTIONS
_end = .;
}

+ASSERT (SIZEOF(.got) == 0, "Unexpected GOT entries detected!")
#ifdef CONFIG_X86_64
ASSERT (SIZEOF(.got.plt) == 0 || SIZEOF(.got.plt) == 0x18,
"Unexpected GOT/PLT entries detected!")
--
2.20.1


2020-01-08 16:12:53

by Arvind Sankar

[permalink] [raw]
Subject: Re: [RFC PATCH 2/3] x86/boot/compressed: force hidden visibility for all symbol references

On Wed, Jan 08, 2020 at 04:47:51PM +0100, Ard Biesheuvel wrote:
> The EFI stub already sets the hidden visibility attribute for the few
> external symbol references that it contains, so it is not needed in
> the context of this series.
>
> In the future, we can revisit this if we want to get rid of the
> various __pure getter functions, but that requires thorough testing on
> other architectures and toolchains, so I'd prefer to leave that for
> later.

We don't need it for the stub right now, but then this bit in the cover
letter is not yet true, we still need to be careful about libstub code.

> ...we can start using ordinary external symbol references in the EFI
> stub without running the risk of boot regressions.

2020-01-08 17:44:39

by Ard Biesheuvel

[permalink] [raw]
Subject: Re: [RFC PATCH 2/3] x86/boot/compressed: force hidden visibility for all symbol references

On Wed, 8 Jan 2020 at 16:40, Arvind Sankar <[email protected]> wrote:
>
> On Wed, Jan 08, 2020 at 11:23:03AM +0100, Ard Biesheuvel wrote:
> > Eliminate all GOT entries in the decompressor binary, by forcing hidden
> > visibility for all symbol references, which informs the compiler that
> > such references will be resolved at link time without the need for
> > allocating GOT entries.
> >
> > To ensure that no GOT entries will creep back in, add an assertion to
> > the decompressor linker script that will fire if the .got section has
> > a non-zero size.
> >
> > Signed-off-by: Ard Biesheuvel <[email protected]>
> > ---
> > arch/x86/boot/compressed/Makefile | 1 +
> > arch/x86/boot/compressed/hidden.h | 19 +++++++++++++++++++
> > arch/x86/boot/compressed/vmlinux.lds.S | 1 +
> > 3 files changed, 21 insertions(+)
> >
> > diff --git a/arch/x86/boot/compressed/Makefile b/arch/x86/boot/compressed/Makefile
> > index 56aa5fa0a66b..361df91b2288 100644
> > --- a/arch/x86/boot/compressed/Makefile
> > +++ b/arch/x86/boot/compressed/Makefile
> > @@ -39,6 +39,7 @@ KBUILD_CFLAGS += $(call cc-disable-warning, address-of-packed-member)
> > KBUILD_CFLAGS += $(call cc-disable-warning, gnu)
> > KBUILD_CFLAGS += -Wno-pointer-sign
> > KBUILD_CFLAGS += $(call cc-option,-fmacro-prefix-map=$(srctree)/=)
> > +KBUILD_CFLAGS += -include hidden.h
> >
>
> This should be added to drivers/firmware/efi/libstub as well in case
> future code changes bring in global references there?

The EFI stub already sets the hidden visibility attribute for the few
external symbol references that it contains, so it is not needed in
the context of this series.

In the future, we can revisit this if we want to get rid of the
various __pure getter functions, but that requires thorough testing on
other architectures and toolchains, so I'd prefer to leave that for
later.

2020-01-08 18:10:58

by Arvind Sankar

[permalink] [raw]
Subject: Re: [RFC PATCH 2/3] x86/boot/compressed: force hidden visibility for all symbol references

On Wed, Jan 08, 2020 at 11:23:03AM +0100, Ard Biesheuvel wrote:
> Eliminate all GOT entries in the decompressor binary, by forcing hidden
> visibility for all symbol references, which informs the compiler that
> such references will be resolved at link time without the need for
> allocating GOT entries.
>
> To ensure that no GOT entries will creep back in, add an assertion to
> the decompressor linker script that will fire if the .got section has
> a non-zero size.
>
> Signed-off-by: Ard Biesheuvel <[email protected]>
> ---
> arch/x86/boot/compressed/Makefile | 1 +
> arch/x86/boot/compressed/hidden.h | 19 +++++++++++++++++++
> arch/x86/boot/compressed/vmlinux.lds.S | 1 +
> 3 files changed, 21 insertions(+)
>
> diff --git a/arch/x86/boot/compressed/Makefile b/arch/x86/boot/compressed/Makefile
> index 56aa5fa0a66b..361df91b2288 100644
> --- a/arch/x86/boot/compressed/Makefile
> +++ b/arch/x86/boot/compressed/Makefile
> @@ -39,6 +39,7 @@ KBUILD_CFLAGS += $(call cc-disable-warning, address-of-packed-member)
> KBUILD_CFLAGS += $(call cc-disable-warning, gnu)
> KBUILD_CFLAGS += -Wno-pointer-sign
> KBUILD_CFLAGS += $(call cc-option,-fmacro-prefix-map=$(srctree)/=)
> +KBUILD_CFLAGS += -include hidden.h
>

This should be added to drivers/firmware/efi/libstub as well in case
future code changes bring in global references there?

2020-01-08 18:47:22

by Ard Biesheuvel

[permalink] [raw]
Subject: Re: [RFC PATCH 2/3] x86/boot/compressed: force hidden visibility for all symbol references

On Wed, 8 Jan 2020 at 16:57, Arvind Sankar <[email protected]> wrote:
>
> On Wed, Jan 08, 2020 at 04:47:51PM +0100, Ard Biesheuvel wrote:
> > The EFI stub already sets the hidden visibility attribute for the few
> > external symbol references that it contains, so it is not needed in
> > the context of this series.
> >
> > In the future, we can revisit this if we want to get rid of the
> > various __pure getter functions, but that requires thorough testing on
> > other architectures and toolchains, so I'd prefer to leave that for
> > later.
>
> We don't need it for the stub right now, but then this bit in the cover
> letter is not yet true, we still need to be careful about libstub code.
>
> > ...we can start using ordinary external symbol references in the EFI
> > stub without running the risk of boot regressions.

Spurious GOT entries will now be caught by the ASSERT() in the linker
script and fail the build instead of causing hard to debug boot
regressions, so it is not entirely untrue either. But I take your
point.