[RFC 00/31] objtool, livepatch: Livepatch module generation

Josh Poimboeuf
2024-09-03T04:00:29Z

Hi,

Here's a new way to build livepatch modules called klp-build.

I started working on it when I realized that objtool already does 99% of
the work needed for detecting function changes.

This is similar in concept to kpatch-build, but the implementation is
much cleaner.

Personally I still have reservations about the "source-based" approach
(klp-convert and friends), including the fragility and performance
concerns of -flive-patching. I would submit that klp-build might be
considered the "official" way to make livepatch modules.

Please try it out and let me know what you think. Based on v6.10.

Also avaiable at:

git://git.kernel.org/pub/scm/linux/kernel/git/jpoimboe/linux.git klp-build-rfc

More details (cribbed from the big final patch):

------

Add a klp-build script which makes use of a new "objtool klp" subcommand
to generate livepatch modules using a source patch as input.

The concept is similar to kpatch-build which has been a successful
out-of-tree project for over a decade. It takes a source .patch as an
input, builds kernels before and after, does a binary diff, and copies
any changed functions into a new object file which is then linked into a
livepatch module.

By making use of existing objtool functionality, and taking from lessons
learned over the last decade of maintaining kpatch-build, the overall
design is much simpler. In fact, it's a complete redesign and has been
written from scratch (no copied code).

Advantages over kpatch-build:

- Runs on vmlinux.o, so it's compatible with late-linked features like
IBT and LTO

- Much simpler design: ~3k fewer LOC

- Makes use of existing objtool CFG functionality to create checksums
for trivially detecting changed functions

- Offset __LINE__ changes are no longer a problem thanks to the
adjust-patch-lines script

- In-tree means less cruft, easier maintenance, and a larger pool of
potential maintainers

To use, run the following from the kernel source root:

scripts/livepatch/klp-build /path/to/my.patch

If it succeeds, the patch module (livepatch.ko) will be created in the
current directory.

TODO:

- specify module name on cmdline
- handle edge cases like correlation of static locals
- support other arches (currently x86-64 only)
- support clang
- performance optimization
- automated testing
- documentation

Josh Poimboeuf (31):
x86/alternative: Refactor INT3 call emulation selftest
x86/module: Improve relocation error messages
x86/kprobes: Remove STACK_FRAME_NON_STANDARD annotation
kernel/sys: Don't reference UTS_RELEASE directly
x86/compiler: Tweak __UNIQUE_ID naming
elfnote: Use __UNIQUE_ID() for note symbols
kbuild: Remove "kmod" prefix from __KBUILD_MODNAME
objtool: Remove .parainstructions reference
objtool: Const string cleanup
objtool: Use 'struct elf' in elf macros
objtool: Add section/symbol type helpers
objtool: 'objname' refactoring
objtool: Support references to all symbol types in special sections
objtool: Refactor add_jump_destinations()
objtool: Interval tree cleanups
objtool: Simplify fatal error handling
objtool: Open up the elf API
objtool: Disallow duplicate prefix symbols
objtool: Add elf_create_file()
objtool: Add UD1 detection
objtool: Fix x86 addend calcuation
objtool: Make find_symbol_containing() less arbitrary
objtool: Handle __pa_symbol() relocations
objtool: Make STACK_FRAME_NON_STANDARD consistent
objtool: Fix interval tree insertion for zero-length symbols
objtool: Make interval tree functions "static inline"
objtool: Fix weak symbol detection
x86/alternative: Create symbols for special section entries
objtool: Calculate function checksums
livepatch: Enable -ffunction-sections -fdata-sections
objtool, livepatch: Livepatch module generation

.gitignore | 3 +
Makefile | 9 +
arch/x86/include/asm/alternative.h | 50 +-
arch/x86/include/asm/asm.h | 24 +-
arch/x86/include/asm/bug.h | 2 +
arch/x86/include/asm/cpufeature.h | 2 +
arch/x86/include/asm/jump_label.h | 2 +
arch/x86/kernel/alternative.c | 51 +-
arch/x86/kernel/kprobes/opt.c | 4 -
arch/x86/kernel/module.c | 15 +-
include/asm-generic/vmlinux.lds.h | 2 +-
include/linux/compiler.h | 8 +-
include/linux/elfnote.h | 12 +-
include/linux/init.h | 3 +-
include/linux/livepatch.h | 25 +-
include/linux/livepatch_ext.h | 83 ++
include/linux/livepatch_patch.h | 73 ++
include/linux/objtool.h | 38 +-
kernel/livepatch/core.c | 8 +-
kernel/sys.c | 2 +-
scripts/Makefile.lib | 5 +-
scripts/livepatch/adjust-patch-lines | 181 +++
scripts/livepatch/klp-build | 355 ++++++
scripts/livepatch/module.c | 120 ++
scripts/module.lds.S | 22 +-
tools/include/linux/livepatch_ext.h | 83 ++
tools/objtool/Build | 4 +-
tools/objtool/Makefile | 34 +-
tools/objtool/arch/loongarch/decode.c | 6 +-
tools/objtool/arch/loongarch/orc.c | 30 +-
tools/objtool/arch/powerpc/decode.c | 6 +-
tools/objtool/arch/x86/decode.c | 118 +-
tools/objtool/arch/x86/orc.c | 27 +-
tools/objtool/arch/x86/special.c | 2 +-
tools/objtool/builtin-check.c | 66 +-
tools/objtool/check.c | 1414 ++++++++++-------------
tools/objtool/elf.c | 1059 +++++++++--------
tools/objtool/include/objtool/arch.h | 5 +-
tools/objtool/include/objtool/builtin.h | 4 +-
tools/objtool/include/objtool/check.h | 5 +-
tools/objtool/include/objtool/elf.h | 156 ++-
tools/objtool/include/objtool/klp.h | 25 +
tools/objtool/include/objtool/objtool.h | 6 +-
tools/objtool/include/objtool/orc.h | 10 +-
tools/objtool/include/objtool/special.h | 2 +-
tools/objtool/include/objtool/warn.h | 50 +-
tools/objtool/klp-diff.c | 1112 ++++++++++++++++++
tools/objtool/klp-link.c | 122 ++
tools/objtool/klp.c | 57 +
tools/objtool/objtool.c | 78 +-
tools/objtool/orc_dump.c | 100 +-
tools/objtool/orc_gen.c | 48 +-
tools/objtool/special.c | 58 +-
tools/objtool/sync-check.sh | 1 +
tools/objtool/weak.c | 11 +-
55 files changed, 4076 insertions(+), 1722 deletions(-)
create mode 100644 include/linux/livepatch_ext.h
create mode 100644 include/linux/livepatch_patch.h
create mode 100755 scripts/livepatch/adjust-patch-lines
create mode 100755 scripts/livepatch/klp-build
create mode 100644 scripts/livepatch/module.c
create mode 100644 tools/include/linux/livepatch_ext.h
create mode 100644 tools/objtool/include/objtool/klp.h
create mode 100644 tools/objtool/klp-diff.c
create mode 100644 tools/objtool/klp-link.c
create mode 100644 tools/objtool/klp.c

--
2.45.2