Commit 00a155c6 authored by Peter Zijlstra's avatar Peter Zijlstra
Browse files
This series introduces new objtool features and a klp-build script to
generate livepatch modules using a source .patch as input.

This builds on concepts from the longstanding out-of-tree kpatch [1]
project which began in 2012 and has been used for many years to generate
livepatch modules for production kernels.  However, this is a complete
rewrite which incorporates hard-earned lessons from 12+ years of
maintaining kpatch.

Key improvements compared to kpatch-build:

  - Integrated with objtool: Leverages objtool's existing control-flow
    graph analysis to help detect changed functions.

  - Works on vmlinux.o: Supports late-linked objects, making it
    compatible with LTO, IBT, and similar.

  - Simplified code base: ~3k fewer lines of code.

  - Upstream: No more out-of-tree #ifdef hacks, far less cruft.

  - Cleaner internals: Vastly simplified logic for symbol/section/reloc
    inclusion and special section extraction.

  - Robust __LINE__ macro handling: Avoids false positive binary diffs
    caused by the __LINE__ macro by introducing a fix-patch-lines script
    which injects #line directives into the source .patch to preserve
    the original line numbers at compile time.

The primary user interface is the klp-build script which does the
following:

  - Builds an original kernel with -function-sections and
    -fdata-sections, plus objtool function checksumming.

  - Applies the .patch file and rebuilds the kernel using the same
    options.

  - Runs 'objtool klp diff' to detect changed functions and generate
    intermediate binary diff objects.

  - Builds a kernel module which links the diff objects with some
    livepatch module init code (scripts/livepatch/init.c).

  - Finalizes the livepatch module (aka work around linker wreckage)
    using 'objtool klp post-link'.

I've tested with a variety of patches on defconfig and Fedora-config
kernels with both GCC and Clang.
parents 044f721c b9976fa4
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -14439,10 +14439,11 @@ T: git git://git.kernel.org/pub/scm/linux/kernel/git/livepatching/livepatching.g
F:	Documentation/ABI/testing/sysfs-kernel-livepatch
F:	Documentation/livepatch/
F:	arch/powerpc/include/asm/livepatch.h
F:	include/linux/livepatch.h
F:	include/linux/livepatch*.h
F:	kernel/livepatch/
F:	kernel/module/livepatch.c
F:	samples/livepatch/
F:	scripts/livepatch/
F:	tools/testing/selftests/livepatch/
LLC (802.2)
+1 −1
Original line number Diff line number Diff line
@@ -19,7 +19,7 @@
#ifdef CONFIG_EXPOLINE_EXTERN
	SYM_CODE_START(\name)
#else
	.pushsection .text.\name,"axG",@progbits,\name,comdat
	.pushsection .text..\name,"axG",@progbits,\name,comdat
	.globl \name
	.hidden \name
	.type \name,@function
+1 −1
Original line number Diff line number Diff line
@@ -51,7 +51,7 @@ SECTIONS
		IRQENTRY_TEXT
		SOFTIRQENTRY_TEXT
		FTRACE_HOTPATCH_TRAMPOLINES_TEXT
		*(.text.*_indirect_*)
		*(.text..*_indirect_*)
		*(.gnu.warning)
		. = ALIGN(PAGE_SIZE);
		_etext = .;		/* End of text section */
+1 −0
Original line number Diff line number Diff line
@@ -261,6 +261,7 @@ config X86
	select HAVE_FUNCTION_ERROR_INJECTION
	select HAVE_KRETPROBES
	select HAVE_RETHOOK
	select HAVE_KLP_BUILD			if X86_64
	select HAVE_LIVEPATCH			if X86_64
	select HAVE_MIXED_BREAKPOINTS_REGS
	select HAVE_MOD_ARCH_SPECIFIC
+4 −0
Original line number Diff line number Diff line
@@ -198,6 +198,7 @@ static inline int alternatives_text_reserved(void *start, void *end)

#define ALTINSTR_ENTRY(ft_flags)					      \
	".pushsection .altinstructions,\"a\"\n"				      \
	ANNOTATE_DATA_SPECIAL						      \
	" .long 771b - .\n"				/* label           */ \
	" .long 774f - .\n"				/* new instruction */ \
	" .4byte " __stringify(ft_flags) "\n"		/* feature + flags */ \
@@ -207,6 +208,7 @@ static inline int alternatives_text_reserved(void *start, void *end)

#define ALTINSTR_REPLACEMENT(newinstr)		/* replacement */	\
	".pushsection .altinstr_replacement, \"ax\"\n"			\
	ANNOTATE_DATA_SPECIAL						\
	"# ALT: replacement\n"						\
	"774:\n\t" newinstr "\n775:\n"					\
	".popsection\n"
@@ -337,6 +339,7 @@ void nop_func(void);
 * instruction. See apply_alternatives().
 */
.macro altinstr_entry orig alt ft_flags orig_len alt_len
	ANNOTATE_DATA_SPECIAL
	.long \orig - .
	.long \alt - .
	.4byte \ft_flags
@@ -365,6 +368,7 @@ void nop_func(void);
	.popsection ;							\
	.pushsection .altinstr_replacement,"ax"	;			\
743:									\
	ANNOTATE_DATA_SPECIAL ;						\
	newinst	;							\
744:									\
	.popsection ;
Loading