[PATCH v2 39/59] x86/Kconfig: Introduce function padding

From: Peter Zijlstra
Date: Fri Sep 02 2022 - 10:32:42 EST


From: Thomas Gleixner <tglx@xxxxxxxxxxxxx>

Now that all functions are 16 byte aligned, add 16 bytes of NOP
padding in front of each function. This prepares things for software
call stack tracking and kCFI/FineIBT.

This significantly increases kernel .text size, around 5.1% on a
x86_64-defconfig-ish build.

However, per the random access argument used for alignment, these 16
extra bytes are code that wouldn't be used. Performance measurements
back this up by showing no significant performance regressions.

Signed-off-by: Thomas Gleixner <tglx@xxxxxxxxxxxxx>
Signed-off-by: Peter Zijlstra (Intel) <peterz@xxxxxxxxxxxxx>
---
Makefile | 3 +++
arch/x86/Kconfig | 12 +++++++++++-
arch/x86/Makefile | 5 +++++
arch/x86/entry/vdso/Makefile | 3 ++-
arch/x86/include/asm/linkage.h | 28 ++++++++++++++++++++++++----
5 files changed, 45 insertions(+), 6 deletions(-)

--- a/Makefile
+++ b/Makefile
@@ -920,6 +920,9 @@ KBUILD_AFLAGS += -fno-lto
export CC_FLAGS_LTO
endif

+PADDING_CFLAGS := -fpatchable-function-entry=$(CONFIG_FUNCTION_PADDING_BYTES),$(CONFIG_FUNCTION_PADDING_BYTES)
+export PADDING_CFLAGS
+
ifdef CONFIG_CFI_CLANG
CC_FLAGS_CFI := -fsanitize=cfi \
-fsanitize-cfi-cross-dso \
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -2427,9 +2427,19 @@ config CC_HAS_SLS
config CC_HAS_RETURN_THUNK
def_bool $(cc-option,-mfunction-return=thunk-extern)

+config CC_HAS_ENTRY_PADDING
+ def_bool $(cc-option,-fpatchable-function-entry=16,16)
+
+config FUNCTION_PADDING_BYTES
+ int
+ default 32 if CALL_THUNKS_DEBUG && !CFI_CLANG
+ default 27 if CALL_THUNKS_DEBUG && CFI_CLANG
+ default 16 if !CFI_CLANG
+ default 11
+
config HAVE_CALL_THUNKS
def_bool y
- depends on RETHUNK && OBJTOOL
+ depends on CC_HAS_ENTRY_PADDING && RETHUNK && OBJTOOL

config CALL_THUNKS
def_bool n
--- a/arch/x86/Makefile
+++ b/arch/x86/Makefile
@@ -202,6 +202,11 @@ ifdef CONFIG_SLS
KBUILD_CFLAGS += -mharden-sls=all
endif

+PADDING_CFLAGS := -fpatchable-function-entry=$(CONFIG_FUNCTION_PADDING_BYTES),$(CONFIG_FUNCTION_PADDING_BYTES)
+ifdef CONFIG_CALL_THUNKS
+ KBUILD_CFLAGS += $(PADDING_CFLAGS)
+endif
+
KBUILD_LDFLAGS += -m elf_$(UTS_MACHINE)

ifdef CONFIG_LTO_CLANG
--- a/arch/x86/entry/vdso/Makefile
+++ b/arch/x86/entry/vdso/Makefile
@@ -92,7 +92,7 @@ ifneq ($(RETPOLINE_VDSO_CFLAGS),)
endif
endif

-$(vobjs): KBUILD_CFLAGS := $(filter-out $(CC_FLAGS_LTO) $(RANDSTRUCT_CFLAGS) $(GCC_PLUGINS_CFLAGS) $(RETPOLINE_CFLAGS),$(KBUILD_CFLAGS)) $(CFL)
+$(vobjs): KBUILD_CFLAGS := $(filter-out $(PADDING_CFLAGS) $(CC_FLAGS_LTO) $(RANDSTRUCT_CFLAGS) $(GCC_PLUGINS_CFLAGS) $(RETPOLINE_CFLAGS),$(KBUILD_CFLAGS)) $(CFL)
$(vobjs): KBUILD_AFLAGS += -DBUILD_VDSO

#
@@ -154,6 +154,7 @@ KBUILD_CFLAGS_32 := $(filter-out $(RANDS
KBUILD_CFLAGS_32 := $(filter-out $(GCC_PLUGINS_CFLAGS),$(KBUILD_CFLAGS_32))
KBUILD_CFLAGS_32 := $(filter-out $(RETPOLINE_CFLAGS),$(KBUILD_CFLAGS_32))
KBUILD_CFLAGS_32 := $(filter-out $(CC_FLAGS_LTO),$(KBUILD_CFLAGS_32))
+KBUILD_CFLAGS_32 := $(filter-out $(PADDING_CFLAGS),$(KBUILD_CFLAGS_32))
KBUILD_CFLAGS_32 += -m32 -msoft-float -mregparm=0 -fpic
KBUILD_CFLAGS_32 += -fno-stack-protector
KBUILD_CFLAGS_32 += $(call cc-option, -foptimize-sibling-calls)
--- a/arch/x86/include/asm/linkage.h
+++ b/arch/x86/include/asm/linkage.h
@@ -13,17 +13,37 @@
#endif /* CONFIG_X86_32 */

#if CONFIG_FUNCTION_ALIGNMENT == 8
-#define __ALIGN .p2align 3, 0x90;
+# define __ALIGN .p2align 3, 0x90;
#elif CONFIG_FUNCTION_ALIGNMENT == 16
-#define __ALIGN .p2align 4, 0x90;
+# define __ALIGN .p2align 4, 0x90;
+#elif CONFIG_FUNCTION_ALIGNMENT == 32
+# define __ALIGN .p2align 5, 0x90
#else
# error Unsupported function alignment
#endif

#define __ALIGN_STR __stringify(__ALIGN)
-#define ASM_FUNC_ALIGN __ALIGN_STR
-#define __FUNC_ALIGN __ALIGN
+
+#ifdef CONFIG_CFI_CLANG
+#define __FUNCTION_PADDING (CONFIG_FUNCTION_ALIGNMENT - 5)
+#else
+#define __FUNCTION_PADDING CONFIG_FUNCTION_ALIGNMENT
+#endif
+
+#if defined(CONFIG_CALL_THUNKS) && !defined(__DISABLE_EXPORTS) && !defined(BUILD_VDSO)
+#define FUNCTION_PADDING .skip __FUNCTION_PADDING, 0x90;
+#else
+#define FUNCTION_PADDING
+#endif
+
+#if (CONFIG_FUNCTION_ALIGNMENT > 8) && !defined(__DISABLE_EXPORTS) && !defined(BULID_VDSO)
+# define __FUNC_ALIGN __ALIGN; FUNCTION_PADDING
+#else
+# define __FUNC_ALIGN __ALIGN
+#endif
+
#define SYM_F_ALIGN __FUNC_ALIGN
+#define ASM_FUNC_ALIGN __stringify(__FUNC_ALIGN)

#ifdef __ASSEMBLY__