• Ard Biesheuvel's avatar
    arm64/kernel: don't ban ADRP to work around Cortex-A53 erratum #843419 · a257e025
    Ard Biesheuvel authored
    Working around Cortex-A53 erratum #843419 involves special handling of
    ADRP instructions that end up in the last two instruction slots of a
    4k page, or whose output register gets overwritten without having been
    read. (Note that the latter instruction sequence is never emitted by
    a properly functioning compiler, which is why it is disregarded by the
    handling of the same erratum in the bfd.ld linker which we rely on for
    the core kernel)
    
    Normally, this gets taken care of by the linker, which can spot such
    sequences at final link time, and insert a veneer if the ADRP ends up
    at a vulnerable offset. However, linux kernel modules are partially
    linked ELF objects, and so there is no 'final link time' other than the
    runtime loading of the module, at which time all the static relocations
    are resolved.
    
    For this reason, we have implemented the #843419 workaround for modules
    by avoiding ADRP instructions altogether, by using the large C model,
    and by passing -mpc-relative-literal-loads to recent versions of GCC
    that may emit adrp/ldr pairs to perform literal loads. However, this
    workaround forces us to keep literal data mixed with the instructions
    in the executable .text segment, and literal data may inadvertently
    turn into an exploitable speculative gadget depending on the relative
    offsets of arbitrary symbols.
    
    So let's reimplement this workaround in a way that allows us to switch
    back to the small C model, and to drop the -mpc-relative-literal-loads
    GCC switch, by patching affected ADRP instructions at runtime:
    - ADRP instructions that do not appear at 4k relative offset 0xff8 or
      0xffc are ignored
    - ADRP instructions that are within 1 MB of their target symbol are
      converted into ADR instructions
    - remaining ADRP instructions are redirected via a veneer that performs
      the load using an unaffected movn/movk sequence.
    Signed-off-by: default avatarArd Biesheuvel <ard.biesheuvel@linaro.org>
    [will: tidied up ADRP -> ADR instruction patching.]
    [will: use ULL suffix for 64-bit immediate]
    Signed-off-by: default avatarWill Deacon <will.deacon@arm.com>
    a257e025
module.c 12.4 KB