diff --git a/.gitignore b/.gitignore index 7124599..6a98fe6 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1 @@ -SOURCES/v0.4.0.tar.gz +SOURCES/v0.6.1.tar.gz diff --git a/.kpatch.metadata b/.kpatch.metadata index ed18222..654277d 100644 --- a/.kpatch.metadata +++ b/.kpatch.metadata @@ -1 +1 @@ -b5de4b89fc9b9bf1c7071c4512800338e98ed0e9 SOURCES/v0.4.0.tar.gz +7a0395e649f58026a3dd66dd13e3bcecdb9e97a4 SOURCES/v0.6.1.tar.gz diff --git a/SOURCES/0001-contrib-disable-upstart-kpatch.conf-install.patch b/SOURCES/0001-contrib-disable-upstart-kpatch.conf-install.patch new file mode 100644 index 0000000..44eb5b4 --- /dev/null +++ b/SOURCES/0001-contrib-disable-upstart-kpatch.conf-install.patch @@ -0,0 +1,46 @@ +From f056d60fb309896a52882fd3fc10fb5305f5a47e Mon Sep 17 00:00:00 2001 +From: Joe Lawrence +Date: Thu, 21 Jun 2018 15:40:20 -0400 +Subject: [PATCH] contrib: disable upstart kpatch.conf install + +Do not install the upstart configuration file to avoid this rhpkg +build complaint: + + Checking for unpackaged file(s): /usr/lib/rpm/check-files /builddir/build/BUILDROOT/kpatch-0.6.1-1.el7.noarch + error: Installed (but unpackaged) file(s) found: + /etc/init/kpatch.conf + Installed (but unpackaged) file(s) found: + /etc/init/kpatch.conf + +We'll need to think of a better way to do this upstream, but for now, +just skip the unneeded file on RHEL. + +Signed-off-by: Joe Lawrence +--- + contrib/Makefile | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/contrib/Makefile b/contrib/Makefile +index 0b0eeeb23a56..e873f27d6eae 100644 +--- a/contrib/Makefile ++++ b/contrib/Makefile +@@ -6,12 +6,12 @@ install: all + $(INSTALL) -d $(SYSTEMDDIR) + $(INSTALL) -m 0644 kpatch.service $(SYSTEMDDIR) + sed -i 's~PREFIX~$(PREFIX)~' $(SYSTEMDDIR)/kpatch.service +- $(INSTALL) -d $(UPSTARTDIR) +- $(INSTALL) -m 0644 kpatch.conf $(UPSTARTDIR) +- sed -i 's~PREFIX~$(PREFIX)~' $(UPSTARTDIR)/kpatch.conf ++# $(INSTALL) -d $(UPSTARTDIR) ++# $(INSTALL) -m 0644 kpatch.conf $(UPSTARTDIR) ++# sed -i 's~PREFIX~$(PREFIX)~' $(UPSTARTDIR)/kpatch.conf + + uninstall: + $(RM) $(SYSTEMDDIR)/kpatch.service +- $(RM) $(UPSTARTDIR)/kpatch.conf ++# $(RM) $(UPSTARTDIR)/kpatch.conf + + clean: +-- +1.8.3.1 + diff --git a/SOURCES/0001-kpatch-add-ABI-backwards-compatibility.patch b/SOURCES/0001-kpatch-add-ABI-backwards-compatibility.patch deleted file mode 100644 index ecc21ce..0000000 --- a/SOURCES/0001-kpatch-add-ABI-backwards-compatibility.patch +++ /dev/null @@ -1,86 +0,0 @@ -From 9eed5d4bac0b43372d98572d923ca84e091c8982 Mon Sep 17 00:00:00 2001 -Message-Id: <9eed5d4bac0b43372d98572d923ca84e091c8982.1508328327.git.jpoimboe@redhat.com> -From: Josh Poimboeuf -Date: Mon, 9 Oct 2017 09:04:46 -0500 -Subject: [PATCH] kpatch: add ABI backwards compatibility - -When running a kernel for a long period of time without rebooting, it's -possible that newer versions of the kpatch script may get installed. So -new versions of the kpatch script need to support old versions of -kpatch.ko. - -Signed-off-by: Josh Poimboeuf ---- - kpatch/kpatch | 35 +++++++++++++++++++++++++++-------- - 1 file changed, 27 insertions(+), 8 deletions(-) - -diff --git a/kpatch/kpatch b/kpatch/kpatch -index ef36087..5998fbc 100755 ---- a/kpatch/kpatch -+++ b/kpatch/kpatch -@@ -27,14 +27,6 @@ INSTALLDIR=/var/lib/kpatch - SCRIPTDIR="$(readlink -f $(dirname $(type -p $0)))" - VERSION="0.4.0" - --# Livepatch is built into the kernel, if it's not present --# we must use kpatch core module. --if [[ -e /sys/kernel/livepatch ]] ; then -- SYSFS="/sys/kernel/livepatch" --else -- SYSFS="/sys/kernel/kpatch" --fi -- - usage_cmd() { - printf ' %-20s\n %s\n' "$1" "$2" >&2 - } -@@ -132,6 +124,23 @@ get_module_name () { - echo $(readelf -p .gnu.linkonce.this_module $1 | grep '\[.*\]' | awk '{print $3}') - } - -+init_sysfs_var() { -+ # If the kernel is configured with CONFIG_LIVEPATCH, use that. -+ # Otherwise, use the kpatch core module (kpatch.ko). -+ if [[ -e /sys/kernel/livepatch ]] ; then -+ # livepatch ABI -+ SYSFS="/sys/kernel/livepatch" -+ -+ elif [[ -e /sys/kernel/kpatch/patches ]] ; then -+ # kpatch pre-0.4 ABI -+ SYSFS="/sys/kernel/kpatch/patches" -+ -+ else -+ # kpatch 0.4 ABI -+ SYSFS="/sys/kernel/kpatch" -+ fi -+} -+ - verify_module_checksum () { - modname=$(get_module_name $1) - [[ -z $modname ]] && return 1 -@@ -158,6 +167,10 @@ load_module () { - echo "loading core module: $COREMOD" - insmod "$COREMOD" || die "failed to load core module" - fi -+ -+ # Now that the core module has been loaded, set $SYSFS to the -+ # correct value based on the loaded core module's ABI. -+ init_sysfs_var - fi - - local modname=$(get_module_name $module) -@@ -222,6 +235,12 @@ get_module_version() { - } - - unset MODULE -+ -+# Initialize the $SYSFS var. This only works if the core module has been -+# loaded. Otherwise, the value of $SYSFS doesn't matter at this point anyway, -+# and we'll have to call this function again after loading it. -+init_sysfs_var -+ - [[ "$#" -lt 1 ]] && usage - case "$1" in - "load") --- -2.13.6 - diff --git a/SOURCES/0002-backport-kpatch-script-livepatch-fixups-753.patch b/SOURCES/0002-backport-kpatch-script-livepatch-fixups-753.patch deleted file mode 100644 index caaa5ab..0000000 --- a/SOURCES/0002-backport-kpatch-script-livepatch-fixups-753.patch +++ /dev/null @@ -1,297 +0,0 @@ -From 2d9606d9b864eec8d81de6952b8816284dec0032 Mon Sep 17 00:00:00 2001 -From: Joe Lawrence -Date: Thu, 16 Nov 2017 14:21:22 -0500 -Subject: [PATCH] backport "kpatch script - livepatch fixups #753" - -This patchset improves livepatch support, most notably adding a -wait-for-transition loop when (un)loading patch modules and signaling of -tasks (with a SIGSTOP/SIGCONT combo) that are stalling the transition. - -commit a2fbce15872167cfeb2bee4dcf66c33e29e4dfe2 -Author: Joe Lawrence -Date: Wed Nov 15 10:44:42 2017 -0500 - - kpatch: don't complain about missing livepatch .kpatch.checksum - - The verify_module_checksum() function reads a kpatch-specific ELF - section to compare on-disk and in-memory kernel modules. The function - only reports a miscompare if the .kpatch.checksum section actually - exists. Livepatches don't have such section, so throw away any "Section - '.kpatch.checksum' was not dumped because it does not exist!" warnings - from readelf. - - Signed-off-by: Joe Lawrence - -commit fb0bc53eb7540460bc8222313d436b7537aa9952 -Author: Joe Lawrence -Date: Wed Nov 15 10:44:42 2017 -0500 - - kpatch: show transitioning patches and stalled tasks - - In 'kpatch list' output, show the current patch state: enabled, - disabled, and livepatch mid-transition states enabling... and - disabling... - - Also provide a list of any tasks that are stalling a livepatch - transition. - - Signed-off-by: Joe Lawrence - -commit 3582e10e42fed7a08b5cf1ce0b470723428b1386 -Author: Joe Lawrence -Date: Wed Nov 15 10:44:42 2017 -0500 - - kpatch: signal stalled processes - - Add a "signal" command line option that iterates over all processes that - may be holding up the current livepatch transition. Send such processes - a SIGSTOP / SIGCONT combination to try and expedite the transition. - - Signed-off-by: Joe Lawrence - -commit 52c12cbad6cd0ca35f892a0b07519b41326ea91e -Author: Joe Lawrence -Date: Wed Nov 15 10:44:42 2017 -0500 - - kpatch: wait for livepatch transitions, poke stragglers - - When loading a livepatch, wait for the patching transition to complete - within a reasonable timeframe, then poke any stalled tasks with a - signal. If the transition is still taking too long, reverse the patch - and unload the livepatch. - - When re-enabling a livepatch, do the same wait and signaling. If the - expected time expires, disable the livepatch. - - When unloading a livepatch, perform the wait/signaling, but only emit an - error message if the transition exceeds the time limit. - - Signed-off-by: Joe Lawrence - -Signed-off-by: Joe Lawrence -diff --git a/kpatch/kpatch b/kpatch/kpatch -index 5998fbc1ba72..a2ac607f6e31 100755 ---- a/kpatch/kpatch -+++ b/kpatch/kpatch -@@ -26,6 +26,8 @@ - INSTALLDIR=/var/lib/kpatch - SCRIPTDIR="$(readlink -f $(dirname $(type -p $0)))" - VERSION="0.4.0" -+POST_ENABLE_WAIT=5 # seconds -+POST_SIGNAL_WAIT=60 # seconds - - usage_cmd() { - printf ' %-20s\n %s\n' "$1" "$2" >&2 -@@ -49,6 +51,8 @@ usage () { - echo >&2 - usage_cmd "list" "list installed patch modules" - echo >&2 -+ usage_cmd "signal" "signal/poke any process stalling the current patch transition" -+ echo >&2 - usage_cmd "version" "display the kpatch version" - exit 1 - } -@@ -145,7 +149,7 @@ verify_module_checksum () { - modname=$(get_module_name $1) - [[ -z $modname ]] && return 1 - -- checksum=$(readelf -p .kpatch.checksum $1 | grep '\[.*\]' | awk '{print $3}') -+ checksum="$(readelf -p .kpatch.checksum "$1" 2>&1 | grep '\[.*\]' | awk '{print $3}')" - - # Fail checksum match only if both exist and diverge - if [[ ! -z $checksum ]] && [[ -e "$SYSFS/${modname}/checksum" ]] ; then -@@ -156,6 +160,119 @@ verify_module_checksum () { - return 0 - } - -+in_transition() { -+ local moddir="$SYSFS/$1" -+ [[ $(cat "$moddir/transition" 2>/dev/null) == "1" ]] && return 0 -+ return 1 -+} -+ -+is_stalled() { -+ local module="$1" -+ local pid="$2" -+ local patch_enabled -+ local patch_state -+ -+ patch_enabled="$(cat "$SYSFS/$module/enabled" 2>/dev/null)" -+ patch_state="$(cat "/proc/$pid/patch_state" 2>/dev/null)" -+ -+ # No patch transition in progress -+ [[ "$patch_state" == "-1" ]] && return 1 -+ -+ [[ -z "$patch_enabled" ]] || [[ -z "$patch_state" ]] && return 1 -+ -+ # Stalls can be determined if the process state does not match -+ # the transition target (ie, "enabled" and "patched", "disabled" -+ # and "unpatched"). The state value enumerations match, so we -+ # can just compare them directly: -+ [[ "$patch_enabled" != "$patch_state" ]] && return 0 -+ return 1 -+} -+ -+get_transition_patch() { -+ local module -+ local modname -+ for module in "$SYSFS"/*; do -+ modname=$(basename "$module") -+ if in_transition "$modname" ; then -+ echo "$modname" -+ return -+ fi -+ done -+} -+ -+show_stalled_processes() { -+ local module -+ local proc_task -+ local tid -+ -+ module=$(get_transition_patch) -+ [[ -z "$module" ]] && return -+ -+ echo "" -+ echo "Stalled processes:" -+ for proc_task in /proc/[0-9]*/task/[0-9]*; do -+ tid=${proc_task#*/task/} -+ is_stalled "$module" "$tid" && echo "$tid $(cat "$proc_task"/comm 2>/dev/null)" -+ done -+} -+ -+signal_stalled_processes() { -+ local module -+ local proc_task -+ local tid -+ -+ module=$(get_transition_patch) -+ [[ -z "$module" ]] && return -+ -+ if [[ -e "/sys/kernel/livepatch/$module/signal" ]] ; then -+ echo 1 > "/sys/kernel/livepatch/$module/signal" -+ else -+ for proc_task in /proc/[0-9]*/task/[0-9]*; do -+ tid=${proc_task#*/task/} -+ if is_stalled "$module" "$tid" ; then -+ if [[ "$tid" -eq "$$" ]] ; then -+ echo "skipping pid $tid $(cat "$proc_task"/comm 2>/dev/null)" -+ else -+ echo "signaling pid $tid $(cat "$proc_task"/comm 2>/dev/null)" -+ kill -SIGSTOP "$tid" -+ sleep .1 -+ kill -SIGCONT "$tid" -+ fi -+ fi -+ done -+ fi -+} -+ -+wait_for_patch_transition() { -+ local module="$1" -+ local i -+ -+ in_transition "$module" || return 0 -+ -+ echo "waiting (up to $POST_ENABLE_WAIT seconds) for patch transition to complete..." -+ for (( i=0; i ${moddir}/enabled || die "failed to re-enable module $modname" -+ if ! wait_for_patch_transition "$modname" ; then -+ echo "module $modname did not complete its transition, disabling..." -+ echo 0 > "${moddir}/enabled" || die "failed to disable module $modname" -+ wait_for_patch_transition "$modname" -+ die "error: failed to re-enable module $modname (transition stalled), patch disabled" -+ fi -+ - return - else - die "error: cannot re-enable patch module $modname, cannot verify checksum match" -@@ -210,6 +334,12 @@ load_module () { - fi - done - -+ if ! wait_for_patch_transition "$modname" ; then -+ echo "module $modname did not complete its transition, unloading..." -+ unload_module "$modname" -+ die "error: failed to load module $modname (transition stalled)" -+ fi -+ - return 0 - } - -@@ -223,6 +353,11 @@ unload_module () { - echo 0 > $ENABLED || die "can't disable $PATCH" - fi - -+ if ! wait_for_patch_transition "$PATCH" ; then -+ die "error: failed to unload module $PATCH (transition stalled)" -+ fi -+ -+ - echo "unloading patch module: $PATCH" - # ignore any error here because rmmod can fail if the module used - # KPATCH_FORCE_UNSAFE. -@@ -352,10 +487,19 @@ case "$1" in - [[ "$#" -ne 1 ]] && usage - echo "Loaded patch modules:" - for module in $SYSFS/*; do -- if [[ -e $module ]] && [[ $(cat $module/enabled) -eq 1 ]]; then -- echo $(basename "$module") -+ if [[ -e "$module" ]]; then -+ modname=$(basename "$module") -+ if [[ "$(cat "$module/enabled" 2>/dev/null)" -eq 1 ]]; then -+ in_transition "$modname" && state="enabling..." \ -+ || state="enabled" -+ else -+ in_transition "$modname" && state="disabling..." \ -+ || state="disabled" -+ fi -+ echo "$modname [$state]" - fi - done -+ show_stalled_processes - echo "" - echo "Installed patch modules:" - for kdir in $INSTALLDIR/*; do -@@ -376,6 +520,11 @@ case "$1" in - modinfo "$MODULE" || die "failed to get info for module $PATCH" - ;; - -+"signal") -+ [[ "$#" -ne 1 ]] && usage -+ signal_stalled_processes -+ ;; -+ - "help"|"-h"|"--help") - usage - ;; --- -1.8.3.1 diff --git a/SPECS/kpatch.spec b/SPECS/kpatch.spec index 3e6aaf4..a0f29ef 100644 --- a/SPECS/kpatch.spec +++ b/SPECS/kpatch.spec @@ -1,14 +1,13 @@ Name: kpatch -Version: 0.4.0 -Release: 3%{?dist} +Version: 0.6.1 +Release: 1%{?dist} Summary: Dynamic kernel patch manager Group: System Environment/Kernel License: GPLv2 URL: https://github.com/dynup/kpatch Source0: https://github.com/dynup/kpatch/archive/v%{version}.tar.gz -Patch0: 0001-kpatch-add-ABI-backwards-compatibility.patch -Patch1: 0002-backport-kpatch-script-livepatch-fixups-753.patch +Patch0: 0001-contrib-disable-upstart-kpatch.conf-install.patch Requires: bash kmod binutils @@ -24,7 +23,6 @@ patch the kernel without rebooting. %prep %setup -q %patch0 -p1 -%patch1 -p1 %build @@ -45,6 +43,9 @@ rm -f %{buildroot}/usr/share/man/man1/kpatch-build.1.gz %changelog +* Thu Jun 21 2018 Joe Lawrence 0.6.1-1 +- update to 0.6.1 (rhbz#1562976) + * Thu Nov 16 2017 Joe Lawrence 0.4.0-3 - kpatch: better livepatch module support (rhbz#1504066)