Re: [PATCH v3 5/7] x86/boot: Remove run-time relocations from .head.text code

Arvind Sankar
2020-06-29T19:28:19Z

On Mon, Jun 29, 2020 at 09:04:04AM -0700, Kees Cook wrote:
> On Mon, Jun 29, 2020 at 10:09:26AM -0400, Arvind Sankar wrote:
> > The assembly code in head_{32,64}.S, while meant to be
> > position-independent, generates run-time relocations because it uses
> > instructions such as
> > leal gdt(%edx), %eax
> > which make the assembler and linker think that the code is using %edx as
> > an index into gdt, and hence gdt needs to be relocated to its run-time
> > address.
> >
> > On 32-bit, with lld Dmitry Golovin reports that this results in a
> > link-time error with default options (i.e. unless -z notext is
> > explicitly passed):
> > LD arch/x86/boot/compressed/vmlinux
> > ld.lld: error: can't create dynamic relocation R_386_32 against local
> > symbol in readonly segment; recompile object files with -fPIC or pass
> > '-Wl,-z,notext' to allow text relocations in the output
> >
> > With the BFD linker, this generates a warning during the build, if
> > --warn-shared-textrel is enabled, which at least Gentoo enables by
> > default:
> > LD arch/x86/boot/compressed/vmlinux
> > ld: arch/x86/boot/compressed/head_32.o: warning: relocation in read-only section `.head.text'
> > ld: warning: creating a DT_TEXTREL in object
> >
> > On 64-bit, it is not possible to link the kernel as -pie with lld, and
> > it is only possible with a BFD linker that supports -z noreloc-overflow,
> > i.e. versions >2.26. This is because these instructions cannot really be
> > relocated: the displacement field is only 32-bits wide, and thus cannot
> > be relocated for a 64-bit load address. The -z noreloc-overflow option
> > simply overrides the linker error, and results in R_X86_64_RELATIVE
> > relocations that apply a 64-bit relocation to a 32-bit field anyway.
> > This happens to work because nothing will process these run-time
> > relocations.
>
> Are any of Thomas Garnier's PIE fixes useful here too? He had a lot of
> fixes to make changes for PC-relative addressing in the various
> assembly bits:
> https://lore.kernel.org/lkml/20200228000105.165012-9-thgarnie@chromium.org/
>

The case there is somewhat different -- he needed to convert non-PIE
code into PIE code, and has to worry about the distinction between
physical and virtual addresses. Here we actually already have PIE code,
so the assembly doesn't really have to change. It's just a matter of
being more precise so that the toolchain understands that it's PIE, and
everything is identity-mapped so it's simpler.