From: Ard Biesheuvel <[email protected]>
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.
[Arvind: fixup -include hidden.h to -include $(srctree)/$(src)/hidden.h]
Signed-off-by: Ard Biesheuvel <[email protected]>
Acked-by: Arvind Sankar <[email protected]>
Signed-off-by: Arvind Sankar <[email protected]>
From: Ard Biesheuvel <[email protected]>
Link: https://lore.kernel.org/r/[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(+)
create mode 100644 arch/x86/boot/compressed/hidden.h
diff --git a/arch/x86/boot/compressed/Makefile b/arch/x86/boot/compressed/Makefile
index 7619742f91c9..b01c8aed0f23 100644
--- a/arch/x86/boot/compressed/Makefile
+++ b/arch/x86/boot/compressed/Makefile
@@ -42,6 +42,7 @@ KBUILD_CFLAGS += $(call cc-disable-warning, gnu)
KBUILD_CFLAGS += -Wno-pointer-sign
KBUILD_CFLAGS += $(call cc-option,-fmacro-prefix-map=$(srctree)/=)
KBUILD_CFLAGS += -fno-asynchronous-unwind-tables
+KBUILD_CFLAGS += -include $(srctree)/$(src)/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..49a17b6b5962
--- /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 b17d218ccdf9..4bcc943842ab 100644
--- a/arch/x86/boot/compressed/vmlinux.lds.S
+++ b/arch/x86/boot/compressed/vmlinux.lds.S
@@ -81,6 +81,7 @@ SECTIONS
DISCARDS
}
+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!")
#else
--
2.26.2
On Mon, Jun 29, 2020 at 10:09:23AM -0400, Arvind Sankar wrote:
> From: Ard Biesheuvel <[email protected]>
>
> 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.
>
> [Arvind: fixup -include hidden.h to -include $(srctree)/$(src)/hidden.h]
>
> Signed-off-by: Ard Biesheuvel <[email protected]>
> Acked-by: Arvind Sankar <[email protected]>
> Signed-off-by: Arvind Sankar <[email protected]>
> From: Ard Biesheuvel <[email protected]>
> Link: https://lore.kernel.org/r/[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(+)
> create mode 100644 arch/x86/boot/compressed/hidden.h
>
> diff --git a/arch/x86/boot/compressed/Makefile b/arch/x86/boot/compressed/Makefile
> index 7619742f91c9..b01c8aed0f23 100644
> --- a/arch/x86/boot/compressed/Makefile
> +++ b/arch/x86/boot/compressed/Makefile
> @@ -42,6 +42,7 @@ KBUILD_CFLAGS += $(call cc-disable-warning, gnu)
> KBUILD_CFLAGS += -Wno-pointer-sign
> KBUILD_CFLAGS += $(call cc-option,-fmacro-prefix-map=$(srctree)/=)
> KBUILD_CFLAGS += -fno-asynchronous-unwind-tables
> +KBUILD_CFLAGS += -include $(srctree)/$(src)/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..49a17b6b5962
> --- /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)
Is this recognized by Clang? I'm assuming so, since I see this already
being used in drivers/firmware/efi/libstub/hidden.h
> diff --git a/arch/x86/boot/compressed/vmlinux.lds.S b/arch/x86/boot/compressed/vmlinux.lds.S
> index b17d218ccdf9..4bcc943842ab 100644
> --- a/arch/x86/boot/compressed/vmlinux.lds.S
> +++ b/arch/x86/boot/compressed/vmlinux.lds.S
> @@ -81,6 +81,7 @@ SECTIONS
> DISCARDS
> }
>
> +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!")
> #else
Reviewed-by: Kees Cook <[email protected]>
--
Kees Cook
On Mon, Jun 29, 2020 at 4:09 PM Arvind Sankar <[email protected]> wrote:
>
> From: Ard Biesheuvel <[email protected]>
>
> 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.
>
> [Arvind: fixup -include hidden.h to -include $(srctree)/$(src)/hidden.h]
>
Thanks for your v3 patchset.
I tried your initial patchset and informed you about the <hidden.h>
include file handling.
Dropped your patchset against Linux v5.7 as I got no (satisfying) replies.
For me this one is missing a Reported-by of mine.
As I want to test the whole v3 series, I will report later.
- Sedat -
> Signed-off-by: Ard Biesheuvel <[email protected]>
> Acked-by: Arvind Sankar <[email protected]>
> Signed-off-by: Arvind Sankar <[email protected]>
> From: Ard Biesheuvel <[email protected]>
> Link: https://lore.kernel.org/r/[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(+)
> create mode 100644 arch/x86/boot/compressed/hidden.h
>
> diff --git a/arch/x86/boot/compressed/Makefile b/arch/x86/boot/compressed/Makefile
> index 7619742f91c9..b01c8aed0f23 100644
> --- a/arch/x86/boot/compressed/Makefile
> +++ b/arch/x86/boot/compressed/Makefile
> @@ -42,6 +42,7 @@ KBUILD_CFLAGS += $(call cc-disable-warning, gnu)
> KBUILD_CFLAGS += -Wno-pointer-sign
> KBUILD_CFLAGS += $(call cc-option,-fmacro-prefix-map=$(srctree)/=)
> KBUILD_CFLAGS += -fno-asynchronous-unwind-tables
> +KBUILD_CFLAGS += -include $(srctree)/$(src)/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..49a17b6b5962
> --- /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 b17d218ccdf9..4bcc943842ab 100644
> --- a/arch/x86/boot/compressed/vmlinux.lds.S
> +++ b/arch/x86/boot/compressed/vmlinux.lds.S
> @@ -81,6 +81,7 @@ SECTIONS
> DISCARDS
> }
>
> +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!")
> #else
> --
> 2.26.2
>
On Tue, 14 Jul 2020 at 12:21, Sedat Dilek <[email protected]> wrote:
>
> On Mon, Jun 29, 2020 at 4:09 PM Arvind Sankar <[email protected]> wrote:
> >
> > From: Ard Biesheuvel <[email protected]>
> >
> > 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.
> >
> > [Arvind: fixup -include hidden.h to -include $(srctree)/$(src)/hidden.h]
> >
>
> Thanks for your v3 patchset.
>
> I tried your initial patchset and informed you about the <hidden.h>
> include file handling.
> Dropped your patchset against Linux v5.7 as I got no (satisfying) replies.
Dropped from where? This series should be taken through the -tip tree.
> For me this one is missing a Reported-by of mine.
>
We don't usually add reported-by lines for issues that were resolved
before the series was merged, given that the reported issue never
existed in mainline to begin with.
> As I want to test the whole v3 series, I will report later.
>
A tested-by is always appreciated.
> - Sedat -
>
> > Signed-off-by: Ard Biesheuvel <[email protected]>
> > Acked-by: Arvind Sankar <[email protected]>
> > Signed-off-by: Arvind Sankar <[email protected]>
> > From: Ard Biesheuvel <[email protected]>
> > Link: https://lore.kernel.org/r/[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(+)
> > create mode 100644 arch/x86/boot/compressed/hidden.h
> >
> > diff --git a/arch/x86/boot/compressed/Makefile b/arch/x86/boot/compressed/Makefile
> > index 7619742f91c9..b01c8aed0f23 100644
> > --- a/arch/x86/boot/compressed/Makefile
> > +++ b/arch/x86/boot/compressed/Makefile
> > @@ -42,6 +42,7 @@ KBUILD_CFLAGS += $(call cc-disable-warning, gnu)
> > KBUILD_CFLAGS += -Wno-pointer-sign
> > KBUILD_CFLAGS += $(call cc-option,-fmacro-prefix-map=$(srctree)/=)
> > KBUILD_CFLAGS += -fno-asynchronous-unwind-tables
> > +KBUILD_CFLAGS += -include $(srctree)/$(src)/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..49a17b6b5962
> > --- /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 b17d218ccdf9..4bcc943842ab 100644
> > --- a/arch/x86/boot/compressed/vmlinux.lds.S
> > +++ b/arch/x86/boot/compressed/vmlinux.lds.S
> > @@ -81,6 +81,7 @@ SECTIONS
> > DISCARDS
> > }
> >
> > +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!")
> > #else
> > --
> > 2.26.2
> >