Skip to content

Conversation

@joe-lawrence
Copy link
Contributor

This patchset aims to resolve two issues in kpatch-build's conversion of function pointers to klp-relocations:

  1. On x86_64, some kernel configurations now rely on the GCC -fpatchable-function-entry option. If this option is specified such that the entry point exists before the end of the nop sequence, pointer relocations to this function will have a non-zero symbol value that create-diff-object must adjust for (equal to M in bytes).
  2. On ppc64le, the function pointer detection was not updated for the so called large model GCC prologue. In this model, the function prologue sequence is slightly different, with pointer relocations to these functions again having non-zero symbol value. For these relocations, we can double check that a R_PPC64_ENTRY relocation exists where the function pointer relocation addend and symbol value point to.

Finally, add a simple function pointer integration test (rather than a precompiled unit test) so that we exercise the compilation of the function pointers that kpatch-build will translate into klp-relocations. This should have detected these problems when they first appeared on supported configurations..

Various kernel arch/compiler/configuration combintions have started
using the -fpatchable-function-entry compiler option to generate the
padding space for fentry hooking.  The full option =N[,M] will:

  Generate N NOPs right at the beginning of each function, with the
  function entry point before the Mth NOP.  If M is omitted, it defaults
  to 0 so the function entry points to the address just at the first NOP.

Cases which specify non-zero M NOPs will result in function entries
offset from their section start (when building with -ffunction-sections)
by some number of bytes.  This value is important for create-diff-object
when considering expected symbol offsets.

Architecture notes as of upstream v6.14:
  - arm64 sets M to 2 (8 bytes total) for CONFIG_DYNAMIC_FTRACE_WITH_CALL_OPS
  - loongarch doesn't set M
  - powerpc only sets M for ppc32
  - riscv doesn't set M
  - s390x doesn't use -fpatchable-function-entry
  - x86_64 sets M to CONFIG_FUNCTION_PADDING_BYTES for CONFIG_CALL_PADDING

Signed-off-by: Joe Lawrence <[email protected]>
With -mcmodel=small|medium on ppc64le, GCC generates an entry point
prolog like:

  0000000000000000 <cmdline_proc_open>:
     0:   00 00 4c 3c     addis   r2,r12,0
                          0: R_PPC64_REL16_HA     .TOC.
     4:   00 00 42 38     addi    r2,r2,0
                          4: R_PPC64_REL16_LO     .TOC.+0x4

But with -mcmodel=large on ppc64le, GCC generates an entry point prolog
like:

  0000000000000000 <cmdline_proc_show-0x8>:
          ...
                          0: R_PPC64_REL64        .TOC.-0x8

  0000000000000008 <cmdline_proc_show>:
     8:   f8 ff 4c e8     ld      r2,-8(r12)
                          8: R_PPC64_ENTRY        *ABS*
     c:   14 62 42 7c     add     r2,r2,r12

In the small/medium memory model version, a function pointer relocation
can be verified by comparing the relocation types (R_PPC64_TOC16_HA or
R_PPC64_TOC16_LO_DS) and that the rela_toc->addend ==
rela_toc->sym->sym.st_value.

In the large memory module case, a function pointer can be verified by
its type (R_PPC64_ADDR64) and whether there exists a R_PPC64_ENTRY
relocation at the location its addend and symbol value point to in the
target .text section.

Signed-off-by: Joe Lawrence <[email protected]>
Add an integration test to verify klp-relocation replacement of certain
function pointers.  In this test, the livepatch's function pointer to
uptime_proc_show should resolve to the original found in the kernel and
not the instance from the livepatch itself.

Signed-off-by: Joe Lawrence <[email protected]>
@joe-lawrence joe-lawrence force-pushed the fix-dynrela-func-pointers branch from bf40acf to e48c770 Compare March 25, 2025 14:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant