• Mark Rutland's avatar
    arm64: use XPACLRI to strip PAC · ca708599
    Mark Rutland authored
    Currently we strip the PAC from pointers using C code, which requires
    generating bitmasks, and conditionally clearing/setting bits depending
    on bit 55. We can do better by using XPACLRI directly.
    
    When the logic was originally written to strip PACs from user pointers,
    contemporary toolchains used for the kernel had assemblers which were
    unaware of the PAC instructions. As stripping the PAC from userspace
    pointers required unconditional clearing of a fixed set of bits (which
    could be performed with a single instruction), it was simpler to
    implement the masking in C than it was to make use of XPACI or XPACLRI.
    
    When support for in-kernel pointer authentication was added, the
    stripping logic was extended to cover TTBR1 pointers, requiring several
    instructions to handle whether to clear/set bits dependent on bit 55 of
    the pointer.
    
    This patch simplifies the stripping of PACs by using XPACLRI directly,
    as contemporary toolchains do within __builtin_return_address(). This
    saves a number of instructions, especially where
    __builtin_return_address() does not implicitly strip the PAC but is
    heavily used (e.g. with tracepoints). As the kernel might be compiled
    with an assembler without knowledge of XPACLRI, it is assembled using
    the 'HINT #7' alias, which results in an identical opcode.
    
    At the same time, I've split ptrauth_strip_insn_pac() into
    ptrauth_strip_user_insn_pac() and ptrauth_strip_kernel_insn_pac()
    helpers so that we can avoid unnecessary PAC stripping when pointer
    authentication is not in use in userspace or kernel respectively.
    
    The underlying xpaclri() macro uses inline assembly which clobbers x30.
    The clobber causes the compiler to save/restore the original x30 value
    in a frame record (protected with PACIASP and AUTIASP when in-kernel
    authentication is enabled), so this does not provide a gadget to alter
    the return address. Similarly this does not adversely affect unwinding
    due to the presence of the frame record.
    
    The ptrauth_user_pac_mask() and ptrauth_kernel_pac_mask() are exported
    from the kernel in ptrace and core dumps, so these are retained. A
    subsequent patch will move them out of <asm/compiler.h>.
    Signed-off-by: default avatarMark Rutland <mark.rutland@arm.com>
    Cc: Amit Daniel Kachhap <amit.kachhap@arm.com>
    Cc: Catalin Marinas <catalin.marinas@arm.com>
    Cc: James Morse <james.morse@arm.com>
    Cc: Kristina Martsenko <kristina.martsenko@arm.com>
    Cc: Will Deacon <will@kernel.org>
    Link: https://lore.kernel.org/r/20230412160134.306148-3-mark.rutland@arm.comSigned-off-by: default avatarWill Deacon <will@kernel.org>
    ca708599
process.c 19.5 KB