Messages in this thread | ![/](/images/icornerl.gif) | | Date | Thu, 18 Apr 2024 13:46:45 -0700 | From | Fangrui Song <> | Subject | Re: [PATCH] x86/purgatory: Switch to the position-independent small code model |
| |
On 2024-04-18, Nick Desaulniers wrote: >On Thu, Apr 18, 2024 at 1:17 PM Ard Biesheuvel <ardb+git@google.com> wrote: >> >> From: Ard Biesheuvel <ardb@kernel.org> >> >> On x86, the ordinary, position dependent 'small' and 'kernel' code models only >> support placement of the executable in 32-bit addressable memory, due to >> the use of 32-bit signed immediates to generate references to global >> variables. For the kernel, this implies that all global variables must >> reside in the top 2 GiB of the kernel virtual address space, where the >> implicit address bits 63:32 are equal to sign bit 31. >> >> This means the kernel code model is not suitable for other bare metal >> executables such as the kexec purgatory, which can be placed arbitrarily >> in the physical address space, where its address may no longer be >> representable as a sign extended 32-bit quantity. For this reason, >> commit >> >> e16c2983fba0 ("x86/purgatory: Change compiler flags from -mcmodel=kernel to -mcmodel=large to fix kexec relocation errors") >> >> switched to the 'large' code model, which uses 64-bit immediates for all >> symbol references, including function calls, in order to avoid relying >> on any assumptions regarding proximity of symbols in the final >> executable. >> >> The large code model is rarely used, clunky and the least likely to >> operate in a similar fashion when comparing GCC and Clang, so it is best >> avoided. This is especially true now that Clang 18 has started to emit >> executable code in two separate sections (.text and .ltext), which >> triggers an issue in the kexec loading code at runtime. >> >> Instead, use the position independent small code model, which makes no >> assumptions about placement but only about proximity, where all >> referenced symbols must be within -/+ 2 GiB, i.e., in range for a >> RIP-relative reference. Use hidden visibility to suppress the use of a >> GOT, which carries absolute addresses that are not covered by static ELF >> relocations, and is therefore incompatible with the kexec loader's >> relocation logic. >> >> Cc: Nathan Chancellor <nathan@kernel.org> >> Cc: Nick Desaulniers <ndesaulniers@google.com> > >Thanks Ard! > >Acked-by: Nick Desaulniers <ndesaulniers@google.com> >Reported-by: ns <0n-s@users.noreply.github.com> >Closes: https://github.com/ClangBuiltLinux/linux/issues/2016 >Fixes: e16c2983fba0 ("x86/purgatory: Change compiler flags from >-mcmodel=kernel to -mcmodel=large to fix kexec relocation errors") > >(I don't have a kexec setup ready to go; maybe someone that does can >help test it.)
LGTM.
Position-dependent small code model may generate R_X86_64_32S relocations with a range of [0,2GiB) (the negative half cannot be used). Position-independent small code model with hidden visibility will generate R_X86_64_PC32 and can typically be quite larger than 2G without hitting an overflow issue.
(I have some notes about R_X86_64_32S at https://maskray.me/blog/2023-05-14-relocation-overflow-and-code-models#x86-64-linker-requirement)
Reviewed-by: Fangrui Song <maskray@google.com>
>> Cc: Bill Wendling <morbo@google.com> >> Cc: Justin Stitt <justinstitt@google.com> >> Cc: Song Liu <song@kernel.org> >> Cc: Ricardo Ribalda <ribalda@kernel.org> >> Cc: Fangrui Song <maskray@google.com> >> Cc: Arthur Eubanks <aeubanks@google.com> >> Link: https://lore.kernel.org/all/20240417-x86-fix-kexec-with-llvm-18-v1-0-5383121e8fb7@kernel.org/ >> Cc: <stable@vger.kernel.org> >> Signed-off-by: Ard Biesheuvel <ardb@kernel.org> >> --- >> arch/x86/purgatory/Makefile | 3 ++- >> 1 file changed, 2 insertions(+), 1 deletion(-) >> >> diff --git a/arch/x86/purgatory/Makefile b/arch/x86/purgatory/Makefile >> index bc31863c5ee6..a18591f6e6d9 100644 >> --- a/arch/x86/purgatory/Makefile >> +++ b/arch/x86/purgatory/Makefile >> @@ -42,7 +42,8 @@ KCOV_INSTRUMENT := n >> # make up the standalone purgatory.ro >> >> PURGATORY_CFLAGS_REMOVE := -mcmodel=kernel >> -PURGATORY_CFLAGS := -mcmodel=large -ffreestanding -fno-zero-initialized-in-bss -g0 >> +PURGATORY_CFLAGS := -mcmodel=small -ffreestanding -fno-zero-initialized-in-bss -g0 >> +PURGATORY_CFLAGS += -fpic -fvisibility=hidden >> PURGATORY_CFLAGS += $(DISABLE_STACKLEAK_PLUGIN) -DDISABLE_BRANCH_PROFILING >> PURGATORY_CFLAGS += -fno-stack-protector >> >> -- >> 2.44.0.769.g3c40516874-goog >> > > >-- >Thanks, >~Nick Desaulniers
| ![\](/images/icornerr.gif) |