Skip to content

kpatch: support eu-readelf as alternative to GNU readelf#1500

Open
stephenchengCloud wants to merge 1 commit intodynup:masterfrom
stephenchengCloud:private/stephencheng/dev
Open

kpatch: support eu-readelf as alternative to GNU readelf#1500
stephenchengCloud wants to merge 1 commit intodynup:masterfrom
stephenchengCloud:private/stephencheng/dev

Conversation

@stephenchengCloud
Copy link
Copy Markdown

The kpatch script is used to load live patches on production systems that may be stripped down, with binutils (which provides readelf) not installed while elfutils (which provides eu-readelf) is available. Add a get_module_section_string() helper that auto-detects the available tool at startup and uses the appropriate invocation for each.

Other readelf usages in the build tooling (kpatch-build, lookup.c, test infrastructure) are left unchanged, as a compiler toolchain including binutils can reasonably be expected in a build environment.

@stephenchengCloud
Copy link
Copy Markdown
Author

Tested:
get module name:

[root@eu1-dt021 ~]#  eu-readelf --string-dump=.gnu.linkonce.this_module lp_6_6_98__23_xs9__6_6_98__24_xs9.ko | awk 'NF>=3 && /^\s*\[/ {print $3; exit}'
lp_6_6_98__23_xs9__6_6_98__24_xs9
[root@eu1-dt021 ~]#
[root@eu1-dt021 ~]# readelf -p .gnu.linkonce.this_module lp_6_6_98__23_xs9__6_6_98__24_xs9.ko | grep '\[.*\]' | awk '{print $3}'
lp_6_6_98__23_xs9__6_6_98__24_xs9

get checksum:

[root@eu1-dt021 ~]# readelf -p .kpatch.checksum test_module_with_checksum.ko | grep '\[.*\]' | awk '{print $3}'
d41d8cd98f00b204e9800998ecf8427e
[root@eu1-dt021 ~]#  eu-readelf --string-dump=.kpatch.checksum test_module_with_checksum.ko | awk 'NF>=3 && /^\s*\[/ {print $3; exit}'
d41d8cd98f00b204e9800998ecf8427e
[root@eu1-dt021 ~]#

empty checksum:

stephenche@40 kpatch (v0.9.9) $ readelf -p .kpatch.checksum lp_6_6_98__23_xs9__6_6_98__24_xs9.ko 2>/dev/null | grep '\[.*\]' | awk '{print $3}'
stephenche@40 kpatch (v0.9.9) $ eu-readelf --string-dump=.kpatch.checksum lp_6_6_98__23_xs9__6_6_98__24_xs9.ko 2>/dev/nul

@joe-lawrence
Copy link
Copy Markdown
Contributor

Hi @stephenchengCloud , sorry for the delay in reviewing. The change seems reasonable, I have a few small suggestions:

1- Copy your awk one-liner to extract the string to the readelf case so they're the same
2a- Check for eu-readelf in the path as well
3a- Add an else case to catch if neither tool is installed
3b- The else case returns 1, then
3c- The callers propogate/check for (3b) failure
4- Move get_module_section_string down to just above get_module_name (not shown here):

diff --git a/kpatch/kpatch b/kpatch/kpatch
index d75bd068356d..347f89230751 100755
--- a/kpatch/kpatch
+++ b/kpatch/kpatch
@@ -27,12 +27,16 @@ INSTALLDIR=/var/lib/kpatch
 SCRIPTDIR="$(readlink -f "$(dirname "$(type -p "$0")")")"
 if command -v readelf >/dev/null 2>&1; then
 	get_module_section_string() {
-		readelf -p "$2" "$1" | grep '\[.*\]' | awk '{print $3}'
+		readelf -p "$2" "$1" | awk 'NF>=3 && /^\s*\[/ {print $3; exit}'
 	}
-else
+elif command -v eu-readelf >/dev/null 2>&1; then
 	get_module_section_string() {
 		eu-readelf --string-dump="$2" "$1" | awk 'NF>=3 && /^\s*\[/ {print $3; exit}'
 	}
+else
+	get_module_section_string() {
+		return 1
+	}
 fi
 VERSION="0.9.11"
 POST_ENABLE_WAIT=15	# seconds
@@ -165,10 +169,10 @@ init_sysfs_var() {
 }
 
 verify_module_checksum () {
-	modname="$(get_module_name "$1")"
+	modname="$(get_module_name "$1")" || return 1
 	[[ -z "$modname" ]] && return 1
 
-	checksum="$(get_module_section_string "$1" .kpatch.checksum 2>/dev/null)"
+	checksum="$(get_module_section_string "$1" .kpatch.checksum 2>/dev/null)" || return 1
 
 	# Fail checksum match only if both exist and diverge
 	if [[ -n "$checksum" ]] && [[ -e "$SYSFS/${modname}/checksum" ]] ; then
@@ -325,7 +329,8 @@ load_module () {
 	fi
 
 	local modname
-	modname="$(get_module_name "$module")"
+	modname="$(get_module_name "$module")" || die "failed to get module name from $module"
+	[[ -z "$modname" ]] && die "failed to get module name from $module"
 	local moddir="$SYSFS/$modname"
 	if [[ -d "$moddir" ]] ; then
 		if [[ "$(cat "${moddir}/enabled")" -eq 0 ]]; then

^^ is untested, but hopefully clarifies the suggestions.

The kpatch script is used to load live patches on production systems
that may be stripped down, with binutils (which provides readelf) not
installed while elfutils (which provides eu-readelf) is available. Add
a get_module_section_string() helper that auto-detects the available
tool at startup and uses the appropriate invocation for each.

Other readelf usages in the build tooling (kpatch-build, lookup.c,
test infrastructure) are left unchanged, as a compiler toolchain
including binutils can reasonably be expected in a build environment.

Signed-off-by: Stephen Cheng <stephen.cheng@citrix.com>
@stephenchengCloud stephenchengCloud force-pushed the private/stephencheng/dev branch from b5cb300 to 3193404 Compare May 6, 2026 02:09
@stephenchengCloud
Copy link
Copy Markdown
Author

Hi @joe-lawrence, thank you for your detailed suggestions.
I've updated the code and done a simple test on the awk change:

$ readelf -p .gnu.linkonce.this_module lp_6_6_98__23_xs9__6_6_98__24_xs9.ko | awk 'NF>=3 && /^\s*\[/ {print $3; exit}'
lp_6_6_98__23_xs9__6_6_98__24_xs9

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.

2 participants