Skip to content

Commit

Permalink
x86/module: Deal with GOT based stack cookie load on Clang < 17
Browse files Browse the repository at this point in the history
Clang versions before 17 will not honour -fdirect-access-external-data
for the load of the stack cookie emitted into each function's prologue
and epilogue.

This is not an issue for the core kernel, as the linker will relax these
loads into LEA instructions that take the address of __stack_chk_guard
directly. For modules, however, we need to work around this, by dealing
with R_X86_64_REX_GOTPCRELX relocations that refer to __stack_chk_guard.

In this case, given that this is a GOT load, the reference should not
refer to __stack_chk_guard directly, but to a memory location that holds
its address. So take the address of __stack_chk_guard into a static
variable, and fix up the relocations to refer to that.

[ mingo: Fix broken R_X86_64_GOTPCRELX definition. ]

Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
Signed-off-by: Brian Gerst <brgerst@gmail.com>
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Link: https://lore.kernel.org/r/20250123190747.745588-7-brgerst@gmail.com
  • Loading branch information
Ard Biesheuvel authored and Ingo Molnar committed Feb 18, 2025
1 parent cb7927f commit 78c4374
Show file tree
Hide file tree
Showing 2 changed files with 18 additions and 2 deletions.
5 changes: 3 additions & 2 deletions arch/x86/include/asm/elf.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,9 @@ typedef struct user_i387_struct elf_fpregset_t;
#define R_X86_64_GLOB_DAT 6 /* Create GOT entry */
#define R_X86_64_JUMP_SLOT 7 /* Create PLT entry */
#define R_X86_64_RELATIVE 8 /* Adjust by program base */
#define R_X86_64_GOTPCREL 9 /* 32 bit signed pc relative
offset to GOT */
#define R_X86_64_GOTPCREL 9 /* 32 bit signed pc relative offset to GOT */
#define R_X86_64_GOTPCRELX 41
#define R_X86_64_REX_GOTPCRELX 42
#define R_X86_64_32 10 /* Direct 32 bit zero extended */
#define R_X86_64_32S 11 /* Direct 32 bit sign extended */
#define R_X86_64_16 12 /* Direct 16 bit zero extended */
Expand Down
15 changes: 15 additions & 0 deletions arch/x86/kernel/module.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#include <linux/jump_label.h>
#include <linux/random.h>
#include <linux/memory.h>
#include <linux/stackprotector.h>

#include <asm/text-patching.h>
#include <asm/page.h>
Expand Down Expand Up @@ -130,6 +131,20 @@ static int __write_relocate_add(Elf64_Shdr *sechdrs,
goto overflow;
size = 4;
break;
#if defined(CONFIG_STACKPROTECTOR) && \
defined(CONFIG_CC_IS_CLANG) && CONFIG_CLANG_VERSION < 170000
case R_X86_64_REX_GOTPCRELX: {
static unsigned long __percpu *const addr = &__stack_chk_guard;

if (sym->st_value != (u64)addr) {
pr_err("%s: Unsupported GOTPCREL relocation\n", me->name);
return -ENOEXEC;
}

val = (u64)&addr + rel[i].r_addend;
fallthrough;
}
#endif
case R_X86_64_PC32:
case R_X86_64_PLT32:
val -= (u64)loc;
Expand Down

0 comments on commit 78c4374

Please sign in to comment.