2022-02-24 16:15:14

by Peter Zijlstra

[permalink] [raw]
Subject: [PATCH v2 05/39] x86: Base IBT bits

Add Kconfig, Makefile and basic instruction support for x86 IBT.

XXX clang is not playing ball, probably lld being 'funny', I'm having
problems with .plt entries appearing all over after linking.

Signed-off-by: Peter Zijlstra (Intel) <[email protected]>
---
arch/x86/Kconfig | 19 ++++++++++++
arch/x86/Makefile | 7 +++-
arch/x86/include/asm/ibt.h | 71 +++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 95 insertions(+), 2 deletions(-)

--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -1861,6 +1861,25 @@ config X86_UMIP
specific cases in protected and virtual-8086 modes. Emulated
results are dummy.

+config CC_HAS_IBT
+ # GCC >= 9 and binutils >= 2.29
+ # Retpoline check to work around https://gcc.gnu.org/bugzilla/show_bug.cgi?id=93654
+ # Clang/LLVM >= 14
+ # fentry check to work around https://reviews.llvm.org/D111108
+ def_bool ((CC_IS_GCC && $(cc-option, -fcf-protection=branch -mindirect-branch-register)) || \
+ (CC_IS_CLANG && $(cc-option, -fcf-protection=branch -mfentry))) && \
+ $(as-instr,endbr64)
+
+config X86_KERNEL_IBT
+ prompt "Indirect Branch Tracking"
+ bool
+ depends on X86_64 && CC_HAS_IBT
+ help
+ Build the kernel with support for Indirect Branch Tracking, a
+ hardware supported CFI scheme. Any indirect call must land on
+ an ENDBR instruction, as such, the compiler will litter the
+ code with them to make this happen.
+
config X86_INTEL_MEMORY_PROTECTION_KEYS
prompt "Memory Protection Keys"
def_bool y
--- a/arch/x86/Makefile
+++ b/arch/x86/Makefile
@@ -36,7 +36,7 @@ endif

# How to compile the 16-bit code. Note we always compile for -march=i386;
# that way we can complain to the user if the CPU is insufficient.
-REALMODE_CFLAGS := -m16 -g -Os -DDISABLE_BRANCH_PROFILING \
+REALMODE_CFLAGS := -m16 -g -Os -DDISABLE_BRANCH_PROFILING -D__DISABLE_EXPORTS \
-Wall -Wstrict-prototypes -march=i386 -mregparm=3 \
-fno-strict-aliasing -fomit-frame-pointer -fno-pic \
-mno-mmx -mno-sse $(call cc-option,-fcf-protection=none)
@@ -62,8 +62,11 @@ export BITS
#
KBUILD_CFLAGS += -mno-sse -mno-mmx -mno-sse2 -mno-3dnow -mno-avx

-# Intel CET isn't enabled in the kernel
+ifeq ($(CONFIG_X86_KERNEL_IBT),y)
+KBUILD_CFLAGS += $(call cc-option,-fcf-protection=branch)
+else
KBUILD_CFLAGS += $(call cc-option,-fcf-protection=none)
+endif

ifeq ($(CONFIG_X86_32),y)
BITS := 32
--- /dev/null
+++ b/arch/x86/include/asm/ibt.h
@@ -0,0 +1,71 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _ASM_X86_IBT_H
+#define _ASM_X86_IBT_H
+
+#include <linux/types.h>
+
+#if defined(CONFIG_X86_KERNEL_IBT) && !defined(__DISABLE_EXPORTS)
+
+#define HAS_KERNEL_IBT 1
+
+#ifndef __ASSEMBLY__
+
+#ifdef CONFIG_X86_64
+#define ASM_ENDBR "endbr64\n\t"
+#else
+#define ASM_ENDBR "endbr32\n\t"
+#endif
+
+#define __noendbr __attribute__((nocf_check))
+
+static inline __attribute_const__ unsigned int gen_endbr(void)
+{
+ unsigned int endbr;
+
+ /*
+ * Generate ENDBR64 in a way that is sure to not result in
+ * an ENDBR64 instruction as immediate.
+ */
+ asm ( "mov $~0xfa1e0ff3, %[endbr]\n\t"
+ "not %[endbr]\n\t"
+ : [endbr] "=&r" (endbr) );
+
+ return endbr;
+}
+
+static inline bool is_endbr(unsigned int val)
+{
+ val &= ~0x01000000U; /* ENDBR32 -> ENDBR64 */
+ return val == gen_endbr();
+}
+
+#else /* __ASSEMBLY__ */
+
+#ifdef CONFIG_X86_64
+#define ENDBR endbr64
+#else
+#define ENDBR endbr32
+#endif
+
+#endif /* __ASSEMBLY__ */
+
+#else /* !IBT */
+
+#define HAS_KERNEL_IBT 0
+
+#ifndef __ASSEMBLY__
+
+#define ASM_ENDBR
+
+#define __noendbr
+
+static inline bool is_endbr(unsigned int val) { return false; }
+
+#else /* __ASSEMBLY__ */
+
+#define ENDBR
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* CONFIG_X86_KERNEL_IBT */
+#endif /* _ASM_X86_IBT_H */



2022-02-25 02:26:23

by Kees Cook

[permalink] [raw]
Subject: Re: [PATCH v2 05/39] x86: Base IBT bits

On Thu, Feb 24, 2022 at 03:51:43PM +0100, Peter Zijlstra wrote:
> Add Kconfig, Makefile and basic instruction support for x86 IBT.
>
> XXX clang is not playing ball, probably lld being 'funny', I'm having
> problems with .plt entries appearing all over after linking.

I'll try to look into this; I know you've been chatting with Nathan
about it. Is there an open bug for it? (And any kind of reproducer
smaller than a 39 patch series we can show the linker folks?) :)

> [...]
> +config X86_KERNEL_IBT
> + prompt "Indirect Branch Tracking"
> + bool
> + depends on X86_64 && CC_HAS_IBT
> + help
> + Build the kernel with support for Indirect Branch Tracking, a
> + hardware supported CFI scheme. Any indirect call must land on

hardware support course-grain forward-edge Control Flow Integrity
protection. It enforces that all indirect calls must land on

> + an ENDBR instruction, as such, the compiler will litter the
> + code with them to make this happen.

"litter the code" -> "instrument the machine code".


> +
> config X86_INTEL_MEMORY_PROTECTION_KEYS
> prompt "Memory Protection Keys"
> def_bool y
> --- a/arch/x86/Makefile
> +++ b/arch/x86/Makefile
> @@ -36,7 +36,7 @@ endif
>
> # How to compile the 16-bit code. Note we always compile for -march=i386;
> # that way we can complain to the user if the CPU is insufficient.
> -REALMODE_CFLAGS := -m16 -g -Os -DDISABLE_BRANCH_PROFILING \
> +REALMODE_CFLAGS := -m16 -g -Os -DDISABLE_BRANCH_PROFILING -D__DISABLE_EXPORTS \
> -Wall -Wstrict-prototypes -march=i386 -mregparm=3 \
> -fno-strict-aliasing -fomit-frame-pointer -fno-pic \
> -mno-mmx -mno-sse $(call cc-option,-fcf-protection=none)

This change seems important separately from this patch, yes? (Or at
least a specific call-out in the commit log.)

Otherwise, looks good.

--
Kees Cook

2022-02-25 09:40:32

by Nathan Chancellor

[permalink] [raw]
Subject: Re: [PATCH v2 05/39] x86: Base IBT bits

On Thu, Feb 24, 2022 at 04:35:51PM -0800, Kees Cook wrote:
> On Thu, Feb 24, 2022 at 03:51:43PM +0100, Peter Zijlstra wrote:
> > Add Kconfig, Makefile and basic instruction support for x86 IBT.
> >
> > XXX clang is not playing ball, probably lld being 'funny', I'm having
> > problems with .plt entries appearing all over after linking.
>
> I'll try to look into this; I know you've been chatting with Nathan
> about it. Is there an open bug for it? (And any kind of reproducer
> smaller than a 39 patch series we can show the linker folks?) :)

I should be able to create a reproducer with cvise and file a bug on
GitHub around this tomorrow, I should have done it after Peter's
comments on IRC.

Cheers,
Nathan

> > [...]
> > +config X86_KERNEL_IBT
> > + prompt "Indirect Branch Tracking"
> > + bool
> > + depends on X86_64 && CC_HAS_IBT
> > + help
> > + Build the kernel with support for Indirect Branch Tracking, a
> > + hardware supported CFI scheme. Any indirect call must land on
>
> hardware support course-grain forward-edge Control Flow Integrity
> protection. It enforces that all indirect calls must land on
>
> > + an ENDBR instruction, as such, the compiler will litter the
> > + code with them to make this happen.
>
> "litter the code" -> "instrument the machine code".
>
>
> > +
> > config X86_INTEL_MEMORY_PROTECTION_KEYS
> > prompt "Memory Protection Keys"
> > def_bool y
> > --- a/arch/x86/Makefile
> > +++ b/arch/x86/Makefile
> > @@ -36,7 +36,7 @@ endif
> >
> > # How to compile the 16-bit code. Note we always compile for -march=i386;
> > # that way we can complain to the user if the CPU is insufficient.
> > -REALMODE_CFLAGS := -m16 -g -Os -DDISABLE_BRANCH_PROFILING \
> > +REALMODE_CFLAGS := -m16 -g -Os -DDISABLE_BRANCH_PROFILING -D__DISABLE_EXPORTS \
> > -Wall -Wstrict-prototypes -march=i386 -mregparm=3 \
> > -fno-strict-aliasing -fomit-frame-pointer -fno-pic \
> > -mno-mmx -mno-sse $(call cc-option,-fcf-protection=none)
>
> This change seems important separately from this patch, yes? (Or at
> least a specific call-out in the commit log.)
>
> Otherwise, looks good.
>
> --
> Kees Cook

2022-02-25 19:11:53

by Peter Zijlstra

[permalink] [raw]
Subject: Re: [PATCH v2 05/39] x86: Base IBT bits

On Thu, Feb 24, 2022 at 04:35:51PM -0800, Kees Cook wrote:

> > --- a/arch/x86/Makefile
> > +++ b/arch/x86/Makefile
> > @@ -36,7 +36,7 @@ endif
> >
> > # How to compile the 16-bit code. Note we always compile for -march=i386;
> > # that way we can complain to the user if the CPU is insufficient.
> > -REALMODE_CFLAGS := -m16 -g -Os -DDISABLE_BRANCH_PROFILING \
> > +REALMODE_CFLAGS := -m16 -g -Os -DDISABLE_BRANCH_PROFILING -D__DISABLE_EXPORTS \
> > -Wall -Wstrict-prototypes -march=i386 -mregparm=3 \
> > -fno-strict-aliasing -fomit-frame-pointer -fno-pic \
> > -mno-mmx -mno-sse $(call cc-option,-fcf-protection=none)
>
> This change seems important separately from this patch, yes? (Or at
> least a specific call-out in the commit log.)

It was to not stuff endbr in realmode code. *something* complained about
it (and Joao independently mentioned it on IRC).

Could be I hit some compile fail somewhere and this was the cleanest way
to simply make it go away.

I'll go mention it somewhere.

2022-02-25 23:46:03

by Nathan Chancellor

[permalink] [raw]
Subject: Re: [PATCH v2 05/39] x86: Base IBT bits

On Thu, Feb 24, 2022 at 05:46:59PM -0700, Nathan Chancellor wrote:
> On Thu, Feb 24, 2022 at 04:35:51PM -0800, Kees Cook wrote:
> > On Thu, Feb 24, 2022 at 03:51:43PM +0100, Peter Zijlstra wrote:
> > > Add Kconfig, Makefile and basic instruction support for x86 IBT.
> > >
> > > XXX clang is not playing ball, probably lld being 'funny', I'm having
> > > problems with .plt entries appearing all over after linking.
> >
> > I'll try to look into this; I know you've been chatting with Nathan
> > about it. Is there an open bug for it? (And any kind of reproducer
> > smaller than a 39 patch series we can show the linker folks?) :)
>
> I should be able to create a reproducer with cvise and file a bug on
> GitHub around this tomorrow, I should have done it after Peter's
> comments on IRC.

https://github.com/ClangBuiltLinux/linux/issues/1606

Cheers,
Nathan

2022-02-26 05:40:28

by Fangrui Song

[permalink] [raw]
Subject: Re: [PATCH v2 05/39] x86: Base IBT bits

On Fri, Feb 25, 2022 at 8:58 PM Kees Cook <[email protected]> wrote:
>
> On Fri, Feb 25, 2022 at 04:29:49PM -0800, Joao Moreira wrote:
> > > https://github.com/ClangBuiltLinux/linux/issues/1606
> >
> > Candidate fix: https://reviews.llvm.org/D120600
>
> And landed! Thanks!
>
> Since this is a pretty small change, do you think it could be backported
> to the clang-14 branch?
>
> --
> Kees Cook

I have pushed it to release/14.x :)
https://github.com/llvm/llvm-project/commit/f8ca5fabdb54fdf64b3dffb38ebf7d0220f415a2

The current release schedule is
https://discourse.llvm.org/t/llvm-14-0-0-release-schedule/5846


--
宋方睿

2022-02-26 05:42:30

by Kees Cook

[permalink] [raw]
Subject: Re: [PATCH v2 05/39] x86: Base IBT bits

On Fri, Feb 25, 2022 at 04:29:49PM -0800, Joao Moreira wrote:
> > https://github.com/ClangBuiltLinux/linux/issues/1606
>
> Candidate fix: https://reviews.llvm.org/D120600

And landed! Thanks!

Since this is a pretty small change, do you think it could be backported
to the clang-14 branch?

--
Kees Cook

2022-02-26 06:18:42

by Kees Cook

[permalink] [raw]
Subject: Re: [PATCH v2 05/39] x86: Base IBT bits

On Fri, Feb 25, 2022 at 08:59:57PM -0800, Fāng-ruì Sòng wrote:
> On Fri, Feb 25, 2022 at 8:58 PM Kees Cook <[email protected]> wrote:
> >
> > On Fri, Feb 25, 2022 at 04:29:49PM -0800, Joao Moreira wrote:
> > > > https://github.com/ClangBuiltLinux/linux/issues/1606
> > >
> > > Candidate fix: https://reviews.llvm.org/D120600
> >
> > And landed! Thanks!
> >
> > Since this is a pretty small change, do you think it could be backported
> > to the clang-14 branch?
> >
> > --
> > Kees Cook
>
> I have pushed it to release/14.x :)
> https://github.com/llvm/llvm-project/commit/f8ca5fabdb54fdf64b3dffb38ebf7d0220f415a2
>
> The current release schedule is
> https://discourse.llvm.org/t/llvm-14-0-0-release-schedule/5846

Great! :)

--
Kees Cook