Live Patching
 help / color / mirror / Atom feed
* Re: [PATCH 4/5] objtool/klp: add -z/--fuzz patch rebasing option
From: Joe Lawrence @ 2026-01-30 20:41 UTC (permalink / raw)
  To: Josh Poimboeuf; +Cc: live-patching, Jiri Kosina, Miroslav Benes, Petr Mladek
In-Reply-To: <fayrtgx5l5wvcwkuxqc4it3t4ft3o7rbn4uojtmzjxq66nniw7@v6om4zyepshh>

On Fri, Jan 30, 2026 at 12:09:35PM -0800, Josh Poimboeuf wrote:
> On Fri, Jan 30, 2026 at 12:59:49PM -0500, Joe Lawrence wrote:
> > @@ -131,6 +133,7 @@ Advanced Options:
> >  				   3|diff	Diff objects
> >  				   4|kmod	Build patch module
> >     -T, --keep-tmp		Preserve tmp dir on exit
> > +   -z, --fuzz[=NUM]		Rebase patches using fuzzy matching [default: 2]
> 
> Ideally I think klp-build should accept a patch level fuzz of 2 by
> default.  If we just made that the default then maybe we don't need this
> option?
> 

Do you mean to drop the optional level value, or to just perform level-2
fuzz rebasing as a matter of course (so no -z option altogether)?

--
Joe


^ permalink raw reply

* [PATCH] klp-build: Do not warn "no correlation" for __irf_[start|end]
From: Song Liu @ 2026-01-30 20:39 UTC (permalink / raw)
  To: live-patching
  Cc: jpoimboe, kernel-team, jikos, mbenes, pmladek, joe.lawrence,
	Song Liu

When compiling with CONFIG_LTO_CLANG_THIN, vmlinux.o has
__irf_[start|end] before the first FILE entry:

$ readelf -sW vmlinux.o
Symbol table '.symtab' contains 597706 entries:
   Num:    Value          Size Type    Bind   Vis      Ndx Name
     0: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT  UND
     1: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT   18 __irf_start
     2: 0000000000000200     0 NOTYPE  LOCAL  DEFAULT   18 __irf_end
     3: 0000000000000000     0 SECTION LOCAL  DEFAULT   17 .text
     4: 0000000000000000     0 SECTION LOCAL  DEFAULT   18 .init.ramfs

This causes klp-build throwing warnings like:

vmlinux.o: warning: objtool: no correlation: __irf_start
vmlinux.o: warning: objtool: no correlation: __irf_end

Fix this by not warn for no correlation before seeing the first FILE
entry.

Signed-off-by: Song Liu <song@kernel.org>
---
 tools/objtool/klp-diff.c | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/tools/objtool/klp-diff.c b/tools/objtool/klp-diff.c
index d94531e3f64e..370e5c79ae66 100644
--- a/tools/objtool/klp-diff.c
+++ b/tools/objtool/klp-diff.c
@@ -363,6 +363,7 @@ static int correlate_symbols(struct elfs *e)
 {
 	struct symbol *file1_sym, *file2_sym;
 	struct symbol *sym1, *sym2;
+	bool found_first_file = false;
 
 	/* Correlate locals */
 	for (file1_sym = first_file_symbol(e->orig),
@@ -432,9 +433,12 @@ static int correlate_symbols(struct elfs *e)
 	}
 
 	for_each_sym(e->orig, sym1) {
+		if (!found_first_file && is_file_sym(sym1))
+			found_first_file = true;
 		if (sym1->twin || dont_correlate(sym1))
 			continue;
-		WARN("no correlation: %s", sym1->name);
+		if (found_first_file)
+			WARN("no correlation: %s", sym1->name);
 	}
 
 	return 0;
-- 
2.47.3


^ permalink raw reply related

* Re: [PATCH 3/5] objtool/klp: validate patches with git apply --recount
From: Joe Lawrence @ 2026-01-30 20:38 UTC (permalink / raw)
  To: Josh Poimboeuf; +Cc: live-patching, Jiri Kosina, Miroslav Benes, Petr Mladek
In-Reply-To: <lqchka76tcwjxitn5tm42keexglnac6iveb44ppgx4c425qsfg@sbcdkfgmebqu>

On Fri, Jan 30, 2026 at 12:05:35PM -0800, Josh Poimboeuf wrote:
> On Fri, Jan 30, 2026 at 12:59:48PM -0500, Joe Lawrence wrote:
> > Consider a patch offset by a line:
> > 
> >   $ cat combined.patch
> >   --- src.orig/fs/proc/cmdline.c	2022-10-24 15:41:08.858760066 -0400
> >   +++ src/fs/proc/cmdline.c	2022-10-24 15:41:11.698715352 -0400
> >   @@ -6,8 +6,7 @@
> >   
> >    static int cmdline_proc_show(struct seq_file *m, void *v)
> >    {
> >   -	seq_puts(m, saved_command_line);
> >   -	seq_putc(m, '\n');
> >   +	seq_printf(m, "%s livepatch=1\n", saved_command_line);
> >    	return 0;
> >    }
> >   
> >   --- a/fs/proc/version.c
> >   +++ b/fs/proc/version.c
> >   @@ -9,6 +9,7 @@
> >   
> >    static int version_proc_show(struct seq_file *m, void *v)
> >    {
> >   +	seq_printf(m, "livepatch ");
> >    	seq_printf(m, linux_proc_banner,
> >    		utsname()->sysname,
> >    		utsname()->release,
> > 
> > GNU patch reports the offset:
> > 
> >   $ patch --dry-run -p1 < combined.patch
> >   checking file fs/proc/cmdline.c
> >   Hunk #1 succeeded at 7 (offset 1 line).
> >   checking file fs/proc/version.c
> > 
> > It would pass the initial check as per validate_patches():
> > 
> >   $ git apply --check < combined.patch && echo "ok"
> >   ok
> > 
> > But later fail the patch application by refresh_patch():
> > 
> >   $ git apply --check --recount < combined.patch
> >   error: patch failed: fs/proc/cmdline.c:6
> >   error: fs/proc/cmdline.c: patch does not apply
> 
> Hm, isn't the whole point of --recount that it ignores the line numbers?
> Or does it just ignore the numbers after the commas (the counts)?
> 

I don't know exactly.  As I continue digging into the test that sent me
down this path, I just found that `git apply --recount` doesn't like
some output generated by `combinediff -q --combine` even with NO line
drift... then if I manually added in corresponding diff command lines
(to make it look more like a .patch file generated by `diff -Nu`), ie:

  diff -Nu src.orig/fs/proc/array.c src/fs/proc/array.c     <---
  --- src.orig/fs/proc/array.c
  +++ src/fs/proc/array.c

Suddenly `git apply --recount` is happy with the patch.

So I suspect that I started with git not liking the hunks generated by
combinediff and drove it to the rebase feature, which solves a more
interesting problem, but by side effect smoothed over this format
issue when it recreated the patch with git.

Anyway, I think this patch still stands on it's own: perform the same
apply/revert check as what would happen in the fixup steps to fail
faster for the user?

--
Joe 


^ permalink raw reply

* Re: [PATCH 4/5] objtool/klp: add -z/--fuzz patch rebasing option
From: Joe Lawrence @ 2026-01-30 20:13 UTC (permalink / raw)
  To: Song Liu
  Cc: live-patching, Josh Poimboeuf, Jiri Kosina, Miroslav Benes,
	Petr Mladek
In-Reply-To: <CAPhsuW59dfVk0hVPFWjgvEifUwviFvnCcMZFGMeZfrw3LJaRZA@mail.gmail.com>

On Fri, Jan 30, 2026 at 11:58:06AM -0800, Song Liu wrote:
> On Fri, Jan 30, 2026 at 10:00 AM Joe Lawrence <joe.lawrence@redhat.com> wrote:
> [...]
> > @@ -807,6 +906,8 @@ build_patch_module() {
> >  process_args "$@"
> >  do_init
> >
> > +maybe_rebase_patches
> > +
> >  if (( SHORT_CIRCUIT <= 1 )); then
> 
> I think we should call maybe_rebase_patches within this
> if condition.
> 

Hi Song,

Ah yeah I stumbled on this, probably overthinking it:

  - we want to validate rebased patches (when requested)
  - validate_patches() isn't really required for step 1 (building the
    original kernel) but ...
  - it's nice to check the patches before going off and building a full
    kernel
  - the patches are needed in step 2 (building the patched kernel) but ...
  - patch validation occurs in step 1

so given the way the short circuiting works, I didn't see a good way to
fold it in there.  The user might want to jump right to building the
patched kernel with patch rebasing.  Maybe that's not valid thinking if
the rebase occurs in step 1 and they are left behind in klp-tmp/ (so
jumping to step 2 will just use the patches in the scratch dir and not
command line?).  It's Friday, maybe I'm missing something obvious? :)

--
Joe


^ permalink raw reply

* Re: [PATCH 4/5] objtool/klp: add -z/--fuzz patch rebasing option
From: Josh Poimboeuf @ 2026-01-30 20:09 UTC (permalink / raw)
  To: Joe Lawrence; +Cc: live-patching, Jiri Kosina, Miroslav Benes, Petr Mladek
In-Reply-To: <20260130175950.1056961-5-joe.lawrence@redhat.com>

On Fri, Jan 30, 2026 at 12:59:49PM -0500, Joe Lawrence wrote:
> @@ -131,6 +133,7 @@ Advanced Options:
>  				   3|diff	Diff objects
>  				   4|kmod	Build patch module
>     -T, --keep-tmp		Preserve tmp dir on exit
> +   -z, --fuzz[=NUM]		Rebase patches using fuzzy matching [default: 2]

Ideally I think klp-build should accept a patch level fuzz of 2 by
default.  If we just made that the default then maybe we don't need this
option?

-- 
Josh

^ permalink raw reply

* Re: [PATCH 3/5] objtool/klp: validate patches with git apply --recount
From: Josh Poimboeuf @ 2026-01-30 20:05 UTC (permalink / raw)
  To: Joe Lawrence; +Cc: live-patching, Jiri Kosina, Miroslav Benes, Petr Mladek
In-Reply-To: <20260130175950.1056961-4-joe.lawrence@redhat.com>

On Fri, Jan 30, 2026 at 12:59:48PM -0500, Joe Lawrence wrote:
> Consider a patch offset by a line:
> 
>   $ cat combined.patch
>   --- src.orig/fs/proc/cmdline.c	2022-10-24 15:41:08.858760066 -0400
>   +++ src/fs/proc/cmdline.c	2022-10-24 15:41:11.698715352 -0400
>   @@ -6,8 +6,7 @@
>   
>    static int cmdline_proc_show(struct seq_file *m, void *v)
>    {
>   -	seq_puts(m, saved_command_line);
>   -	seq_putc(m, '\n');
>   +	seq_printf(m, "%s livepatch=1\n", saved_command_line);
>    	return 0;
>    }
>   
>   --- a/fs/proc/version.c
>   +++ b/fs/proc/version.c
>   @@ -9,6 +9,7 @@
>   
>    static int version_proc_show(struct seq_file *m, void *v)
>    {
>   +	seq_printf(m, "livepatch ");
>    	seq_printf(m, linux_proc_banner,
>    		utsname()->sysname,
>    		utsname()->release,
> 
> GNU patch reports the offset:
> 
>   $ patch --dry-run -p1 < combined.patch
>   checking file fs/proc/cmdline.c
>   Hunk #1 succeeded at 7 (offset 1 line).
>   checking file fs/proc/version.c
> 
> It would pass the initial check as per validate_patches():
> 
>   $ git apply --check < combined.patch && echo "ok"
>   ok
> 
> But later fail the patch application by refresh_patch():
> 
>   $ git apply --check --recount < combined.patch
>   error: patch failed: fs/proc/cmdline.c:6
>   error: fs/proc/cmdline.c: patch does not apply

Hm, isn't the whole point of --recount that it ignores the line numbers?
Or does it just ignore the numbers after the commas (the counts)?

-- 
Josh

^ permalink raw reply

* Re: [PATCH 2/5] objtool/klp: handle patches that add new files
From: Josh Poimboeuf @ 2026-01-30 20:02 UTC (permalink / raw)
  To: Joe Lawrence; +Cc: live-patching, Jiri Kosina, Miroslav Benes, Petr Mladek
In-Reply-To: <20260130175950.1056961-3-joe.lawrence@redhat.com>

On Fri, Jan 30, 2026 at 12:59:47PM -0500, Joe Lawrence wrote:
> diff --git a/scripts/livepatch/klp-build b/scripts/livepatch/klp-build
> index 964f9ed5ee1b..5a8c592c4c15 100755
> --- a/scripts/livepatch/klp-build
> +++ b/scripts/livepatch/klp-build
> @@ -426,6 +426,8 @@ refresh_patch() {
>  	local patch="$1"
>  	local tmpdir="$PATCH_TMP_DIR"
>  	local files=()
> +	local orig_files=()
> +	local patched_files=()
>  
>  	rm -rf "$tmpdir"
>  	mkdir -p "$tmpdir/a"
> @@ -434,12 +436,20 @@ refresh_patch() {
>  	# Get all source files affected by the patch
>  	get_patch_files "$patch" | mapfile -t files
>  
> -	# Copy orig source files to 'a'
> -	( cd "$SRC" && echo "${files[@]}" | xargs cp --parents --target-directory="$tmpdir/a" )
> +	# Copy orig source files to 'a', filter to only existing files
> +	for file in "${files[@]}"; do
> +		[[ "$file" != "dev/null" ]] && [[ -f "$SRC/$file" ]] && orig_files+=("$file")

Can we fix get_patch_files() so it filters out /dev/null (or "dev/null"
as it appears to be for some reason)?  I don't think any of its callers
would want that.

Also I'm thinking these checks would be more precise if they parsed the
patch file directly to get the before/after file names, as that would
catch more cases of malformed patches.

So maybe we'd just need something like get_patch_input_files() and
get_patch_output_files() here (not sure about the naming)?

BTW, for the patch subject prefixes I've been using
"livepatch/klp-build" for changes to klp-build and "objtool/klp" for
objtool/klp-diff.c, so let's keep doing that unless anybody has any
better suggestions.

-- 
Josh

^ permalink raw reply

* Re: [PATCH 4/5] objtool/klp: add -z/--fuzz patch rebasing option
From: Song Liu @ 2026-01-30 19:58 UTC (permalink / raw)
  To: Joe Lawrence
  Cc: live-patching, Josh Poimboeuf, Jiri Kosina, Miroslav Benes,
	Petr Mladek
In-Reply-To: <20260130175950.1056961-5-joe.lawrence@redhat.com>

On Fri, Jan 30, 2026 at 10:00 AM Joe Lawrence <joe.lawrence@redhat.com> wrote:
[...]
> @@ -807,6 +906,8 @@ build_patch_module() {
>  process_args "$@"
>  do_init
>
> +maybe_rebase_patches
> +
>  if (( SHORT_CIRCUIT <= 1 )); then

I think we should call maybe_rebase_patches within this
if condition.

Thanks,
Song

>         status "Validating patch(es)"
>         validate_patches

^ permalink raw reply

* Re: [PATCH 0/5] objtool/klp-build: small fixups and enhancements
From: Song Liu @ 2026-01-30 19:18 UTC (permalink / raw)
  To: Joe Lawrence
  Cc: live-patching, Josh Poimboeuf, Jiri Kosina, Miroslav Benes,
	Petr Mladek
In-Reply-To: <20260130175950.1056961-1-joe.lawrence@redhat.com>

On Fri, Jan 30, 2026 at 10:00 AM Joe Lawrence <joe.lawrence@redhat.com> wrote:
>
> Hi Josh,
>
> While porting over some internal tests to use klp-build, I tripped over
> a few small usability bugs and nits.  These are aren't show-stoppers,
> but a few were pretty esoteric to debug and might lead some users down
> similar rabbit holes.
>
> Look for per-patch failure messages and reproducers in the individual
> patch diffstat areas.  LMK if any of those details should make it into
> the commit messages as I assumed they were only interesting for
> reviewing context.

The commit messages look good to me. We can add some of those
extra contexts in selftests.

For the set
Acked-by: Song Liu <song@kernel.org>

^ permalink raw reply

* Re: [PATCH 4/5] objtool/klp: add -z/--fuzz patch rebasing option
From: Song Liu @ 2026-01-30 19:13 UTC (permalink / raw)
  To: Joe Lawrence
  Cc: live-patching, Josh Poimboeuf, Jiri Kosina, Miroslav Benes,
	Petr Mladek
In-Reply-To: <20260130175950.1056961-5-joe.lawrence@redhat.com>

On Fri, Jan 30, 2026 at 10:00 AM Joe Lawrence <joe.lawrence@redhat.com> wrote:
>
> The klp-build script is currently very strict with input patches,
> requiring them to apply cleanly via `git apply --recount`.  This
> prevents the use of patches with minor contextual fuzz relative to the
> target kernel sources.
>
> Add an optional -z/--fuzz option to allow klp-build to "rebase" input
> patches within its klp-tmp/ scratch space.  When enabled, the script
> utilizes GNU patch's fuzzy matching to apply changes to a temporary
> directory and then creates a normalized version of the patch using `git
> diff --no-index`.
>
> This rebased patch contains the exact line counts and context required
> for the subsequent klp-build fixup and build steps, allowing users to
> reuse a patch across similar kernel streams.
>
> Signed-off-by: Joe Lawrence <joe.lawrence@redhat.com>

LTGM.

Acked-by: Song Liu <song@kernel.org>

With one nitpick below.
[...]
>
> +# Rebase a patch using GNU patch with fuzz
> +# Outputs path to rebased patch on success, non-zero on failure
> +rebase_patch() {
> +       local idx="$1"
> +       local input_patch="$2"
> +       local patch_name="$(basename "$input_patch" .patch)"
> +       local work_dir="$REBASE_DIR/$idx-$patch_name"
> +       local output_patch="$work_dir/rebased.patch"
> +       local files=()
> +       local file
> +
> +       rm -rf "$work_dir"
> +       mkdir -p "$work_dir/orig" "$work_dir/patched"
> +
> +       get_patch_files "$input_patch" | mapfile -t files
> +
> +       # Copy original files (before patch)
> +       for file in "${files[@]}"; do
> +               [[ "$file" == "dev/null" ]] && continue
> +               if [[ -f "$SRC/$file" ]]; then
> +                       mkdir -p "$work_dir/orig/$(dirname "$file")"
> +                       cp -f "$SRC/$file" "$work_dir/orig/$file"
> +               fi
> +       done
> +
> +       # Apply with fuzz
> +       (
> +               cd "$SRC"
> +               sed -n '/^-- /q;p' "$input_patch" | \
> +                       patch -p1 \

I think we should add -s here, and.

> +                               -F"$FUZZ_FACTOR" \
> +                               --no-backup-if-mismatch \
> +                               -r /dev/null \
> +                               --forward >&2
> +       ) || return 1
> +
> +       # Copy patched files (after patch)
> +       for file in "${files[@]}"; do
> +               [[ "$file" == "dev/null" ]] && continue
> +               if [[ -f "$SRC/$file" ]]; then
> +                       mkdir -p "$work_dir/patched/$(dirname "$file")"
> +                       cp -f "$SRC/$file" "$work_dir/patched/$file"
> +               fi
> +       done
> +
> +       # Revert with fuzz
> +       (
> +               cd "$SRC"
> +               sed -n '/^-- /q;p' "$input_patch" | \
> +                       patch -p1 -R \

.. here, so that we can avoid a bunch of "patching file" messages.

> +                               -F"$FUZZ_FACTOR" \
> +                               --no-backup-if-mismatch \
> +                               -r /dev/null >&2
> +       ) || {
> +               warn "fuzzy revert failed; source tree may be corrupted"
> +               return 1
> +       }

^ permalink raw reply

* [PATCH 5/5] objtool/klp: provide friendlier error messages
From: Joe Lawrence @ 2026-01-30 17:59 UTC (permalink / raw)
  To: live-patching; +Cc: Josh Poimboeuf, Jiri Kosina, Miroslav Benes, Petr Mladek
In-Reply-To: <20260130175950.1056961-1-joe.lawrence@redhat.com>

Provide a little bit more context behind some of the klp-build failure
modes clarify which of the user-provided patches is unsupported,
doesn't apply, and which kernel build failed.

Signed-off-by: Joe Lawrence <joe.lawrence@redhat.com>
---
 scripts/livepatch/klp-build | 11 ++++++-----
 1 file changed, 6 insertions(+), 5 deletions(-)

diff --git a/scripts/livepatch/klp-build b/scripts/livepatch/klp-build
index 535ca18e32c5..64a18c2ae1ba 100755
--- a/scripts/livepatch/klp-build
+++ b/scripts/livepatch/klp-build
@@ -429,7 +429,7 @@ check_unsupported_patches() {
 		for file in "${files[@]}"; do
 			case "$file" in
 				lib/*|*.S)
-					die "unsupported patch to $file"
+					die "$patch unsupported patch to $file"
 					;;
 			esac
 		done
@@ -449,7 +449,7 @@ apply_patch() {
 		# The sed strips the version signature from 'git format-patch',
 		# otherwise 'git apply --recount' warns.
 		sed -n '/^-- /q;p' "$patch" |
-			git apply "${extra_args[@]}"
+			git apply "${extra_args[@]}" || die "$patch doesn't apply (retry with --fuzz?)"
 	)
 
 	APPLIED_PATCHES+=("$patch")
@@ -601,6 +601,7 @@ clean_kernel() {
 }
 
 build_kernel() {
+	local build="$1"
 	local log="$TMP_DIR/build.log"
 	local objtool_args=()
 	local cmd=()
@@ -638,7 +639,7 @@ build_kernel() {
 		"${cmd[@]}"							\
 			1> >(tee -a "$log")					\
 			2> >(tee -a "$log" | grep0 -v "modpost.*undefined!" >&2)
-	)
+	) || die "$build kernel build failed"
 }
 
 find_objects() {
@@ -913,7 +914,7 @@ if (( SHORT_CIRCUIT <= 1 )); then
 	validate_patches
 	status "Building original kernel"
 	clean_kernel
-	build_kernel
+	build_kernel "Original"
 	status "Copying original object files"
 	copy_orig_objects
 fi
@@ -923,7 +924,7 @@ if (( SHORT_CIRCUIT <= 2 )); then
 	fix_patches
 	apply_patches
 	status "Building patched kernel"
-	build_kernel
+	build_kernel "Patched"
 	revert_patches
 	status "Copying patched object files"
 	copy_patched_objects
-- 
2.52.0


^ permalink raw reply related

* [PATCH 4/5] objtool/klp: add -z/--fuzz patch rebasing option
From: Joe Lawrence @ 2026-01-30 17:59 UTC (permalink / raw)
  To: live-patching; +Cc: Josh Poimboeuf, Jiri Kosina, Miroslav Benes, Petr Mladek
In-Reply-To: <20260130175950.1056961-1-joe.lawrence@redhat.com>

The klp-build script is currently very strict with input patches,
requiring them to apply cleanly via `git apply --recount`.  This
prevents the use of patches with minor contextual fuzz relative to the
target kernel sources.

Add an optional -z/--fuzz option to allow klp-build to "rebase" input
patches within its klp-tmp/ scratch space.  When enabled, the script
utilizes GNU patch's fuzzy matching to apply changes to a temporary
directory and then creates a normalized version of the patch using `git
diff --no-index`.

This rebased patch contains the exact line counts and context required
for the subsequent klp-build fixup and build steps, allowing users to
reuse a patch across similar kernel streams.

Signed-off-by: Joe Lawrence <joe.lawrence@redhat.com>
---
 scripts/livepatch/klp-build | 105 +++++++++++++++++++++++++++++++++++-
 1 file changed, 103 insertions(+), 2 deletions(-)

Using the same 1-line-offset input combined.patch from the previous
patch in this set and adding --fuzz, we can successfully now build it:

  $ ./scripts/livepatch/klp-build -T --fuzz combined.patch
  Rebasing 1 patch(es)
  -> combined.patch
  patching file fs/proc/cmdline.c
  Hunk #1 succeeded at 7 (offset 1 line).
  patching file fs/proc/version.c
  patching file fs/proc/cmdline.c
  Hunk #1 succeeded at 7 (offset 1 line).
  patching file fs/proc/version.c
  Validating patch(es)
  Building original kernel
  Copying original object files
  Fixing patch(es)
  Building patched kernel
  Copying patched object files
  Diffing objects
  vmlinux.o: changed function: cmdline_proc_show
  vmlinux.o: changed function: version_proc_show
  Building patch module: livepatch-combined.ko
  SUCCESS 

diff --git a/scripts/livepatch/klp-build b/scripts/livepatch/klp-build
index 2313bc909f58..535ca18e32c5 100755
--- a/scripts/livepatch/klp-build
+++ b/scripts/livepatch/klp-build
@@ -26,6 +26,7 @@ REPLACE=1
 SHORT_CIRCUIT=0
 JOBS="$(getconf _NPROCESSORS_ONLN)"
 VERBOSE="-s"
+FUZZ_FACTOR=""
 shopt -o xtrace | grep -q 'on' && XTRACE=1
 
 # Avoid removing the previous $TMP_DIR until args have been fully processed.
@@ -49,6 +50,7 @@ KMOD_DIR="$TMP_DIR/kmod"
 STASH_DIR="$TMP_DIR/stash"
 TIMESTAMP="$TMP_DIR/timestamp"
 PATCH_TMP_DIR="$TMP_DIR/tmp"
+REBASE_DIR="$TMP_DIR/rebase"
 
 KLP_DIFF_LOG="$DIFF_DIR/diff.log"
 
@@ -131,6 +133,7 @@ Advanced Options:
 				   3|diff	Diff objects
 				   4|kmod	Build patch module
    -T, --keep-tmp		Preserve tmp dir on exit
+   -z, --fuzz[=NUM]		Rebase patches using fuzzy matching [default: 2]
 
 EOF
 }
@@ -145,8 +148,8 @@ process_args() {
 	local long
 	local args
 
-	short="hfj:o:vdS:T"
-	long="help,show-first-changed,jobs:,output:,no-replace,verbose,debug,short-circuit:,keep-tmp"
+	short="hfj:o:vdS:Tz::"
+	long="help,show-first-changed,jobs:,output:,no-replace,verbose,debug,short-circuit:,keep-tmp,fuzz::"
 
 	args=$(getopt --options "$short" --longoptions "$long" -- "$@") || {
 		echo; usage; exit
@@ -204,6 +207,14 @@ process_args() {
 				keep_tmp=1
 				shift
 				;;
+			-z | --fuzz)
+				if [[ -n "$2" ]]; then
+					FUZZ_FACTOR="$2"
+				else
+					FUZZ_FACTOR=2
+				fi
+				shift 2
+				;;
 			--)
 				shift
 				break
@@ -304,6 +315,94 @@ get_patch_files() {
 		| sort -u
 }
 
+# Rebase a patch using GNU patch with fuzz
+# Outputs path to rebased patch on success, non-zero on failure
+rebase_patch() {
+	local idx="$1"
+	local input_patch="$2"
+	local patch_name="$(basename "$input_patch" .patch)"
+	local work_dir="$REBASE_DIR/$idx-$patch_name"
+	local output_patch="$work_dir/rebased.patch"
+	local files=()
+	local file
+
+	rm -rf "$work_dir"
+	mkdir -p "$work_dir/orig" "$work_dir/patched"
+
+	get_patch_files "$input_patch" | mapfile -t files
+
+	# Copy original files (before patch)
+	for file in "${files[@]}"; do
+		[[ "$file" == "dev/null" ]] && continue
+		if [[ -f "$SRC/$file" ]]; then
+			mkdir -p "$work_dir/orig/$(dirname "$file")"
+			cp -f "$SRC/$file" "$work_dir/orig/$file"
+		fi
+	done
+
+	# Apply with fuzz
+	(
+		cd "$SRC"
+		sed -n '/^-- /q;p' "$input_patch" | \
+			patch -p1 \
+				-F"$FUZZ_FACTOR" \
+				--no-backup-if-mismatch \
+				-r /dev/null \
+				--forward >&2
+	) || return 1
+
+	# Copy patched files (after patch)
+	for file in "${files[@]}"; do
+		[[ "$file" == "dev/null" ]] && continue
+		if [[ -f "$SRC/$file" ]]; then
+			mkdir -p "$work_dir/patched/$(dirname "$file")"
+			cp -f "$SRC/$file" "$work_dir/patched/$file"
+		fi
+	done
+
+	# Revert with fuzz
+	(
+		cd "$SRC"
+		sed -n '/^-- /q;p' "$input_patch" | \
+			patch -p1 -R \
+				-F"$FUZZ_FACTOR" \
+				--no-backup-if-mismatch \
+				-r /dev/null >&2
+	) || {
+		warn "fuzzy revert failed; source tree may be corrupted"
+		return 1
+	}
+
+	# Generate clean patch from captured state
+	( cd "$work_dir" && git diff --no-index --no-prefix orig patched ) > "$output_patch" || true
+
+	echo "$output_patch"
+}
+
+# If the user specified --fuzz, iterate through PATCHES and rebase them
+# Updates PATCHES array in-place with rebased patch paths
+maybe_rebase_patches() {
+	local i
+	local idx
+	local patch
+	local rebased
+
+	[[ -z "$FUZZ_FACTOR" ]] && return 0
+
+	status "Rebasing ${#PATCHES[@]} patch(es)"
+
+	mkdir -p "$REBASE_DIR"
+
+	idx=0001
+	for i in "${!PATCHES[@]}"; do
+		patch="${PATCHES[$i]}"
+		echo "-> $(basename "$patch")"
+		rebased=$(rebase_patch "$idx" "$patch") || die "rebase failed: $patch"
+		PATCHES[i]="$rebased"
+		idx=$(printf "%04d" $(( 10#$idx + 1 )))
+	done
+}
+
 # Make sure git re-stats the changed files
 git_refresh() {
 	local patch="$1"
@@ -807,6 +906,8 @@ build_patch_module() {
 process_args "$@"
 do_init
 
+maybe_rebase_patches
+
 if (( SHORT_CIRCUIT <= 1 )); then
 	status "Validating patch(es)"
 	validate_patches
-- 
2.52.0


^ permalink raw reply related

* [PATCH 3/5] objtool/klp: validate patches with git apply --recount
From: Joe Lawrence @ 2026-01-30 17:59 UTC (permalink / raw)
  To: live-patching; +Cc: Josh Poimboeuf, Jiri Kosina, Miroslav Benes, Petr Mladek
In-Reply-To: <20260130175950.1056961-1-joe.lawrence@redhat.com>

The klp-build script performs a sanity check on user-provided patches
using `git apply --check`.  However, this check is less strict than the
subsequent patch fixup phase, which runs `git apply --recount`.

As a result, patches with line count drift (fuzz) may pass the initial
validation but fail during fixup. Update the initial validation phase to
include the '--recount' flag.  This ensures a consistent check across
both phases and allows the script to fail fast on malformed or drifted
patches.

Signed-off-by: Joe Lawrence <joe.lawrence@redhat.com>
---
 scripts/livepatch/klp-build | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

Here are the build errors:

  $ ./scripts/livepatch/klp-build -T combined.patch 
  Validating patch(es)
  Building original kernel
  
  Copying original object files
  Fixing patch(es)
  error: patch failed: fs/proc/cmdline.c:6
  error: fs/proc/cmdline.c: patch does not apply
  error: klp-build: line 350: 'git apply "${extra_args[@]}"'
  error: klp-build: line 351: '( cd "$SRC"; sed -n '/^-- /q;p' "$patch" | git apply "${extra_args[@]}" )'

This was a strange one to debug, but I finally narrowed it down to
pecular `git apply` behavior depending on the presence of the --recount
flag.

Consider a patch offset by a line:

  $ cat combined.patch
  --- src.orig/fs/proc/cmdline.c	2022-10-24 15:41:08.858760066 -0400
  +++ src/fs/proc/cmdline.c	2022-10-24 15:41:11.698715352 -0400
  @@ -6,8 +6,7 @@
  
   static int cmdline_proc_show(struct seq_file *m, void *v)
   {
  -	seq_puts(m, saved_command_line);
  -	seq_putc(m, '\n');
  +	seq_printf(m, "%s livepatch=1\n", saved_command_line);
   	return 0;
   }
  
  --- a/fs/proc/version.c
  +++ b/fs/proc/version.c
  @@ -9,6 +9,7 @@
  
   static int version_proc_show(struct seq_file *m, void *v)
   {
  +	seq_printf(m, "livepatch ");
   	seq_printf(m, linux_proc_banner,
   		utsname()->sysname,
   		utsname()->release,

GNU patch reports the offset:

  $ patch --dry-run -p1 < combined.patch
  checking file fs/proc/cmdline.c
  Hunk #1 succeeded at 7 (offset 1 line).
  checking file fs/proc/version.c

It would pass the initial check as per validate_patches():

  $ git apply --check < combined.patch && echo "ok"
  ok

But later fail the patch application by refresh_patch():

  $ git apply --check --recount < combined.patch
  error: patch failed: fs/proc/cmdline.c:6
  error: fs/proc/cmdline.c: patch does not apply

Adding the same --recount argument to validate_patches() would allow the
script to fail fast and not (cryptically) way later:

  $ ./scripts/livepatch/klp-build -T combined.patch
  Validating patch(es)
  error: patch failed: fs/proc/cmdline.c:6
  error: fs/proc/cmdline.c: patch does not apply
  error: klp-build: combined.patch doesn't apply
  error: klp-build: line 453: '( cd "$SRC"; sed -n '/^-- /q;p' "$patch" | git apply "${extra_args[@]}" || die "$patch doesn't apply" )'

diff --git a/scripts/livepatch/klp-build b/scripts/livepatch/klp-build
index 5a8c592c4c15..2313bc909f58 100755
--- a/scripts/livepatch/klp-build
+++ b/scripts/livepatch/klp-build
@@ -379,10 +379,11 @@ revert_patch() {
 }
 
 apply_patches() {
+	local extra_args=("$@")
 	local patch
 
 	for patch in "${PATCHES[@]}"; do
-		apply_patch "$patch"
+		apply_patch "$patch" "${extra_args[@]}"
 	done
 }
 
@@ -399,8 +400,8 @@ revert_patches() {
 
 validate_patches() {
 	check_unsupported_patches
-	apply_patches
-	revert_patches
+	apply_patches --recount
+	revert_patches --recount
 }
 
 do_init() {
-- 
2.52.0


^ permalink raw reply related

* [PATCH 0/5] objtool/klp-build: small fixups and enhancements
From: Joe Lawrence @ 2026-01-30 17:59 UTC (permalink / raw)
  To: live-patching; +Cc: Josh Poimboeuf, Jiri Kosina, Miroslav Benes, Petr Mladek

Hi Josh,

While porting over some internal tests to use klp-build, I tripped over
a few small usability bugs and nits.  These are aren't show-stoppers,
but a few were pretty esoteric to debug and might lead some users down
similar rabbit holes.

Look for per-patch failure messages and reproducers in the individual
patch diffstat areas.  LMK if any of those details should make it into
the commit messages as I assumed they were only interesting for
reviewing context.

Finally these are very lightly tested, so any additional patches you'd
like to send through these changes would be welcome.

-- Joe


Joe Lawrence (5):
  objtool/klp: limit parent .git directory search
  objtool/klp: handle patches that add new files
  objtool/klp: validate patches with git apply --recount
  objtool/klp: add -z/--fuzz patch rebasing option
  objtool/klp: provide friendlier error messages

 scripts/livepatch/klp-build | 144 ++++++++++++++++++++++++++++++++----
 1 file changed, 130 insertions(+), 14 deletions(-)

-- 
2.52.0


^ permalink raw reply

* [PATCH 2/5] objtool/klp: handle patches that add new files
From: Joe Lawrence @ 2026-01-30 17:59 UTC (permalink / raw)
  To: live-patching; +Cc: Josh Poimboeuf, Jiri Kosina, Miroslav Benes, Petr Mladek
In-Reply-To: <20260130175950.1056961-1-joe.lawrence@redhat.com>

The klp-build script prepares a clean patch by populating two temporary
directories ('a' and 'b') with source files and diffing the result.
However, this process currently fails when a patch introduces a new
source file as the script attempts to copy files that do not yet exist
in the original source tree.

Update the file-copying logic in refresh_patch() to verify existence
before processing:

- Filter the files list to ensure only files currently present in $SRC
  are copied to the 'a' directory.
- Apply the patch, then verify file existence again before copying
  to the 'b' directory.
- Ignore "/dev/null" entries, which represent non-existent files in
  patch headers.

This allows klp-build to successfully process patches that add new
source files to the kernel.

Signed-off-by: Joe Lawrence <joe.lawrence@redhat.com>
---
 scripts/livepatch/klp-build | 18 ++++++++++++++----
 1 file changed, 14 insertions(+), 4 deletions(-)

This problem was found with a simple patch that included a new header
file:

  diff --git a/fs/proc/cmdline.c b/fs/proc/cmdline.c
  index a6f76121955f..d1927ad00bb3 100644
  --- a/fs/proc/cmdline.c
  +++ b/fs/proc/cmdline.c
  @@ -4,11 +4,11 @@
   #include <linux/proc_fs.h>
   #include <linux/seq_file.h>
   #include "internal.h"
  +#include "test.h"
   
   static int cmdline_proc_show(struct seq_file *m, void *v)
   {
  -       seq_puts(m, saved_command_line);
  -       seq_putc(m, '\n');
  +       seq_printf(m, test_string, saved_command_line);
          return 0;
   }
   
  diff --git a/fs/proc/test.h b/fs/proc/test.h
  new file mode 100644
  index 000000000000..94de7114cf86
  --- /dev/null
  +++ b/fs/proc/test.h
  @@ -0,0 +1 @@
  +#define test_string "%s klp=1\n"

And the build failure:

  $ ./scripts/livepatch/klp-build /tmp/new-file-test.patch
  Validating patch(es)
  error: dev/null: does not exist and --remove not passed
  fatal: Unable to process path dev/null
  error: klp-build: line 315: 'git update-index -q --refresh -- "${files[@]}"'
  error: klp-build: line 316: '( cd "$SRC"; git update-index -q --refresh -- "${files[@]}" )'
  error: fs/proc/test.h: No such file or directory
  error: patch failed: fs/proc/cmdline.c:4
  error: fs/proc/cmdline.c: patch does not apply
  error: klp-build: line 366: 'git apply --reverse "${extra_args[@]}"'
  error: klp-build: line 367: 'echo "error: $SCRIPT: $*" 1>&2'

While I don't think the script needs to handle a patch that is trying to
add completely new compilation units (that would require Makefile
changes, generate new .o files, etc.), I do think it would be helpful to
at least support patches that add new header/included files.  For
example, a common klp-macros.h file may be helpful to mimic the old
kpatch-build kpatch-macros.h, collect shadow variable IDs, etc.

diff --git a/scripts/livepatch/klp-build b/scripts/livepatch/klp-build
index 964f9ed5ee1b..5a8c592c4c15 100755
--- a/scripts/livepatch/klp-build
+++ b/scripts/livepatch/klp-build
@@ -426,6 +426,8 @@ refresh_patch() {
 	local patch="$1"
 	local tmpdir="$PATCH_TMP_DIR"
 	local files=()
+	local orig_files=()
+	local patched_files=()
 
 	rm -rf "$tmpdir"
 	mkdir -p "$tmpdir/a"
@@ -434,12 +436,20 @@ refresh_patch() {
 	# Get all source files affected by the patch
 	get_patch_files "$patch" | mapfile -t files
 
-	# Copy orig source files to 'a'
-	( cd "$SRC" && echo "${files[@]}" | xargs cp --parents --target-directory="$tmpdir/a" )
+	# Copy orig source files to 'a', filter to only existing files
+	for file in "${files[@]}"; do
+		[[ "$file" != "dev/null" ]] && [[ -f "$SRC/$file" ]] && orig_files+=("$file")
+	done
+	( cd "$SRC" && echo "${orig_files[@]}" | xargs cp --parents --target-directory="$tmpdir/a" )
 
-	# Copy patched source files to 'b'
+	# Copy patched source files to 'b', filter to only existing
+	# files after patch application
 	apply_patch "$patch" --recount
-	( cd "$SRC" && echo "${files[@]}" | xargs cp --parents --target-directory="$tmpdir/b" )
+	for file in "${files[@]}"; do
+		[[ "$file" != "dev/null" ]] && [[ -f "$SRC/$file" ]] && patched_files+=("$file")
+	done
+	( cd "$SRC" && echo "${patched_files[@]}" | xargs cp --parents --target-directory="$tmpdir/b" )
+
 	revert_patch "$patch" --recount
 
 	# Diff 'a' and 'b' to make a clean patch
-- 
2.52.0


^ permalink raw reply related

* [PATCH 1/5] objtool/klp: limit parent .git directory search
From: Joe Lawrence @ 2026-01-30 17:59 UTC (permalink / raw)
  To: live-patching; +Cc: Josh Poimboeuf, Jiri Kosina, Miroslav Benes, Petr Mladek
In-Reply-To: <20260130175950.1056961-1-joe.lawrence@redhat.com>

When klp-build runs git commands, they may search upwards for a .git/
directory if one isn't found in the current $SRC path. This can lead to
unexpected behavior if the kernel source is nested within another git
tree.

Set and export GIT_CEILING_DIRECTORIES to the parent of $SRC to restrict
git lookups to the local kernel tree only. This ensures that git
operations remain consistent and prevents picking up repository state
from parent directories.

Signed-off-by: Joe Lawrence <joe.lawrence@redhat.com>
---
 scripts/livepatch/klp-build | 3 +++
 1 file changed, 3 insertions(+)

I encountered this failure mode when running klp-build out of a kernel
source rpm extraction inside a testing git repo tree.  In this case,
there is no <kernel_dir>/.git, but there is one further up the directory
hierarchy.  This confuses the script when it tries to fixup the patch as
git commands will keep looking for a .git in parent directories unless
otherwise bounded [1].

Here's a quick repo:

  $ cd /tmp
  $ mkdir test_dir
  $ cd test_dir

  # Force a /tmp/test_dir/.git
  $ git init

  $ git clone --depth=1 --branch=v6.19-rc4 git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
  $ cd linux

  $ wget https://raw.githubusercontent.com/dynup/kpatch/refs/heads/master/examples/cmdline-string.patch

  # Basic config for livepatching ...
  $ make -j$(nproc) defconfig
  $ ./scripts/config --file .config \
      --set-val CONFIG_FTRACE y \
      --set-val CONFIG_KALLSYMS_ALL y \
      --set-val CONFIG_FUNCTION_TRACER y \
      --set-val CONFIG_DYNAMIC_FTRACE y \
      --set-val CONFIG_DYNAMIC_DEBUG y \
      --set-val CONFIG_LIVEPATCH y
  $ make olddefconfig

  # GOOD BUILD
  $ ./scripts/livepatch/klp-build -T cmdline-string.patch
  Validating patch(es)
  Building original kernel
  Copying original object files
  Fixing patch(es)
  Building patched kernel
  Copying patched object files
  Diffing objects
  vmlinux.o: changed function: cmdline_proc_show
  Building patch module: livepatch-cmdline-string.ko
  SUCCESS

  # BAD BUILD - remove .git/ to simulate rpm/tarball
  $ rm -rf .git
  $ ./scripts/livepatch/klp-build -T cmdline-string.patch
  Validating patch(es)
  Building original kernel
  Copying original object files
  Fixing patch(es)
  error: No valid patches in input (allow with "--allow-empty")
  error: klp-build: line 350: 'git apply "${extra_args[@]}"'
  error: klp-build: line 351: '( cd "$SRC"; sed -n '/^-- /q;p' "$patch" | git apply "${extra_args[@]}" )'

[1] https://git-scm.com/book/be/v2/Git-Internals-Environment-Variables#:~:text=GIT_DIR%20is%20the%20location,your%20shell%20prompt.

diff --git a/scripts/livepatch/klp-build b/scripts/livepatch/klp-build
index 882272120c9e..964f9ed5ee1b 100755
--- a/scripts/livepatch/klp-build
+++ b/scripts/livepatch/klp-build
@@ -52,6 +52,9 @@ PATCH_TMP_DIR="$TMP_DIR/tmp"
 
 KLP_DIFF_LOG="$DIFF_DIR/diff.log"
 
+# Restrict Git repository lookup to the local $SRC path
+export GIT_CEILING_DIRECTORIES="$(dirname "$SRC")"
+
 grep0() {
 	command grep "$@" || true
 }
-- 
2.52.0


^ permalink raw reply related

* Re: [PATCH] klp-build: Support clang/llvm built kernel
From: Josh Poimboeuf @ 2026-01-29 18:08 UTC (permalink / raw)
  To: Song Liu; +Cc: live-patching, kernel-team, jikos, mbenes, pmladek, joe.lawrence
In-Reply-To: <20260129170321.700854-1-song@kernel.org>

On Thu, Jan 29, 2026 at 09:03:21AM -0800, Song Liu wrote:
> When the kernel is built with clang/llvm, it is expected to run make
> with "make LLVM=1 ...". The same is needed when building livepatches.
> 
> Use CONFIG_CC_IS_CLANG as the flag to detect kernel built with
> clang/llvm, and add LLVM=1 to make commands from klp-build
> 
> Signed-off-by: Song Liu <song@kernel.org>

Indeed, I had tested by exporting LLVM=1, but this is better...  Thanks!

-- 
Josh

^ permalink raw reply

* [PATCH] klp-build: Support clang/llvm built kernel
From: Song Liu @ 2026-01-29 17:03 UTC (permalink / raw)
  To: live-patching
  Cc: jpoimboe, kernel-team, jikos, mbenes, pmladek, joe.lawrence,
	Song Liu

When the kernel is built with clang/llvm, it is expected to run make
with "make LLVM=1 ...". The same is needed when building livepatches.

Use CONFIG_CC_IS_CLANG as the flag to detect kernel built with
clang/llvm, and add LLVM=1 to make commands from klp-build

Signed-off-by: Song Liu <song@kernel.org>
---
 scripts/livepatch/klp-build | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/scripts/livepatch/klp-build b/scripts/livepatch/klp-build
index a73515a82272..6a446ca7d968 100755
--- a/scripts/livepatch/klp-build
+++ b/scripts/livepatch/klp-build
@@ -49,6 +49,7 @@ KMOD_DIR="$TMP_DIR/kmod"
 STASH_DIR="$TMP_DIR/stash"
 TIMESTAMP="$TMP_DIR/timestamp"
 PATCH_TMP_DIR="$TMP_DIR/tmp"
+USE_LLVM=0
 
 KLP_DIFF_LOG="$DIFF_DIR/diff.log"
 
@@ -249,6 +250,8 @@ validate_config() {
 	[[ -v CONFIG_GCC_PLUGIN_RANDSTRUCT ]] &&	\
 		die "kernel option 'CONFIG_GCC_PLUGIN_RANDSTRUCT' not supported"
 
+	[[ -v CONFIG_CC_IS_CLANG ]] && USE_LLVM=1
+
 	return 0
 }
 
@@ -480,6 +483,7 @@ clean_kernel() {
 	cmd+=("--silent")
 	cmd+=("-j$JOBS")
 	cmd+=("clean")
+	[[ "$USE_LLVM" -eq 1 ]] && cmd+=("LLVM=1")
 
 	(
 		cd "$SRC"
@@ -519,6 +523,7 @@ build_kernel() {
 	cmd+=("OBJTOOL_ARGS=${objtool_args[*]}")
 	cmd+=("vmlinux")
 	cmd+=("modules")
+	[[ "$USE_LLVM" -eq 1 ]] && cmd+=("LLVM=1")
 
 	(
 		cd "$SRC"
@@ -764,6 +769,7 @@ build_patch_module() {
 	cmd+=("--directory=.")
 	cmd+=("M=$KMOD_DIR")
 	cmd+=("KCFLAGS=${cflags[*]}")
+	[[ "$USE_LLVM" -eq 1 ]] && cmd+=("LLVM=1")
 
 	# Build a "normal" kernel module with init.c and the diffed objects
 	(
-- 
2.47.3


^ permalink raw reply related

* Re: [PATCH] livepatch/klp-build: Require Clang assembler >= 20
From: Song Liu @ 2026-01-28 21:42 UTC (permalink / raw)
  To: Josh Poimboeuf
  Cc: x86, linux-kernel, live-patching, Breno Leitao, Puranjay Mohan,
	Peter Zijlstra
In-Reply-To: <957fd52e375d0e2cfa3ac729160da995084a7f5e.1769562556.git.jpoimboe@kernel.org>

On Tue, Jan 27, 2026 at 5:12 PM Josh Poimboeuf <jpoimboe@kernel.org> wrote:
>
> Some special sections specify their ELF section entsize, for example:
>
>   .pushsection section, "M", @progbits, 8
>
> The entsize (8 in this example) is needed by objtool klp-diff for
> extracting individual entries.
>
> Clang assembler versions older than 20 silently ignore the above
> construct and set entsize to 0, resulting in the following error:
>
>   .discard.annotate_data: missing special section entsize or annotations
>
> Add a klp-build check to prevent the use of Clang assembler versions
> prior to 20.
>
> Fixes: 24ebfcd65a87 ("livepatch/klp-build: Introduce klp-build script for generating livepatch modules")
> Reported-by: Song Liu <song@kernel.org>
> Signed-off-by: Josh Poimboeuf <jpoimboe@kernel.org>

Acked-by: Song Liu <song@kernel.org>

^ permalink raw reply

* [PATCH] livepatch/klp-build: Require Clang assembler >= 20
From: Josh Poimboeuf @ 2026-01-28  1:12 UTC (permalink / raw)
  To: x86
  Cc: linux-kernel, live-patching, Breno Leitao, Puranjay Mohan,
	Peter Zijlstra, Song Liu

Some special sections specify their ELF section entsize, for example:

  .pushsection section, "M", @progbits, 8

The entsize (8 in this example) is needed by objtool klp-diff for
extracting individual entries.

Clang assembler versions older than 20 silently ignore the above
construct and set entsize to 0, resulting in the following error:

  .discard.annotate_data: missing special section entsize or annotations

Add a klp-build check to prevent the use of Clang assembler versions
prior to 20.

Fixes: 24ebfcd65a87 ("livepatch/klp-build: Introduce klp-build script for generating livepatch modules")
Reported-by: Song Liu <song@kernel.org>
Signed-off-by: Josh Poimboeuf <jpoimboe@kernel.org>
---
For tip/objtool/urgent.

 scripts/livepatch/klp-build | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/scripts/livepatch/klp-build b/scripts/livepatch/klp-build
index a73515a82272..809e198a561d 100755
--- a/scripts/livepatch/klp-build
+++ b/scripts/livepatch/klp-build
@@ -249,6 +249,10 @@ validate_config() {
 	[[ -v CONFIG_GCC_PLUGIN_RANDSTRUCT ]] &&	\
 		die "kernel option 'CONFIG_GCC_PLUGIN_RANDSTRUCT' not supported"
 
+	[[ -v CONFIG_AS_IS_LLVM ]] &&				\
+		[[ "$CONFIG_AS_VERSION" -lt 200000 ]] &&	\
+		die "Clang assembler version < 20 not supported"
+
 	return 0
 }
 
-- 
2.52.0


^ permalink raw reply related

* Re: [PATCH] livepatch/klp-build: Fix klp-build vs CONFIG_MODULE_SRCVERSION_ALL
From: Song Liu @ 2026-01-27  0:36 UTC (permalink / raw)
  To: Josh Poimboeuf
  Cc: x86, linux-kernel, live-patching, Breno Leitao, Puranjay Mohan,
	Peter Zijlstra
In-Reply-To: <c41b6629e02775e4c1015259aa36065b3fe2f0f3.1769471792.git.jpoimboe@kernel.org>

On Mon, Jan 26, 2026 at 3:56 PM Josh Poimboeuf <jpoimboe@kernel.org> wrote:
>
> When building a patch to a single-file kernel module with
> CONFIG_MODULE_SRCVERSION_ALL enabled, the klp-build module link fails in
> modpost:
>
>   Diffing objects
>   drivers/md/raid0.o: changed function: raid0_run
>   Building patch module: livepatch-0001-patch-raid0_run.ko
>   drivers/md/raid0.c: No such file or directory
>   ...
>
> The problem here is that klp-build copied drivers/md/.raid0.o.cmd to the
> module build directory, but it didn't also copy over the input source
> file listed in the .cmd file:
>
>   source_drivers/md/raid0.o := drivers/md/raid0.c
>
> So modpost dies due to the missing .c file which is needed for
> calculating checksums for CONFIG_MODULE_SRCVERSION_ALL.
>
> Instead of copying the original .cmd file, just create an empty one.
> Modpost only requires that it exists.  The original object's build
> dependencies are irrelevant for the frankenobjects used by klp-build.
>
> Fixes: 24ebfcd65a87 ("livepatch/klp-build: Introduce klp-build script for generating livepatch modules")
> Reported-by: Song Liu <song@kernel.org>
> Signed-off-by: Josh Poimboeuf <jpoimboe@kernel.org>

Tested-by: Song Liu <song@kernel.org>

Thanks for the fix!

^ permalink raw reply

* [PATCH] livepatch/klp-build: Fix klp-build vs CONFIG_MODULE_SRCVERSION_ALL
From: Josh Poimboeuf @ 2026-01-26 23:56 UTC (permalink / raw)
  To: x86
  Cc: linux-kernel, live-patching, Breno Leitao, Puranjay Mohan,
	Peter Zijlstra, Song Liu

When building a patch to a single-file kernel module with
CONFIG_MODULE_SRCVERSION_ALL enabled, the klp-build module link fails in
modpost:

  Diffing objects
  drivers/md/raid0.o: changed function: raid0_run
  Building patch module: livepatch-0001-patch-raid0_run.ko
  drivers/md/raid0.c: No such file or directory
  ...

The problem here is that klp-build copied drivers/md/.raid0.o.cmd to the
module build directory, but it didn't also copy over the input source
file listed in the .cmd file:

  source_drivers/md/raid0.o := drivers/md/raid0.c

So modpost dies due to the missing .c file which is needed for
calculating checksums for CONFIG_MODULE_SRCVERSION_ALL.

Instead of copying the original .cmd file, just create an empty one.
Modpost only requires that it exists.  The original object's build
dependencies are irrelevant for the frankenobjects used by klp-build.

Fixes: 24ebfcd65a87 ("livepatch/klp-build: Introduce klp-build script for generating livepatch modules")
Reported-by: Song Liu <song@kernel.org>
Signed-off-by: Josh Poimboeuf <jpoimboe@kernel.org>
---
 scripts/livepatch/klp-build | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/scripts/livepatch/klp-build b/scripts/livepatch/klp-build
index 882272120c9e..a73515a82272 100755
--- a/scripts/livepatch/klp-build
+++ b/scripts/livepatch/klp-build
@@ -555,13 +555,11 @@ copy_orig_objects() {
 		local file_dir="$(dirname "$file")"
 		local orig_file="$ORIG_DIR/$rel_file"
 		local orig_dir="$(dirname "$orig_file")"
-		local cmd_file="$file_dir/.$(basename "$file").cmd"
 
 		[[ ! -f "$file" ]] && die "missing $(basename "$file") for $_file"
 
 		mkdir -p "$orig_dir"
 		cp -f "$file" "$orig_dir"
-		[[ -e "$cmd_file" ]] && cp -f "$cmd_file" "$orig_dir"
 	done
 	xtrace_restore
 
@@ -740,15 +738,17 @@ build_patch_module() {
 		local orig_dir="$(dirname "$orig_file")"
 		local kmod_file="$KMOD_DIR/$rel_file"
 		local kmod_dir="$(dirname "$kmod_file")"
-		local cmd_file="$orig_dir/.$(basename "$file").cmd"
+		local cmd_file="$kmod_dir/.$(basename "$file").cmd"
 
 		mkdir -p "$kmod_dir"
 		cp -f "$file" "$kmod_dir"
-		[[ -e "$cmd_file" ]] && cp -f "$cmd_file" "$kmod_dir"
 
 		# Tell kbuild this is a prebuilt object
 		cp -f "$file" "${kmod_file}_shipped"
 
+		# Make modpost happy
+		touch "$cmd_file"
+
 		echo -n " $rel_file" >> "$makefile"
 	done
 
-- 
2.52.0


^ permalink raw reply related

* Re: [PATCH] objtool/klp: Fix bug table handling for __WARN_printf()
From: Song Liu @ 2026-01-26 18:44 UTC (permalink / raw)
  To: Josh Poimboeuf
  Cc: x86, linux-kernel, live-patching, Breno Leitao, Puranjay Mohan,
	Peter Zijlstra
In-Reply-To: <a8e0a714b9da962858842b9aecd63b4900927c88.1769406850.git.jpoimboe@kernel.org>

On Sun, Jan 25, 2026 at 9:56 PM Josh Poimboeuf <jpoimboe@kernel.org> wrote:
>
> Running objtool klp-diff on a changed function which uses WARN() can
> fail with:
>
>   vmlinux.o: error: objtool: md_run+0x866: failed to convert reloc sym '__bug_table' to its proper format
>
> The problem is that since commit 5b472b6e5bd9 ("x86_64/bug: Implement
> __WARN_printf()"), each __WARN_printf() call site now directly
> references its bug table entry.  klp-diff errors out when it can't
> convert such section-based references to object symbols (because bug
> table entries don't have symbols).
>
> Luckily, klp-diff already has code to create symbols for bug table
> entries.  Move that code earlier, before function diffing.
>
> Fixes: dd590d4d57eb ("objtool/klp: Introduce klp diff subcommand for diffing object files")
> Fixes: 5b472b6e5bd9 ("x86_64/bug: Implement __WARN_printf()")
> Reported-by: Song Liu <song@kernel.org>
> Signed-off-by: Josh Poimboeuf <jpoimboe@kernel.org>

Tested-by: Song Liu <song@kernel.org>

Thanks for the fix!

^ permalink raw reply

* [PATCH] objtool/klp: Fix bug table handling for __WARN_printf()
From: Josh Poimboeuf @ 2026-01-26  5:56 UTC (permalink / raw)
  To: x86
  Cc: linux-kernel, live-patching, Breno Leitao, Puranjay Mohan,
	Peter Zijlstra, Song Liu

Running objtool klp-diff on a changed function which uses WARN() can
fail with:

  vmlinux.o: error: objtool: md_run+0x866: failed to convert reloc sym '__bug_table' to its proper format

The problem is that since commit 5b472b6e5bd9 ("x86_64/bug: Implement
__WARN_printf()"), each __WARN_printf() call site now directly
references its bug table entry.  klp-diff errors out when it can't
convert such section-based references to object symbols (because bug
table entries don't have symbols).

Luckily, klp-diff already has code to create symbols for bug table
entries.  Move that code earlier, before function diffing.

Fixes: dd590d4d57eb ("objtool/klp: Introduce klp diff subcommand for diffing object files")
Fixes: 5b472b6e5bd9 ("x86_64/bug: Implement __WARN_printf()")
Reported-by: Song Liu <song@kernel.org>
Signed-off-by: Josh Poimboeuf <jpoimboe@kernel.org>
---
For tip/objtool/urgent.

 tools/objtool/klp-diff.c | 14 +++++++++++---
 1 file changed, 11 insertions(+), 3 deletions(-)

diff --git a/tools/objtool/klp-diff.c b/tools/objtool/klp-diff.c
index bb6b711d4e73..76aa77c26655 100644
--- a/tools/objtool/klp-diff.c
+++ b/tools/objtool/klp-diff.c
@@ -1425,9 +1425,6 @@ static int clone_special_sections(struct elfs *e)
 {
 	struct section *patched_sec;
 
-	if (create_fake_symbols(e->patched))
-		return -1;
-
 	for_each_sec(e->patched, patched_sec) {
 		if (is_special_section(patched_sec)) {
 			if (clone_special_section(e, patched_sec))
@@ -1704,6 +1701,17 @@ int cmd_klp_diff(int argc, const char **argv)
 	if (!e.out)
 		return -1;
 
+	/*
+	 * Special section fake symbols are needed so that individual special
+	 * section entries can be extracted by clone_special_sections().
+	 *
+	 * Note the fake symbols are also needed by clone_included_functions()
+	 * because __WARN_printf() call sites add references to bug table
+	 * entries in the calling functions.
+	 */
+	if (create_fake_symbols(e.patched))
+		return -1;
+
 	if (clone_included_functions(&e))
 		return -1;
 
-- 
2.52.0


^ permalink raw reply related

* Re: [PATCH v3 0/2] Improve handling of the __klp_{objects,funcs} sections in modules
From: Josh Poimboeuf @ 2026-01-23 17:50 UTC (permalink / raw)
  To: Petr Pavlu
  Cc: Jiri Kosina, Miroslav Benes, Petr Mladek, Joe Lawrence,
	Luis Chamberlain, Daniel Gomez, Sami Tolvanen, Aaron Tomlin,
	Peter Zijlstra, live-patching, linux-modules, linux-kernel
In-Reply-To: <20260123102825.3521961-1-petr.pavlu@suse.com>

On Fri, Jan 23, 2026 at 11:26:55AM +0100, Petr Pavlu wrote:
> Changes since v2 [1]:
> - Generalize the helper function that locates __klp_objects in a module
>   to allow it to find any data in other sections as well.
> 
> Changes since v1 [2]:
> - Generalize the helper function that locates __klp_objects in a module
>   to allow it to find objects in other sections as well.
> 
> [1] https://lore.kernel.org/linux-modules/20260121082842.3050453-1-petr.pavlu@suse.com/
> [2] https://lore.kernel.org/linux-modules/20260114123056.2045816-1-petr.pavlu@suse.com/
> 
> Petr Pavlu (2):
>   livepatch: Fix having __klp_objects relics in non-livepatch modules
>   livepatch: Free klp_{object,func}_ext data after initialization

Thanks!

Acked-by: Josh Poimboeuf <jpoimboe@kernel.org>

-- 
Josh

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox