[PATCH 00/13] arm64: extable: remove anonymous out-of-line fixups
Mark Rutland
mark.rutland at arm.com
Wed Oct 13 04:00:46 PDT 2021
We recently realised that out-of-line extable fixups cause a number of problems
for backtracing (mattering both for developers and for RELIABLE_STACKTRACE and
LIVEPATCH). Dmitry spotted a confusing backtrace, which we identified was due
to problems with unwinding fixups, as summarized in:
https://lore.kernel.org/linux-arm-kernel/20210927171812.GB9201@C02TD0UTHF1T.local/
The gist is that while backtracing through a fixup, the fixup gets symmbolized
as an offset from the nearest prior symbol (which happens to be
`__entry_tramp_text_end`), and we the backtrace misses the function that was
being fixed up (because the fixup handling adjusts the PC, then the fixup does
a direct branch back to the original function). We can't reliably map from an
arbitrary PC in the fixup text back to the original function.
The way we create fixups is a bit unfortunate: most fixups are generated from
common templates, and only differ in register to be poked and the address to
branch back to, leading to redundant copies of the same logic that must pollute
Since the fixups are all written in assembly, and duplicated for each fixup
site, we can only perform very simple fixups, and can't handle any complex
triage that we might need for some exceptions (e.g. MTE faults).
This series address these concerns by getting rid of the out-of-line anonymous
fixup logic:
* For plain assembly functions, we move the fixup into the body of
the function, after the usual return, as we already do for our cache
routines. This simplifies the source code, and only adds a handful of
instructions to the main body of `.text`.
This is handled by the first three patches, which I think are trivial and
could be queued regardless of the rest of the series.
* For inline assembly, we add specialised handlers which run in exception
context to update registers, then adjust the PC *within* the faulting
function. This requires some new glue to capture the handler and metadata in
struct exception_table_entry (costing 32 bits per fixup), but for any
non-trivial fixup (which is all of the inline asm cases), this removes at
least two instructions of out-of-line fixup.
As the fixups are now handled from C code in exception context, we can more
easily extend these in future with more complex triage if necessary.
Overall, this doesn't have an appreciable impact on Image size (in local
testing the size of the Image was identical before/after), but does shift the
boundary between .text and .ordata, making .text smaller and .rodata bigger.
.text somewhat while growing .rodata somewhat.
I've tested this with both GCC and clang (including with clang CFI), and
everything is working as expected.
Other than changes to backtracing, there should be no functional change as a
result of this series.
Thanks
Mark.
Mark Rutland (13):
arm64: lib: __arch_clear_user(): fold fixups into body
arm64: lib: __arch_copy_from_user(): fold fixups into body
arm64: lib: __arch_copy_to_user(): fold fixups into body
arm64: kvm: use kvm_exception_table_entry
arm64: factor out GPR numbering helpers
arm64: gpr-num: support W registers
arm64: extable: consolidate definitions
arm64: extable: make fixup_exception() return bool
arm64: extable: use `ex` for `exception_table_entry`
arm64: extable: add `type` and `data` fields
arm64: extable: add a dedicated uaccess handler
arm64: extable: add load_unaligned_zeropad() handler
arm64: vmlinux.lds.S: remove `.fixup` section
arch/arm64/include/asm/asm-extable.h | 95 +++++++++++++++++++++++++++++++++
arch/arm64/include/asm/asm-uaccess.h | 7 ++-
arch/arm64/include/asm/assembler.h | 29 +---------
arch/arm64/include/asm/extable.h | 23 +++++---
arch/arm64/include/asm/futex.h | 25 +++------
arch/arm64/include/asm/gpr-num.h | 26 +++++++++
arch/arm64/include/asm/kvm_asm.h | 7 +--
arch/arm64/include/asm/sysreg.h | 25 +++------
arch/arm64/include/asm/uaccess.h | 26 ++-------
arch/arm64/include/asm/word-at-a-time.h | 21 ++------
arch/arm64/kernel/armv8_deprecated.c | 12 ++---
arch/arm64/kernel/traps.c | 9 +---
arch/arm64/kernel/vmlinux.lds.S | 1 -
arch/arm64/kvm/hyp/include/hyp/switch.h | 10 ++--
arch/arm64/lib/clear_user.S | 9 ++--
arch/arm64/lib/copy_from_user.S | 7 +--
arch/arm64/lib/copy_to_user.S | 7 +--
arch/arm64/mm/extable.c | 85 +++++++++++++++++++++++++----
arch/arm64/net/bpf_jit_comp.c | 9 ++--
scripts/sorttable.c | 30 +++++++++++
20 files changed, 306 insertions(+), 157 deletions(-)
create mode 100644 arch/arm64/include/asm/asm-extable.h
create mode 100644 arch/arm64/include/asm/gpr-num.h
--
2.11.0
More information about the linux-arm-kernel
mailing list