diff -Nru kpatch-0.5.0/contrib/kpatch.conf kpatch-0.8.0/contrib/kpatch.conf --- kpatch-0.5.0/contrib/kpatch.conf 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/contrib/kpatch.conf 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1,29 @@ +# Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. + +# This upstart version lacks the ability of unloading modules with +# the "stop" directive, as upstart does not support a feature like +# systemd's RemainAfterExit option. + + +description "Apply kpatch kernel patches" + +start on runlevel [2345] # Roughly equivalent to multi-user.target + +# We are not a daemon +task + +# Emulating systemd's ConditionKernelCommandLine option. +pre-start script + if [[ -e /proc/cmdline ]] + then + grep -q "kpatch.enable=0" /proc/cmdline && exit 1 + else + dmesg | grep -q "Command line.*kpatch.enable=0" && exit 1 + fi + + exit 0 +end script + +# Main process (start) +exec PREFIX/sbin/kpatch load --all + diff -Nru kpatch-0.5.0/contrib/kpatch.service kpatch-0.8.0/contrib/kpatch.service --- kpatch-0.5.0/contrib/kpatch.service 2017-12-21 05:02:48.000000000 +0000 +++ kpatch-0.8.0/contrib/kpatch.service 2019-08-28 17:34:00.000000000 +0000 @@ -6,7 +6,6 @@ Type=oneshot RemainAfterExit=yes ExecStart=PREFIX/sbin/kpatch load --all -ExecStop=PREFIX/sbin/kpatch unload --all [Install] WantedBy=multi-user.target diff -Nru kpatch-0.5.0/contrib/kpatch.spec kpatch-0.8.0/contrib/kpatch.spec --- kpatch-0.5.0/contrib/kpatch.spec 2017-12-21 05:02:48.000000000 +0000 +++ kpatch-0.8.0/contrib/kpatch.spec 2019-08-28 17:34:00.000000000 +0000 @@ -1,7 +1,7 @@ Name: kpatch Summary: Dynamic kernel patching -Version: 0.4.0 -License: GPLv2 +Version: 0.8.0 +License: GPLv2 Group: System Environment/Kernel URL: http://github.com/dynup/kpatch Release: 1%{?dist} @@ -14,7 +14,7 @@ # needed for the kernel specific module %define KVER %(uname -r) -%description +%description kpatch is a Linux dynamic kernel patching tool which allows you to patch a running kernel without rebooting or restarting any processes. It enables sysadmins to apply critical security patches to the kernel immediately, without @@ -60,10 +60,10 @@ %prep -%setup -q +%setup -q %build -make %{_smp_mflags} +make %{_smp_mflags} %install rm -rf %{buildroot} @@ -79,6 +79,7 @@ %{_sbindir}/kpatch %{_mandir}/man1/kpatch.1* %{_usr}/lib/systemd/system/* +%{_sysconfdir}/init/kpatch.conf %files %{KVER} %defattr(-,root,root,-) @@ -92,6 +93,101 @@ %{_mandir}/man1/kpatch-build.1* %changelog +* Wed Aug 21 2019 Artem Savkov - 0.8.0 +- kpatch.ko atomic replace fixes +- Fixes for potential problems found by covscan +- Remove manual signaling logic from kpatch utility +- Don't strip callback symbols +- Allow dynamic debug static keys + +* Wed Jul 24 2019 Josh Poimboeuf - 0.7.1 +- Fix several powerpc-specific bugs, including two which can result in kernel + panics +- Use rpmbuild --nodeps for installing srpm on Fedora/RHEL +- Fix inconsistent unit test failures for FAIL tests + +* Thu Jul 18 2019 Artem Savkov - 0.7.0 +- Multiple memory leak fixes in kpatch-build +- livepatch-patch-hook compatability fixes for kernels 5.1+ +- Making kpatch-build compatible with custom gcc names +- Added rhel-rebased integration tests +- kpatch.service will no longer unload modules on stop +- kpatch load will no longer fail if a module is already loaded and enabled +- kpatch-build will now check for *_fixup section changes on ppc64le and will + fail on such changes +- Add support for R_X86_64_PLT32 +- don't allow jump labels +- ppc64le-specific kpatch-build fixes + +* Fri Apr 12 2019 Joe Lawrence - 0.6.3 +- Lots of integration test work +- Better support for building out-of-tree modules +- Updated manpage options, drop deprecated distro specific mentions +- README.md updates for shadow variables, out-of-tree modules +- Fix core module compilation with CONFIG_HAVE_ARCH_PREL32_RELOCATIONS +- kpatch-build detects and abort on unsupported options + GCC_PLUGIN_LATENT_ENTROPY, GCC_PLUGIN_RANDSTRUCT +- Fix patch linking with 4.20+ +- Other minor shellcheck and kpatch-build fixups + +* Tue Oct 2 2018 Joe Lawrence - 0.6.2 +- ppc64le: relax .text section addralign value check +- gcc8: unit-tests +- gcc8: support parent/child symbol relations +- gcc8: handle functions changing subsection +- gcc8: consider ".text.hot" sections bundleable +- kpatch-build: bugfix for less aggressive clean build-cache +- ubuntu: remove "-signed" substring from the kernel source package name +- ubuntu: explicitly note elfutils dependency +- upstream 4.18: unit-tests +- upstream 4.18: KCFLAGS -mcount-record support support +- RHEL-8: don't care who provides yumdownloader +- RHEL-8: account for quirky SRPM / release name conventions + +* Tue May 29 2018 Joe Lawrence - 0.6.1 +- Increase the transition timeout, helpful for large CPU count systems +- Miscellaneous unit testing, ppc64, etc. fixes + +* Mon Apr 22 2018 Josh Poimboeuf - 0.6.0 +- Support and converted to livepatch-style hooks. +- Lots of misc bugfixes and cleanups +- Manpage, README.md fixups +- More PPC64 work +- "Undefined reference" build failure rework +- Livepatch disable retries +- New unit testing framework + +* Thu Dec 21 2017 Josh Poimboeuf - 0.5.0 +- Basic ppc64le support +- kpatch: load automatically signals stalled processes after a timeout +- kpatch: list shows stalled processes +- kpatch: signal signals stalled processes +- kpatch-build: multiple source patches can be combined into a single binary patch module +- kpatch-build: -n|--name option for giving a custom name to the patch module +- kpatch-build: additional -d options for more verbose debug modes +- The module prefix is now either livepatch- or kpatch- depending on the underlying patching technology + +* Mon Mar 13 2017 Josh Poimboeuf - 0.4.0 +- The tools underlying kpatch-build have been made more modular, in preparation for making create-diff-object more generally useful to other use cases (kernel livepatch, Xen live patching, user space patching). +- Support for all new upstream kernels up to 4.10. +- KASLR support. +- Many other bug fixes and improvements. + +* Thu Oct 11 2016 Jessica Yu - 0.3.4 +- bump version to 0.3.4 + +* Fri Aug 19 2016 Josh Poimboeuf - 0.3.3 +- bump version to 0.3.3 + +* Thu Feb 18 2016 Josh Poimboeuf - 0.3.2 +- bump version to 0.3.2 + +* Thu Nov 19 2015 Josh Poimboeuf - 0.3.1 +- Get kernel version from vmlinux if the kernel source tree is used + +* Wed Nov 18 2015 Josh Poimboeuf - 0.3.0 +- kpatch-build: fix gcc_version_check: both "GNU" and "GCC" are possible + * Wed Dec 3 2014 Josh Poimboeuf - 0.2.2-1 - rebased to current version diff -Nru kpatch-0.5.0/contrib/Makefile kpatch-0.8.0/contrib/Makefile --- kpatch-0.5.0/contrib/Makefile 2017-12-21 05:02:48.000000000 +0000 +++ kpatch-0.8.0/contrib/Makefile 2019-08-28 17:34:00.000000000 +0000 @@ -6,8 +6,12 @@ $(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 uninstall: $(RM) $(SYSTEMDDIR)/kpatch.service + $(RM) $(UPSTARTDIR)/kpatch.conf clean: diff -Nru kpatch-0.5.0/debian/changelog kpatch-0.8.0/debian/changelog --- kpatch-0.5.0/debian/changelog 2019-02-18 08:39:39.000000000 +0000 +++ kpatch-0.8.0/debian/changelog 2019-08-28 17:37:11.000000000 +0000 @@ -1,3 +1,22 @@ +kpatch (0.8.0-0ubuntu1) eoan; urgency=low + + * Upstream bump to 0.8.0 + * These remaining patches have been refreshed to apply to the updated + upstream: + - kpatch-build-adjust-dirs.patch + - use-debian-rules-for-ubuntu-builds.patch + - ubuntu-kernel-variants.patch + * Packaging changes to produce only kpatch and kpatch-build + - kpatch-dkms will be deprecated in the upstream soon + - kmod-fix-symbol-lookup-on-linux-4.19.patch no longer needed + * Enhance ubuntu-kernel-variants.patch to support additional kernel flavors + * Added missing devscripts dependency, required by kpatch-build + * Added elfutils dependency for ppc64el support + * Added gcc plugin devpackage dependency for ppc64el support + * Extra patch for xenial shellcheck version + + -- Benjamin M Romer Wed, 28 Aug 2019 13:37:11 -0400 + kpatch (0.5.0-0ubuntu2) disco; urgency=medium * Import v0.6 pataches from unstable for v4.19/v5 compat. diff -Nru kpatch-0.5.0/debian/control kpatch-0.8.0/debian/control --- kpatch-0.5.0/debian/control 2018-04-12 01:41:51.000000000 +0000 +++ kpatch-0.8.0/debian/control 2019-08-28 17:37:11.000000000 +0000 @@ -3,15 +3,16 @@ Priority: optional Maintainer: Ubuntu Kernel Team XSBC-Original-Maintainer: Chris J Arges -Build-Depends: debhelper (>= 9), libelf-dev, dkms, shellcheck +Build-Depends: debhelper (>= 9), libelf-dev, shellcheck, gcc-9-plugin-dev Standards-Version: 3.9.8 Homepage: http://github.com/dynup/kpatch #Vcs-Git: git://anonscm.debian.org/collab-maint/kpatch.git #Vcs-Browser: https://anonscm.debian.org/gitweb/?p=collab-maint/kpatch.git;a=summary Package: kpatch -Architecture: linux-amd64 -Depends: ${shlibs:Depends}, ${misc:Depends}, kpatch-dkms, +Architecture: any +Replaces: kpatch-dkms +Depends: ${shlibs:Depends}, ${misc:Depends}, linux-headers-amd64 | linux-headers-generic Description: Runtime tools for Kpatch kpatch is a Linux dynamic kernel patching tool which allows you to patch a @@ -21,24 +22,15 @@ for scheduled reboot windows. It gives more control over up-time without sacrificing security or stability. -Package: kpatch-dkms -Architecture: linux-amd64 -Depends: ${shlibs:Depends}, ${misc:Depends}, dkms -Description: DKMS module for Kpatch - This package contains the Kpatch module built with DKMS. It installs the source - and makefiles into the appropriate locations in order to handle various kernel - versions. - Package: kpatch-build -Architecture: linux-amd64 +Architecture: any Depends: ${shlibs:Depends}, ${misc:Depends}, dpkg-dev, debhelper (>= 5), - dh-systemd, cpio, kernel-wedge, kmod, makedumpfile, libelf-dev, + dh-systemd, cpio, kernel-wedge, kmod, makedumpfile, libelf-dev, devscripts, libnewt-dev, libiberty-dev, rsync, libdw-dev, libpci-dev, pkg-config, flex, bison, libunwind8-dev, openssl, libssl-dev, libaudit-dev, bc, python-dev, gawk, libudev-dev, autoconf, automake, libtool, uuid-dev, xmlto, docbook-utils, - ghostscript, transfig, bzip2, sharutils, asciidoc + ghostscript, transfig, bzip2, sharutils, asciidoc, elfutils Suggests: ccache Description: Build Tools for Kpatch and Livepatch kpatch-build is a tool that can build both kpatch and livepatch modules from a given patch. - diff -Nru kpatch-0.5.0/debian/kpatch-dkms.dkms kpatch-0.8.0/debian/kpatch-dkms.dkms --- kpatch-0.5.0/debian/kpatch-dkms.dkms 2016-07-27 23:12:29.000000000 +0000 +++ kpatch-0.8.0/debian/kpatch-dkms.dkms 1970-01-01 00:00:00.000000000 +0000 @@ -1,11 +0,0 @@ -MAKE="make -C kmod/ KPATCH_BUILD=/lib/modules/${kernelver}/build" -BUILT_MODULE_NAME="kpatch" -BUILT_MODULE_LOCATION="kmod/core" -DEST_MODULE_LOCATION="/updates/dkms" -CLEAN="make -C kmod/ clean" -PACKAGE_NAME="kpatch" -PACKAGE_VERSION=#MODULE_VERSION# -REMAKE_INITRD="no" -STRIP="no" -AUTOINSTALL="yes" -POST_BUILD="post-dkms.sh #MODULE_VERSION# ${kernelver}" diff -Nru kpatch-0.5.0/debian/patches/kmod-fix-symbol-lookup-on-linux-4.19.patch kpatch-0.8.0/debian/patches/kmod-fix-symbol-lookup-on-linux-4.19.patch --- kpatch-0.5.0/debian/patches/kmod-fix-symbol-lookup-on-linux-4.19.patch 2019-02-18 08:38:22.000000000 +0000 +++ kpatch-0.8.0/debian/patches/kmod-fix-symbol-lookup-on-linux-4.19.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,41 +0,0 @@ -From: Ben Hutchings -Date: Mon, 07 Jan 2019 19:19:42 +0000 -Subject: kmod: Fix symbol lookup on Linux 4.19 - -Since Linux 4.19, symbols may contain either an absolute address or a -self-relative offset, depending on -CONFIG_HAVE_ARCH_PREL32_RELOCATIONS. The function to resolve the -address is unfortunately not inline or exported, so copy it here. - -Since the configuration symbol didn't exist before, we don't need to -add an explicit kernel version check. - ---- ---- a/kmod/core/core.c -+++ b/kmod/core/core.c -@@ -636,6 +636,16 @@ static int kpatch_find_object_symbol(con - return -EINVAL; - } - -+/* Copied from kernel/module.c */ -+static unsigned long kernel_symbol_value(const struct kernel_symbol *sym) -+{ -+#ifdef CONFIG_HAVE_ARCH_PREL32_RELOCATIONS -+ return (unsigned long)offset_to_ptr(&sym->value_offset); -+#else -+ return sym->value; -+#endif -+} -+ - /* - * External symbols are located outside the parent object (where the parent - * object is either vmlinux or the kmod being patched). -@@ -651,7 +661,7 @@ static int kpatch_find_external_symbol(c - sym = find_symbol(name, NULL, NULL, true, true); - preempt_enable(); - if (sym) { -- *addr = sym->value; -+ *addr = kernel_symbol_value(sym); - return 0; - } - diff -Nru kpatch-0.5.0/debian/patches/kpatch-build-adjust-dirs.patch kpatch-0.8.0/debian/patches/kpatch-build-adjust-dirs.patch --- kpatch-0.5.0/debian/patches/kpatch-build-adjust-dirs.patch 2018-04-12 01:41:51.000000000 +0000 +++ kpatch-0.8.0/debian/patches/kpatch-build-adjust-dirs.patch 2019-08-28 17:37:11.000000000 +0000 @@ -7,7 +7,7 @@ --- a/kpatch-build/kpatch-build +++ b/kpatch-build/kpatch-build -@@ -159,9 +159,9 @@ +@@ -161,9 +161,9 @@ TOOLSDIR="$SCRIPTDIR" DATADIR="$(readlink -f "$SCRIPTDIR/../kmod")" PLUGINDIR="$(readlink -f "$SCRIPTDIR/gcc-plugins")" @@ -19,7 +19,7 @@ DATADIR="$(readlink -f "$SCRIPTDIR/../share/kpatch")" PLUGINDIR="$TOOLSDIR" else -@@ -174,12 +174,12 @@ +@@ -176,12 +176,12 @@ if [[ -e "$SCRIPTDIR/create-diff-object" ]]; then # git repo SYMVERSFILE="$DATADIR/core/Module.symvers" @@ -34,4 +34,4 @@ + SYMVERSFILE="$(readlink -f "/lib/modules/$ARCHVERSION/updates/dkms/kpatch.Module.symvers")" fi fi - + diff -Nru kpatch-0.5.0/debian/patches/kpatch-build-fix-clean-target.patch kpatch-0.8.0/debian/patches/kpatch-build-fix-clean-target.patch --- kpatch-0.5.0/debian/patches/kpatch-build-fix-clean-target.patch 2019-02-18 08:38:37.000000000 +0000 +++ kpatch-0.8.0/debian/patches/kpatch-build-fix-clean-target.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,17 +0,0 @@ -From: Ben Hutchings -Date: Mon, 07 Jan 2019 19:37:04 +0000 -Subject: kpatch-build: Fix clean target - -The clean target uses brace-expansion which is a bash extension not -supported by e.g. dash. Force use of bash for this target. - ---- ---- a/kpatch-build/Makefile -+++ b/kpatch-build/Makefile -@@ -43,5 +43,6 @@ uninstall: - $(RM) -R $(LIBEXECDIR) - $(RM) $(BINDIR)/kpatch-build - -+clean: SHELL = /bin/bash - clean: - $(RM) $(TARGETS) *.{o,d} insn/*.{o,d} gcc-plugins/*.{so,d} diff -Nru kpatch-0.5.0/debian/patches/remove-dkms.patch kpatch-0.8.0/debian/patches/remove-dkms.patch --- kpatch-0.5.0/debian/patches/remove-dkms.patch 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/debian/patches/remove-dkms.patch 2019-08-28 17:37:11.000000000 +0000 @@ -0,0 +1,13 @@ +--- a/Makefile.inc ++++ b/Makefile.inc +@@ -17,10 +17,5 @@ + SYSTEMDDIR = $(DESTDIR)$(PREFIX)/lib/systemd/system + UPSTARTDIR = $(DESTDIR)/etc/init + +-# The core module is only supported on x86_64 +-ifeq ($(ARCH),x86_64) +-BUILDMOD ?= yes +-endif +- + .PHONY: all install clean + .DEFAULT: all diff -Nru kpatch-0.5.0/debian/patches/series kpatch-0.8.0/debian/patches/series --- kpatch-0.5.0/debian/patches/series 2019-02-18 08:39:39.000000000 +0000 +++ kpatch-0.8.0/debian/patches/series 2019-08-28 17:37:11.000000000 +0000 @@ -1,6 +1,5 @@ +remove-dkms.patch kpatch-build-adjust-dirs.patch use-debian-rules-for-ubuntu-builds.patch ubuntu-kernel-variants.patch -kmod-fix-symbol-lookup-on-linux-4.19.patch -kpatch-build-fix-clean-target.patch -shellcheck.patch +xenial-shellcheck-fixes.patch diff -Nru kpatch-0.5.0/debian/patches/shellcheck.patch kpatch-0.8.0/debian/patches/shellcheck.patch --- kpatch-0.5.0/debian/patches/shellcheck.patch 2019-02-18 08:39:39.000000000 +0000 +++ kpatch-0.8.0/debian/patches/shellcheck.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,42 +0,0 @@ -Description: implement more shellcheck things -Author: Dimitri John Ledkov - - ---- kpatch-0.5.0.orig/kpatch-build/kpatch-build -+++ kpatch-0.5.0/kpatch-build/kpatch-build -@@ -167,7 +167,7 @@ ubuntu_build_external() { - - # $1 >= $2 - version_gte() { -- [ "$1" = "$(echo -e "$1\n$2" | sort -rV | head -n1)" ] -+ [ "$1" = "$(echo -e "$1\\n$2" | sort -rV | head -n1)" ] - } - - is_rhel() { -@@ -323,7 +323,7 @@ find_parent_obj() { - pdir="${absdir#$pwddir/}" - file="$(basename "$1")" - grepname="${1%.o}" -- grepname="$grepname\.o" -+ grepname="$grepname\\.o" - if [[ "$DEEP_FIND" -eq 1 ]]; then - num=0 - if [[ -n "$last_deep_find" ]]; then -@@ -724,7 +724,7 @@ if [[ $DISTRO = ubuntu ]]; then - fakeroot debian/rules clean 2>&1 | logger || die - MAKEFLAGS="--no-print-directory" debian/rules -j "$CPUS" \ - "build-$FLAVOR" build_image=vmlinux builddir="$TEMPDIR" \ -- enable_zfs=false CROSS_COMPILE="$TOOLSDIR/kpatch-gcc\ " 2>&1 | logger \ -+ enable_zfs=false CROSS_COMPILE="$TOOLSDIR/kpatch-gcc\\ " 2>&1 | logger \ - || die - ubuntu_build_external spl --with-linux="$SRCDIR" \ - --with-linux-obj="$TEMPDIR/build-$FLAVOR" | logger || die -@@ -752,7 +752,7 @@ if [[ $DISTRO = ubuntu ]]; then - rm -f "debian/stamps/stamp-build-$FLAVOR" - MAKEFLAGS="--no-print-directory" debian/rules -j "$CPUS" \ - "build-$FLAVOR" build_image=vmlinux \ -- CROSS_COMPILE="$TOOLSDIR/kpatch-gcc\ " enable_zfs=false \ -+ CROSS_COMPILE="$TOOLSDIR/kpatch-gcc\\ " enable_zfs=false \ - LDFLAGS_vmlinux="--warn-unresolved-symbols" \ - KBUILD_MODPOST_WARN=1 builddir="$TEMPDIR" 2>&1 | logger || die - else diff -Nru kpatch-0.5.0/debian/patches/ubuntu-kernel-variants.patch kpatch-0.8.0/debian/patches/ubuntu-kernel-variants.patch --- kpatch-0.5.0/debian/patches/ubuntu-kernel-variants.patch 2018-04-12 01:41:51.000000000 +0000 +++ kpatch-0.8.0/debian/patches/ubuntu-kernel-variants.patch 2019-08-28 17:37:11.000000000 +0000 @@ -1,77 +1,89 @@ -Description: Support Ubuntu kernel variants (lowlatency) - Update the kpatch-build program so that it will build non-generic ubuntu - kernels (i.e. lowlatency). The flavor is determined from the running - kernel, or from the vmlinux specified by the user. +Description: support ubuntu kernel flavors + Add support for kernel flavors (generic, lowlatency, aws, etc...) the flavor + may contain dashes and/or tildes, so handle these cases. Author: Benjamin M Romer -Last-Update: 2018-02-07 - +Last-Update: 2018-10-22 +--- +This patch header follows DEP-3: http://dep.debian.net/deps/dep3/ --- a/kpatch-build/kpatch-build +++ b/kpatch-build/kpatch-build -@@ -49,6 +49,7 @@ - DEBUG=0 - SKIPCLEANUP=0 - SKIPGCCCHECK=0 -+FLAVOR=$(uname -r | cut -d - -f 3) - ARCH_KCFLAGS="" - declare -a PATCH_LIST - APPLIED_PATCHES=0 -@@ -151,8 +152,8 @@ - TARGET=$1 - EXTDIR="$TEMPDIR/build-generic/" - shift -- mkdir -p "$TEMPDIR/build-generic/$TARGET" -- cd "$TEMPDIR/build-generic/$TARGET" || die -+ mkdir -p "$TEMPDIR/build-$FLAVOR/$TARGET" -+ cd "$TEMPDIR/build-$FLAVOR/$TARGET" || die - if [ ! -e Makefile ]; then - bash "$SRCDIR/$TARGET/configure" "$@" 2>&1 | logger || die - make "-j$CPUS" EXTDIR="$EXTDIR" CROSS_COMPILE="$TOOLSDIR/kpatch-gcc " 2>&1 | logger || die -@@ -525,6 +526,7 @@ - - # Extract the target kernel version from vmlinux in this case. - ARCHVERSION="$(strings "$VMLINUX" | grep -m 1 -e "^Linux version" | awk '{ print($3); }')" -+ FLAVOR=${ARCHVERSION##*-} +@@ -423,7 +423,7 @@ + echo " (not recommended)" >&2 + } + +-options="$(getopt -o ha:r:s:c:v:j:t:n:o:de: -l "help,archversion:,sourcerpm:,sourcedir:,config:,vmlinux:,jobs:,target:,name:,output:,oot-module:,debug,skip-gcc-check,skip-cleanup" -- "$@")" || die "getopt failed" ++options="$(getopt -o ha:r:s:c:v:j:t:n:o:def: -l "help,archversion:,sourcerpm:,sourcedir:,config:,vmlinux:,jobs:,target:,name:,output:,oot-module:,debug,skip-gcc-check,skip-cleanup,flavor:" -- "$@")" || die "getopt failed" + + eval set -- "$options" + +@@ -494,6 +494,10 @@ + echo "WARNING: Skipping gcc version matching check (not recommended)" + SKIPGCCCHECK=1 + ;; ++ -f|--flavor) ++ FLAVOR="$2" ++ shift ++ ;; + *) + [[ "$1" = "--" ]] && shift && continue + [[ ! -f "$1" ]] && die "patch file '$1' not found" +@@ -551,11 +555,23 @@ + + # Extract the target kernel version from vmlinux in this case. + ARCHVERSION="$(strings "$VMLINUX" | grep -m 1 -e "^Linux version" | awk '{ print($3); }')" ++ FLAV=${ARCHVERSION#*-*-} ++ if [[ -n "$FLAVOR" ]]; then ++ if [[ "$FLAVOR" != "$FLAV" ]]; then ++ die "specified flavor $FLAVOR does not match vmlinux ($FLAV)" ++ fi ++ else ++ FLAVOR=$FLAV ++ fi + else + ARCHVERSION="$(modinfo -F vermagic "$OOT_MODULE" | awk '{print $1}')" + fi fi - + ++if [[ -z "$FLAVOR" ]]; then ++ FLAVOR=$(uname -r | cut -d - -f 3) ++fi ++ [[ -z "$ARCHVERSION" ]] && ARCHVERSION="$(uname -r)" -@@ -717,18 +719,18 @@ - if [[ $DISTRO = ubuntu ]]; then - mv "$SRCDIR/debian" "$SRCDIR/debian.master" "$TEMPDIR" - make mrproper 2>&1 | logger || die -- rm -rf "$TEMPDIR/build-generic/spl" "$TEMPDIR/build-generic/zfs" -+ rm -rf "$TEMPDIR/build-$FLAVOR/spl" "$TEMPDIR/build-$FLAVOR/zfs" - mv "$TEMPDIR/debian" "$TEMPDIR/debian.master" "$SRCDIR" + + [[ "$SKIPCLEANUP" -eq 0 ]] && trap cleanup EXIT INT TERM HUP +@@ -775,7 +791,7 @@ fakeroot debian/rules clean 2>&1 | logger || die - MAKEFLAGS="--no-print-directory" debian/rules -j "$CPUS" \ -- build-generic build_image=vmlinux builddir="$TEMPDIR" \ -+ "build-$FLAVOR" build_image=vmlinux builddir="$TEMPDIR" \ - enable_zfs=false CROSS_COMPILE="$TOOLSDIR/kpatch-gcc\ " 2>&1 | logger \ + # shellcheck disable=SC1117 + MAKEFLAGS="--no-print-directory" fakeroot \ +- debian/rules -j "$CPUS" build-generic build_image=vmlinux \ ++ debian/rules -j "$CPUS" "build-$FLAVOR" build_image=vmlinux \ + builddir="$TEMPDIR" enable_zfs=false \ + CROSS_COMPILE="$TOOLSDIR/kpatch-gcc\ " 2>&1 | logger \ || die - ubuntu_build_external spl --with-linux="$SRCDIR" \ -- --with-linux-obj="$TEMPDIR/build-generic" | logger || die -+ --with-linux-obj="$TEMPDIR/build-$FLAVOR" | logger || die - ubuntu_build_external zfs --with-linux="$SRCDIR" \ -- --with-linux-obj="$TEMPDIR/build-generic" --with-spl="$SRCDIR/spl" \ -- --with-spl-obj="$TEMPDIR/build-generic/spl" --with-config=kernel | logger || die -+ --with-linux-obj="$TEMPDIR/build-$FLAVOR" --with-spl="$SRCDIR/spl" \ -+ --with-spl-obj="$TEMPDIR/build-$FLAVOR/spl" --with-config=kernel | logger || die - else - ./scripts/setlocalversion --save-scmversion || die - make mrproper 2>&1 | logger || die -@@ -747,9 +749,9 @@ +@@ -794,10 +810,10 @@ + KPATCH_GCC_SRCDIR="$SRCDIR" + export KPATCH_GCC_SRCDIR if [[ $DISTRO = ubuntu ]]; then - ubuntu_build_external spl || die - ubuntu_build_external zfs || die - rm -f debian/stamps/stamp-build-generic + rm -f "debian/stamps/stamp-build-$FLAVOR" - MAKEFLAGS="--no-print-directory" debian/rules -j "$CPUS" \ -- build-generic build_image=vmlinux \ -+ "build-$FLAVOR" build_image=vmlinux \ + # shellcheck disable=SC1117 + MAKEFLAGS="--no-print-directory" fakeroot \ +- debian/rules -j "$CPUS" build-generic build_image=vmlinux \ ++ debian/rules -j "$CPUS" "build-$FLAVOR" build_image=vmlinux \ CROSS_COMPILE="$TOOLSDIR/kpatch-gcc\ " enable_zfs=false \ LDFLAGS_vmlinux="--warn-unresolved-symbols" \ KBUILD_MODPOST_WARN=1 builddir="$TEMPDIR" 2>&1 | logger || die -@@ -774,7 +776,7 @@ +@@ -821,7 +837,7 @@ + fi + + if [[ $DISTRO = ubuntu ]]; then +- [[ -n "$OOT_MODULE" ]] || grep -q vmlinux "$TEMPDIR/build-generic/Module.symvers" || die "truncated $TEMPDIR/build-generic/Module.symvers file" ++ [[ -n "$OOT_MODULE" ]] || grep -q vmlinux "$TEMPDIR/build-$FLAVOR/Module.symvers" || die "truncated $TEMPDIR/build-$FLAVOR/Module.symvers file" + else + [[ -n "$OOT_MODULE" ]] ||grep -q vmlinux "$SRCDIR/Module.symvers" || die "truncated $SRCDIR/Module.symvers file" + fi +@@ -832,7 +848,7 @@ do mkdir -p "$TEMPDIR/patched/$(dirname "$i")" || die if [[ $DISTRO = ubuntu ]]; then @@ -80,8 +92,8 @@ else cp -f "$SRCDIR/$i" "$TEMPDIR/patched/$i" || die fi -@@ -820,7 +822,7 @@ - +@@ -878,7 +894,7 @@ + mkdir -p "output/$(dirname "$i")" if [[ "$DISTRO" = ubuntu ]]; then - cd "$TEMPDIR/build-generic" || die @@ -89,21 +101,39 @@ else cd "$SRCDIR" || die fi -@@ -835,7 +837,7 @@ - if [[ "$DISTRO" = ubuntu ]]; then - # create-diff-object orig.o patched.o kernel-object output.o Module.symvers patch-mod-name - "$TOOLSDIR"/create-diff-object "orig/$i" "patched/$i" "$KOBJFILE" \ -- "output/$i" "$TEMPDIR/build-generic/Module.symvers" "${MODNAME//-/_}" 2>&1 | logger 1 -+ "output/$i" "$TEMPDIR/build-$FLAVOR/Module.symvers" "${MODNAME//-/_}" 2>&1 | logger 1 - check_pipe_status create-diff-object - else - # create-diff-object orig.o patched.o kernel-object output.o Module.symvers patch-mod-name -@@ -897,7 +899,7 @@ +@@ -890,7 +906,7 @@ + KOBJFILE_PATH="$VMLINUX" + SYMTAB="${TEMPDIR}/${KOBJFILE_NAME}.symtab" + if [[ "$DISTRO" = ubuntu ]]; then +- SYMVERS_FILE="$TEMPDIR/build-generic/Module.symvers" ++ SYMVERS_FILE="$TEMPDIR/build-$FLAVOR/Module.symvers" + else + SYMVERS_FILE="$SRCDIR/Module.symvers" + fi +@@ -899,7 +915,7 @@ + KOBJFILE_PATH="$OOT_MODULE" + SYMTAB="${TEMPDIR}/module/${KOBJFILE_NAME}.symtab" + if [[ "$DISTRO" = ubuntu ]]; then +- SYMVERS_FILE="$TEMPDIR/build-generic/Module.symvers" ++ SYMVERS_FILE="$TEMPDIR/build-$FLAVOR/Module.symvers" + else + SYMVERS_FILE="$SRCDIR/Module.symvers" + fi +@@ -912,7 +928,7 @@ + KOBJFILE_PATH="${TEMPDIR}/module/$KOBJFILE" + SYMTAB="${KOBJFILE_PATH}.symtab" + if [[ "$DISTRO" = ubuntu ]]; then +- SYMVERS_FILE="$TEMPDIR/build-generic/Module.symvers" ++ SYMVERS_FILE="$TEMPDIR/build-$FLAVOR/Module.symvers" + else + SYMVERS_FILE="$SRCDIR/Module.symvers" + fi +@@ -983,7 +999,7 @@ cd "$TEMPDIR/patch" || die - - if [ "$DISTRO" = ubuntu ]; then -- KPATCH_BUILD="$TEMPDIR/build-generic" KPATCH_NAME="$MODNAME" \ -+ KPATCH_BUILD="$TEMPDIR/build-$FLAVOR" KPATCH_NAME="$MODNAME" \ - KBUILD_EXTRA_SYMBOLS="$KBUILD_EXTRA_SYMBOLS" \ - KPATCH_LDFLAGS="$KPATCH_LDFLAGS" \ - make 2>&1 | logger || die + if [[ -z "$OOT_MODULE" ]]; then + if [[ "$DISTRO" == ubuntu ]]; then +- KPATCH_BUILD="$TEMPDIR/build-generic" ++ KPATCH_BUILD="$TEMPDIR/build-$FLAVOR" + else + KPATCH_BUILD="$SRCDIR" + fi diff -Nru kpatch-0.5.0/debian/patches/use-debian-rules-for-ubuntu-builds.patch kpatch-0.8.0/debian/patches/use-debian-rules-for-ubuntu-builds.patch --- kpatch-0.5.0/debian/patches/use-debian-rules-for-ubuntu-builds.patch 2018-04-12 01:41:51.000000000 +0000 +++ kpatch-0.8.0/debian/patches/use-debian-rules-for-ubuntu-builds.patch 2019-08-28 17:37:11.000000000 +0000 @@ -4,70 +4,35 @@ so it matches how the Ubuntu kernel is actually made. Author: Benjamin M Romer -Last-Update: 2018-02-07 +Last-Update: 2019-08-29 --- a/kpatch-build/kpatch-build +++ b/kpatch-build/kpatch-build -@@ -114,9 +114,10 @@ - # we've reverted our patch(es). - [[ -d "$SRCDIR/.git" ]] && (cd "$SRCDIR" && git update-index -q --refresh) - -- # restore original .config and vmlinux if they were removed with mrproper -+ # restore original .config, vmlinux, and debian if they were removed with mrproper - [[ -e "$TEMPDIR/.config" ]] && mv -f "$TEMPDIR/.config" "$SRCDIR/" +@@ -117,8 +117,9 @@ + + remove_patches + +- # restore original vmlinux if it was overwritten by sourcedir build ++ # restore original vmlinux and debian if it was overwritten by sourcedir build [[ -e "$TEMPDIR/vmlinux" ]] && mv -f "$TEMPDIR/vmlinux" "$SRCDIR/" + [[ -e "$TEMPDIR/debian.bak" ]] && cp -rf "$TEMPDIR/debian.bak" "$SRCDIR/debian" - + [[ "$DEBUG" -eq 0 ]] && rm -rf "$TEMPDIR" rm -rf "$RPMTOPDIR" -@@ -144,6 +145,25 @@ +@@ -611,6 +612,9 @@ + CONFIGFILE="/boot/config-${ARCHVERSION}" fi - } - -+# builds external packages for ubuntu kernels (i.e. zfs) -+ubuntu_build_external() { -+ BACKTO=$(pwd) -+ TARGET=$1 -+ EXTDIR="$TEMPDIR/build-generic/" -+ shift -+ mkdir -p "$TEMPDIR/build-generic/$TARGET" -+ cd "$TEMPDIR/build-generic/$TARGET" || die -+ if [ ! -e Makefile ]; then -+ bash "$SRCDIR/$TARGET/configure" "$@" 2>&1 | logger || die -+ make "-j$CPUS" EXTDIR="$EXTDIR" CROSS_COMPILE="$TOOLSDIR/kpatch-gcc " 2>&1 | logger || die -+ else -+ make "-j$CPUS" EXTDIR="$EXTDIR" CROSS_COMPILE="$TOOLSDIR/kpatch-gcc " \ -+ LDFLAGS_vmlinux="--warn-unresolved-symbols" \ -+ KBUILD_MODPOST_WARN=1 2>&1 | logger || die -+ fi -+ cd "$BACKTO" || die -+} -+ - # $1 >= $2 - version_gte() { - [ "$1" = "$(echo -e "$1\n$2" | sort -rV | head -n1)" ] -@@ -554,6 +574,9 @@ - # save vmlinux before it gets removed with mrproper - [[ "$VMLINUX" -ef "$SRCDIR"/vmlinux ]] && cp -f "$VMLINUX" "$TEMPDIR/vmlinux" && VMLINUX="$TEMPDIR/vmlinux" - + + # save debian before it gets removed with mrproper + [[ -e "$SRCDIR/debian" ]] && cp -rf "$SRCDIR/debian" "$TEMPDIR/debian.bak" + elif [[ -e "$SRCDIR"/.config ]] && [[ -e "$VERSIONFILE" ]] && [[ "$(cat "$VERSIONFILE")" = "$ARCHVERSION" ]]; then echo "Using cache at $SRCDIR" - -@@ -601,7 +624,6 @@ - # url may be changed for a different mirror - url="http://archive.ubuntu.com/ubuntu/pool/main/l" - sublevel="SUBLEVEL = 0" -- UBUNTU_KERNEL=1 - - elif [[ "$DISTRO" = debian ]]; then - -@@ -622,9 +644,7 @@ + +@@ -681,9 +685,7 @@ (dget -u "$url/${pkgname}/${dscname}" 2>&1) | logger || die "dget: Could not fetch/unpack $url/${pkgname}/${dscname}" mv "${pkgname}-$KVER" "$SRCDIR" || die - cp "/boot/config-${ARCHVERSION}" "$SRCDIR/.config" || die + [[ -z "$CONFIGFILE" ]] && CONFIGFILE="/boot/config-${ARCHVERSION}" - if [[ "$ARCHVERSION" == *-* ]]; then - echo "-${ARCHVERSION#*-}" > "$SRCDIR/localversion" || die - fi @@ -75,13 +40,10 @@ # for some reason the Ubuntu kernel versions don't follow the # upstream SUBLEVEL; they are always at SUBLEVEL 0 sed -i "s/^SUBLEVEL.*/${sublevel}/" "$SRCDIR/Makefile" || die -@@ -694,24 +714,53 @@ - fi - - echo "Building original kernel" --./scripts/setlocalversion --save-scmversion || die --make mrproper 2>&1 | logger || die --cp -f "$CONFIGFILE" "$SRCDIR/.config" +@@ -766,10 +768,23 @@ + + echo "Building original source" + [[ -n "$OOT_MODULE" ]] || ./scripts/setlocalversion --save-scmversion || die -unset KPATCH_GCC_TEMPDIR -# $TARGETS used as list, no quotes. -# shellcheck disable=SC2086 @@ -89,44 +51,37 @@ +if [[ $DISTRO = ubuntu ]]; then + mv "$SRCDIR/debian" "$SRCDIR/debian.master" "$TEMPDIR" + make mrproper 2>&1 | logger || die -+ rm -rf "$TEMPDIR/build-generic/spl" "$TEMPDIR/build-generic/zfs" + mv "$TEMPDIR/debian" "$TEMPDIR/debian.master" "$SRCDIR" + fakeroot debian/rules clean 2>&1 | logger || die -+ MAKEFLAGS="--no-print-directory" debian/rules -j "$CPUS" \ -+ build-generic build_image=vmlinux builddir="$TEMPDIR" \ -+ enable_zfs=false CROSS_COMPILE="$TOOLSDIR/kpatch-gcc\ " 2>&1 | logger \ ++ # shellcheck disable=SC1117 ++ MAKEFLAGS="--no-print-directory" fakeroot \ ++ debian/rules -j "$CPUS" build-generic build_image=vmlinux \ ++ builddir="$TEMPDIR" enable_zfs=false \ ++ CROSS_COMPILE="$TOOLSDIR/kpatch-gcc\ " 2>&1 | logger \ + || die -+ ubuntu_build_external spl --with-linux="$SRCDIR" \ -+ --with-linux-obj="$TEMPDIR/build-generic" | logger || die -+ ubuntu_build_external zfs --with-linux="$SRCDIR" \ -+ --with-linux-obj="$TEMPDIR/build-generic" --with-spl="$SRCDIR/spl" \ -+ --with-spl-obj="$TEMPDIR/build-generic/spl" --with-config=kernel | logger || die +else -+ ./scripts/setlocalversion --save-scmversion || die -+ make mrproper 2>&1 | logger || die -+ cp -f "$CONFIGFILE" "$SRCDIR/.config" + unset KPATCH_GCC_TEMPDIR -+ # $TARGETS used as list, no quotes | logger. ++ # $TARGETS used as list, no quotes. + # shellcheck disable=SC2086 + CROSS_COMPILE="$TOOLSDIR/kpatch-gcc " make "-j$CPUS" $TARGETS 2>&1 | logger || die +fi - - echo "Building patched kernel" + + echo "Building patched source" apply_patches - mkdir -p "$TEMPDIR/orig" "$TEMPDIR/patched" - KPATCH_GCC_TEMPDIR="$TEMPDIR" +@@ -778,11 +793,21 @@ export KPATCH_GCC_TEMPDIR + KPATCH_GCC_SRCDIR="$SRCDIR" + export KPATCH_GCC_SRCDIR -# $TARGETS used as list, no quotes. -# shellcheck disable=SC2086 -CROSS_COMPILE="$TOOLSDIR/kpatch-gcc " \ - KBUILD_MODPOST_WARN=1 \ - make "-j$CPUS" $TARGETS 2>&1 | logger || die +if [[ $DISTRO = ubuntu ]]; then -+ ubuntu_build_external spl || die -+ ubuntu_build_external zfs || die + rm -f debian/stamps/stamp-build-generic -+ MAKEFLAGS="--no-print-directory" debian/rules -j "$CPUS" \ -+ build-generic build_image=vmlinux \ ++ # shellcheck disable=SC1117 ++ MAKEFLAGS="--no-print-directory" fakeroot \ ++ debian/rules -j "$CPUS" build-generic build_image=vmlinux \ + CROSS_COMPILE="$TOOLSDIR/kpatch-gcc\ " enable_zfs=false \ + LDFLAGS_vmlinux="--warn-unresolved-symbols" \ + KBUILD_MODPOST_WARN=1 builddir="$TEMPDIR" 2>&1 | logger || die @@ -135,13 +90,24 @@ + # shellcheck disable=SC2086 + CROSS_COMPILE="$TOOLSDIR/kpatch-gcc " \ + KBUILD_MODPOST_WARN=1 \ -+ make "-j$CPUS" $TARGETS 3>&1 | logger || die ++ make "-j$CPUS" $TARGETS 2>&1 | logger || die +fi -+ - grep "undefined reference" "$LOGFILE" | grep -qv kpatch_shadow && die - grep "undefined!" "$LOGFILE" | grep -qv kpatch_shadow && die - -@@ -724,7 +773,11 @@ + + # source.c:(.section+0xFF): undefined reference to `symbol' + grep "undefined reference" "$LOGFILE" | sed -r "s/^.*\`(.*)'$/\\1/" \ +@@ -795,14 +820,22 @@ + die "no changed objects found" + fi + +-[[ -n "$OOT_MODULE" ]] || grep -q vmlinux "$SRCDIR/Module.symvers" || die "truncated $SRCDIR/Module.symvers file" ++if [[ $DISTRO = ubuntu ]]; then ++ [[ -n "$OOT_MODULE" ]] || grep -q vmlinux "$TEMPDIR/build-generic/Module.symvers" || die "truncated $TEMPDIR/build-generic/Module.symvers file" ++else ++ [[ -n "$OOT_MODULE" ]] ||grep -q vmlinux "$SRCDIR/Module.symvers" || die "truncated $SRCDIR/Module.symvers file" ++fi + + # Read as words, no quotes. + # shellcheck disable=SC2013 for i in $(cat "$TEMPDIR/changed_objs") do mkdir -p "$TEMPDIR/patched/$(dirname "$i")" || die @@ -152,11 +118,11 @@ + cp -f "$SRCDIR/$i" "$TEMPDIR/patched/$i" || die + fi done - + echo "Extracting new and modified ELF sections" -@@ -766,7 +819,11 @@ +@@ -844,7 +877,11 @@ [[ "$i" = usr/initramfs_data.o ]] && continue - + mkdir -p "output/$(dirname "$i")" - cd "$SRCDIR" || die + if [[ "$DISTRO" = ubuntu ]]; then @@ -165,35 +131,49 @@ + cd "$SRCDIR" || die + fi find_kobj "$i" - if [[ "$KOBJFILE" = vmlinux ]]; then - KOBJFILE="$VMLINUX" -@@ -775,10 +832,17 @@ - fi cd "$TEMPDIR" || die if [[ -e "orig/$i" ]]; then -- # create-diff-object orig.o patched.o kernel-object output.o Module.symvers patch-mod-name -- "$TOOLSDIR"/create-diff-object "orig/$i" "patched/$i" "$KOBJFILE" \ -- "output/$i" "$SRCDIR/Module.symvers" "${MODNAME//-/_}" 2>&1 | logger 1 -- check_pipe_status create-diff-object -+ if [[ "$DISTRO" = ubuntu ]]; then -+ # create-diff-object orig.o patched.o kernel-object output.o Module.symvers patch-mod-name -+ "$TOOLSDIR"/create-diff-object "orig/$i" "patched/$i" "$KOBJFILE" \ -+ "output/$i" "$TEMPDIR/build-generic/Module.symvers" "${MODNAME//-/_}" 2>&1 | logger 1 -+ check_pipe_status create-diff-object -+ else -+ # create-diff-object orig.o patched.o kernel-object output.o Module.symvers patch-mod-name -+ "$TOOLSDIR"/create-diff-object "orig/$i" "patched/$i" "$KOBJFILE" \ -+ "output/$i" "$SRCDIR/Module.symvers" "${MODNAME//-/_}" 2>&1 | logger 1 -+ check_pipe_status create-diff-object -+ fi - # create-diff-object returns 3 if no functional change is found - [[ "$rc" -eq 0 ]] || [[ "$rc" -eq 3 ]] || ERROR="$((ERROR + 1))" - if [[ "$rc" -eq 0 ]]; then -@@ -814,13 +878,6 @@ - +@@ -852,12 +889,20 @@ + KOBJFILE_NAME=vmlinux + KOBJFILE_PATH="$VMLINUX" + SYMTAB="${TEMPDIR}/${KOBJFILE_NAME}.symtab" +- SYMVERS_FILE="$SRCDIR/Module.symvers" ++ if [[ "$DISTRO" = ubuntu ]]; then ++ SYMVERS_FILE="$TEMPDIR/build-generic/Module.symvers" ++ else ++ SYMVERS_FILE="$SRCDIR/Module.symvers" ++ fi + elif [[ "$(basename "$KOBJFILE")" = "$(basename "$OOT_MODULE")" ]]; then + KOBJFILE_NAME="$(basename --suffix=.ko "$OOT_MODULE")" + KOBJFILE_PATH="$OOT_MODULE" + SYMTAB="${TEMPDIR}/module/${KOBJFILE_NAME}.symtab" +- SYMVERS_FILE="$TEMPDIR/Module.symvers" ++ if [[ "$DISTRO" = ubuntu ]]; then ++ SYMVERS_FILE="$TEMPDIR/build-generic/Module.symvers" ++ else ++ SYMVERS_FILE="$SRCDIR/Module.symvers" ++ fi + BUILDDIR="/lib/modules/$ARCHVERSION/build/" + cp "$SRCDIR/Module.symvers" "$SYMVERS_FILE" + awk '{ print $1 "\t" $2 "\t" $3 "\t" $4}' "${BUILDDIR}/Module.symvers" >> "$SYMVERS_FILE" +@@ -866,7 +911,11 @@ + KOBJFILE_NAME="${KOBJFILE_NAME/-/_}" + KOBJFILE_PATH="${TEMPDIR}/module/$KOBJFILE" + SYMTAB="${KOBJFILE_PATH}.symtab" +- SYMVERS_FILE="$SRCDIR/Module.symvers" ++ if [[ "$DISTRO" = ubuntu ]]; then ++ SYMVERS_FILE="$TEMPDIR/build-generic/Module.symvers" ++ else ++ SYMVERS_FILE="$SRCDIR/Module.symvers" ++ fi + fi + + readelf -s --wide "$KOBJFILE_PATH" > "$SYMTAB" +@@ -915,13 +964,6 @@ + echo "Building patch module: $MODNAME.ko" - --if [[ ! -z "$UBUNTU_KERNEL" ]]; then + +-if [[ -z "$USERSRCDIR" ]] && [[ "$DISTRO" = ubuntu ]]; then - # UBUNTU: add UTS_UBUNTU_RELEASE_ABI to utsrelease.h after regenerating it - UBUNTU_ABI="${ARCHVERSION#*-}" - UBUNTU_ABI="${UBUNTU_ABI%-*}" @@ -203,45 +183,27 @@ cd "$TEMPDIR/output" || die # $KPATCH_LDFLAGS and result of find used as list, no quotes. # shellcheck disable=SC2086,SC2046 -@@ -839,10 +896,17 @@ - +@@ -940,7 +982,11 @@ + cd "$TEMPDIR/patch" || die - --KPATCH_BUILD="$SRCDIR" KPATCH_NAME="$MODNAME" \ --KBUILD_EXTRA_SYMBOLS="$KBUILD_EXTRA_SYMBOLS" \ --KPATCH_LDFLAGS="$KPATCH_LDFLAGS" \ -- make 2>&1 | logger || die -+if [ "$DISTRO" = ubuntu ]; then -+ KPATCH_BUILD="$TEMPDIR/build-generic" KPATCH_NAME="$MODNAME" \ -+ KBUILD_EXTRA_SYMBOLS="$KBUILD_EXTRA_SYMBOLS" \ -+ KPATCH_LDFLAGS="$KPATCH_LDFLAGS" \ -+ make 2>&1 | logger || die -+else -+ KPATCH_BUILD="$SRCDIR" KPATCH_NAME="$MODNAME" \ -+ KBUILD_EXTRA_SYMBOLS="$KBUILD_EXTRA_SYMBOLS" \ -+ KPATCH_LDFLAGS="$KPATCH_LDFLAGS" \ -+ make 2>&1 | logger || die -+fi - - if ! "$KPATCH_MODULE"; then - if [[ -z "$KPATCH_LDFLAGS" ]]; then + if [[ -z "$OOT_MODULE" ]]; then +- KPATCH_BUILD="$SRCDIR" ++ if [[ "$DISTRO" == ubuntu ]]; then ++ KPATCH_BUILD="$TEMPDIR/build-generic" ++ else ++ KPATCH_BUILD="$SRCDIR" ++ fi + else + KPATCH_BUILD="/lib/modules/$ARCHVERSION/build" + fi --- a/kpatch-build/kpatch-gcc +++ b/kpatch-build/kpatch-gcc @@ -16,7 +16,7 @@ - if [[ "$TOOLCHAINCMD" = "gcc" ]] ; then + if [[ "$TOOLCHAINCMD" =~ "gcc" ]] ; then while [ "$#" -gt 0 ]; do if [ "$1" = "-o" ]; then - obj="$2" + obj="${2##"$EXTDIR"}" - + # skip copying the temporary .o files created by # recordmcount.pl -@@ -60,7 +60,7 @@ - elif [[ "$TOOLCHAINCMD" = "ld" ]] ; then - while [ "$#" -gt 0 ]; do - if [ "$1" = "-o" ]; then -- obj="$2" -+ obj="${2##"$EXTDIR"}" - case "$obj" in - *.ko) - mkdir -p "$KPATCH_GCC_TEMPDIR/module/$(dirname "$obj")" diff -Nru kpatch-0.5.0/debian/patches/xenial-shellcheck-fixes.patch kpatch-0.8.0/debian/patches/xenial-shellcheck-fixes.patch --- kpatch-0.5.0/debian/patches/xenial-shellcheck-fixes.patch 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/debian/patches/xenial-shellcheck-fixes.patch 2019-08-28 17:37:11.000000000 +0000 @@ -0,0 +1,40 @@ +--- a/kpatch-build/kpatch-build ++++ b/kpatch-build/kpatch-build +@@ -689,7 +689,9 @@ + sublevel="SUBLEVEL =" + fi + ++ # shellcheck disable=SC2016 + pkgname="$(dpkg-query -W -f='${Source}' "linux-image-$ARCHVERSION" | sed s/-signed//)" ++ # shellcheck disable=SC2016 + pkgver="$(dpkg-query -W -f='${Version}' "linux-image-$ARCHVERSION")" + dscname="${pkgname}_${pkgver}.dsc" + +--- a/kpatch-build/kpatch-gcc ++++ b/kpatch-build/kpatch-gcc +@@ -13,6 +13,7 @@ + + declare -a args=("$@") + ++# shellcheck disable=SC2076 + if [[ "$TOOLCHAINCMD" =~ "gcc" ]] ; then + while [ "$#" -gt 0 ]; do + if [ "$1" = "-o" ]; then +--- a/kpatch/kpatch ++++ b/kpatch/kpatch +@@ -310,6 +310,7 @@ + out="$(LC_ALL=C insmod "$module" 2>&1)" + [[ -z "$out" ]] && break + echo "$out" 1>&2 ++ # shellcheck disable=SC2076 + [[ ! "$out" =~ "Device or resource busy" ]] && + die "failed to load module $module" + +@@ -348,6 +349,7 @@ + out="$(export LC_ALL=C; sh -c "echo 0 > $enabled" 2>&1)" + [[ -z "$out" ]] && break + echo "$out" 1>&2 ++ # shellcheck disable=SC2076 + if [[ ! "$out" =~ "Device or resource busy" ]]; then + die "failed to disable module $modname" + fi diff -Nru kpatch-0.5.0/debian/post-dkms.sh kpatch-0.8.0/debian/post-dkms.sh --- kpatch-0.5.0/debian/post-dkms.sh 2016-07-27 23:12:29.000000000 +0000 +++ kpatch-0.8.0/debian/post-dkms.sh 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -#!/bin/bash -module_version=$1 -kernelver=$2 -mkdir -p /lib/modules/$kernelver/updates/dkms/ -cp /var/lib/dkms/kpatch/$module_version/build/kmod/core/Module.symvers /lib/modules/$kernelver/updates/dkms/kpatch.Module.symvers diff -Nru kpatch-0.5.0/debian/rules kpatch-0.8.0/debian/rules --- kpatch-0.5.0/debian/rules 2016-08-16 13:48:01.000000000 +0000 +++ kpatch-0.8.0/debian/rules 2019-08-28 17:37:11.000000000 +0000 @@ -13,10 +13,3 @@ override_dh_auto_install: dh_auto_install -- PREFIX=/usr -override_dh_install: - mkdir -p debian/tmp/usr/src/kpatch-$(VERSION) - dh_install -pkpatch-dkms -X.o -X.ko -Xkmod/patch kmod/ usr/src/kpatch-$(VERSION) - dh_install -pkpatch-dkms Makefile.inc usr/src/kpatch-$(VERSION) - dh_install -pkpatch-dkms debian/post-dkms.sh usr/src/kpatch-$(VERSION) - dh_dkms -V $(VERSION) - dh_install diff -Nru kpatch-0.5.0/doc/patch-author-guide.md kpatch-0.8.0/doc/patch-author-guide.md --- kpatch-0.5.0/doc/patch-author-guide.md 2017-12-21 05:02:48.000000000 +0000 +++ kpatch-0.8.0/doc/patch-author-guide.md 2019-08-28 17:34:00.000000000 +0000 @@ -105,53 +105,143 @@ kpatch creates a barrier between the calling of old functions and new functions. -### Use a kpatch load hook +### Use a kpatch callback macro -If you need to change the contents of an existing variable in-place, you can -use the `KPATCH_LOAD_HOOK` macro to specify a function to be called when the -patch module is loaded. +Kpatch supports livepatch style callbacks, as described by the kernel's +[Documentation/livepatch/callbacks.txt](https://github.com/torvalds/linux/blob/master/Documentation/livepatch/callbacks.txt). -`kpatch-macros.h` provides `KPATCH_LOAD_HOOK` and `KPATCH_UNLOAD_HOOK` macros -to define such functions. The signature of both hook functions is `void -foo(void)`. Their execution context is as follows: +`kpatch-macros.h` defines the following macros that can be used to +register such callbacks: -* For patches to vmlinux or already loaded kernel modules, hook functions +* `KPATCH_PRE_PATCH_CALLBACK` - executed before patching +* `KPATCH_POST_PATCH_CALLBACK` - executed after patching +* `KPATCH_PRE_UNPATCH_CALLBACK` - executed before unpatching, complements the + post-patch callback. +* `KPATCH_POST_UNPATCH_CALLBACK` - executed after unpatching, complements the + pre-patch callback. + +A pre-patch callback routine has the following signature: + +``` +static int callback(patch_object *obj) { } +``` + +and any non-zero return status indicates failure to the kpatch core. For more +information on pre-patch callback failure, see the **Pre-patch return status** +section below. + +Post-patch, pre-unpatch, and post-unpatch callback routines all share the +following signature: + +``` +static void callback(patch_object *obj) { } +``` + +Generally pre-patch callbacks are paired with post-unpatch callbacks, meaning +that anything the former allocates or sets up should be torn down by the former +callback. Likewise for post-patch and pre-unpatch callbacks. + +#### Pre-patch return status + +If kpatch is currently patching already-loaded objects (vmlinux always by +definition as well as any currently loaded kernel modules), a non-zero pre-patch +callback status results in the kpatch core reverting the current +patch-in-progress. The kpatch-module is rejected, completely reverted, and +unloaded. + +If kpatch is patching a newly loaded kernel module, then a failing pre-patch +callback will only result in a WARN message. This is non-intuitive and a +deviation from livepatch callback behavior, but the result of a limitation of +kpatch and linux module notifiers. + +In both cases, if a pre-patch callback fails, none of its other callbacks will +be executed. + +#### Callback context + +* For patches to vmlinux or already loaded kernel modules, callback functions will be run by `stop_machine` as part of applying or removing a patch. -(Therefore the hooks must not block or sleep.) +(Therefore the callbacks must not block or sleep.) * For patches to kernel modules which haven't been loaded yet, a -module-notifier will execute load hooks when the associated module is loaded -into the `MODULE_STATE_COMING` state. The load hook is called before any -module_init code. - -Example: a kpatch fix for CVE-2016-5389 utilized the `KPATCH_LOAD_HOOK` and -`KPATCH_UNLOAD_HOOK` macros to modify variable `sysctl_tcp_challenge_ack_limit` -in-place: +module-notifier will execute callbacks when the associated module is loaded +into the `MODULE_STATE_COMING` state. The pre and post-patch callbacks +are called before any module_init code. + +Example: a kpatch fix for CVE-2016-5389 could utilize the +`KPATCH_PRE_PATCH_CALLBACK` and `KPATCH_POST_UNPATCH_CALLBACK` macros to modify +variable `sysctl_tcp_challenge_ack_limit` in-place: ``` ++#include "kpatch-macros.h" ++ +static bool kpatch_write = false; -+void kpatch_load_tcp_send_challenge_ack(void) ++static int kpatch_pre_patch_tcp_send_challenge_ack(patch_object *obj) +{ + if (sysctl_tcp_challenge_ack_limit == 100) { + sysctl_tcp_challenge_ack_limit = 1000; + kpatch_write = true; + } ++ return 0; +} -+void kpatch_unload_tcp_send_challenge_ack(void) +static void kpatch_post_unpatch_tcp_send_challenge_ack(patch_object *obj) +{ + if (kpatch_write && sysctl_tcp_challenge_ack_limit == 1000) + sysctl_tcp_challenge_ack_limit = 100; +} -+#include "kpatch-macros.h" -+KPATCH_LOAD_HOOK(kpatch_load_tcp_send_challenge_ack); -+KPATCH_UNLOAD_HOOK(kpatch_unload_tcp_send_challenge_ack); ++KPATCH_PRE_PATCH_CALLBACK(kpatch_pre_patch_tcp_send_challenge_ack); ++KPATCH_POST_UNPATCH_CALLBACK(kpatch_post_unpatch_tcp_send_challenge_ack); ``` -Don't forget to protect access to the data as needed. - -Also be careful when upgrading. If patch A has a load hook which writes to X, -and then you load patch B which is a superset of A, in some cases you may want -to prevent patch B from writing to X, if A is already loaded. +Don't forget to protect access to the data as needed. Please note that +spinlocks and mutexes / sleeping locks can't be used from stop_machine +context. Also note the pre-patch callback return code will be ignored by the +kernel's module notifier, so it does not affect the target module or livepatch +module status. This means: + +* Pre-patch callbacks to loaded objects (vmlinux, loaded kernel modules) are + run from stop_machine(), so they may only inspect lock state (i.e. + spin_is_locked(), mutex_is_locked()) and optionally return -EBUSY to prevent + patching. + +* Post-patch, pre-unpatch, and post-unpatch callbacks to loaded objects are + also run from stop_machine(), so the same locking context applies. No + return status is supported. + +* Deferred pre-patch callbacks to newly loading objects do not run from + stop_machine(), so they may spin or schedule, i.e. spin_lock(), + mutex_lock()). Return status is ignored. + +* Post-patch, pre-unpatch, and post-unpatch callbacks to unloading objects are + also *not* run from stop_machine(), so they may spin or sleep. No return + status is supported. + +Unfortunately there is no simple, all-case-inclusive kpatch callback +implementation that handles data structures and mutual exclusion. + +A few workarounds: + +1. If a given lock/mutex is held and released by the same set of functions +(that is, functions that take a lock/mutex always release it before +returning), a trivial change to those functions can re-purpose kpatch's +activeness safety check to avoid patching when the lock/mutex may be held. +This assumes that all lock/mutex holders can be patched. + +2. If it can be assured that all patch targets will be loaded before the +kpatch patch module, pre-patch callbacks may return -EBUSY if the lock/mutex +is held to block the patching. + +3. Finally, if a kpatch is disabled or removed and while all patch targets are +still loaded, then all unpatch callbacks will run from stop_machine() -- the +unpatching cannot be stopped at this point and the callbacks cannot spin or +sleep. + + With that in mind, it is probably easiest to omit unpatching callbacks +at this point. + +Also be careful when upgrading. If patch A has a pre/post-patch callback which +writes to X, and then you load patch B which is a superset of A, in some cases +you may want to prevent patch B from writing to X, if A is already loaded. ### Use a shadow variable @@ -339,7 +429,7 @@ Any code which runs in an `__init` function or during module or device initialization is problematic, as it may have already run before the patch was -applied. The patch may require a load hook function which detects whether such +applied. The patch may require a pre-patch callback which detects whether such init code has run, and which rewrites or changes the original initialization to force it into the desired state. Some changes involving hardware init are inherently incompatible with live patching. diff -Nru kpatch-0.5.0/.git/config kpatch-0.8.0/.git/config --- kpatch-0.5.0/.git/config 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/.git/config 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1,11 @@ +[core] + repositoryformatversion = 0 + filemode = true + bare = false + logallrefupdates = true +[remote "origin"] + url = https://github.com/dynup/kpatch.git + fetch = +refs/heads/*:refs/remotes/origin/* +[branch "master"] + remote = origin + merge = refs/heads/master diff -Nru kpatch-0.5.0/.git/description kpatch-0.8.0/.git/description --- kpatch-0.5.0/.git/description 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/.git/description 2019-08-28 17:33:59.000000000 +0000 @@ -0,0 +1 @@ +Unnamed repository; edit this file 'description' to name the repository. diff -Nru kpatch-0.5.0/.git/HEAD kpatch-0.8.0/.git/HEAD --- kpatch-0.5.0/.git/HEAD 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/.git/HEAD 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1 @@ +ref: refs/heads/master diff -Nru kpatch-0.5.0/.git/hooks/applypatch-msg.sample kpatch-0.8.0/.git/hooks/applypatch-msg.sample --- kpatch-0.5.0/.git/hooks/applypatch-msg.sample 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/.git/hooks/applypatch-msg.sample 2019-08-28 17:33:59.000000000 +0000 @@ -0,0 +1,15 @@ +#!/bin/sh +# +# An example hook script to check the commit log message taken by +# applypatch from an e-mail message. +# +# The hook should exit with non-zero status after issuing an +# appropriate message if it wants to stop the commit. The hook is +# allowed to edit the commit message file. +# +# To enable this hook, rename this file to "applypatch-msg". + +. git-sh-setup +commitmsg="$(git rev-parse --git-path hooks/commit-msg)" +test -x "$commitmsg" && exec "$commitmsg" ${1+"$@"} +: diff -Nru kpatch-0.5.0/.git/hooks/commit-msg.sample kpatch-0.8.0/.git/hooks/commit-msg.sample --- kpatch-0.5.0/.git/hooks/commit-msg.sample 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/.git/hooks/commit-msg.sample 2019-08-28 17:33:59.000000000 +0000 @@ -0,0 +1,24 @@ +#!/bin/sh +# +# An example hook script to check the commit log message. +# Called by "git commit" with one argument, the name of the file +# that has the commit message. The hook should exit with non-zero +# status after issuing an appropriate message if it wants to stop the +# commit. The hook is allowed to edit the commit message file. +# +# To enable this hook, rename this file to "commit-msg". + +# Uncomment the below to add a Signed-off-by line to the message. +# Doing this in a hook is a bad idea in general, but the prepare-commit-msg +# hook is more suited to it. +# +# SOB=$(git var GIT_AUTHOR_IDENT | sed -n 's/^\(.*>\).*$/Signed-off-by: \1/p') +# grep -qs "^$SOB" "$1" || echo "$SOB" >> "$1" + +# This example catches duplicate Signed-off-by lines. + +test "" = "$(grep '^Signed-off-by: ' "$1" | + sort | uniq -c | sed -e '/^[ ]*1[ ]/d')" || { + echo >&2 Duplicate Signed-off-by lines. + exit 1 +} diff -Nru kpatch-0.5.0/.git/hooks/fsmonitor-watchman.sample kpatch-0.8.0/.git/hooks/fsmonitor-watchman.sample --- kpatch-0.5.0/.git/hooks/fsmonitor-watchman.sample 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/.git/hooks/fsmonitor-watchman.sample 2019-08-28 17:33:59.000000000 +0000 @@ -0,0 +1,114 @@ +#!/usr/bin/perl + +use strict; +use warnings; +use IPC::Open2; + +# An example hook script to integrate Watchman +# (https://facebook.github.io/watchman/) with git to speed up detecting +# new and modified files. +# +# The hook is passed a version (currently 1) and a time in nanoseconds +# formatted as a string and outputs to stdout all files that have been +# modified since the given time. Paths must be relative to the root of +# the working tree and separated by a single NUL. +# +# To enable this hook, rename this file to "query-watchman" and set +# 'git config core.fsmonitor .git/hooks/query-watchman' +# +my ($version, $time) = @ARGV; + +# Check the hook interface version + +if ($version == 1) { + # convert nanoseconds to seconds + $time = int $time / 1000000000; +} else { + die "Unsupported query-fsmonitor hook version '$version'.\n" . + "Falling back to scanning...\n"; +} + +my $git_work_tree; +if ($^O =~ 'msys' || $^O =~ 'cygwin') { + $git_work_tree = Win32::GetCwd(); + $git_work_tree =~ tr/\\/\//; +} else { + require Cwd; + $git_work_tree = Cwd::cwd(); +} + +my $retry = 1; + +launch_watchman(); + +sub launch_watchman { + + my $pid = open2(\*CHLD_OUT, \*CHLD_IN, 'watchman -j --no-pretty') + or die "open2() failed: $!\n" . + "Falling back to scanning...\n"; + + # In the query expression below we're asking for names of files that + # changed since $time but were not transient (ie created after + # $time but no longer exist). + # + # To accomplish this, we're using the "since" generator to use the + # recency index to select candidate nodes and "fields" to limit the + # output to file names only. Then we're using the "expression" term to + # further constrain the results. + # + # The category of transient files that we want to ignore will have a + # creation clock (cclock) newer than $time_t value and will also not + # currently exist. + + my $query = <<" END"; + ["query", "$git_work_tree", { + "since": $time, + "fields": ["name"], + "expression": ["not", ["allof", ["since", $time, "cclock"], ["not", "exists"]]] + }] + END + + print CHLD_IN $query; + close CHLD_IN; + my $response = do {local $/; }; + + die "Watchman: command returned no output.\n" . + "Falling back to scanning...\n" if $response eq ""; + die "Watchman: command returned invalid output: $response\n" . + "Falling back to scanning...\n" unless $response =~ /^\{/; + + my $json_pkg; + eval { + require JSON::XS; + $json_pkg = "JSON::XS"; + 1; + } or do { + require JSON::PP; + $json_pkg = "JSON::PP"; + }; + + my $o = $json_pkg->new->utf8->decode($response); + + if ($retry > 0 and $o->{error} and $o->{error} =~ m/unable to resolve root .* directory (.*) is not watched/) { + print STDERR "Adding '$git_work_tree' to watchman's watch list.\n"; + $retry--; + qx/watchman watch "$git_work_tree"/; + die "Failed to make watchman watch '$git_work_tree'.\n" . + "Falling back to scanning...\n" if $? != 0; + + # Watchman will always return all files on the first query so + # return the fast "everything is dirty" flag to git and do the + # Watchman query just to get it over with now so we won't pay + # the cost in git to look up each individual file. + print "/\0"; + eval { launch_watchman() }; + exit 0; + } + + die "Watchman: $o->{error}.\n" . + "Falling back to scanning...\n" if $o->{error}; + + binmode STDOUT, ":utf8"; + local $, = "\0"; + print @{$o->{files}}; +} diff -Nru kpatch-0.5.0/.git/hooks/post-update.sample kpatch-0.8.0/.git/hooks/post-update.sample --- kpatch-0.5.0/.git/hooks/post-update.sample 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/.git/hooks/post-update.sample 2019-08-28 17:33:59.000000000 +0000 @@ -0,0 +1,8 @@ +#!/bin/sh +# +# An example hook script to prepare a packed repository for use over +# dumb transports. +# +# To enable this hook, rename this file to "post-update". + +exec git update-server-info diff -Nru kpatch-0.5.0/.git/hooks/pre-applypatch.sample kpatch-0.8.0/.git/hooks/pre-applypatch.sample --- kpatch-0.5.0/.git/hooks/pre-applypatch.sample 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/.git/hooks/pre-applypatch.sample 2019-08-28 17:33:59.000000000 +0000 @@ -0,0 +1,14 @@ +#!/bin/sh +# +# An example hook script to verify what is about to be committed +# by applypatch from an e-mail message. +# +# The hook should exit with non-zero status after issuing an +# appropriate message if it wants to stop the commit. +# +# To enable this hook, rename this file to "pre-applypatch". + +. git-sh-setup +precommit="$(git rev-parse --git-path hooks/pre-commit)" +test -x "$precommit" && exec "$precommit" ${1+"$@"} +: diff -Nru kpatch-0.5.0/.git/hooks/pre-commit.sample kpatch-0.8.0/.git/hooks/pre-commit.sample --- kpatch-0.5.0/.git/hooks/pre-commit.sample 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/.git/hooks/pre-commit.sample 2019-08-28 17:33:59.000000000 +0000 @@ -0,0 +1,49 @@ +#!/bin/sh +# +# An example hook script to verify what is about to be committed. +# Called by "git commit" with no arguments. The hook should +# exit with non-zero status after issuing an appropriate message if +# it wants to stop the commit. +# +# To enable this hook, rename this file to "pre-commit". + +if git rev-parse --verify HEAD >/dev/null 2>&1 +then + against=HEAD +else + # Initial commit: diff against an empty tree object + against=$(git hash-object -t tree /dev/null) +fi + +# If you want to allow non-ASCII filenames set this variable to true. +allownonascii=$(git config --bool hooks.allownonascii) + +# Redirect output to stderr. +exec 1>&2 + +# Cross platform projects tend to avoid non-ASCII filenames; prevent +# them from being added to the repository. We exploit the fact that the +# printable range starts at the space character and ends with tilde. +if [ "$allownonascii" != "true" ] && + # Note that the use of brackets around a tr range is ok here, (it's + # even required, for portability to Solaris 10's /usr/bin/tr), since + # the square bracket bytes happen to fall in the designated range. + test $(git diff --cached --name-only --diff-filter=A -z $against | + LC_ALL=C tr -d '[ -~]\0' | wc -c) != 0 +then + cat <<\EOF +Error: Attempt to add a non-ASCII file name. + +This can cause problems if you want to work with people on other platforms. + +To be portable it is advisable to rename the file. + +If you know what you are doing you can disable this check using: + + git config hooks.allownonascii true +EOF + exit 1 +fi + +# If there are whitespace errors, print the offending file names and fail. +exec git diff-index --check --cached $against -- diff -Nru kpatch-0.5.0/.git/hooks/prepare-commit-msg.sample kpatch-0.8.0/.git/hooks/prepare-commit-msg.sample --- kpatch-0.5.0/.git/hooks/prepare-commit-msg.sample 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/.git/hooks/prepare-commit-msg.sample 2019-08-28 17:33:59.000000000 +0000 @@ -0,0 +1,42 @@ +#!/bin/sh +# +# An example hook script to prepare the commit log message. +# Called by "git commit" with the name of the file that has the +# commit message, followed by the description of the commit +# message's source. The hook's purpose is to edit the commit +# message file. If the hook fails with a non-zero status, +# the commit is aborted. +# +# To enable this hook, rename this file to "prepare-commit-msg". + +# This hook includes three examples. The first one removes the +# "# Please enter the commit message..." help message. +# +# The second includes the output of "git diff --name-status -r" +# into the message, just before the "git status" output. It is +# commented because it doesn't cope with --amend or with squashed +# commits. +# +# The third example adds a Signed-off-by line to the message, that can +# still be edited. This is rarely a good idea. + +COMMIT_MSG_FILE=$1 +COMMIT_SOURCE=$2 +SHA1=$3 + +/usr/bin/perl -i.bak -ne 'print unless(m/^. Please enter the commit message/..m/^#$/)' "$COMMIT_MSG_FILE" + +# case "$COMMIT_SOURCE,$SHA1" in +# ,|template,) +# /usr/bin/perl -i.bak -pe ' +# print "\n" . `git diff --cached --name-status -r` +# if /^#/ && $first++ == 0' "$COMMIT_MSG_FILE" ;; +# *) ;; +# esac + +# SOB=$(git var GIT_COMMITTER_IDENT | sed -n 's/^\(.*>\).*$/Signed-off-by: \1/p') +# git interpret-trailers --in-place --trailer "$SOB" "$COMMIT_MSG_FILE" +# if test -z "$COMMIT_SOURCE" +# then +# /usr/bin/perl -i.bak -pe 'print "\n" if !$first_line++' "$COMMIT_MSG_FILE" +# fi diff -Nru kpatch-0.5.0/.git/hooks/pre-push.sample kpatch-0.8.0/.git/hooks/pre-push.sample --- kpatch-0.5.0/.git/hooks/pre-push.sample 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/.git/hooks/pre-push.sample 2019-08-28 17:33:59.000000000 +0000 @@ -0,0 +1,53 @@ +#!/bin/sh + +# An example hook script to verify what is about to be pushed. Called by "git +# push" after it has checked the remote status, but before anything has been +# pushed. If this script exits with a non-zero status nothing will be pushed. +# +# This hook is called with the following parameters: +# +# $1 -- Name of the remote to which the push is being done +# $2 -- URL to which the push is being done +# +# If pushing without using a named remote those arguments will be equal. +# +# Information about the commits which are being pushed is supplied as lines to +# the standard input in the form: +# +# +# +# This sample shows how to prevent push of commits where the log message starts +# with "WIP" (work in progress). + +remote="$1" +url="$2" + +z40=0000000000000000000000000000000000000000 + +while read local_ref local_sha remote_ref remote_sha +do + if [ "$local_sha" = $z40 ] + then + # Handle delete + : + else + if [ "$remote_sha" = $z40 ] + then + # New branch, examine all commits + range="$local_sha" + else + # Update to existing branch, examine new commits + range="$remote_sha..$local_sha" + fi + + # Check for WIP commit + commit=`git rev-list -n 1 --grep '^WIP' "$range"` + if [ -n "$commit" ] + then + echo >&2 "Found WIP commit in $local_ref, not pushing" + exit 1 + fi + fi +done + +exit 0 diff -Nru kpatch-0.5.0/.git/hooks/pre-rebase.sample kpatch-0.8.0/.git/hooks/pre-rebase.sample --- kpatch-0.5.0/.git/hooks/pre-rebase.sample 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/.git/hooks/pre-rebase.sample 2019-08-28 17:33:59.000000000 +0000 @@ -0,0 +1,169 @@ +#!/bin/sh +# +# Copyright (c) 2006, 2008 Junio C Hamano +# +# The "pre-rebase" hook is run just before "git rebase" starts doing +# its job, and can prevent the command from running by exiting with +# non-zero status. +# +# The hook is called with the following parameters: +# +# $1 -- the upstream the series was forked from. +# $2 -- the branch being rebased (or empty when rebasing the current branch). +# +# This sample shows how to prevent topic branches that are already +# merged to 'next' branch from getting rebased, because allowing it +# would result in rebasing already published history. + +publish=next +basebranch="$1" +if test "$#" = 2 +then + topic="refs/heads/$2" +else + topic=`git symbolic-ref HEAD` || + exit 0 ;# we do not interrupt rebasing detached HEAD +fi + +case "$topic" in +refs/heads/??/*) + ;; +*) + exit 0 ;# we do not interrupt others. + ;; +esac + +# Now we are dealing with a topic branch being rebased +# on top of master. Is it OK to rebase it? + +# Does the topic really exist? +git show-ref -q "$topic" || { + echo >&2 "No such branch $topic" + exit 1 +} + +# Is topic fully merged to master? +not_in_master=`git rev-list --pretty=oneline ^master "$topic"` +if test -z "$not_in_master" +then + echo >&2 "$topic is fully merged to master; better remove it." + exit 1 ;# we could allow it, but there is no point. +fi + +# Is topic ever merged to next? If so you should not be rebasing it. +only_next_1=`git rev-list ^master "^$topic" ${publish} | sort` +only_next_2=`git rev-list ^master ${publish} | sort` +if test "$only_next_1" = "$only_next_2" +then + not_in_topic=`git rev-list "^$topic" master` + if test -z "$not_in_topic" + then + echo >&2 "$topic is already up to date with master" + exit 1 ;# we could allow it, but there is no point. + else + exit 0 + fi +else + not_in_next=`git rev-list --pretty=oneline ^${publish} "$topic"` + /usr/bin/perl -e ' + my $topic = $ARGV[0]; + my $msg = "* $topic has commits already merged to public branch:\n"; + my (%not_in_next) = map { + /^([0-9a-f]+) /; + ($1 => 1); + } split(/\n/, $ARGV[1]); + for my $elem (map { + /^([0-9a-f]+) (.*)$/; + [$1 => $2]; + } split(/\n/, $ARGV[2])) { + if (!exists $not_in_next{$elem->[0]}) { + if ($msg) { + print STDERR $msg; + undef $msg; + } + print STDERR " $elem->[1]\n"; + } + } + ' "$topic" "$not_in_next" "$not_in_master" + exit 1 +fi + +<<\DOC_END + +This sample hook safeguards topic branches that have been +published from being rewound. + +The workflow assumed here is: + + * Once a topic branch forks from "master", "master" is never + merged into it again (either directly or indirectly). + + * Once a topic branch is fully cooked and merged into "master", + it is deleted. If you need to build on top of it to correct + earlier mistakes, a new topic branch is created by forking at + the tip of the "master". This is not strictly necessary, but + it makes it easier to keep your history simple. + + * Whenever you need to test or publish your changes to topic + branches, merge them into "next" branch. + +The script, being an example, hardcodes the publish branch name +to be "next", but it is trivial to make it configurable via +$GIT_DIR/config mechanism. + +With this workflow, you would want to know: + +(1) ... if a topic branch has ever been merged to "next". Young + topic branches can have stupid mistakes you would rather + clean up before publishing, and things that have not been + merged into other branches can be easily rebased without + affecting other people. But once it is published, you would + not want to rewind it. + +(2) ... if a topic branch has been fully merged to "master". + Then you can delete it. More importantly, you should not + build on top of it -- other people may already want to + change things related to the topic as patches against your + "master", so if you need further changes, it is better to + fork the topic (perhaps with the same name) afresh from the + tip of "master". + +Let's look at this example: + + o---o---o---o---o---o---o---o---o---o "next" + / / / / + / a---a---b A / / + / / / / + / / c---c---c---c B / + / / / \ / + / / / b---b C \ / + / / / / \ / + ---o---o---o---o---o---o---o---o---o---o---o "master" + + +A, B and C are topic branches. + + * A has one fix since it was merged up to "next". + + * B has finished. It has been fully merged up to "master" and "next", + and is ready to be deleted. + + * C has not merged to "next" at all. + +We would want to allow C to be rebased, refuse A, and encourage +B to be deleted. + +To compute (1): + + git rev-list ^master ^topic next + git rev-list ^master next + + if these match, topic has not merged in next at all. + +To compute (2): + + git rev-list master..topic + + if this is empty, it is fully merged to "master". + +DOC_END diff -Nru kpatch-0.5.0/.git/hooks/pre-receive.sample kpatch-0.8.0/.git/hooks/pre-receive.sample --- kpatch-0.5.0/.git/hooks/pre-receive.sample 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/.git/hooks/pre-receive.sample 2019-08-28 17:33:59.000000000 +0000 @@ -0,0 +1,24 @@ +#!/bin/sh +# +# An example hook script to make use of push options. +# The example simply echoes all push options that start with 'echoback=' +# and rejects all pushes when the "reject" push option is used. +# +# To enable this hook, rename this file to "pre-receive". + +if test -n "$GIT_PUSH_OPTION_COUNT" +then + i=0 + while test "$i" -lt "$GIT_PUSH_OPTION_COUNT" + do + eval "value=\$GIT_PUSH_OPTION_$i" + case "$value" in + echoback=*) + echo "echo from the pre-receive-hook: ${value#*=}" >&2 + ;; + reject) + exit 1 + esac + i=$((i + 1)) + done +fi diff -Nru kpatch-0.5.0/.git/hooks/update.sample kpatch-0.8.0/.git/hooks/update.sample --- kpatch-0.5.0/.git/hooks/update.sample 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/.git/hooks/update.sample 2019-08-28 17:33:59.000000000 +0000 @@ -0,0 +1,128 @@ +#!/bin/sh +# +# An example hook script to block unannotated tags from entering. +# Called by "git receive-pack" with arguments: refname sha1-old sha1-new +# +# To enable this hook, rename this file to "update". +# +# Config +# ------ +# hooks.allowunannotated +# This boolean sets whether unannotated tags will be allowed into the +# repository. By default they won't be. +# hooks.allowdeletetag +# This boolean sets whether deleting tags will be allowed in the +# repository. By default they won't be. +# hooks.allowmodifytag +# This boolean sets whether a tag may be modified after creation. By default +# it won't be. +# hooks.allowdeletebranch +# This boolean sets whether deleting branches will be allowed in the +# repository. By default they won't be. +# hooks.denycreatebranch +# This boolean sets whether remotely creating branches will be denied +# in the repository. By default this is allowed. +# + +# --- Command line +refname="$1" +oldrev="$2" +newrev="$3" + +# --- Safety check +if [ -z "$GIT_DIR" ]; then + echo "Don't run this script from the command line." >&2 + echo " (if you want, you could supply GIT_DIR then run" >&2 + echo " $0 )" >&2 + exit 1 +fi + +if [ -z "$refname" -o -z "$oldrev" -o -z "$newrev" ]; then + echo "usage: $0 " >&2 + exit 1 +fi + +# --- Config +allowunannotated=$(git config --bool hooks.allowunannotated) +allowdeletebranch=$(git config --bool hooks.allowdeletebranch) +denycreatebranch=$(git config --bool hooks.denycreatebranch) +allowdeletetag=$(git config --bool hooks.allowdeletetag) +allowmodifytag=$(git config --bool hooks.allowmodifytag) + +# check for no description +projectdesc=$(sed -e '1q' "$GIT_DIR/description") +case "$projectdesc" in +"Unnamed repository"* | "") + echo "*** Project description file hasn't been set" >&2 + exit 1 + ;; +esac + +# --- Check types +# if $newrev is 0000...0000, it's a commit to delete a ref. +zero="0000000000000000000000000000000000000000" +if [ "$newrev" = "$zero" ]; then + newrev_type=delete +else + newrev_type=$(git cat-file -t $newrev) +fi + +case "$refname","$newrev_type" in + refs/tags/*,commit) + # un-annotated tag + short_refname=${refname##refs/tags/} + if [ "$allowunannotated" != "true" ]; then + echo "*** The un-annotated tag, $short_refname, is not allowed in this repository" >&2 + echo "*** Use 'git tag [ -a | -s ]' for tags you want to propagate." >&2 + exit 1 + fi + ;; + refs/tags/*,delete) + # delete tag + if [ "$allowdeletetag" != "true" ]; then + echo "*** Deleting a tag is not allowed in this repository" >&2 + exit 1 + fi + ;; + refs/tags/*,tag) + # annotated tag + if [ "$allowmodifytag" != "true" ] && git rev-parse $refname > /dev/null 2>&1 + then + echo "*** Tag '$refname' already exists." >&2 + echo "*** Modifying a tag is not allowed in this repository." >&2 + exit 1 + fi + ;; + refs/heads/*,commit) + # branch + if [ "$oldrev" = "$zero" -a "$denycreatebranch" = "true" ]; then + echo "*** Creating a branch is not allowed in this repository" >&2 + exit 1 + fi + ;; + refs/heads/*,delete) + # delete branch + if [ "$allowdeletebranch" != "true" ]; then + echo "*** Deleting a branch is not allowed in this repository" >&2 + exit 1 + fi + ;; + refs/remotes/*,commit) + # tracking branch + ;; + refs/remotes/*,delete) + # delete tracking branch + if [ "$allowdeletebranch" != "true" ]; then + echo "*** Deleting a tracking branch is not allowed in this repository" >&2 + exit 1 + fi + ;; + *) + # Anything else (is there anything else?) + echo "*** Update hook: unknown type of update to ref $refname of type $newrev_type" >&2 + exit 1 + ;; +esac + +# --- Finished +exit 0 Binary files /tmp/tmpBdNVYc/KTsX7THi47/kpatch-0.5.0/.git/index and /tmp/tmpBdNVYc/Msn2LiqoFe/kpatch-0.8.0/.git/index differ diff -Nru kpatch-0.5.0/.git/info/exclude kpatch-0.8.0/.git/info/exclude --- kpatch-0.5.0/.git/info/exclude 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/.git/info/exclude 2019-08-28 17:33:59.000000000 +0000 @@ -0,0 +1,6 @@ +# git ls-files --others --exclude-from=.git/info/exclude +# Lines that start with '#' are comments. +# For a project mostly in C, the following would be a good set of +# exclude patterns (uncomment them if you want to use them): +# *.[oa] +# *~ diff -Nru kpatch-0.5.0/.git/logs/HEAD kpatch-0.8.0/.git/logs/HEAD --- kpatch-0.5.0/.git/logs/HEAD 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/.git/logs/HEAD 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1 @@ +0000000000000000000000000000000000000000 30a7dd677bcc25bd70070f7f9d16a88c190b8b0b Benjamin M Romer 1567013640 -0400 clone: from https://github.com/dynup/kpatch.git diff -Nru kpatch-0.5.0/.git/logs/refs/heads/master kpatch-0.8.0/.git/logs/refs/heads/master --- kpatch-0.5.0/.git/logs/refs/heads/master 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/.git/logs/refs/heads/master 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1 @@ +0000000000000000000000000000000000000000 30a7dd677bcc25bd70070f7f9d16a88c190b8b0b Benjamin M Romer 1567013640 -0400 clone: from https://github.com/dynup/kpatch.git diff -Nru kpatch-0.5.0/.git/logs/refs/remotes/origin/HEAD kpatch-0.8.0/.git/logs/refs/remotes/origin/HEAD --- kpatch-0.5.0/.git/logs/refs/remotes/origin/HEAD 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/.git/logs/refs/remotes/origin/HEAD 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1 @@ +0000000000000000000000000000000000000000 30a7dd677bcc25bd70070f7f9d16a88c190b8b0b Benjamin M Romer 1567013640 -0400 clone: from https://github.com/dynup/kpatch.git Binary files /tmp/tmpBdNVYc/KTsX7THi47/kpatch-0.5.0/.git/objects/pack/pack-222482408f1d0647adf58c83080fb8ab67c7d423.idx and /tmp/tmpBdNVYc/Msn2LiqoFe/kpatch-0.8.0/.git/objects/pack/pack-222482408f1d0647adf58c83080fb8ab67c7d423.idx differ Binary files /tmp/tmpBdNVYc/KTsX7THi47/kpatch-0.5.0/.git/objects/pack/pack-222482408f1d0647adf58c83080fb8ab67c7d423.pack and /tmp/tmpBdNVYc/Msn2LiqoFe/kpatch-0.8.0/.git/objects/pack/pack-222482408f1d0647adf58c83080fb8ab67c7d423.pack differ diff -Nru kpatch-0.5.0/.git/packed-refs kpatch-0.8.0/.git/packed-refs --- kpatch-0.5.0/.git/packed-refs 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/.git/packed-refs 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1,31 @@ +# pack-refs with: peeled fully-peeled sorted +30a7dd677bcc25bd70070f7f9d16a88c190b8b0b refs/remotes/origin/master +258ac3f39a14d52d73868d24770b5b6f5786eca2 refs/tags/0.5.0 +135b438af0b9c9d903b01b3386c74add1401dda1 refs/tags/v0.1.0 +0f3f8ae3369cec5be61c73bf559a8df0c82f9df4 refs/tags/v0.1.1 +6ed046f1c2a770099ae984e305fc2260480749f0 refs/tags/v0.1.10 +2601b154d3351b3411043fcff4ccd71fbb039e1d refs/tags/v0.1.2 +a705c223fc6efa87a8d7521c791e9515ad6d981c refs/tags/v0.1.3 +3ca8106987bad32dcc60ff9c54d687b92033c0c1 refs/tags/v0.1.4 +f4bba70412801a475eed21087e2dd8cae6b94996 refs/tags/v0.1.5 +92fb49e6f2ec98684b35df6f50976e25fa8eced8 refs/tags/v0.1.6 +44ad2ba733063438616ecbf4222da5caebd62a6e refs/tags/v0.1.7 +576ee094420918c6d431d9d97b135046f138e919 refs/tags/v0.1.8 +ce8bb40fc06cc2cd6c4d02199ee3a895bfadb551 refs/tags/v0.1.9 +688a03d8b629287a5ffb501bfa28dd9a3781e10f refs/tags/v0.2.0 +0fd7f7f0be4287e95af4d2c69e57865fea63dcb1 refs/tags/v0.2.1 +f817265c5adbc11b71f853b804cfacd6ab85db7c refs/tags/v0.2.2 +f4b5eded0c14ef4f2d6b6d801f1519659e84e217 refs/tags/v0.3.0 +b60d3acddb7b96b3b6dd7a4c519189a05b0a4d18 refs/tags/v0.3.1 +706b63ad99cc00c539970961b1950da303cb1f3b refs/tags/v0.3.2 +fa557bd11da59a9a4aea20f3a74125ead2477792 refs/tags/v0.3.3 +4e1a5962dabf08b6aefe2584c28d26fc594e8fb6 refs/tags/v0.3.4 +810f9243826219cca9276d364512bb88411aa863 refs/tags/v0.4.0 +258ac3f39a14d52d73868d24770b5b6f5786eca2 refs/tags/v0.5.0 +d5eb921af14b707079ce70809ad64eddfdb1f00f refs/tags/v0.6.0 +7f550f01bd308cf058ae782327d29c8916cc5602 refs/tags/v0.6.1 +7305d6c29a45594c44036601e42909b5e5132bdc refs/tags/v0.6.2 +f4ed9ff76997114ed838a3b964508d721f19f293 refs/tags/v0.6.3 +535e91767900c12ccd49eb5c9fe1732a0c1d85bb refs/tags/v0.7.0 +d7c5810e2a6acacfa5fec1e38d2f75af8e8c818c refs/tags/v0.7.1 +2a29bc7dea9a7da12705c7b50315eee1acdd9156 refs/tags/v0.8.0 diff -Nru kpatch-0.5.0/.git/refs/heads/master kpatch-0.8.0/.git/refs/heads/master --- kpatch-0.5.0/.git/refs/heads/master 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/.git/refs/heads/master 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1 @@ +30a7dd677bcc25bd70070f7f9d16a88c190b8b0b diff -Nru kpatch-0.5.0/.git/refs/remotes/origin/HEAD kpatch-0.8.0/.git/refs/remotes/origin/HEAD --- kpatch-0.5.0/.git/refs/remotes/origin/HEAD 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/.git/refs/remotes/origin/HEAD 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1 @@ +ref: refs/remotes/origin/master diff -Nru kpatch-0.5.0/.gitignore kpatch-0.8.0/.gitignore --- kpatch-0.5.0/.gitignore 2017-12-21 05:02:48.000000000 +0000 +++ kpatch-0.8.0/.gitignore 2019-08-28 17:34:00.000000000 +0000 @@ -9,6 +9,7 @@ *.so .tmp_versions Module.symvers +kmod/core/.cache.mk kpatch-build/lookup kpatch-build/create-diff-object kpatch-build/create-klp-module diff -Nru kpatch-0.5.0/.gitmodules kpatch-0.8.0/.gitmodules --- kpatch-0.5.0/.gitmodules 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/.gitmodules 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1,3 @@ +[submodule "test/unit/objs"] + path = test/unit/objs + url = https://github.com/dynup/kpatch-unit-test-objs.git diff -Nru kpatch-0.5.0/kmod/core/core.c kpatch-0.8.0/kmod/core/core.c --- kpatch-0.5.0/kmod/core/core.c 2017-12-21 05:02:48.000000000 +0000 +++ kpatch-0.8.0/kmod/core/core.c 2019-08-28 17:34:00.000000000 +0000 @@ -58,6 +58,7 @@ !defined(CONFIG_HAVE_FENTRY) || \ !defined(CONFIG_MODULES) || \ !defined(CONFIG_SYSFS) || \ + !defined(CONFIG_STACKTRACE) || \ !defined(CONFIG_KALLSYMS_ALL) #error "CONFIG_FUNCTION_TRACER, CONFIG_HAVE_FENTRY, CONFIG_MODULES, CONFIG_SYSFS, CONFIG_KALLSYMS_ALL kernel config options are required" #endif @@ -82,6 +83,11 @@ unsigned long pos; }; +struct kpatch_apply_patch_args { + struct kpatch_module *kpmod; + bool replace; +}; + /* this is a double loop, use goto instead of break */ #define do_for_each_linked_func(kpmod, func) { \ struct kpatch_object *_object; \ @@ -139,7 +145,7 @@ #define MAX_STACK_TRACE_DEPTH 64 static unsigned long stack_entries[MAX_STACK_TRACE_DEPTH]; -struct stack_trace trace = { +static struct stack_trace trace = { .max_entries = ARRAY_SIZE(stack_entries), .entries = &stack_entries[0], }; @@ -206,7 +212,8 @@ } static int kpatch_backtrace_address_verify(struct kpatch_module *kpmod, - unsigned long address) + unsigned long address, + bool replace) { struct kpatch_func *func; int i; @@ -241,8 +248,11 @@ } while_for_each_linked_func(); /* in the replace case, need to check the func hash as well */ - hash_for_each_rcu(kpatch_func_hash, i, func, node) { - if (func->op == KPATCH_OP_UNPATCH && !func->force) { + if (replace) { + hash_for_each_rcu(kpatch_func_hash, i, func, node) { + if (func->op != KPATCH_OP_UNPATCH || func->force) + continue; + ret = kpatch_compare_addresses(address, func->new_addr, func->new_size, @@ -261,7 +271,8 @@ * * This function is called from stop_machine() context. */ -static int kpatch_verify_activeness_safety(struct kpatch_module *kpmod) +static int kpatch_verify_activeness_safety(struct kpatch_module *kpmod, + bool replace) { struct task_struct *g, *t; int i; @@ -283,7 +294,8 @@ if (trace.entries[i] == ULONG_MAX) break; ret = kpatch_backtrace_address_verify(kpmod, - trace.entries[i]); + trace.entries[i], + replace); if (ret) goto out; } @@ -305,21 +317,76 @@ return ret; } +static inline int pre_patch_callback(struct kpatch_object *object) +{ + int ret; + + if (kpatch_object_linked(object) && + object->pre_patch_callback) { + ret = (*object->pre_patch_callback)(object); + if (ret) { + object->callbacks_enabled = false; + return ret; + } + } + object->callbacks_enabled = true; + + return 0; +} + +static inline void post_patch_callback(struct kpatch_object *object) +{ + if (kpatch_object_linked(object) && + object->post_patch_callback && + object->callbacks_enabled) + (*object->post_patch_callback)(object); +} + +static inline void pre_unpatch_callback(struct kpatch_object *object) +{ + if (kpatch_object_linked(object) && + object->pre_unpatch_callback && + object->callbacks_enabled) + (*object->pre_unpatch_callback)(object); +} + +static inline void post_unpatch_callback(struct kpatch_object *object) +{ + if (kpatch_object_linked(object) && + object->post_unpatch_callback && + object->callbacks_enabled) + (*object->post_unpatch_callback)(object); +} + /* Called from stop_machine */ static int kpatch_apply_patch(void *data) { - struct kpatch_module *kpmod = data; + struct kpatch_apply_patch_args *args = data; + struct kpatch_module *kpmod; struct kpatch_func *func; - struct kpatch_hook *hook; + struct hlist_node *tmp; struct kpatch_object *object; int ret; + int i; - ret = kpatch_verify_activeness_safety(kpmod); + kpmod = args->kpmod; + + ret = kpatch_verify_activeness_safety(kpmod, args->replace); if (ret) { kpatch_state_finish(KPATCH_STATE_FAILURE); return ret; } + /* run any user-defined pre-patch callbacks */ + list_for_each_entry(object, &kpmod->objects, list) { + ret = pre_patch_callback(object); + if (ret) { + pr_err("pre-patch callback failed!\n"); + kpatch_state_finish(KPATCH_STATE_FAILURE); + goto err; + } + } + /* tentatively add the new funcs to the global func hash */ do_for_each_linked_func(kpmod, func) { hash_add_rcu(kpatch_func_hash, &func->node, func->old_addr); @@ -341,19 +408,34 @@ hash_del_rcu(&func->node); } while_for_each_linked_func(); - return -EBUSY; + ret = -EBUSY; + goto err; } - /* run any user-defined load hooks */ - list_for_each_entry(object, &kpmod->objects, list) { - if (!kpatch_object_linked(object)) - continue; - list_for_each_entry(hook, &object->hooks_load, list) - (*hook->hook)(); + /* + * The new patch has been applied successfully. Remove the functions + * provided by the replaced patches (if any) from hash, to make sure + * they will not be executed anymore. + */ + if (args->replace) { + hash_for_each_safe(kpatch_func_hash, i, tmp, func, node) { + if (func->op != KPATCH_OP_UNPATCH) + continue; + hash_del_rcu(&func->node); + } } + /* run any user-defined post-patch callbacks */ + list_for_each_entry(object, &kpmod->objects, list) + post_patch_callback(object); return 0; +err: + /* undo pre-patch callbacks by calling post-unpatch counterparts */ + list_for_each_entry(object, &kpmod->objects, list) + post_unpatch_callback(object); + + return ret; } /* Called from stop_machine */ @@ -361,35 +443,43 @@ { struct kpatch_module *kpmod = data; struct kpatch_func *func; - struct kpatch_hook *hook; struct kpatch_object *object; int ret; - ret = kpatch_verify_activeness_safety(kpmod); + ret = kpatch_verify_activeness_safety(kpmod, false); if (ret) { kpatch_state_finish(KPATCH_STATE_FAILURE); return ret; } + /* run any user-defined pre-unpatch callbacks */ + list_for_each_entry(object, &kpmod->objects, list) + pre_unpatch_callback(object); + /* Check if any inconsistent NMI has happened while updating */ ret = kpatch_state_finish(KPATCH_STATE_SUCCESS); - if (ret == KPATCH_STATE_FAILURE) - return -EBUSY; + if (ret == KPATCH_STATE_FAILURE) { + ret = -EBUSY; + goto err; + } /* Succeeded, remove all updating funcs from hash table */ do_for_each_linked_func(kpmod, func) { hash_del_rcu(&func->node); } while_for_each_linked_func(); - /* run any user-defined unload hooks */ - list_for_each_entry(object, &kpmod->objects, list) { - if (!kpatch_object_linked(object)) - continue; - list_for_each_entry(hook, &object->hooks_unload, list) - (*hook->hook)(); - } + /* run any user-defined post-unpatch callbacks */ + list_for_each_entry(object, &kpmod->objects, list) + post_unpatch_callback(object); return 0; + +err: + /* undo pre-unpatch callbacks by calling post-patch counterparts */ + list_for_each_entry(object, &kpmod->objects, list) + post_patch_callback(object); + + return ret; } /* @@ -590,7 +680,11 @@ sym = find_symbol(name, NULL, NULL, true, true); preempt_enable(); if (sym) { +#ifdef CONFIG_HAVE_ARCH_PREL32_RELOCATIONS + *addr = (unsigned long)offset_to_ptr(&sym->value_offset); +#else *addr = sym->value; +#endif return 0; } @@ -635,6 +729,7 @@ case R_X86_64_NONE: continue; case R_X86_64_PC32: + case R_X86_64_PLT32: loc = dynrela->dest; val = (u32)(dynrela->src + dynrela->addend - dynrela->dest); @@ -723,8 +818,10 @@ } } - if (object->mod) + if (object->mod) { module_put(object->mod); + object->mod = NULL; + } return 0; } @@ -801,14 +898,13 @@ return ret; } -static int kpatch_module_notify(struct notifier_block *nb, unsigned long action, - void *data) +static int kpatch_module_notify_coming(struct notifier_block *nb, + unsigned long action, void *data) { struct module *mod = data; struct kpatch_module *kpmod; struct kpatch_object *object; struct kpatch_func *func; - struct kpatch_hook *hook; int ret = 0; bool found = false; @@ -839,29 +935,110 @@ pr_notice("patching newly loaded module '%s'\n", object->name); - /* run any user-defined load hooks */ - list_for_each_entry(hook, &object->hooks_load, list) - (*hook->hook)(); + /* run user-defined pre-patch callback */ + ret = pre_patch_callback(object); + if (ret) { + pr_err("pre-patch callback failed!\n"); + goto out; /* and WARN */ + } /* add to the global func hash */ list_for_each_entry(func, &object->funcs, list) hash_add_rcu(kpatch_func_hash, &func->node, func->old_addr); + /* run user-defined post-patch callback */ + post_patch_callback(object); out: up(&kpatch_mutex); /* no way to stop the module load on error */ WARN(ret, "error (%d) patching newly loaded module '%s'\n", ret, object->name); + + return 0; +} + +static int kpatch_module_notify_going(struct notifier_block *nb, + unsigned long action, void *data) +{ + struct module *mod = data; + struct kpatch_module *kpmod; + struct kpatch_object *object; + struct kpatch_func *func; + bool found = false; + + if (action != MODULE_STATE_GOING) + return 0; + + down(&kpatch_mutex); + + list_for_each_entry(kpmod, &kpmod_list, list) { + list_for_each_entry(object, &kpmod->objects, list) { + if (!kpatch_object_linked(object)) + continue; + if (!strcmp(object->name, mod->name)) { + found = true; + goto done; + } + } + } +done: + if (!found) + goto out; + + /* run user-defined pre-unpatch callback */ + pre_unpatch_callback(object); + + /* remove from the global func hash */ + list_for_each_entry(func, &object->funcs, list) + hash_del_rcu(&func->node); + + /* run user-defined pre-unpatch callback */ + post_unpatch_callback(object); + + kpatch_unlink_object(object); + +out: + up(&kpatch_mutex); + return 0; } +/* + * Remove the obsolete functions from the ftrace filter. + * Return 1 if one or more of such functions have 'force' flag set, + * 0 otherwise. + */ +static int kpatch_ftrace_remove_unpatched_funcs(void) +{ + struct kpatch_module *kpmod; + struct kpatch_func *func; + int force = 0; + + list_for_each_entry(kpmod, &kpmod_list, list) { + do_for_each_linked_func(kpmod, func) { + if (func->op != KPATCH_OP_UNPATCH) + continue; + if (func->force) + force = 1; + WARN_ON(kpatch_ftrace_remove_func(func->old_addr)); + } while_for_each_linked_func(); + } + + return force; +} + int kpatch_register(struct kpatch_module *kpmod, bool replace) { - int ret, i, force = 0; + int ret, i; struct kpatch_object *object, *object_err = NULL; struct kpatch_func *func; + struct kpatch_apply_patch_args args = { + .kpmod = kpmod, + .replace = replace, + }; + if (!kpmod->mod || list_empty(&kpmod->objects)) return -EINVAL; @@ -913,24 +1090,18 @@ * Idle the CPUs, verify activeness safety, and atomically make the new * functions visible to the ftrace handler. */ - ret = stop_machine(kpatch_apply_patch, kpmod, NULL); + ret = stop_machine(kpatch_apply_patch, &args, NULL); /* - * For the replace case, remove any obsolete funcs from the hash and - * the ftrace filter, and disable the owning patch module so that it - * can be removed. + * For the replace case, remove any obsolete funcs from the ftrace + * filter, and disable the owning patch module so that it can be + * removed. */ if (!ret && replace) { struct kpatch_module *kpmod2, *safe; + int force; - hash_for_each_rcu(kpatch_func_hash, i, func, node) { - if (func->op != KPATCH_OP_UNPATCH) - continue; - if (func->force) - force = 1; - hash_del_rcu(&func->node); - WARN_ON(kpatch_ftrace_remove_func(func->old_addr)); - } + force = kpatch_ftrace_remove_unpatched_funcs(); list_for_each_entry_safe(kpmod2, safe, &kpmod_list, list) { if (kpmod == kpmod2) @@ -1100,10 +1271,14 @@ EXPORT_SYMBOL(kpatch_unregister); -static struct notifier_block kpatch_module_nb = { - .notifier_call = kpatch_module_notify, +static struct notifier_block kpatch_module_nb_coming = { + .notifier_call = kpatch_module_notify_coming, .priority = INT_MIN, /* called last */ }; +static struct notifier_block kpatch_module_nb_going = { + .notifier_call = kpatch_module_notify_going, + .priority = INT_MAX, /* called first */ +}; static int kpatch_init(void) { @@ -1125,12 +1300,17 @@ if (!kpatch_root_kobj) return -ENOMEM; - ret = register_module_notifier(&kpatch_module_nb); + ret = register_module_notifier(&kpatch_module_nb_coming); if (ret) goto err_root_kobj; + ret = register_module_notifier(&kpatch_module_nb_going); + if (ret) + goto err_unregister_coming; return 0; +err_unregister_coming: + WARN_ON(unregister_module_notifier(&kpatch_module_nb_coming)); err_root_kobj: kobject_put(kpatch_root_kobj); return ret; @@ -1141,7 +1321,8 @@ rcu_barrier(); WARN_ON(kpatch_num_patched != 0); - WARN_ON(unregister_module_notifier(&kpatch_module_nb)); + WARN_ON(unregister_module_notifier(&kpatch_module_nb_coming)); + WARN_ON(unregister_module_notifier(&kpatch_module_nb_going)); kobject_put(kpatch_root_kobj); } diff -Nru kpatch-0.5.0/kmod/core/kpatch.h kpatch-0.8.0/kmod/core/kpatch.h --- kpatch-0.5.0/kmod/core/kpatch.h 2017-12-21 05:02:48.000000000 +0000 +++ kpatch-0.8.0/kmod/core/kpatch.h 2019-08-28 17:34:00.000000000 +0000 @@ -60,18 +60,17 @@ struct list_head list; }; -struct kpatch_hook { - struct list_head list; - void (*hook)(void); -}; - struct kpatch_object { struct list_head list; const char *name; struct list_head funcs; struct list_head dynrelas; - struct list_head hooks_load; - struct list_head hooks_unload; + + int (*pre_patch_callback)(struct kpatch_object *); + void (*post_patch_callback)(struct kpatch_object *); + void (*pre_unpatch_callback)(struct kpatch_object *); + void (*post_unpatch_callback)(struct kpatch_object *); + bool callbacks_enabled; /* private */ struct module *mod; diff -Nru kpatch-0.5.0/kmod/core/Makefile kpatch-0.8.0/kmod/core/Makefile --- kpatch-0.5.0/kmod/core/Makefile 2017-12-21 05:02:48.000000000 +0000 +++ kpatch-0.8.0/kmod/core/Makefile 2019-08-28 17:34:00.000000000 +0000 @@ -1,6 +1,6 @@ # make rules KPATCH_BUILD ?= /lib/modules/$(shell uname -r)/build -KERNELRELEASE := $(lastword $(subst /, , $(dir $(KPATCH_BUILD)))) +KERNELRELEASE := $(lastword $(subst /, , $(dir $(patsubst %/,%,$(KPATCH_BUILD))))) THISDIR := $(abspath $(dir $(lastword $(MAKEFILE_LIST)))) ifeq ($(wildcard $(KPATCH_BUILD)),) diff -Nru kpatch-0.5.0/kmod/patch/kpatch.h kpatch-0.8.0/kmod/patch/kpatch.h --- kpatch-0.5.0/kmod/patch/kpatch.h 2017-12-21 05:02:48.000000000 +0000 +++ kpatch-0.8.0/kmod/patch/kpatch.h 2019-08-28 17:34:00.000000000 +0000 @@ -60,18 +60,17 @@ struct list_head list; }; -struct kpatch_hook { - struct list_head list; - void (*hook)(void); -}; - struct kpatch_object { struct list_head list; const char *name; struct list_head funcs; struct list_head dynrelas; - struct list_head hooks_load; - struct list_head hooks_unload; + + int (*pre_patch_callback)(struct kpatch_object *); + void (*post_patch_callback)(struct kpatch_object *); + void (*pre_unpatch_callback)(struct kpatch_object *); + void (*post_unpatch_callback)(struct kpatch_object *); + bool callbacks_enabled; /* private */ struct module *mod; diff -Nru kpatch-0.5.0/kmod/patch/kpatch.lds.S kpatch-0.8.0/kmod/patch/kpatch.lds.S --- kpatch-0.5.0/kmod/patch/kpatch.lds.S 2017-12-21 05:02:48.000000000 +0000 +++ kpatch-0.8.0/kmod/patch/kpatch.lds.S 2019-08-28 17:34:00.000000000 +0000 @@ -9,23 +9,36 @@ SECTIONS { - .kpatch.hooks.load : { - __kpatch_hooks_load = . ; - *(.kpatch.hooks.load) - __kpatch_hooks_load_end = . ; + .kpatch.callbacks.pre_patch : { + __kpatch_callbacks_pre_patch = . ; + *(.kpatch.callbacks.pre_patch) + __kpatch_callbacks_pre_patch_end = . ; /* * Pad the end of the section with zeros in case the section is empty. * This prevents the kernel from discarding the section at module - * load time. __kpatch_hooks_load_end will still point to the end of - * the section before the padding. If the .kpatch.hooks.load section - * is empty, __kpatch_hooks_load equals __kpatch_hooks_load_end. + * load time. __kpatch_callbacks_pre_patch_end will still point to the + * end of the section before the padding. If the + * .kpatch.callbacks.pre_patch section is empty, + * __kpatch_callbacks_pre_patch equals __kpatch_callbacks_pre_patch_end. */ QUAD(0); } - .kpatch.hooks.unload : { - __kpatch_hooks_unload = . ; - *(.kpatch.hooks.unload) - __kpatch_hooks_unload_end = . ; + .kpatch.callbacks.post_patch : { + __kpatch_callbacks_post_patch = . ; + *(.kpatch.callbacks.post_patch) + __kpatch_callbacks_post_patch_end = . ; + QUAD(0); + } + .kpatch.callbacks.pre_unpatch : { + __kpatch_callbacks_pre_unpatch = . ; + *(.kpatch.callbacks.pre_unpatch) + __kpatch_callbacks_pre_unpatch_end = . ; + QUAD(0); + } + .kpatch.callbacks.post_unpatch : { + __kpatch_callbacks_post_unpatch = . ; + *(.kpatch.callbacks.post_unpatch) + __kpatch_callbacks_post_unpatch_end = . ; QUAD(0); } .kpatch.force : { diff -Nru kpatch-0.5.0/kmod/patch/kpatch-macros.h kpatch-0.8.0/kmod/patch/kpatch-macros.h --- kpatch-0.5.0/kmod/patch/kpatch-macros.h 2017-12-21 05:02:48.000000000 +0000 +++ kpatch-0.8.0/kmod/patch/kpatch-macros.h 2019-08-28 17:34:00.000000000 +0000 @@ -3,19 +3,7 @@ #include #include - -typedef void (*kpatch_loadcall_t)(void); -typedef void (*kpatch_unloadcall_t)(void); - -struct kpatch_load { - kpatch_loadcall_t fn; - char *objname; /* filled in by create-diff-object */ -}; - -struct kpatch_unload { - kpatch_unloadcall_t fn; - char *objname; /* filled in by create-diff-object */ -}; +#include /* * KPATCH_IGNORE_SECTION macro @@ -39,37 +27,73 @@ #define KPATCH_IGNORE_FUNCTION(_fn) \ void *__kpatch_ignore_func_##_fn __section(.kpatch.ignore.functions) = _fn; -/* - * KPATCH_LOAD_HOOK macro - * - * The first line only ensures that the hook being registered has the required - * function signature. If not, there is compile error on this line. - * - * The section line declares a struct kpatch_load to be allocated in a new - * .kpatch.hook.load section. This kpatch_load_data symbol is later stripped - * by create-diff-object so that it can be declared in multiple objects that - * are later linked together, avoiding global symbol collision. Since multiple - * hooks can be registered, the .kpatch.hook.load section is a table of struct - * kpatch_load elements that will be executed in series by the kpatch core - * module at load time, assuming the kernel object (module) is currently - * loaded; otherwise, the hook is called when module to be patched is loaded - * via the module load notifier. - */ -#define KPATCH_LOAD_HOOK(_fn) \ - static inline kpatch_loadcall_t __loadtest(void) { return _fn; } \ - struct kpatch_load kpatch_load_data __section(.kpatch.hooks.load) = { \ + +/* Support for livepatch callbacks */ +#if IS_ENABLED(CONFIG_LIVEPATCH) +# ifdef RHEL_RELEASE_CODE +# if RHEL_RELEASE_CODE >= RHEL_RELEASE_VERSION(7, 5) +# define HAS_LIVEPATCH_CALLBACKS +# endif +# elif LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0) +# define HAS_LIVEPATCH_CALLBACKS +# endif +#endif + +#ifdef HAS_LIVEPATCH_CALLBACKS +# include +typedef struct klp_object patch_object; +#else +# include "kpatch.h" +typedef struct kpatch_object patch_object; +#endif /* HAS_LIVEPATCH_CALLBACKS */ + +typedef int (*kpatch_pre_patch_call_t)(patch_object *obj); +typedef void (*kpatch_post_patch_call_t)(patch_object *obj); +typedef void (*kpatch_pre_unpatch_call_t)(patch_object *obj); +typedef void (*kpatch_post_unpatch_call_t)(patch_object *obj); + +struct kpatch_pre_patch_callback { + kpatch_pre_patch_call_t fn; + char *objname; /* filled in by create-diff-object */ +}; + +struct kpatch_post_patch_callback { + kpatch_post_patch_call_t fn; + char *objname; /* filled in by create-diff-object */ +}; + +struct kpatch_pre_unpatch_callback { + kpatch_pre_unpatch_call_t fn; + char *objname; /* filled in by create-diff-object */ +}; + +struct kpatch_post_unpatch_callback { + kpatch_post_unpatch_call_t fn; + char *objname; /* filled in by create-diff-object */ +}; + + +#define KPATCH_PRE_PATCH_CALLBACK(_fn) \ + static inline kpatch_pre_patch_call_t __pre_patchtest(void) { return _fn; } \ + static struct kpatch_pre_patch_callback kpatch_pre_patch_data __section(.kpatch.callbacks.pre_patch) __used = { \ .fn = _fn, \ .objname = NULL \ }; - -/* - * KPATCH_UNLOAD_HOOK macro - * - * Same as LOAD hook with s/load/unload/ - */ -#define KPATCH_UNLOAD_HOOK(_fn) \ - static inline kpatch_unloadcall_t __unloadtest(void) { return _fn; } \ - struct kpatch_unload kpatch_unload_data __section(.kpatch.hooks.unload) = { \ +#define KPATCH_POST_PATCH_CALLBACK(_fn) \ + static inline kpatch_post_patch_call_t __post_patchtest(void) { return _fn; } \ + static struct kpatch_post_patch_callback kpatch_post_patch_data __section(.kpatch.callbacks.post_patch) __used = { \ + .fn = _fn, \ + .objname = NULL \ + }; +#define KPATCH_PRE_UNPATCH_CALLBACK(_fn) \ + static inline kpatch_pre_unpatch_call_t __pre_unpatchtest(void) { return _fn; } \ + static struct kpatch_pre_unpatch_callback kpatch_pre_unpatch_data __section(.kpatch.callbacks.pre_unpatch) __used = { \ + .fn = _fn, \ + .objname = NULL \ + }; +#define KPATCH_POST_UNPATCH_CALLBACK(_fn) \ + static inline kpatch_post_unpatch_call_t __post_unpatchtest(void) { return _fn; } \ + static struct kpatch_post_unpatch_callback kpatch_post_unpatch_data __section(.kpatch.callbacks.post_unpatch) __used = { \ .fn = _fn, \ .objname = NULL \ }; diff -Nru kpatch-0.5.0/kmod/patch/kpatch-patch.h kpatch-0.8.0/kmod/patch/kpatch-patch.h --- kpatch-0.5.0/kmod/patch/kpatch-patch.h 2017-12-21 05:02:48.000000000 +0000 +++ kpatch-0.8.0/kmod/patch/kpatch-patch.h 2019-08-28 17:34:00.000000000 +0000 @@ -43,8 +43,20 @@ int addend; }; -struct kpatch_patch_hook { - void (*hook)(void); +struct kpatch_pre_patch_callback { + int (*callback)(void *obj); + char *objname; +}; +struct kpatch_post_patch_callback { + void (*callback)(void *obj); + char *objname; +}; +struct kpatch_pre_unpatch_callback { + void (*callback)(void *obj); + char *objname; +}; +struct kpatch_post_unpatch_callback { + void (*callback)(void *obj); char *objname; }; diff -Nru kpatch-0.5.0/kmod/patch/kpatch-patch-hook.c kpatch-0.8.0/kmod/patch/kpatch-patch-hook.c --- kpatch-0.5.0/kmod/patch/kpatch-patch-hook.c 2017-12-21 05:02:48.000000000 +0000 +++ kpatch-0.8.0/kmod/patch/kpatch-patch-hook.c 2019-08-28 17:34:00.000000000 +0000 @@ -32,8 +32,10 @@ extern struct kpatch_patch_func __kpatch_funcs[], __kpatch_funcs_end[]; extern struct kpatch_patch_dynrela __kpatch_dynrelas[], __kpatch_dynrelas_end[]; -extern struct kpatch_patch_hook __kpatch_hooks_load[], __kpatch_hooks_load_end[]; -extern struct kpatch_patch_hook __kpatch_hooks_unload[], __kpatch_hooks_unload_end[]; +extern struct kpatch_pre_patch_callback __kpatch_callbacks_pre_patch[], __kpatch_callbacks_pre_patch_end[]; +extern struct kpatch_post_patch_callback __kpatch_callbacks_post_patch[], __kpatch_callbacks_post_patch_end[]; +extern struct kpatch_pre_unpatch_callback __kpatch_callbacks_pre_unpatch[], __kpatch_callbacks_pre_unpatch_end[]; +extern struct kpatch_post_unpatch_callback __kpatch_callbacks_post_unpatch[], __kpatch_callbacks_post_unpatch_end[]; extern unsigned long __kpatch_force_funcs[], __kpatch_force_funcs_end[]; extern char __kpatch_checksum[]; @@ -182,8 +184,6 @@ object->name = name; INIT_LIST_HEAD(&object->funcs); INIT_LIST_HEAD(&object->dynrelas); - INIT_LIST_HEAD(&object->hooks_load); - INIT_LIST_HEAD(&object->hooks_unload); list_add_tail(&object->list, head); @@ -203,7 +203,6 @@ struct kpatch_object *object, *object_safe; struct kpatch_func *func, *func_safe; struct kpatch_dynrela *dynrela, *dynrela_safe; - struct kpatch_hook *hook, *hook_safe; list_for_each_entry_safe(object, object_safe, &kpmod.objects, list) { list_for_each_entry_safe(func, func_safe, &object->funcs, @@ -216,16 +215,6 @@ list_del(&dynrela->list); kfree(dynrela); } - list_for_each_entry_safe(hook, hook_safe, - &object->hooks_load, list) { - list_del(&hook->list); - kfree(hook); - } - list_for_each_entry_safe(hook, hook_safe, - &object->hooks_unload, list) { - list_del(&hook->list); - kfree(hook); - } list_del(&object->list); kobject_put(&object->kobj); } @@ -303,38 +292,84 @@ return 0; } -static int patch_make_hook_lists(struct list_head *objects) +static int patch_set_callbacks(struct list_head *objects) { + struct kpatch_pre_patch_callback *p_pre_patch_callback; + struct kpatch_post_patch_callback *p_post_patch_callback; + struct kpatch_pre_unpatch_callback *p_pre_unpatch_callback; + struct kpatch_post_unpatch_callback *p_post_unpatch_callback; struct kpatch_object *object; - struct kpatch_patch_hook *p_hook; - struct kpatch_hook *hook; - for (p_hook = __kpatch_hooks_load; p_hook < __kpatch_hooks_load_end; - p_hook++) { - object = patch_find_or_add_object(objects, p_hook->objname); + for (p_pre_patch_callback = __kpatch_callbacks_pre_patch; + p_pre_patch_callback < __kpatch_callbacks_pre_patch_end; + p_pre_patch_callback++) { + + object = patch_find_or_add_object(objects, p_pre_patch_callback->objname); if (!object) return -ENOMEM; - hook = kzalloc(sizeof(*hook), GFP_KERNEL); - if (!hook) + if (object->pre_patch_callback) { + pr_err("extra pre-patch callback for object: %s\n", + object->name); + return -EINVAL; + } + + object->pre_patch_callback = + (int (*)(struct kpatch_object *)) p_pre_patch_callback->callback; + } + + for (p_post_patch_callback = __kpatch_callbacks_post_patch; + p_post_patch_callback < __kpatch_callbacks_post_patch_end; + p_post_patch_callback++) { + + object = patch_find_or_add_object(objects, p_post_patch_callback->objname); + if (!object) return -ENOMEM; - hook->hook = p_hook->hook; - list_add_tail(&hook->list, &object->hooks_load); + if (object->post_patch_callback) { + pr_err("extra post-patch callback for object: %s\n", + object->name); + return -EINVAL; + } + + object->post_patch_callback = + (void (*)(struct kpatch_object *)) p_post_patch_callback->callback; } - for (p_hook = __kpatch_hooks_unload; p_hook < __kpatch_hooks_unload_end; - p_hook++) { - object = patch_find_or_add_object(objects, p_hook->objname); + for (p_pre_unpatch_callback = __kpatch_callbacks_pre_unpatch; + p_pre_unpatch_callback < __kpatch_callbacks_pre_unpatch_end; + p_pre_unpatch_callback++) { + + object = patch_find_or_add_object(objects, p_pre_unpatch_callback->objname); if (!object) return -ENOMEM; - hook = kzalloc(sizeof(*hook), GFP_KERNEL); - if (!hook) + if (object->pre_unpatch_callback) { + pr_err("extra pre-unpatch callback for object: %s\n", + object->name); + return -EINVAL; + } + + object->pre_unpatch_callback = + (void (*)(struct kpatch_object *)) p_pre_unpatch_callback->callback; + } + + for (p_post_unpatch_callback = __kpatch_callbacks_post_unpatch; + p_post_unpatch_callback < __kpatch_callbacks_post_unpatch_end; + p_post_unpatch_callback++) { + + object = patch_find_or_add_object(objects, p_post_unpatch_callback->objname); + if (!object) return -ENOMEM; - hook->hook = p_hook->hook; - list_add_tail(&hook->list, &object->hooks_unload); + if (object->post_unpatch_callback) { + pr_err("extra post-unpatch callback for object: %s\n", + object->name); + return -EINVAL; + } + + object->post_unpatch_callback = + (void (*)(struct kpatch_object *)) p_post_unpatch_callback->callback; } return 0; } @@ -360,7 +395,7 @@ if (ret) goto err_objects; - ret = patch_make_hook_lists(&kpmod.objects); + ret = patch_set_callbacks(&kpmod.objects); if (ret) goto err_objects; diff -Nru kpatch-0.5.0/kmod/patch/livepatch-patch-hook.c kpatch-0.8.0/kmod/patch/livepatch-patch-hook.c --- kpatch-0.5.0/kmod/patch/livepatch-patch-hook.c 2017-12-21 05:02:48.000000000 +0000 +++ kpatch-0.8.0/kmod/patch/livepatch-patch-hook.c 2019-08-28 17:34:00.000000000 +0000 @@ -47,9 +47,31 @@ #define HAVE_SYMPOS #endif -#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0) || \ - defined(RHEL_RELEASE_CODE) -#define HAVE_IMMEDIATE +#ifdef RHEL_RELEASE_CODE +# if RHEL_RELEASE_CODE <= RHEL_RELEASE_VERSION(7, 5) +# define HAVE_IMMEDIATE +# endif +#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0) && \ + LINUX_VERSION_CODE <= KERNEL_VERSION(4, 15, 0)) +# define HAVE_IMMEDIATE +#endif + +#ifdef RHEL_RELEASE_CODE +# if RHEL_RELEASE_CODE >= RHEL_RELEASE_VERSION(7, 5) +# define HAVE_CALLBACKS +# endif +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0) +# define HAVE_CALLBACKS +#endif + +#ifdef RHEL_RELEASE_CODE +# if (RHEL_RELEASE_CODE >= RHEL_RELEASE_VERSION(7, 8) && \ + RHEL_RELEASE_CODE < RHEL_RELEASE_VERSION(8, 0)) || \ + RHEL_RELEASE_CODE >= RHEL_RELEASE_VERSION(8, 2) +# define HAVE_SIMPLE_ENABLE +# endif +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(5, 1, 0) +# define HAVE_SIMPLE_ENABLE #endif /* @@ -70,7 +92,7 @@ * done, the scaffold structs are no longer needed. */ -struct klp_patch *lpatch; +static struct klp_patch *lpatch; static LIST_HEAD(patch_objects); static int patch_objects_nr; @@ -78,6 +100,9 @@ struct list_head list; struct list_head funcs; struct list_head relocs; +#ifdef HAVE_CALLBACKS + struct klp_callbacks callbacks; +#endif const char *name; int funcs_nr, relocs_nr; }; @@ -209,6 +234,101 @@ } } +extern struct kpatch_pre_patch_callback __kpatch_callbacks_pre_patch[], __kpatch_callbacks_pre_patch_end[]; +extern struct kpatch_post_patch_callback __kpatch_callbacks_post_patch[], __kpatch_callbacks_post_patch_end[]; +extern struct kpatch_pre_unpatch_callback __kpatch_callbacks_pre_unpatch[], __kpatch_callbacks_pre_unpatch_end[]; +extern struct kpatch_post_unpatch_callback __kpatch_callbacks_post_unpatch[], __kpatch_callbacks_post_unpatch_end[]; + +#ifdef HAVE_CALLBACKS +static int add_callbacks_to_patch_objects(void) +{ + struct kpatch_pre_patch_callback *p_pre_patch_callback; + struct kpatch_post_patch_callback *p_post_patch_callback; + struct kpatch_pre_unpatch_callback *p_pre_unpatch_callback; + struct kpatch_post_unpatch_callback *p_post_unpatch_callback; + struct patch_object *object; + + for (p_pre_patch_callback = __kpatch_callbacks_pre_patch; + p_pre_patch_callback < __kpatch_callbacks_pre_patch_end; + p_pre_patch_callback++) { + object = patch_find_object_by_name(p_pre_patch_callback->objname); + if (!object) + return -ENOMEM; + if (object->callbacks.pre_patch) { + pr_err("extra pre-patch callback for object: %s\n", + object->name ? object->name : "vmlinux"); + return -EINVAL; + } + object->callbacks.pre_patch = (int (*)(struct klp_object *)) + p_pre_patch_callback->callback; + } + + for (p_post_patch_callback = __kpatch_callbacks_post_patch; + p_post_patch_callback < __kpatch_callbacks_post_patch_end; + p_post_patch_callback++) { + object = patch_find_object_by_name(p_post_patch_callback->objname); + if (!object) + return -ENOMEM; + if (object->callbacks.post_patch) { + pr_err("extra post-patch callback for object: %s\n", + object->name ? object->name : "vmlinux"); + return -EINVAL; + } + object->callbacks.post_patch = (void (*)(struct klp_object *)) + p_post_patch_callback->callback; + } + + for (p_pre_unpatch_callback = __kpatch_callbacks_pre_unpatch; + p_pre_unpatch_callback < __kpatch_callbacks_pre_unpatch_end; + p_pre_unpatch_callback++) { + object = patch_find_object_by_name(p_pre_unpatch_callback->objname); + if (!object) + return -ENOMEM; + if (object->callbacks.pre_unpatch) { + pr_err("extra pre-unpatch callback for object: %s\n", + object->name ? object->name : "vmlinux"); + return -EINVAL; + } + object->callbacks.pre_unpatch = (void (*)(struct klp_object *)) + p_pre_unpatch_callback->callback; + } + + for (p_post_unpatch_callback = __kpatch_callbacks_post_unpatch; + p_post_unpatch_callback < __kpatch_callbacks_post_unpatch_end; + p_post_unpatch_callback++) { + object = patch_find_object_by_name(p_post_unpatch_callback->objname); + if (!object) + return -ENOMEM; + if (object->callbacks.post_unpatch) { + pr_err("extra post-unpatch callback for object: %s\n", + object->name ? object->name : "vmlinux"); + return -EINVAL; + } + object->callbacks.post_unpatch = (void (*)(struct klp_object *)) + p_post_unpatch_callback->callback; + } + + return 0; +} +#else /* HAVE_CALLBACKS */ +static inline int add_callbacks_to_patch_objects(void) +{ + if (__kpatch_callbacks_pre_patch != + __kpatch_callbacks_pre_patch_end || + __kpatch_callbacks_post_patch != + __kpatch_callbacks_post_patch_end || + __kpatch_callbacks_pre_unpatch != + __kpatch_callbacks_pre_unpatch_end || + __kpatch_callbacks_post_unpatch != + __kpatch_callbacks_post_unpatch_end) { + pr_err("patch callbacks are not supported\n"); + return -EINVAL; + } + + return 0; +} +#endif /* HAVE_CALLBACKS */ + extern struct kpatch_patch_func __kpatch_funcs[], __kpatch_funcs_end[]; #ifndef HAVE_ELF_RELOCS extern struct kpatch_patch_dynrela __kpatch_dynrelas[], __kpatch_dynrelas_end[]; @@ -247,6 +367,10 @@ } #endif + ret = add_callbacks_to_patch_objects(); + if (ret) + goto out; + /* past this point, only possible return code is -ENOMEM */ ret = -ENOMEM; @@ -261,7 +385,7 @@ goto out; lpatch->mod = THIS_MODULE; lpatch->objs = lobjects; -#if defined(__powerpc__) && defined(HAVE_IMMEDIATE) +#if defined(__powerpc64__) && defined(HAVE_IMMEDIATE) lpatch->immediate = true; #endif @@ -310,6 +434,10 @@ } #endif /* HAVE_ELF_RELOCS */ +#ifdef HAVE_CALLBACKS + lobject->callbacks = object->callbacks; +#endif + i++; } @@ -319,15 +447,19 @@ */ patch_free_scaffold(); +#ifndef HAVE_SIMPLE_ENABLE ret = klp_register_patch(lpatch); if (ret) { patch_free_livepatch(lpatch); return ret; } +#endif ret = klp_enable_patch(lpatch); if (ret) { +#ifndef HAVE_SIMPLE_ENABLE WARN_ON(klp_unregister_patch(lpatch)); +#endif patch_free_livepatch(lpatch); return ret; } @@ -341,7 +473,10 @@ static void __exit patch_exit(void) { +#ifndef HAVE_SIMPLE_ENABLE WARN_ON(klp_unregister_patch(lpatch)); +#endif + patch_free_livepatch(lpatch); } module_init(patch_init); diff -Nru kpatch-0.5.0/kmod/patch/Makefile kpatch-0.8.0/kmod/patch/Makefile --- kpatch-0.5.0/kmod/patch/Makefile 2017-12-21 05:02:48.000000000 +0000 +++ kpatch-0.8.0/kmod/patch/Makefile 2019-08-28 17:34:00.000000000 +0000 @@ -11,13 +11,15 @@ endif obj-m += $(KPATCH_NAME).o +ldflags-y += -T $(src)/kpatch.lds +extra-y := kpatch.lds -$(KPATCH_NAME)-objs += patch-hook.o kpatch.lds output.o +$(KPATCH_NAME)-objs += patch-hook.o output.o all: $(KPATCH_NAME).ko $(KPATCH_NAME).ko: - $(KPATCH_MAKE) $(KPATCH_NAME).ko + $(KPATCH_MAKE) patch-hook.o: patch-hook.c kpatch-patch-hook.c livepatch-patch-hook.c $(KPATCH_MAKE) patch-hook.o diff -Nru kpatch-0.5.0/kpatch/kpatch kpatch-0.8.0/kpatch/kpatch --- kpatch-0.5.0/kpatch/kpatch 2017-12-21 05:02:48.000000000 +0000 +++ kpatch-0.8.0/kpatch/kpatch 2019-08-28 17:34:00.000000000 +0000 @@ -25,10 +25,15 @@ INSTALLDIR=/var/lib/kpatch SCRIPTDIR="$(readlink -f "$(dirname "$(type -p "$0")")")" -VERSION="0.4.0" -POST_ENABLE_WAIT=5 # seconds +VERSION="0.8.0" +POST_ENABLE_WAIT=15 # seconds POST_SIGNAL_WAIT=60 # seconds +# How many times to try loading the patch if activeness safety check fails. +MAX_LOAD_ATTEMPTS=5 +# How long to wait before retry, in seconds. +RETRY_INTERVAL=2 + usage_cmd() { printf ' %-20s\n %s\n' "$1" "$2" >&2 } @@ -39,8 +44,8 @@ echo "usage: kpatch []" >&2 echo >&2 echo "Valid commands:" >&2 - usage_cmd "install [-k|--kernel-version=] " "install patch module to the initrd to be loaded at boot" - usage_cmd "uninstall [-k|--kernel-version=] " "uninstall patch module from the initrd" + usage_cmd "install [-k|--kernel-version=] " "install patch module to be loaded at boot" + usage_cmd "uninstall [-k|--kernel-version=] " "uninstall patch module" echo >&2 usage_cmd "load --all" "load all installed patch modules into the running kernel" usage_cmd "load " "load patch module into the running kernel" @@ -121,7 +126,7 @@ } core_loaded () { - grep -q -e "T klp_register_patch" -e "T kpatch_register" /proc/kallsyms + grep -q -e "T klp_enable_patch" -e "T kpatch_register" /proc/kallsyms } get_module_name () { @@ -152,7 +157,7 @@ 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 + if [[ -n "$checksum" ]] && [[ -e "$SYSFS/${modname}/checksum" ]] ; then sysfs_checksum="$(cat "$SYSFS/${modname}/checksum")" [[ "$checksum" == "$sysfs_checksum" ]] || return 1 fi @@ -225,21 +230,8 @@ [[ -z "$module" ]] && return if [[ -e "/sys/kernel/livepatch/$module/signal" ]] ; then + echo "signaling stalled process(es):" 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 } @@ -258,7 +250,7 @@ sleep 1s done - echo "patch transition has stalled, signaling stalled process(es):" + echo "patch transition has stalled!" signal_stalled_processes echo "waiting (up to $POST_SIGNAL_WAIT seconds) for patch transition to complete..." @@ -309,31 +301,31 @@ die "error: cannot re-enable patch module $modname, cannot verify checksum match" fi else - die "error: module named $modname already loaded and enabled" + echo "module named $modname already loaded and enabled" fi + else + echo "loading patch module: $module" + local i=0 + while true; do + out="$(LC_ALL=C insmod "$module" 2>&1)" + [[ -z "$out" ]] && break + echo "$out" 1>&2 + [[ ! "$out" =~ "Device or resource busy" ]] && + die "failed to load module $module" + + # "Device or resource busy" means the activeness safety check + # failed. Retry in a few seconds. + i=$((i+1)) + if [[ $i -eq $MAX_LOAD_ATTEMPTS ]]; then + die "failed to load module $module" + break + else + warn "retrying..." + sleep $RETRY_INTERVAL + fi + done fi - echo "loading patch module: $module" - local i=0 - while true; do - out="$(insmod "$module" 2>&1)" - [[ -z "$out" ]] && break - echo "$out" 1>&2 - [[ ! "$out" =~ "Device or resource busy" ]] && - die "failed to load module $module" - - # "Device or resource busy" means the activeness safety check - # failed. Retry in a few seconds. - i=$((i+1)) - if [[ $i = 5 ]]; then - die "failed to load module $module" - break - else - warn "retrying..." - sleep 2 - fi - done - if ! wait_for_patch_transition "$modname" ; then echo "module $modname did not complete its transition, unloading..." unload_module "$modname" @@ -343,19 +335,44 @@ return 0 } -unload_module () { - PATCH="${1//-/_}" - PATCH="${PATCH%.ko}" - ENABLED="$SYSFS/$PATCH/enabled" - [[ -e "$ENABLED" ]] || die "patch module $1 is not loaded" - if [[ "$(cat "$ENABLED")" -eq 1 ]]; then - echo "disabling patch module: $PATCH" - echo 0 > "$ENABLED" || die "can't disable $PATCH" +disable_patch () { + local modname="$1" + + local enabled="$SYSFS/$modname/enabled" + [[ -e "$enabled" ]] || die "patch module $1 is not loaded" + + if [[ "$(cat "$enabled")" -eq 1 ]]; then + echo "disabling patch module: $modname" + local i=0 + while true; do + out="$(export LC_ALL=C; sh -c "echo 0 > $enabled" 2>&1)" + [[ -z "$out" ]] && break + echo "$out" 1>&2 + if [[ ! "$out" =~ "Device or resource busy" ]]; then + die "failed to disable module $modname" + fi + + # "Device or resource busy" means the activeness safety check + # failed. Retry in a few seconds. + i=$((i+1)) + if [[ $i -eq $MAX_LOAD_ATTEMPTS ]]; then + die "failed to disable module $modname" + else + warn "retrying..." + sleep $RETRY_INTERVAL + fi + done fi - if ! wait_for_patch_transition "$PATCH" ; then - die "error: failed to unload module $PATCH (transition stalled)" + if ! wait_for_patch_transition "$modname" ; then + die "transition stalled for $modname" fi +} + +unload_module () { + PATCH="${1//-/_}" + PATCH="${PATCH%.ko}" + disable_patch "$PATCH" echo "unloading patch module: $PATCH" # ignore any error here because rmmod can fail if the module used @@ -439,7 +456,7 @@ echo "installing $PATCH ($KVER)" mkdir -p "$INSTALLDIR/$KVER" || die "failed to create install directory" cp -f "$PATCH" "$INSTALLDIR/$KVER" || die "failed to install module $PATCH" - systemctl enable kpatch.service + command -v systemctl > /dev/null 2>&1 && systemctl enable kpatch.service ;; "uninstall") @@ -503,7 +520,7 @@ echo "Installed patch modules:" for kdir in "$INSTALLDIR"/*; do [[ -e "$kdir" ]] || continue - for module in "$kdir"/*; do + for module in "$kdir"/*.ko; do [[ -e "$module" ]] || continue mod_name "$module" echo "$MODNAME ($(basename "$kdir"))" diff -Nru kpatch-0.5.0/kpatch-build/create-diff-object.c kpatch-0.8.0/kpatch-build/create-diff-object.c --- kpatch-0.5.0/kpatch-build/create-diff-object.c 2017-12-21 05:02:48.000000000 +0000 +++ kpatch-0.8.0/kpatch-build/create-diff-object.c 2019-08-28 17:34:00.000000000 +0000 @@ -52,14 +52,15 @@ #include "kpatch-patch.h" #include "kpatch-elf.h" #include "kpatch-intermediate.h" +#include "kpatch.h" #define DIFF_FATAL(format, ...) \ ({ \ fprintf(stderr, "ERROR: %s: " format "\n", childobj, ##__VA_ARGS__); \ - error(2, 0, "unreconcilable difference"); \ + error(EXIT_STATUS_DIFF_FATAL, 0, "unreconcilable difference"); \ }) -#ifdef __powerpc__ +#ifdef __powerpc64__ #define ABSOLUTE_RELA_TYPE R_PPC64_ADDR64 #else #define ABSOLUTE_RELA_TYPE R_X86_64_64 @@ -67,6 +68,12 @@ char *childobj; +enum subsection { + SUBSECTION_NORMAL, + SUBSECTION_HOT, + SUBSECTION_UNLIKELY +}; + enum loglevel loglevel = NORMAL; /******************* @@ -75,6 +82,7 @@ struct special_section { char *name; int (*group_size)(struct kpatch_elf *kelf, int offset); + int unsupported; }; /************* @@ -90,7 +98,14 @@ if (sym->type == STT_FUNC && !strncmp(sym->sec->name, ".text.unlikely.",15) && - !strcmp(sym->sec->name + 15, sym->name)) + (!strcmp(sym->sec->name + 15, sym->name) || + (strstr(sym->name, ".cold.") && + !strncmp(sym->sec->name + 15, sym->name, strlen(sym->sec->name) - 15)))) + return 1; + + if (sym->type == STT_FUNC && + !strncmp(sym->sec->name, ".text.hot.",10) && + !strcmp(sym->sec->name + 10, sym->name)) return 1; if (sym->type == STT_OBJECT && @@ -99,6 +114,16 @@ return 1; if (sym->type == STT_OBJECT && + !strncmp(sym->sec->name, ".data.rel.", 10) && + !strcmp(sym->sec->name + 10, sym->name)) + return 1; + + if (sym->type == STT_OBJECT && + !strncmp(sym->sec->name, ".data.rel.ro.", 13) && + !strcmp(sym->sec->name + 13, sym->name)) + return 1; + + if (sym->type == STT_OBJECT && !strncmp(sym->sec->name, ".rodata.",8) && !strcmp(sym->sec->name + 8, sym->name)) return 1; @@ -111,7 +136,7 @@ return 0; } -#ifdef __powerpc__ +#ifdef __powerpc64__ /* Symbol st_others value for powerpc */ #define STO_PPC64_LOCAL_BIT 5 #define STO_PPC64_LOCAL_MASK (7 << STO_PPC64_LOCAL_BIT) @@ -137,7 +162,7 @@ */ static int is_gcc6_localentry_bundled_sym(struct symbol *sym) { - return (PPC64_LOCAL_ENTRY_OFFSET(sym->sym.st_other) && + return ((PPC64_LOCAL_ENTRY_OFFSET(sym->sym.st_other) != 0) && sym->sym.st_value == 8); } #else @@ -147,6 +172,16 @@ } #endif +static struct rela *toc_rela(const struct rela *rela) +{ + if (rela->type != R_PPC64_TOC16_HA && + rela->type != R_PPC64_TOC16_LO_DS) + return (struct rela *)rela; + + /* Will return NULL for .toc constant entries */ + return find_rela_by_offset(rela->sym->sec->rela, rela->addend); +} + /* * When compiling with -ffunction-sections and -fdata-sections, almost every * symbol gets its own dedicated section. We call such symbols "bundled" @@ -171,6 +206,47 @@ } /* + * During optimization gcc may move unlikely execution branches into *.cold + * subfunctions. kpatch_detect_child_functions detects such subfunctions and + * crossreferences them with their parent functions through parent/child + * pointers. + */ +static void kpatch_detect_child_functions(struct kpatch_elf *kelf) +{ + struct symbol *sym; + + list_for_each_entry(sym, &kelf->symbols, list) { + char *coldstr; + + coldstr = strstr(sym->name, ".cold."); + if (coldstr != NULL) { + char *pname; + + pname = strndup(sym->name, coldstr - sym->name); + if (!pname) + ERROR("strndup"); + + sym->parent = find_symbol_by_name(&kelf->symbols, pname); + free(pname); + + if (!sym->parent) + ERROR("failed to find parent function for %s", sym->name); + + sym->parent->child = sym; + } + } +} + +static bool is_dynamic_debug_symbol(struct symbol *sym) +{ + if (sym->type == STT_OBJECT && !strcmp(sym->sec->name, "__verbose")) + return true; + if (sym->type == STT_SECTION && !strcmp(sym->name, "__verbose")) + return true; + return false; +} + +/* * This function detects whether the given symbol is a "special" static local * variable (for lack of a better term). * @@ -182,8 +258,8 @@ static char *prefixes[] = { "__key.", "__warned.", - "descriptor.", "__func__.", + "__FUNCTION__.", "_rs.", "CSWTCH.", NULL, @@ -193,12 +269,12 @@ if (!sym) return 0; - if (sym->type == STT_SECTION) { - /* __verbose section contains the descriptor variables */ - if (!strcmp(sym->name, "__verbose")) - return 1; + /* pr_debug() uses static local variables in the __verbose section */ + if (is_dynamic_debug_symbol(sym)) + return 1; - /* otherwise make sure section is bundled */ + if (sym->type == STT_SECTION) { + /* make sure section is bundled */ if (!sym->sec->sym) return 0; @@ -242,85 +318,83 @@ static int rela_equal(struct rela *rela1, struct rela *rela2) { -#ifdef __powerpc__ - struct section *toc_relasec1, *toc_relasec2; - struct rela *r_toc_relasec1, *r_toc_relasec2; -#endif + struct rela *rela_toc1, *rela_toc2; + unsigned long toc_data1 = 0, toc_data2 = 0; /* = 0 to prevent gcc warning */ if (rela1->type != rela2->type || rela1->offset != rela2->offset) return 0; - if (rela1->string) - return rela2->string && !strcmp(rela1->string, rela2->string); - -#ifdef __powerpc__ -/* - * Relocation section '.rela.toc' at offset 0x91f0 contains 122 entries: - * Offset Info Type Symbol's Value Symbol's Name + Addend - * [...] - * 0000000000000090 0000001c00000026 R_PPC64_ADDR64 0000000000000000 .rodata.__dev_remove_pack.str1.8 + 0 - * 0000000000000098 0000001a00000026 R_PPC64_ADDR64 0000000000000000 .rodata.__dev_getfirstbyhwtype.str1.8 + 0 - * 00000000000000a0 0000001a00000026 R_PPC64_ADDR64 0000000000000000 .rodata.__dev_getfirstbyhwtype.str1.8 + 10 - * 00000000000000a8 000000cb00000026 R_PPC64_ADDR64 0000000000000000 dev_base_lock + 0 - * - * Relocation section '.rela.text.netdev_master_upper_dev_get' at offset 0xe38 contains 10 entries: - * Offset Info Type Symbol's Value Symbol's Name + Addend - * [...] - * 00000000000000a0 0000004e00000032 R_PPC64_TOC16_HA 0000000000000000 .toc + 98 - * 00000000000000a8 0000004e00000040 R_PPC64_TOC16_LO_DS 0000000000000000 .toc + 98 - * 00000000000000ac 0000004e00000032 R_PPC64_TOC16_HA 0000000000000000 .toc + a0 - * 00000000000000b0 0000004e00000040 R_PPC64_TOC16_LO_DS 0000000000000000 .toc + a0 - * 00000000000000b4 000000b90000000a R_PPC64_REL24 0000000000000000 printk + 0 - * 00000000000000bc 000000a10000000a R_PPC64_REL24 0000000000000000 dump_stack + 0 - * - * With -mcmodel=large on ppc64le, GCC might generate entries in the .toc - * section for relocation symbol references. The .toc offsets may change - * between the original and patched .o, so comparing ".toc + offset" isn't - * right. Compare the .toc-based symbols by reading the corresponding relas - * from the .toc section. - */ - if (!strcmp(rela1->sym->name, ".toc") && - !strcmp(rela2->sym->name, ".toc")) { - - toc_relasec1 = rela1->sym->sec->rela; - if (!toc_relasec1) - ERROR("cannot find .rela.toc"); - - r_toc_relasec1 = find_rela_by_offset(toc_relasec1, rela1->addend); - if (!r_toc_relasec1) + /* + * With -mcmodel=large on ppc64le, GCC might generate entries in the .toc + * section for relocation symbol references. The .toc offsets may change + * between the original and patched .o, so comparing ".toc + offset" isn't + * right. Compare the .toc-based symbols by reading the corresponding relas + * from the .toc section. + */ + rela_toc1 = toc_rela(rela1); + if (!rela_toc1) { + /* + * .toc section entries are mostly place holder for relocation entries, specified + * in .rela.toc section. Sometimes, .toc section may have constants as entries. + * These constants are not reference to any symbols, but plain instructions mostly + * due to some arithmetics in the functions referring them. + * + * They are referred by the functions like normal .toc entries, these entries can + * not be resolved to any symbols. + * + * Disassembly of section .toc: + * + * 0000000000000000 <.toc>: + * ... + * 148: R_PPC64_ADDR64 .data.capacity_margin + * 150: 0b d7 a3 70 andi. r3,r5,55051 + * 154: 3d 0a d7 a3 lhz r30,2621(r23) + * 158: R_PPC64_ADDR64 sched_max_numa_distance + * + * Relocation section '.rela.toc' at offset 0xadac0 contains 160 entries: + * Offset Info Type Symbol's Value Symbol's Name + Addend + * ... + * 0000000000000148 0000009100000026 R_PPC64_ADDR64 0000000000000000 .data.capacity_margin + 0 + * 0000000000000158 000001a500000026 R_PPC64_ADDR64 0000000000000000 sched_max_numa_distance + 0 + * + * Relocation section '.rela.text.select_task_rq_fair' at offset 0x90e98 contains 37 entries: + * Offset Info Type Symbol's Value Symbol's Name + Addend + * ... + * 00000000000004a0 0000008800000032 R_PPC64_TOC16_HA 0000000000000000 .toc + 148 + * 00000000000004ac 0000008800000040 R_PPC64_TOC16_LO_DS 0000000000000000 .toc + 148 + * 0000000000000514 0000008800000032 R_PPC64_TOC16_HA 0000000000000000 .toc + 150 + * 000000000000051c 0000008800000040 R_PPC64_TOC16_LO_DS 0000000000000000 .toc + 150 + */ + memcpy(&toc_data1, rela1->sym->sec->data->d_buf + rela1->addend, sizeof(toc_data1)); + if (!toc_data1) ERROR(".toc entry not found %s + %x", rela1->sym->name, rela1->addend); + } - toc_relasec2 = rela2->sym->sec->rela; - if (!toc_relasec2) - ERROR("cannot find .rela.toc"); - - r_toc_relasec2 = find_rela_by_offset(toc_relasec2, rela2->addend); - if (!r_toc_relasec2) + rela_toc2 = toc_rela(rela2); + if (!rela_toc2) { + memcpy(&toc_data2, rela2->sym->sec->data->d_buf + rela2->addend, sizeof(toc_data2)); + if (!toc_data2) ERROR(".toc entry not found %s + %x", rela2->sym->name, rela2->addend); + } - if (r_toc_relasec1->string) - return r_toc_relasec2->string && - !strcmp(r_toc_relasec1->string, r_toc_relasec2->string); + if (!rela_toc1 && !rela_toc2) + return toc_data1 == toc_data2; - if ((r_toc_relasec1->addend != r_toc_relasec2->addend)) - return 0; + if (!rela_toc1 || !rela_toc2) + return 0; - if (is_special_static(r_toc_relasec1->sym)) - return !kpatch_mangled_strcmp(r_toc_relasec1->sym->name, - r_toc_relasec2->sym->name); + if (rela_toc1->string) + return rela_toc2->string && !strcmp(rela_toc1->string, rela_toc2->string); - return !strcmp(r_toc_relasec1->sym->name, r_toc_relasec2->sym->name); - } -#endif - if (rela1->addend != rela2->addend) + if (rela_toc1->addend != rela_toc2->addend) return 0; - if (is_special_static(rela1->sym)) - return !kpatch_mangled_strcmp(rela1->sym->name, - rela2->sym->name); + if (is_special_static(rela_toc1->sym)) + return !kpatch_mangled_strcmp(rela_toc1->sym->name, + rela_toc2->sym->name); - return !strcmp(rela1->sym->name, rela2->sym->name); + return !strcmp(rela_toc1->sym->name, rela_toc2->sym->name); } static void kpatch_compare_correlated_rela_section(struct section *sec) @@ -367,8 +441,9 @@ /* Compare section headers (must match or fatal) */ if (sec1->sh.sh_type != sec2->sh.sh_type || sec1->sh.sh_flags != sec2->sh.sh_flags || - sec1->sh.sh_addralign != sec2->sh.sh_addralign || - sec1->sh.sh_entsize != sec2->sh.sh_entsize) + sec1->sh.sh_entsize != sec2->sh.sh_entsize || + (sec1->sh.sh_addralign != sec2->sh.sh_addralign && + !is_text_section(sec1))) DIFF_FATAL("%s section header details differ", sec1->name); /* Short circuit for mcount sections, we rebuild regardless */ @@ -423,7 +498,7 @@ * 1) immediate move of the line number to %esi * 2) (optional) string section rela * 3) (optional) __warned.xxxxx static local rela - * 4) warn_slowpath_* or __might_sleep or ___might_sleep rela + * 4) warn_slowpath_* or __might_sleep or some other similar rela */ static int kpatch_line_macro_change_only(struct section *sec) { @@ -461,15 +536,16 @@ length)) continue; - /* verify it's a mov immediate to %esi */ + /* verify it's a mov immediate to %edx or %esi */ insn_get_opcode(&insn1); insn_get_opcode(&insn2); - if (insn1.opcode.value != 0xbe || insn2.opcode.value != 0xbe) + if (!(insn1.opcode.value == 0xba && insn2.opcode.value == 0xba) && + !(insn1.opcode.value == 0xbe && insn2.opcode.value == 0xbe)) return 0; /* * Verify zero or more string relas followed by a - * warn_slowpath_* or __might_sleep or ___might_sleep rela. + * warn_slowpath_* or another similar rela. */ found = 0; list_for_each_entry(rela, &sec->rela->relas, list) { @@ -480,8 +556,78 @@ if (!strncmp(rela->sym->name, "__warned.", 9)) continue; if (!strncmp(rela->sym->name, "warn_slowpath_", 14) || + (!strcmp(rela->sym->name, "__warn_printk")) || + (!strcmp(rela->sym->name, "__might_sleep")) || + (!strcmp(rela->sym->name, "___might_sleep")) || + (!strcmp(rela->sym->name, "__might_fault")) || + (!strcmp(rela->sym->name, "printk")) || + (!strcmp(rela->sym->name, "lockdep_rcu_suspicious"))) { + found = 1; + break; + } + return 0; + } + if (!found) + return 0; + + lineonly = 1; + } + + if (!lineonly) + ERROR("no instruction changes detected for changed section %s", + sec->name); + + return 1; +} +#elif __powerpc64__ +#define PPC_INSTR_LEN 4 +#define PPC_RA_OFFSET 16 + +static int kpatch_line_macro_change_only(struct section *sec) +{ + unsigned long start1, start2, size, offset; + unsigned int instr1, instr2; + struct rela *rela; + int lineonly = 0, found; + + if (sec->status != CHANGED || + is_rela_section(sec) || + !is_text_section(sec) || + sec->sh.sh_size != sec->twin->sh.sh_size || + !sec->rela || + sec->rela->status != SAME) + return 0; + + start1 = (unsigned long)sec->twin->data->d_buf; + start2 = (unsigned long)sec->data->d_buf; + size = sec->sh.sh_size; + for (offset = 0; offset < size; offset += PPC_INSTR_LEN) { + if (!memcmp((void *)start1 + offset, (void *)start2 + offset, + PPC_INSTR_LEN)) + continue; + + instr1 = *(unsigned int *)(start1 + offset) >> PPC_RA_OFFSET; + instr2 = *(unsigned int *)(start2 + offset) >> PPC_RA_OFFSET; + + /* verify it's a load immediate to r5 */ + if (!(instr1 == 0x38a0 && instr2 == 0x38a0)) + return 0; + + found = 0; + list_for_each_entry(rela, &sec->rela->relas, list) { + if (rela->offset < offset + PPC_INSTR_LEN) + continue; + if (toc_rela(rela) && toc_rela(rela)->string) + continue; + if (!strncmp(rela->sym->name, "__warned.", 9)) + continue; + if (!strncmp(rela->sym->name, "warn_slowpath_", 14) || + (!strcmp(rela->sym->name, "__warn_printk")) || (!strcmp(rela->sym->name, "__might_sleep")) || - (!strcmp(rela->sym->name, "___might_sleep"))) { + (!strcmp(rela->sym->name, "___might_sleep")) || + (!strcmp(rela->sym->name, "__might_fault")) || + (!strcmp(rela->sym->name, "printk")) || + (!strcmp(rela->sym->name, "lockdep_rcu_suspicious"))) { found = 1; break; } @@ -533,12 +679,34 @@ if (sec->base->sym && sec->base->sym->status != CHANGED) sec->base->sym->status = sec->status; } else { - if (sec->sym && sec->sym->status != CHANGED) - sec->sym->status = sec->status; + struct symbol *sym = sec->sym; + + if (sym && sym->status != CHANGED) + sym->status = sec->status; + + if (sym && sym->child && sym->status == SAME && + sym->child->sec->status == CHANGED) + sym->status = CHANGED; } } } +static enum subsection kpatch_subsection_type(struct section *sec) +{ + if (!strncmp(sec->name, ".text.unlikely.", 15)) + return SUBSECTION_UNLIKELY; + + if (!strncmp(sec->name, ".text.hot.", 10)) + return SUBSECTION_HOT; + + return SUBSECTION_NORMAL; +} + +static int kpatch_subsection_changed(struct section *sec1, struct section *sec2) +{ + return kpatch_subsection_type(sec1) != kpatch_subsection_type(sec2); +} + static void kpatch_compare_correlated_symbol(struct symbol *sym) { struct symbol *sym1 = sym, *sym2 = sym->twin; @@ -551,10 +719,12 @@ /* * If two symbols are correlated but their sections are not, then the * symbol has changed sections. This is only allowed if the symbol is - * moving out of an ignored section. + * moving out of an ignored section, or moving between normal/hot/unlikely + * subsections. */ if (sym1->sec && sym2->sec && sym1->sec->twin != sym2->sec) { - if (sym2->sec->twin && sym2->sec->twin->ignore) + if ((sym2->sec->twin && sym2->sec->twin->ignore) || + kpatch_subsection_changed(sym1->sec, sym2->sec)) sym->status = CHANGED; else DIFF_FATAL("symbol changed sections: %s", sym1->name); @@ -747,6 +917,7 @@ if (!strstr(sym->name, ".isra.") && !strstr(sym->name, ".constprop.") && + !strstr(sym->name, ".cold.") && !strstr(sym->name, ".part.")) continue; @@ -810,7 +981,7 @@ static struct symbol *kpatch_find_static_twin(struct section *sec, struct symbol *sym) { - struct rela *rela; + struct rela *rela, *rela_toc; if (!sec->twin) return NULL; @@ -818,13 +989,17 @@ /* find the patched object's corresponding variable */ list_for_each_entry(rela, &sec->twin->relas, list) { - if (rela->sym->twin) + rela_toc = toc_rela(rela); + if (!rela_toc) + continue; /* skip toc constants */ + + if (rela_toc->sym->twin) continue; - if (kpatch_mangled_strcmp(rela->sym->name, sym->name)) + if (kpatch_mangled_strcmp(rela_toc->sym->name, sym->name)) continue; - return rela->sym; + return rela_toc->sym; } return NULL; @@ -913,12 +1088,16 @@ list_for_each_entry(sec, &base->sections, list) { if (!is_rela_section(sec) || - is_debug_section(sec)) + is_debug_section(sec) || + !strcmp(sec->name, ".rela.toc")) continue; list_for_each_entry(rela, &sec->relas, list) { - sym = rela->sym; + if (!toc_rela(rela)) + continue; /* skip toc constants */ + sym = toc_rela(rela)->sym; + if (!kpatch_is_normal_static_local(sym)) continue; @@ -949,8 +1128,8 @@ if (bundled != patched_bundled) ERROR("bundle mismatch for symbol %s", sym->name); if (!bundled && sym->sec->twin != patched_sym->sec) - ERROR("sections %s and %s aren't correlated", - sym->sec->name, patched_sym->sec->name); + ERROR("sections %s and %s aren't correlated for symbol %s", + sym->sec->name, patched_sym->sec->name, sym->name); log_debug("renaming and correlating static local %s to %s\n", patched_sym->name, sym->name); @@ -1067,6 +1246,10 @@ start = (unsigned long)sec->base->data->d_buf; end = start + sec->base->sh.sh_size; + + if (end <= start) + ERROR("bad section size"); + rela_addr = start + rela->offset; for (insn_addr = start; insn_addr < end; insn_addr += insn->length) { insn_init(insn, (void *)insn_addr, 1); @@ -1081,6 +1264,28 @@ } #endif +static bool is_callback_section(struct section *sec) { + + static char *callback_sections[] = { + ".kpatch.callbacks.pre_patch", + ".kpatch.callbacks.post_patch", + ".kpatch.callbacks.pre_unpatch", + ".kpatch.callbacks.post_unpatch", + ".rela.kpatch.callbacks.pre_patch", + ".rela.kpatch.callbacks.post_patch", + ".rela.kpatch.callbacks.pre_unpatch", + ".rela.kpatch.callbacks.post_unpatch", + NULL, + }; + char **callback_sec; + + for (callback_sec = callback_sections; *callback_sec; callback_sec++) + if (!strcmp(sec->name, *callback_sec)) + return true; + + return false; +} + /* * Mangle the relas a little. The compiler will sometimes use section symbols * to reference local objects and functions rather than the object or function @@ -1115,29 +1320,24 @@ rela->sym = rela->sym->sec->sym; /* - * ppc64le: a GCC 6+ bundled function is at - * offset 8 in its section. + * On ppc64le with GCC6+, even with + * -ffunction-sections, the function symbol + * starts 8 bytes past the beginning of the + * section, because the .TOC pointer is at the + * beginning, right before the code. So even + * though the symbol is bundled, we can't + * assume it's at offset 0 in the section. */ rela->addend -= rela->sym->sym.st_value; continue; } -#ifdef __powerpc__ - /* - * With -mcmodel=large, R_PPC64_REL24 is only used for - * functions. Assuming the function is bundled in a - * section, the section symbol should have been - * replaced with a text symbol already. Otherwise, - * bail out. If we hit this situation, more core is - * needed here to calculate the value of 'add_off'. - */ - if (rela->type == R_PPC64_REL24) - ERROR("Unexpected relocation type R_PPC64_REL24 for %s\n", rela->sym->name); - +#ifdef __powerpc64__ add_off = 0; #else - if (rela->type == R_X86_64_PC32) { + if (rela->type == R_X86_64_PC32 || + rela->type == R_X86_64_PLT32) { struct insn insn; rela_insn(sec, rela, &insn); add_off = (long)insn.next_byte - @@ -1158,6 +1358,7 @@ int start, end; if (sym->type == STT_SECTION || + !sym->sec || sym->sec != rela->sym->sec) continue; @@ -1166,8 +1367,8 @@ if (!is_text_section(sym->sec) && rela->type == R_X86_64_32S && - rela->addend == sym->sec->sh.sh_size && - end == sym->sec->sh.sh_size) { + rela->addend == (int)sym->sec->sh.sh_size && + end == (int)sym->sec->sh.sh_size) { /* * A special case where gcc needs a @@ -1225,7 +1426,7 @@ int errs = 0; list_for_each_entry(sym, &kelf->symbols, list) { - if (sym->type != STT_FUNC || sym->status != CHANGED) + if (sym->type != STT_FUNC || sym->status != CHANGED || sym->parent) continue; if (!sym->twin->has_func_profiling) { log_normal("function %s has no fentry/mcount call, unable to patch\n", @@ -1263,12 +1464,11 @@ /* * ensure we aren't including .data.* or .bss.* - * (.data.unlikely is ok b/c it only has __warned vars) + * (.data.unlikely and .data.once is ok b/c it only has __warned vars) */ if (sec->include && sec->status != NEW && - (!strncmp(sec->name, ".data", 5) || - !strncmp(sec->name, ".bss", 4)) && - strcmp(sec->name, ".data.unlikely")) { + (!strncmp(sec->name, ".data", 5) || !strncmp(sec->name, ".bss", 4)) && + (strcmp(sec->name, ".data.unlikely") && strcmp(sec->name, ".data.once"))) { log_normal("data section %s selected for inclusion\n", sec->name); errs++; @@ -1279,50 +1479,85 @@ DIFF_FATAL("%d unsupported section change(s)", errs); } -#define inc_printf(fmt, ...) \ - log_debug("%*s" fmt, recurselevel, "", ##__VA_ARGS__); +static void kpatch_include_symbol(struct symbol *sym); -static void kpatch_include_symbol(struct symbol *sym, int recurselevel) +static void kpatch_include_section(struct section *sec) { struct rela *rela; - struct section *sec; - inc_printf("start include_symbol(%s)\n", sym->name); - sym->include = 1; - inc_printf("symbol %s is included\n", sym->name); - /* - * Check if sym is a non-local symbol (sym->sec is NULL) or - * if an unchanged local symbol. This a base case for the - * inclusion recursion. - */ - if (!sym->sec || sym->sec->include || - (sym->type != STT_SECTION && sym->status == SAME)) - goto out; - sec = sym->sec; + /* Include the section and its section symbol */ + if (sec->include) + return; sec->include = 1; - inc_printf("section %s is included\n", sec->name); - if (sec->secsym && sec->secsym != sym) { + if (sec->secsym) sec->secsym->include = 1; - inc_printf("section symbol %s is included\n", sec->secsym->name); - } + + /* + * Include the section's rela section and then recursively include the + * symbols needed by its relas. + */ if (!sec->rela) - goto out; + return; sec->rela->include = 1; - inc_printf("section %s is included\n", sec->rela->name); list_for_each_entry(rela, &sec->rela->relas, list) - kpatch_include_symbol(rela->sym, recurselevel+1); -out: - inc_printf("end include_symbol(%s)\n", sym->name); - return; + kpatch_include_symbol(rela->sym); +} + +static void kpatch_include_symbol(struct symbol *sym) +{ + /* + * This function is called recursively from kpatch_include_section(). + * Make sure we don't get into an endless loop. + */ + if (sym->include) + return; + + /* + * The symbol gets included even if its section isn't needed, as it + * might be needed: either permanently for a rela, or temporarily for + * the later creation of a dynrela. + */ + sym->include = 1; + + /* + * For a function/object symbol, if it has a section, we only need to + * include the section if it has changed. Otherwise the symbol will be + * used by relas/dynrelas to link to the real symbol externally. + * + * For section symbols, we always include the section because + * references to them can't otherwise be resolved externally. + */ + if (sym->sec && (sym->type == STT_SECTION || sym->status != SAME)) + kpatch_include_section(sym->sec); } static void kpatch_include_standard_elements(struct kpatch_elf *kelf) { struct section *sec; - struct rela *rela; list_for_each_entry(sec, &kelf->sections, list) { - /* include these sections even if they haven't changed */ + /* + * Include the following sections even if they haven't changed. + * + * Notes about some of the more interesting sections: + * + * - With -fdata-sections, .rodata is only used for: + * + * switch jump tables; + * KASAN data (with KASAN enabled, which is rare); and + * an ugly hack in vmx_vcpu_run(). + * + * Those data are all local to the functions which use them. + * So it's safe to include .rodata. + * + * - On ppc64le, the .toc section is used for all data + * accesses. + * + * Note that if any of these sections have rela sections, they + * will also be included in their entirety. That may result in + * some extra (unused) dynrelas getting created, which should + * be harmless. + */ if (!strcmp(sec->name, ".shstrtab") || !strcmp(sec->name, ".strtab") || !strcmp(sec->name, ".symtab") || @@ -1330,21 +1565,7 @@ !strcmp(sec->name, ".rodata") || (!strncmp(sec->name, ".rodata.", 8) && strstr(sec->name, ".str1."))) { - sec->include = 1; - if (sec->secsym) - sec->secsym->include = 1; - } - - /* - * On ppc64le, the .rela.toc section refers to symbols which - * are needed for function symbol relocations. Include all the - * symbols. - */ - if (!strcmp(sec->name, ".rela.toc")) - { - sec->include = 1; - list_for_each_entry(rela, &sec->relas, list) - kpatch_include_symbol(rela->sym, 0); + kpatch_include_section(sec); } } @@ -1352,7 +1573,7 @@ list_entry(kelf->symbols.next, struct symbol, list)->include = 1; } -static int kpatch_include_hook_elements(struct kpatch_elf *kelf) +static int kpatch_include_callback_elements(struct kpatch_elf *kelf) { struct section *sec; struct symbol *sym; @@ -1361,38 +1582,27 @@ /* include load/unload sections */ list_for_each_entry(sec, &kelf->sections, list) { - if (!strcmp(sec->name, ".kpatch.hooks.load") || - !strcmp(sec->name, ".kpatch.hooks.unload") || - !strcmp(sec->name, ".rela.kpatch.hooks.load") || - !strcmp(sec->name, ".rela.kpatch.hooks.unload")) { - sec->include = 1; - found = 1; - if (is_rela_section(sec)) { - /* include hook dependencies */ - rela = list_entry(sec->relas.next, - struct rela, list); - sym = rela->sym; - log_normal("found hook: %s\n",sym->name); - kpatch_include_symbol(sym, 0); - /* strip the hook symbol */ - sym->include = 0; - sym->sec->sym = NULL; - /* use section symbol instead */ - rela->sym = sym->sec->secsym; - } else { - sec->secsym->include = 1; - } + if (!is_callback_section(sec)) + continue; + + sec->include = 1; + found = 1; + if (is_rela_section(sec)) { + /* include callback dependencies */ + rela = list_entry(sec->relas.next, struct rela, list); + sym = rela->sym; + log_normal("found callback: %s\n",sym->name); + kpatch_include_symbol(sym); + } else { + sec->secsym->include = 1; } } - /* - * Strip temporary global load/unload function pointer objects - * used by the kpatch_[load|unload]() macros. - */ - list_for_each_entry(sym, &kelf->symbols, list) - if (!strcmp(sym->name, "kpatch_load_data") || - !strcmp(sym->name, "kpatch_unload_data")) + /* Strip temporary global structures used by the callback macros. */ + list_for_each_entry(sym, &kelf->symbols, list) { + if (sym->sec && is_callback_section(sym->sec)) sym->include = 0; + } return found; } @@ -1435,7 +1645,7 @@ list_for_each_entry(sym, &kelf->symbols, list) { if (sym->bind == STB_GLOBAL && sym->sec && sym->status == NEW) { - kpatch_include_symbol(sym, 0); + kpatch_include_symbol(sym); nr++; } } @@ -1448,13 +1658,11 @@ struct symbol *sym; int changed_nr = 0; - log_debug("\n=== Inclusion Tree ===\n"); - list_for_each_entry(sym, &kelf->symbols, list) { if (sym->status == CHANGED && sym->type == STT_FUNC) { changed_nr++; - kpatch_include_symbol(sym, 0); + kpatch_include_symbol(sym); } if (sym->type == STT_FILE) @@ -1469,7 +1677,7 @@ struct symbol *sym; list_for_each_entry(sym, &kelf->symbols, list) { - if (!sym->include || !sym->sec || sym->type != STT_FUNC) + if (!sym->include || !sym->sec || sym->type != STT_FUNC || sym->parent) continue; if (sym->status == NEW) log_normal("new function: %s\n", sym->name); @@ -1531,7 +1739,7 @@ if (sym->sec && !sym->sec->include) /* break link to non-included section */ sym->sec = NULL; - + } *kelfout = out; @@ -1585,6 +1793,21 @@ return size; } +static int jump_table_group_size(struct kpatch_elf *kelf, int offset) +{ + static int size = 0; + char *str; + + if (!size) { + str = getenv("JUMP_STRUCT_SIZE"); + if (!str) + ERROR("JUMP_STRUCT_SIZE not set"); + size = atoi(str); + } + + return size; +} + #ifdef __x86_64__ static int parainstructions_group_size(struct kpatch_elf *kelf, int offset) { @@ -1621,7 +1844,7 @@ return 4; } #endif -#ifdef __powerpc__ +#ifdef __powerpc64__ static int fixup_entry_group_size(struct kpatch_elf *kelf, int offset) { static int size = 0; @@ -1639,7 +1862,12 @@ static int fixup_lwsync_group_size(struct kpatch_elf *kelf, int offset) { - return 4; + return 8; +} + +static int fixup_barrier_nospec_group_size(struct kpatch_elf *kelf, int offset) +{ + return 8; } #endif @@ -1685,6 +1913,8 @@ /* last group */ struct section *fixupsec; fixupsec = find_section_by_name(&kelf->sections, ".fixup"); + if (!fixupsec) + ERROR("missing .fixup section"); return fixupsec->sh.sh_size - offset; } @@ -1696,16 +1926,6 @@ .name = "__bug_table", .group_size = bug_table_group_size, }, -#ifdef __x86_64__ - { - .name = ".smp_locks", - .group_size = smp_locks_group_size, - }, - { - .name = ".parainstructions", - .group_size = parainstructions_group_size, - }, -#endif { .name = ".fixup", .group_size = fixup_group_size, @@ -1714,34 +1934,56 @@ .name = "__ex_table", /* must come after .fixup */ .group_size = ex_table_group_size, }, + { + .name = "__jump_table", + .group_size = jump_table_group_size, + }, #ifdef __x86_64__ { + .name = ".smp_locks", + .group_size = smp_locks_group_size, + }, + { + .name = ".parainstructions", + .group_size = parainstructions_group_size, + }, + { .name = ".altinstructions", .group_size = altinstructions_group_size, }, #endif -#ifdef __powerpc__ +#ifdef __powerpc64__ { .name = "__ftr_fixup", .group_size = fixup_entry_group_size, + .unsupported = 1, }, { .name = "__mmu_ftr_fixup", .group_size = fixup_entry_group_size, + .unsupported = 1, }, { .name = "__fw_ftr_fixup", .group_size = fixup_entry_group_size, + .unsupported = 1, }, { .name = "__lwsync_fixup", .group_size = fixup_lwsync_group_size, + .unsupported = 1, + }, + { + .name = "__barrier_nospec_fixup", + .group_size = fixup_barrier_nospec_group_size, + .unsupported = 1, }, #endif {}, }; -static int should_keep_rela_group(struct section *sec, int start, int size) +static int should_keep_rela_group(struct section *sec, unsigned int start, + unsigned int size) { struct rela *rela; int found = 0; @@ -1792,7 +2034,8 @@ { struct rela *rela, *safe; char *src, *dest; - int group_size, src_offset, dest_offset, include; + unsigned int group_size, src_offset, dest_offset, include; + int jump_table = !strcmp(special->name, "__jump_table"); LIST_HEAD(newrelas); @@ -1810,7 +2053,6 @@ } } - group_size = 0; src_offset = 0; dest_offset = 0; for ( ; src_offset < sec->base->sh.sh_size; src_offset += group_size) { @@ -1833,6 +2075,52 @@ if (!include) continue; + if (special->unsupported) + DIFF_FATAL("unsupported reference to special section %s", sec->base->name); + + /* + * Jump labels (aka static keys or static branches) aren't + * actually supported for the time being. Warn on all + * non-tracepoint jump labels when they occur in a replacement + * function. An inert tracepoint is harmless enough, but a + * broken static key can cause unexpected behavior. + * + * Here we hard-code knowledge about the contents of the + * jump_label struct. It has three fields: code, target, and + * key. + */ + if (jump_table) { + struct rela *code, *key; + int i = 0; + + list_for_each_entry(rela, &sec->relas, list) { + if (rela->offset >= src_offset && + rela->offset < src_offset + group_size) { + if (i == 0) + code = rela; + else if (i == 2) + key = rela; + i++; + } + } + + if (i != 3) + ERROR("BUG: __jump_table has an unexpected format"); + + /* inert tracepoints are harmless */ + if (!strncmp(key->sym->name, "__tracepoint_", 13)) + continue; + + /* inert dynamic debug printks are harmless */ + if (is_dynamic_debug_symbol(key->sym)) + continue; + + ERROR("Found a jump label at %s()+0x%x, using key %s. Jump labels aren't currently supported. Use static_key_enabled() instead.", + code->sym->name, code->addend, key->sym->name); + + continue; + } + /* * Copy all relas in the group. It's possible that the relas * aren't sorted (e.g. .rela.fixup), so go through the entire @@ -1891,6 +2179,118 @@ sec->base->data->d_size = dest_offset; } +#define ORC_IP_PTR_SIZE 4 + +/* + * This function is similar to kpatch_regenerate_special_section(), but + * customized for the ORC-related sections. ORC is more special than the other + * special sections because each ORC entry is split into .orc_unwind (struct + * orc_entry) and .orc_unwind_ip. + */ +static void kpatch_regenerate_orc_sections(struct kpatch_elf *kelf) +{ + struct rela *rela, *safe; + char *src, *dest, *str; + unsigned int src_idx = 0, dest_idx = 0, orc_entry_size; + struct section *orc_sec, *ip_sec; + + + str = getenv("ORC_STRUCT_SIZE"); + if (!str) + return; + orc_entry_size = atoi(str); + + if (!orc_entry_size) + ERROR("bad ORC_STRUCT_SIZE"); + + LIST_HEAD(newrelas); + + orc_sec = find_section_by_name(&kelf->sections, ".orc_unwind"); + ip_sec = find_section_by_name(&kelf->sections, ".orc_unwind_ip"); + + if (!orc_sec || !ip_sec) + return; + + if (orc_sec->sh.sh_size % orc_entry_size != 0) + ERROR("bad .orc_unwind size"); + + if (ip_sec->sh.sh_size != + (orc_sec->sh.sh_size / orc_entry_size) * ORC_IP_PTR_SIZE) + ERROR(".orc_unwind/.orc_unwind_ip size mismatch"); + + src = orc_sec->data->d_buf; + dest = malloc(orc_sec->sh.sh_size); + if (!dest) + ERROR("malloc"); + + list_for_each_entry_safe(rela, safe, &ip_sec->rela->relas, list) { + + if (rela->sym->type != STT_FUNC || !rela->sym->sec->include) + goto next; + + /* copy orc entry */ + memcpy(dest + (dest_idx * orc_entry_size), + src + (src_idx * orc_entry_size), + orc_entry_size); + + /* move ip rela */ + list_del(&rela->list); + list_add_tail(&rela->list, &newrelas); + rela->offset = dest_idx * ORC_IP_PTR_SIZE; + rela->sym->include = 1; + + dest_idx++; +next: + src_idx++; + } + + if (!dest_idx) { + /* no changed or global functions referenced */ + orc_sec->status = ip_sec->status = ip_sec->rela->status = SAME; + orc_sec->include = ip_sec->include = ip_sec->rela->include = 0; + free(dest); + return; + } + + /* overwrite with new relas list */ + list_replace(&newrelas, &ip_sec->rela->relas); + + /* include the sections */ + orc_sec->include = ip_sec->include = ip_sec->rela->include = 1; + + /* + * Update data buf/size. + * + * The ip section can keep its old (zeroed data), though its size has + * possibly decreased. The ip rela section's data buf and size will be + * regenerated in kpatch_rebuild_rela_section_data(). + */ + orc_sec->data->d_buf = dest; + orc_sec->data->d_size = dest_idx * orc_entry_size; + ip_sec->data->d_size = dest_idx * ORC_IP_PTR_SIZE; +} + +static void kpatch_check_relocations(struct kpatch_elf *kelf) +{ + struct rela *rela; + struct section *sec; + Elf_Data *sdata; + + list_for_each_entry(sec, &kelf->sections, list) { + if (!is_rela_section(sec)) + continue; + list_for_each_entry(rela, &sec->relas, list) { + if (rela->sym->sec) { + sdata = rela->sym->sec->data; + if (rela->addend > (int)sdata->d_size) { + ERROR("out-of-range relocation %s+%x in %s", rela->sym->sec->name, + rela->addend, sec->name); + } + } + } + } +} + static void kpatch_include_debug_sections(struct kpatch_elf *kelf) { struct section *sec; @@ -1950,6 +2350,7 @@ * from the section data comparison, but this is a simpler way. */ strsec->include = 1; + strsec->secsym->include = 1; name = strsec->data->d_buf + rela->addend; ignoresec = find_section_by_name(&kelf->sections, name); if (!ignoresec) @@ -2012,6 +2413,10 @@ log_normal("NOTICE: no change detected in function %s, unnecessary KPATCH_IGNORE_FUNCTION()?\n", rela->sym->name); rela->sym->status = SAME; rela->sym->sec->status = SAME; + + if (rela->sym->child) + rela->sym->child->status = SAME; + if (rela->sym->sec->secsym) rela->sym->sec->secsym->status = SAME; if (rela->sym->sec->rela) @@ -2028,15 +2433,13 @@ static void kpatch_create_kpatch_arch_section(struct kpatch_elf *kelf, char *objname) { struct special_section *special; - struct kpatch_arch *entries; struct symbol *strsym; struct section *sec, *karch_sec; struct rela *rela; int nr, index = 0; nr = sizeof(special_sections) / sizeof(special_sections[0]); - karch_sec = create_section_pair(kelf, ".kpatch.arch", sizeof(*entries), nr); - entries = karch_sec->data->d_buf; + karch_sec = create_section_pair(kelf, ".kpatch.arch", sizeof(struct kpatch_arch), nr); /* lookup strings symbol */ strsym = find_symbol_by_name(&kelf->symbols, ".kpatch.strings"); @@ -2057,7 +2460,7 @@ rela->sym = sec->secsym; rela->type = ABSOLUTE_RELA_TYPE; rela->addend = 0; - rela->offset = index * sizeof(*entries) + \ + rela->offset = index * sizeof(struct kpatch_arch) + \ offsetof(struct kpatch_arch, sec); /* entries[index].objname */ @@ -2065,7 +2468,7 @@ rela->sym = strsym; rela->type = ABSOLUTE_RELA_TYPE; rela->addend = offset_of_string(&kelf->strings, objname); - rela->offset = index * sizeof(*entries) + \ + rela->offset = index * sizeof(struct kpatch_arch) + \ offsetof(struct kpatch_arch, objname); index++; @@ -2125,7 +2528,7 @@ sec->rela->include = 1; /* include all symbols referenced by relas */ list_for_each_entry(rela, &sec->rela->relas, list) - rela->sym->include = 1; + kpatch_include_symbol(rela->sym); } } @@ -2150,6 +2553,8 @@ sec->rela->include = 0; } } + + kpatch_regenerate_orc_sections(kelf); } static struct sym_compare_type *kpatch_elf_locals(struct kpatch_elf *kelf) @@ -2181,7 +2586,7 @@ continue; sym_array[i].type = sym->type; - sym_array[i++].name = sym->name; + sym_array[i++].name = strdup(sym->name); } sym_array[i].type = 0; sym_array[i].name = NULL; @@ -2190,7 +2595,7 @@ } static void kpatch_create_patches_sections(struct kpatch_elf *kelf, - struct lookup_table *table, char *hint, + struct lookup_table *table, char *objname) { int nr, index, objname_offset; @@ -2203,7 +2608,7 @@ /* count patched functions */ nr = 0; list_for_each_entry(sym, &kelf->symbols, list) - if (sym->type == STT_FUNC && sym->status == CHANGED) + if (sym->type == STT_FUNC && sym->status == CHANGED && !sym->parent) nr++; /* create text/rela section pair */ @@ -2222,12 +2627,12 @@ /* populate sections */ index = 0; list_for_each_entry(sym, &kelf->symbols, list) { - if (sym->type == STT_FUNC && sym->status == CHANGED) { + if (sym->type == STT_FUNC && sym->status == CHANGED && !sym->parent) { if (sym->bind == STB_LOCAL) { if (lookup_local_symbol(table, sym->name, &result)) - ERROR("lookup_local_symbol %s (%s)", - sym->name, hint); + ERROR("lookup_local_symbol %s", + sym->name); } else { if(lookup_global_symbol(table, sym->name, &result)) @@ -2239,7 +2644,7 @@ /* * Convert global symbols to local so other objects in - * the patch module (like the patch hook object's init + * the patch module (like the patch callback object's init * code) won't link to this function and call it before * its relocations have been applied. */ @@ -2302,9 +2707,79 @@ !strcmp(name, "kpatch_shadow_get")); } +/* + * If the patched code refers to a symbol, for example, calls a function + * or stores a pointer to a function somewhere, the address of that symbol + * must be resolved somehow before the patch is applied. The symbol may be + * present in the original code too, so the patch may refer either to that + * version of the symbol (dynrela is used for that) or to its patched + * version directly (with a normal relocation). + * + * Dynrelas may be needed for the symbols not present in this object file + * (rela->sym->sec is NULL), because it is unknown if the patched versions + * of these symbols exist and where they are. + * + * The patched code can usually refer to a symbol from this object file + * directly. If it is a function, this may also improve performance because + * it will not be needed to call the original function first, find the + * patched one and then use Ftrace to pass control to it. + * + * There is an exception though, at least on x86. It is safer to use + * a dynrela if the patched code stores a pointer to a function somewhere + * (relocation of type R_X86_64_32S). The function could be used as + * a callback and some kinds of callbacks are called asynchronously. If + * the patch module sets such callback and is unloaded shortly after, + * the kernel could try to call the function via an invalid pointer and + * would crash. With dynrela, the kernel would call the original function + * in that case. + */ +static int function_ptr_rela(const struct rela *rela) +{ + const struct rela *rela_toc = toc_rela(rela); + + return (rela_toc && rela_toc->sym->type == STT_FUNC && + !rela_toc->sym->parent && + /* skip switch table on PowerPC */ + rela_toc->addend == (int)rela_toc->sym->sym.st_value && + (rela->type == R_X86_64_32S || + rela->type == R_PPC64_TOC16_HA || + rela->type == R_PPC64_TOC16_LO_DS)); +} + +static int may_need_dynrela(const struct rela *rela) +{ + /* + * References to .TOC. are treated specially by the module loader and + * should never be converted to dynrelas. + */ + if (rela->type == R_PPC64_REL16_HA || rela->type == R_PPC64_REL16_LO || + rela->type == R_PPC64_REL64) + return 0; + + if (!rela->sym->sec) + return 1; + + /* + * Nested functions used as callbacks are a special case. + * They are not supposed to be visible outside of the + * function that defines them. Their names may differ in + * the original and the patched kernels which makes it + * difficult to use dynrelas. Fortunately, nested functions + * are rare and are unlikely to be used as asynchronous + * callbacks, so the patched code can refer to them directly. + * It seems, one can only distinguish such functions by their + * names containing a dot. Other kinds of functions with + * such names (e.g. optimized copies of functions) are + * unlikely to be used as callbacks. + */ + return (function_ptr_rela(rela) && + toc_rela(rela)->sym->status != NEW && + !strchr(toc_rela(rela)->sym->name, '.')); +} + static void kpatch_create_intermediate_sections(struct kpatch_elf *kelf, struct lookup_table *table, - char *hint, char *objname, + char *objname, char *pmod_name) { int nr, index; @@ -2326,8 +2801,28 @@ continue; if (!strcmp(sec->name, ".rela.kpatch.funcs")) continue; - list_for_each_entry(rela, &sec->relas, list) + list_for_each_entry(rela, &sec->relas, list) { nr++; /* upper bound on number of kpatch relas and symbols */ + /* + * Relocation section '.rela.toc' at offset 0xcc6b0 contains 46 entries: + * ... + * 0000000000000138 0000002a00000026 R_PPC64_ADDR64 0000000000000000 .text.deferred_put_nlk_sk + 8 + * + * Relocation section '.rela.text.netlink_release' at offset 0xcadf0 contains 44 entries: + * ... + * 0000000000000398 0000007300000032 R_PPC64_TOC16_HA 0000000000000000 .toc + 138 + * 00000000000003a0 0000007300000040 R_PPC64_TOC16_LO_DS 0000000000000000 .toc + 138 + * + * On PowerPC, may_need_dynrela() should be using rela's reference in .rela.toc for + * the rela like in the example, where the sym name is .toc + offset. In such case, + * the checks are performed on both rela and its reference in .rela.toc. Where the + * rela is checked for rela->type and its corresponding rela in .rela.toc for function + * pointer/switch label. If rela->need_dynrela needs to be set, it's referenced rela + * in (.rela.toc)->need_dynrela is set, as they represent the function sym. + */ + if (may_need_dynrela(rela)) + toc_rela(rela)->need_dynrela = 1; + } } /* create .kpatch.relocations text/rela section pair */ @@ -2357,11 +2852,13 @@ if (!is_rela_section(sec)) continue; if (!strcmp(sec->name, ".rela.kpatch.funcs") || - !strcmp(sec->name, ".rela.kpatch.dynrelas")) + !strcmp(sec->name, ".rela.kpatch.relocations") || + !strcmp(sec->name, ".rela.kpatch.symbols")) continue; list_for_each_entry_safe(rela, safe, &sec->relas, list) { - if (rela->sym->sec) + if (!rela->need_dynrela) continue; + /* * Allow references to core module symbols to remain as * normal relas, since the core module may not be @@ -2408,8 +2905,8 @@ ret = lookup_local_symbol(table, rela->sym->name, &result); if (ret) - ERROR("lookup_local_symbol %s:%s needed for %s", - hint, rela->sym->name, sec->base->name); + ERROR("lookup_local_symbol %s needed for %s", + rela->sym->name, sec->base->name); } else if (vmlinux) { @@ -2418,7 +2915,7 @@ * a global symbol. Use a normal rela for * exported symbols and a dynrela otherwise. */ -#ifdef __powerpc__ +#ifdef __powerpc64__ /* * An exported symbol might be local to an * object file and any access to the function @@ -2514,6 +3011,9 @@ offsetof(struct kpatch_symbol, objname); /* Fill in krelas[index] */ + if (is_gcc6_localentry_bundled_sym(rela->sym) && + rela->addend == (int)rela->sym->sym.st_value) + rela->addend -= rela->sym->sym.st_value; krelas[index].addend = rela->addend; krelas[index].type = rela->type; krelas[index].external = external; @@ -2547,7 +3047,15 @@ rela2->offset = index * sizeof(*krelas) + \ offsetof(struct kpatch_relocation, ksym); - rela->sym->strip = 1; + /* + * Mark the referred to symbol for removal but + * only if it is not from this object file. + * The symbols from this object file may be needed + * later (for example, they may have relocations + * of their own which should be processed). + */ + if (!rela->sym->sec) + rela->sym->strip = 1; list_del(&rela->list); free(rela); @@ -2563,13 +3071,27 @@ krela_sec->sh.sh_size = krela_sec->data->d_size; } -static void kpatch_create_hooks_objname_rela(struct kpatch_elf *kelf, char *objname) +static void kpatch_create_callbacks_objname_rela(struct kpatch_elf *kelf, char *objname) { struct section *sec; struct rela *rela; struct symbol *strsym; int objname_offset; + struct callback { char *name; int offset; }; + static struct callback callbacks[] = { + { .name = ".rela.kpatch.callbacks.pre_patch", + .offset = offsetof(struct kpatch_pre_patch_callback, objname) }, + { .name = ".rela.kpatch.callbacks.post_patch", + .offset = offsetof(struct kpatch_post_patch_callback, objname) }, + { .name = ".rela.kpatch.callbacks.pre_unpatch", + .offset = offsetof(struct kpatch_pre_unpatch_callback, objname) }, + { .name = ".rela.kpatch.callbacks.post_unpatch", + .offset = offsetof(struct kpatch_post_patch_callback, objname) }, + { .name = NULL, .offset = 0 }, + }; + struct callback *callbackp; + /* lookup strings symbol */ strsym = find_symbol_by_name(&kelf->symbols, ".kpatch.strings"); if (!strsym) @@ -2579,19 +3101,20 @@ objname_offset = offset_of_string(&kelf->strings, objname); list_for_each_entry(sec, &kelf->sections, list) { - if (strcmp(sec->name, ".rela.kpatch.hooks.load") && - strcmp(sec->name, ".rela.kpatch.hooks.unload")) - continue; - - ALLOC_LINK(rela, &sec->relas); - rela->sym = strsym; - rela->type = ABSOLUTE_RELA_TYPE; - rela->addend = objname_offset; - rela->offset = offsetof(struct kpatch_patch_hook, objname); + for (callbackp = callbacks; callbackp->name; callbackp++) { + if (!strcmp(callbackp->name, sec->name)) { + ALLOC_LINK(rela, &sec->relas); + rela->sym = strsym; + rela->type = ABSOLUTE_RELA_TYPE; + rela->addend = objname_offset; + rela->offset = callbackp->offset; + break; + } + } } } -#ifdef __powerpc__ +#ifdef __powerpc64__ void kpatch_create_mcount_sections(struct kpatch_elf *kelf) { } #else /* @@ -2607,7 +3130,7 @@ struct section *sec, *relasec; struct symbol *sym; struct rela *rela; - void **funcs, *newdata; + void *newdata; unsigned char *insn; nr = 0; @@ -2617,9 +3140,8 @@ nr++; /* create text/rela section pair */ - sec = create_section_pair(kelf, "__mcount_loc", sizeof(*funcs), nr); + sec = create_section_pair(kelf, "__mcount_loc", sizeof(void*), nr); relasec = sec->rela; - funcs = sec->data->d_buf; /* populate sections */ index = 0; @@ -2638,28 +3160,39 @@ rela->sym = sym; rela->type = R_X86_64_64; rela->addend = 0; - rela->offset = index * sizeof(*funcs); + rela->offset = index * sizeof(void*); /* * Modify the first instruction of the function to "callq * __fentry__" so that ftrace will be happy. */ newdata = malloc(sym->sec->data->d_size); + if (!newdata) + ERROR("malloc"); + memcpy(newdata, sym->sec->data->d_buf, sym->sec->data->d_size); sym->sec->data->d_buf = newdata; insn = newdata; - if (insn[0] != 0xf) - ERROR("%s: unexpected instruction at the start of the function", - sym->name); - insn[0] = 0xe8; - insn[1] = 0; - insn[2] = 0; - insn[3] = 0; - insn[4] = 0; rela = list_first_entry(&sym->sec->rela->relas, struct rela, list); - rela->type = R_X86_64_PC32; + + /* + * R_X86_64_NONE is only generated by older versions of kernel/gcc + * which use the mcount script. + */ + if (rela->type == R_X86_64_NONE) { + if (insn[0] != 0xf) + ERROR("%s: unexpected instruction at the start of the function", + sym->name); + insn[0] = 0xe8; + insn[1] = 0; + insn[2] = 0; + insn[3] = 0; + insn[4] = 0; + + rela->type = R_X86_64_PC32; + } index++; } @@ -2751,12 +3284,66 @@ } } +/* + * Don't allow sibling calls from patched functions on ppc64le. Before doing a + * sibling call, the patched function restores the stack to its caller's stack. + * The kernel-generated stub then writes the patch module's r2 (toc) value to + * the caller's stack, corrupting it, eventually causing a panic after it + * returns to the caller and the caller tries to use the livepatch module's toc + * value. + * + * In theory we could instead a) generate a custom stub, or b) modify the + * kernel livepatch_handler code to save/restore the stack r2 value, but this + * is easier for now. + */ +static void kpatch_no_sibling_calls_ppc64le(struct kpatch_elf *kelf) +{ +#ifdef __powerpc64__ + struct symbol *sym; + unsigned int insn; + unsigned long offset; + + list_for_each_entry(sym, &kelf->symbols, list) { + if (sym->type != STT_FUNC || sym->status != CHANGED) + continue; + + for (offset = 0; offset < sym->sec->data->d_size; offset += 4) { + + insn = *(unsigned int *)(sym->sec->data->d_buf + offset); + + /* + * The instruction 0x48000000 can be assumed to be a + * sibling call: + * + * Bits 0-5 (opcode) == 0x9: unconditional branch + * Bit 30 (absolute) == 0: relative address + * Bit 31 (link) == 0: doesn't set LR (not a call) + * + * Bits 6-29 (branch address) == zero, which means + * it's either a branch to self (infinite loop), or + * there's a REL24 relocation for the address which + * will be written by the linker or the kernel. + */ + if (insn != 0x48000000) + continue; + + /* Make sure it's not a branch-to-self: */ + if (!find_rela_by_offset(sym->sec->rela, offset)) + continue; + + ERROR("Found an unsupported sibling call at %s()+0x%lx. Add __attribute__((optimize(\"-fno-optimize-sibling-calls\"))) to %s() definition.", + sym->name, sym->sym.st_value + offset, sym->name); + } + } +#endif +} + struct arguments { - char *args[6]; + char *args[7]; int debug; }; -static char args_doc[] = "original.o patched.o kernel-object output.o Module.symvers patch-module-name"; +static char args_doc[] = "original.o patched.o parent-name parent-symtab Module.symvers patch-module-name output.o"; static struct argp_option options[] = { {"debug", 'd', NULL, 0, "Show debug output" }, @@ -2775,13 +3362,13 @@ arguments->debug = 1; break; case ARGP_KEY_ARG: - if (state->arg_num >= 6) + if (state->arg_num >= 7) /* Too many arguments. */ argp_usage (state); arguments->args[state->arg_num] = arg; break; case ARGP_KEY_END: - if (state->arg_num < 6) + if (state->arg_num < 7) /* Not enough arguments. */ argp_usage (state); break; @@ -2797,13 +3384,13 @@ { struct kpatch_elf *kelf_base, *kelf_patched, *kelf_out; struct arguments arguments; - int num_changed, hooks_exist, new_globals_exist; + int num_changed, callbacks_exist, new_globals_exist; struct lookup_table *lookup; struct section *sec, *symtab; struct symbol *sym; - char *hint = NULL, *objname, *pos; - char *mod_symvers_path, *pmod_name; - struct sym_compare_type *base_locals; + char *hint = NULL, *orig_obj, *patched_obj, *parent_name; + char *parent_symtab, *mod_symvers, *patch_name, *output_obj; + struct sym_compare_type *base_locals, *sym_comp; arguments.debug = 0; argp_parse (&argp, argc, argv, 0, NULL, &arguments); @@ -2812,34 +3399,41 @@ elf_version(EV_CURRENT); - childobj = basename(arguments.args[0]); + orig_obj = arguments.args[0]; + patched_obj = arguments.args[1]; + parent_name = arguments.args[2]; + parent_symtab = arguments.args[3]; + mod_symvers = arguments.args[4]; + patch_name = arguments.args[5]; + output_obj = arguments.args[6]; - mod_symvers_path = arguments.args[4]; - pmod_name = arguments.args[5]; + childobj = basename(orig_obj); - kelf_base = kpatch_elf_open(arguments.args[0]); - kelf_patched = kpatch_elf_open(arguments.args[1]); + kelf_base = kpatch_elf_open(orig_obj); + kelf_patched = kpatch_elf_open(patched_obj); kpatch_bundle_symbols(kelf_base); kpatch_bundle_symbols(kelf_patched); + kpatch_detect_child_functions(kelf_base); + kpatch_detect_child_functions(kelf_patched); + kpatch_compare_elf_headers(kelf_base->elf, kelf_patched->elf); kpatch_check_program_headers(kelf_base->elf); kpatch_check_program_headers(kelf_patched->elf); list_for_each_entry(sym, &kelf_base->symbols, list) { if (sym->type == STT_FILE) { - hint = sym->name; + hint = strdup(sym->name); break; } } - if (!hint) - ERROR("FILE symbol not found in base. Stripped?\n"); + if (!hint) { + log_normal("WARNING: FILE symbol not found in base. Stripped object file or assembly source?\n"); + return EXIT_STATUS_NO_CHANGE; + } - /* create symbol lookup table */ base_locals = kpatch_elf_locals(kelf_base); - lookup = lookup_open(arguments.args[2], mod_symvers_path, hint, base_locals); - free(base_locals); kpatch_mark_grouped_sections(kelf_patched); kpatch_replace_sections_syms(kelf_base); @@ -2866,22 +3460,24 @@ kpatch_include_standard_elements(kelf_patched); num_changed = kpatch_include_changed_functions(kelf_patched); kpatch_include_debug_sections(kelf_patched); - hooks_exist = kpatch_include_hook_elements(kelf_patched); + callbacks_exist = kpatch_include_callback_elements(kelf_patched); kpatch_include_force_elements(kelf_patched); new_globals_exist = kpatch_include_new_globals(kelf_patched); + kpatch_process_special_sections(kelf_patched); + kpatch_print_changes(kelf_patched); kpatch_dump_kelf(kelf_patched); - kpatch_process_special_sections(kelf_patched); kpatch_verify_patchability(kelf_patched); if (!num_changed && !new_globals_exist) { - if (hooks_exist) - log_debug("no changed functions were found, but hooks exist\n"); + if (callbacks_exist) + log_debug("no changed functions were found, but callbacks exist\n"); else { log_debug("no changed functions were found\n"); - return 3; /* 1 is ERROR, 2 is DIFF_FATAL */ + free(hint); + return EXIT_STATUS_NO_CHANGE; } } @@ -2896,27 +3492,22 @@ */ kpatch_elf_teardown(kelf_patched); - /* extract module name (destructive to arguments.modulefile) */ - objname = basename(arguments.args[2]); - if (!strncmp(objname, "vmlinux-", 8)) - objname = "vmlinux"; - else { - pos = strchr(objname,'.'); - if (pos) { - /* kernel module */ - *pos = '\0'; - pos = objname; - while ((pos = strchr(pos, '-'))) - *pos++ = '_'; - } + /* create symbol lookup table */ + lookup = lookup_open(parent_symtab, mod_symvers, hint, base_locals); + for (sym_comp = base_locals; sym_comp && sym_comp->name; sym_comp++) { + free(sym_comp->name); } + free(base_locals); + free(hint); + + kpatch_no_sibling_calls_ppc64le(kelf_out); /* create strings, patches, and dynrelas sections */ kpatch_create_strings_elements(kelf_out); - kpatch_create_patches_sections(kelf_out, lookup, hint, objname); - kpatch_create_intermediate_sections(kelf_out, lookup, hint, objname, pmod_name); - kpatch_create_kpatch_arch_section(kelf_out, objname); - kpatch_create_hooks_objname_rela(kelf_out, objname); + kpatch_create_patches_sections(kelf_out, lookup, parent_name); + kpatch_create_intermediate_sections(kelf_out, lookup, parent_name, patch_name); + kpatch_create_kpatch_arch_section(kelf_out, parent_name); + kpatch_create_callbacks_objname_rela(kelf_out, parent_name); kpatch_build_strings_section_data(kelf_out); kpatch_create_mcount_sections(kelf_out); @@ -2937,6 +3528,9 @@ * buffers from the relas lists. */ symtab = find_section_by_name(&kelf_out->sections, ".symtab"); + if (!symtab) + ERROR("missing .symtab section"); + list_for_each_entry(sec, &kelf_out->sections, list) { if (!is_rela_section(sec)) continue; @@ -2944,16 +3538,18 @@ sec->sh.sh_info = sec->base->index; kpatch_rebuild_rela_section_data(sec); } + kpatch_check_relocations(kelf_out); kpatch_create_shstrtab(kelf_out); kpatch_create_strtab(kelf_out); kpatch_create_symtab(kelf_out); kpatch_dump_kelf(kelf_out); - kpatch_write_output_elf(kelf_out, kelf_patched->elf, arguments.args[3]); + kpatch_write_output_elf(kelf_out, kelf_patched->elf, output_obj); + lookup_close(lookup); kpatch_elf_free(kelf_patched); kpatch_elf_teardown(kelf_out); kpatch_elf_free(kelf_out); - return 0; + return EXIT_STATUS_SUCCESS; } diff -Nru kpatch-0.5.0/kpatch-build/create-klp-module.c kpatch-0.8.0/kpatch-build/create-klp-module.c --- kpatch-0.5.0/kpatch-build/create-klp-module.c 2017-12-21 05:02:48.000000000 +0000 +++ kpatch-0.8.0/kpatch-build/create-klp-module.c 2019-08-28 17:34:00.000000000 +0000 @@ -57,9 +57,7 @@ if (!rela) ERROR("name of ksym not found?"); - name = strdup(strings + rela->addend); - if (!name) - ERROR("strdup"); + name = strings + rela->addend; /* Get objname of ksym */ rela = find_rela_by_offset(ksymsec->rela, @@ -67,9 +65,7 @@ if (!rela) ERROR("objname of ksym not found?"); - objname = strdup(strings + rela->addend); - if (!objname) - ERROR("strdup"); + objname = strings + rela->addend; snprintf(pos, 32, "%lu", ksym->pos); /* .klp.sym.objname.name,pos */ @@ -81,7 +77,7 @@ return sym; } - ALLOC_LINK(sym, &kelf->symbols); + ALLOC_LINK(sym, NULL); sym->name = strdup(buf); if (!sym->name) ERROR("strdup"); @@ -93,6 +89,25 @@ */ sym->sym.st_shndx = SHN_LIVEPATCH; sym->sym.st_info = GELF_ST_INFO(sym->bind, sym->type); + /* + * Figure out where to put the new symbol: + * a) locals need to be grouped together, before globals + * b) globals can be tacked into the end of the list + */ + if (is_local_sym(sym)) { + struct list_head *head; + struct symbol *s; + + head = &kelf->symbols; + list_for_each_entry(s, &kelf->symbols, list) { + if (!is_local_sym(s)) + break; + head = &s->list; + } + list_add_tail(&sym->list, head); + } else { + list_add_tail(&sym->list, &kelf->symbols); + } return sym; } @@ -183,9 +198,7 @@ if (!rela) ERROR("find_rela_by_offset"); - objname = strdup(strings + rela->addend); - if (!objname) - ERROR("strdup"); + objname = strings + rela->addend; /* Get the .kpatch.symbol entry for the rela src */ rela = find_rela_by_offset(krelasec->rela, @@ -231,7 +244,6 @@ static void create_klp_arch_sections(struct kpatch_elf *kelf, char *strings) { struct section *karch, *sec, *base = NULL; - struct kpatch_arch *entries; struct rela *rela, *rela2; char *secname, *objname = NULL; char buf[256]; @@ -241,11 +253,10 @@ if (!karch) return; - entries = karch->data->d_buf; - nr = karch->data->d_size / sizeof(*entries); + nr = karch->data->d_size / sizeof(struct kpatch_arch); for (index = 0; index < nr; index++) { - offset = index * sizeof(*entries); + offset = index * sizeof(struct kpatch_arch); /* Get the base section (.parainstructions or .altinstructions) */ rela = find_rela_by_offset(karch->rela, @@ -263,9 +274,7 @@ if (!rela) ERROR("find_rela_by_offset"); - objname = strdup(strings + rela->addend); - if (!objname) - ERROR("strdup"); + objname = strings + rela->addend; /* Example: .klp.arch.vmlinux..parainstructions */ snprintf(buf, 256, "%s%s.%s", KLP_ARCH_PREFIX, objname, base->name); @@ -292,6 +301,27 @@ * single .klp.arch.vmlinux..parainstructions section */ old_size = sec->data->d_size; + + /* + * Due to a quirk in how .parainstructions gets linked, the + * section size doesn't encompass the last 4 bytes of the last + * entry. Align the old size properly before merging. + */ + if (!strcmp(base->name, ".parainstructions")) { + char *str; + static int align_mask = 0; + + if (!align_mask) { + str = getenv("PARA_STRUCT_SIZE"); + if (!str) + ERROR("PARA_STRUCT_SIZE not set"); + + align_mask = atoi(str) - 1; + } + + old_size = (old_size + align_mask) & ~align_mask; + } + new_size = old_size + base->data->d_size; sec->data->d_buf = realloc(sec->data->d_buf, new_size); sec->data->d_size = new_size; @@ -316,7 +346,7 @@ */ static void remove_arch_sections(struct kpatch_elf *kelf) { - int i; + size_t i; char *arch_sections[] = { ".parainstructions", ".rela.parainstructions", @@ -331,7 +361,7 @@ static void remove_intermediate_sections(struct kpatch_elf *kelf) { - int i; + size_t i; char *intermediate_sections[] = { ".kpatch.symbols", ".rela.kpatch.symbols", @@ -456,6 +486,9 @@ /* Rebuild rela sections, new klp rela sections will be rebuilt too. */ symtab = find_section_by_name(&kelf->sections, ".symtab"); + if (!symtab) + ERROR("missing .symtab section"); + list_for_each_entry(sec, &kelf->sections, list) { if (!is_rela_section(sec)) continue; diff -Nru kpatch-0.5.0/kpatch-build/create-kpatch-module.c kpatch-0.8.0/kpatch-build/create-kpatch-module.c --- kpatch-0.5.0/kpatch-build/create-kpatch-module.c 2017-12-21 05:02:48.000000000 +0000 +++ kpatch-0.8.0/kpatch-build/create-kpatch-module.c 2019-08-28 17:34:00.000000000 +0000 @@ -126,7 +126,7 @@ static void remove_intermediate_sections(struct kpatch_elf *kelf) { - int i; + size_t i; char *intermediate_sections[] = { ".kpatch.symbols", ".rela.kpatch.symbols", @@ -231,6 +231,9 @@ kpatch_reindex_elements(kelf); symtab = find_section_by_name(&kelf->sections, ".symtab"); + if (!symtab) + ERROR("missing .symtab section"); + list_for_each_entry(sec, &kelf->sections, list) { if (!is_rela_section(sec)) continue; diff -Nru kpatch-0.5.0/kpatch-build/gcc-plugins/gcc-common.h kpatch-0.8.0/kpatch-build/gcc-plugins/gcc-common.h --- kpatch-0.5.0/kpatch-build/gcc-plugins/gcc-common.h 2017-12-21 05:02:48.000000000 +0000 +++ kpatch-0.8.0/kpatch-build/gcc-plugins/gcc-common.h 2019-08-28 17:34:00.000000000 +0000 @@ -96,6 +96,10 @@ #include "predict.h" #include "ipa-utils.h" +#if BUILDING_GCC_VERSION >= 8000 +#include "stringpool.h" +#endif + #if BUILDING_GCC_VERSION >= 4009 #include "attribs.h" #include "varasm.h" diff -Nru kpatch-0.5.0/kpatch-build/gcc-plugins/ppc64le-plugin.c kpatch-0.8.0/kpatch-build/gcc-plugins/ppc64le-plugin.c --- kpatch-0.5.0/kpatch-build/gcc-plugins/ppc64le-plugin.c 2017-12-21 05:02:48.000000000 +0000 +++ kpatch-0.8.0/kpatch-build/gcc-plugins/ppc64le-plugin.c 2019-08-28 17:34:00.000000000 +0000 @@ -72,7 +72,7 @@ { const char * const plugin_name = plugin_info->base_name; - PASS_INFO(ppc64le_plugin, "dwarf2", 1, PASS_POS_INSERT_BEFORE); + PASS_INFO(ppc64le_plugin, "vregs", 1, PASS_POS_INSERT_AFTER); if (!plugin_default_version_check(version, &gcc_version)) error(1, 0, PLUGIN_NAME ": incompatible gcc/plugin versions"); diff -Nru kpatch-0.5.0/kpatch-build/kpatch-build kpatch-0.8.0/kpatch-build/kpatch-build --- kpatch-0.5.0/kpatch-build/kpatch-build 2017-12-21 05:02:48.000000000 +0000 +++ kpatch-0.8.0/kpatch-build/kpatch-build 2019-08-28 17:34:00.000000000 +0000 @@ -29,8 +29,8 @@ # - Either uses a specified kernel source directory or downloads the kernel # source package for the currently running kernel # - Unpacks and prepares the source package for building if necessary -# - Builds the base kernel (vmlinux) -# - Builds the patched kernel and monitors changed objects +# - Builds the base kernel or module +# - Builds the patched kernel/module and monitors changed objects # - Builds the patched objects with gcc flags -f[function|data]-sections # - Runs kpatch tools to create and link the patch kernel module @@ -50,8 +50,10 @@ SKIPCLEANUP=0 SKIPGCCCHECK=0 ARCH_KCFLAGS="" +DEBUG_KCFLAGS="" declare -a PATCH_LIST APPLIED_PATCHES=0 +OOT_MODULE= warn() { echo "ERROR: $1" >&2 @@ -104,18 +106,18 @@ patch="${PATCH_LIST[$idx]}" patch -p1 -R -d "$SRCDIR" < "$patch" &> /dev/null done + + # If $SRCDIR was a git repo, make sure git actually sees that + # we've reverted our patch(es). + [[ -d "$SRCDIR/.git" ]] && (cd "$SRCDIR" && git update-index -q --refresh) } cleanup() { rm -f "$SRCDIR/.scmversion" remove_patches - # If $SRCDIR was a git repo, make sure git actually sees that - # we've reverted our patch(es). - [[ -d "$SRCDIR/.git" ]] && (cd "$SRCDIR" && git update-index -q --refresh) - # restore original .config and vmlinux if they were removed with mrproper - [[ -e "$TEMPDIR/.config" ]] && mv -f "$TEMPDIR/.config" "$SRCDIR/" + # restore original vmlinux if it was overwritten by sourcedir build [[ -e "$TEMPDIR/vmlinux" ]] && mv -f "$TEMPDIR/vmlinux" "$SRCDIR/" [[ "$DEBUG" -eq 0 ]] && rm -rf "$TEMPDIR" @@ -125,7 +127,7 @@ } clean_cache() { - rm -rf "$CACHEDIR" + rm -rf "${CACHEDIR:?}"/* mkdir -p "$TEMPDIR" || die "Couldn't create $TEMPDIR" } @@ -140,13 +142,13 @@ cp core* /tmp die "core file at /tmp/$(ls core*)" fi - die "no core file found, run 'ulimit -c unlimited' and try to recreate" + die "There was a SIGSEGV, but no core dump was found in the current directory. Depending on your distro you might find it in /var/lib/systemd/coredump or /var/crash." fi } # $1 >= $2 version_gte() { - [ "$1" = "$(echo -e "$1\n$2" | sort -rV | head -n1)" ] + [ "$1" = "$(echo -e "$1\\n$2" | sort -rV | head -n1)" ] } is_rhel() { @@ -187,7 +189,7 @@ } gcc_version_from_file() { - readelf -p .comment "$1" | grep -o 'GCC:.*' + readelf -p .comment "$1" | grep -o 'GCC:.*' | head -n 1 } gcc_version_check() { @@ -199,8 +201,11 @@ echo 'void main(void) {}' > "$c" out="$(gcc -c -pg -ffunction-sections -o "$o" "$c" 2>&1)" gccver="$(gcc_version_from_file "$o")" - kgccver="$(gcc_version_from_file "$VMLINUX")" - rm -f "$c" "$o" + if [[ -n "$OOT_MODULE" ]]; then + kgccver="$(gcc_version_from_file "$OOT_MODULE")" + else + kgccver="$(gcc_version_from_file "$VMLINUX")" + fi if [[ -n "$out" ]]; then warn "gcc >= 4.8 required for -pg -ffunction-settings" @@ -208,6 +213,12 @@ return 1 fi + out="$(gcc -c -gz=none -o "$o" "$c" 2>&1)" + if [[ -z "$out" ]]; then + DEBUG_KCFLAGS="-gz=none" + fi + rm -f "$c" "$o" + # ensure gcc version matches that used to build the kernel if [[ "$gccver" != "$kgccver" ]]; then warn "gcc/kernel version mismatch" @@ -222,33 +233,40 @@ } find_special_section_data_ppc64le() { + + [[ "$CONFIG_JUMP_LABEL" -eq 0 ]] && AWK_OPTIONS="-vskip_j=1" + SPECIAL_VARS="$(readelf -wi "$VMLINUX" | gawk --non-decimal-data ' - BEGIN { f = b = e = 0 } + BEGIN { f = b = e = j = 0 } # Set state if name matches f == 0 && /DW_AT_name.* fixup_entry[[:space:]]*$/ {f = 1; next} b == 0 && /DW_AT_name.* bug_entry[[:space:]]*$/ {b = 1; next} e == 0 && /DW_AT_name.* exception_table_entry[[:space:]]*$/ {e = 1; next} + j == 0 && /DW_AT_name.* jump_entry[[:space:]]*$/ {j = 1; next} # Reset state unless this abbrev describes the struct size f == 1 && !/DW_AT_byte_size/ { f = 0; next } b == 1 && !/DW_AT_byte_size/ { b = 0; next } e == 1 && !/DW_AT_byte_size/ { e = 0; next } + j == 1 && !/DW_AT_byte_size/ { j = 0; next } # Now that we know the size, stop parsing for it - f == 1 {printf("export FIXUP_STRUCT_SIZE=%d\n", $4); a = 2} + f == 1 {printf("export FIXUP_STRUCT_SIZE=%d\n", $4); f = 2} b == 1 {printf("export BUG_STRUCT_SIZE=%d\n", $4); b = 2} e == 1 {printf("export EX_STRUCT_SIZE=%d\n", $4); e = 2} + j == 1 {printf("export JUMP_STRUCT_SIZE=%d\n", $4); j = 2} # Bail out once we have everything - f == 2 && b == 2 && e == 2 {exit}')" + f == 2 && b == 2 && e == 2 && (j == 2 || skip_j) {exit}')" [[ -n "$SPECIAL_VARS" ]] && eval "$SPECIAL_VARS" [[ -z "$FIXUP_STRUCT_SIZE" ]] && die "can't find special struct fixup_entry size" [[ -z "$BUG_STRUCT_SIZE" ]] && die "can't find special struct bug_entry size" [[ -z "$EX_STRUCT_SIZE" ]] && die "can't find special struct exception_table_entry size" + [[ -z "$JUMP_STRUCT_SIZE" && "$CONFIG_JUMP_LABEL" -ne 0 ]] && die "can't find special struct jump_entry size" return } @@ -260,30 +278,41 @@ fi [[ "$CONFIG_PARAVIRT" -eq 0 ]] && AWK_OPTIONS="-vskip_p=1" + [[ "$CONFIG_UNWINDER_ORC" -eq 0 ]] && AWK_OPTIONS="$AWK_OPTIONS -vskip_o=1" + [[ "$CONFIG_JUMP_LABEL" -eq 0 ]] && AWK_OPTIONS="$AWK_OPTIONS -vskip_j=1" + + # If $AWK_OPTIONS are blank gawk would treat "" as a blank script + # shellcheck disable=SC2086 SPECIAL_VARS="$(readelf -wi "$VMLINUX" | gawk --non-decimal-data $AWK_OPTIONS ' - BEGIN { a = b = p = e = 0 } + BEGIN { a = b = p = e = o = j = 0 } # Set state if name matches a == 0 && /DW_AT_name.* alt_instr[[:space:]]*$/ {a = 1; next} b == 0 && /DW_AT_name.* bug_entry[[:space:]]*$/ {b = 1; next} p == 0 && /DW_AT_name.* paravirt_patch_site[[:space:]]*$/ {p = 1; next} e == 0 && /DW_AT_name.* exception_table_entry[[:space:]]*$/ {e = 1; next} + o == 0 && /DW_AT_name.* orc_entry[[:space:]]*$/ {o = 1; next} + j == 0 && /DW_AT_name.* jump_entry[[:space:]]*$/ {j = 1; next} # Reset state unless this abbrev describes the struct size a == 1 && !/DW_AT_byte_size/ { a = 0; next } b == 1 && !/DW_AT_byte_size/ { b = 0; next } p == 1 && !/DW_AT_byte_size/ { p = 0; next } e == 1 && !/DW_AT_byte_size/ { e = 0; next } + o == 1 && !/DW_AT_byte_size/ { o = 0; next } + j == 1 && !/DW_AT_byte_size/ { j = 0; next } # Now that we know the size, stop parsing for it a == 1 {printf("export ALT_STRUCT_SIZE=%d\n", $4); a = 2} b == 1 {printf("export BUG_STRUCT_SIZE=%d\n", $4); b = 2} p == 1 {printf("export PARA_STRUCT_SIZE=%d\n", $4); p = 2} e == 1 {printf("export EX_STRUCT_SIZE=%d\n", $4); e = 2} + o == 1 {printf("export ORC_STRUCT_SIZE=%d\n", $4); o = 2} + j == 1 {printf("export JUMP_STRUCT_SIZE=%d\n", $4); j = 2} # Bail out once we have everything - a == 2 && b == 2 && (p == 2 || skip_p) && e == 2 {exit}')" + a == 2 && b == 2 && (p == 2 || skip_p) && e == 2 && (o == 2 || skip_o) && (j == 2 || skip_j) {exit}')" [[ -n "$SPECIAL_VARS" ]] && eval "$SPECIAL_VARS" @@ -291,6 +320,8 @@ [[ -z "$BUG_STRUCT_SIZE" ]] && die "can't find special struct bug_entry size" [[ -z "$EX_STRUCT_SIZE" ]] && die "can't find special struct paravirt_patch_site size" [[ -z "$PARA_STRUCT_SIZE" && "$CONFIG_PARAVIRT" -ne 0 ]] && die "can't find special struct paravirt_patch_site size" + [[ -z "$ORC_STRUCT_SIZE" && "$CONFIG_UNWINDER_ORC" -ne 0 ]] && die "can't find special struct orc_entry size" + [[ -z "$JUMP_STRUCT_SIZE" && "$CONFIG_JUMP_LABEL" -ne 0 ]] && die "can't find special struct jump_entry size" return } @@ -302,7 +333,7 @@ pdir="${absdir#$pwddir/}" file="$(basename "$1")" grepname="${1%.o}" - grepname="$grepname\.o" + grepname="$grepname\\.o" if [[ "$DEEP_FIND" -eq 1 ]]; then num=0 if [[ -n "$last_deep_find" ]]; then @@ -310,8 +341,8 @@ num="$(grep -l "$grepname" "$last_deep_find"/.*.cmd | grep -Fvc "$pdir/.${file}.cmd")" fi if [[ "$num" -eq 0 ]]; then - parent="$(find ./* -name ".*.cmd" -print0 | xargs -0 grep -l "$grepname" | grep -Fv "$pdir/.${file}.cmd" | cut -c3- | head -n1)" - num="$(find ./* -name ".*.cmd" -print0 | xargs -0 grep -l "$grepname" | grep -Fvc "$pdir/.${file}.cmd")" + parent="$(find . -name ".*.cmd" -print0 | xargs -0 grep -l "$grepname" | grep -Fv "$pdir/.${file}.cmd" | cut -c3- | head -n1)" + num="$(find . -name ".*.cmd" -print0 | xargs -0 grep -l "$grepname" | grep -Fvc "$pdir/.${file}.cmd")" [[ "$num" -eq 1 ]] && last_deep_find="$(dirname "$parent")" fi else @@ -342,6 +373,7 @@ [[ "$KOBJFILE" = *.ko ]] && return case "$KOBJFILE" in */built-in.o|\ + */built-in.a|\ arch/x86/lib/lib.a|\ arch/x86/kernel/head*.o|\ arch/x86/kernel/ebda.o|\ @@ -383,12 +415,14 @@ echo " -d, --debug Enable 'xtrace' and keep scratch files" >&2 echo " in /tmp" >&2 echo " (can be specified multiple times)" >&2 + echo " -e, --oot-module Enable patching out-of-tree module," >&2 + echo " specify current version of module" >&2 echo " --skip-cleanup Skip post-build cleanup" >&2 echo " --skip-gcc-check Skip gcc version matching check" >&2 echo " (not recommended)" >&2 } -options="$(getopt -o ha:r:s:c:v:j:t:n:o:d -l "help,archversion:,sourcerpm:,sourcedir:,config:,vmlinux:,jobs:,target:,name:,output:,debug,skip-gcc-check,skip-cleanup" -- "$@")" || die "getopt failed" +options="$(getopt -o ha:r:s:c:v:j:t:n:o:de: -l "help,archversion:,sourcerpm:,sourcedir:,config:,vmlinux:,jobs:,target:,name:,output:,oot-module:,debug,skip-gcc-check,skip-cleanup" -- "$@")" || die "getopt failed" eval set -- "$options" @@ -446,6 +480,11 @@ echo "DEBUG mode enabled" fi ;; + -e|--oot-module) + [[ ! -f "$2" ]] && die "out-of-tree module '$2' not found" + OOT_MODULE="$(readlink -f "$2")" + shift + ;; --skip-cleanup) echo "Skipping cleanup" SKIPCLEANUP=1 @@ -474,8 +513,7 @@ fi if [[ -n "$ARCHVERSION" ]] && [[ -n "$VMLINUX" ]]; then - warn "--archversion is incompatible with --vmlinux" - exit 1 + die "--archversion is incompatible with --vmlinux" fi if [[ -n "$SRCRPM" ]]; then @@ -486,6 +524,12 @@ rpmname="$(basename "$SRCRPM")" ARCHVERSION="${rpmname%.src.rpm}.$(uname -m)" ARCHVERSION="${ARCHVERSION#kernel-}" + ARCHVERSION="${ARCHVERSION#alt-}" +fi + +if [[ -n "$OOT_MODULE" ]] && [[ -z "$USERSRCDIR" ]]; then + warn "--oot-module requires --sourcedir" + exit 1 fi # ensure cachedir and tempdir are setup properly and cleaned @@ -500,11 +544,15 @@ fi SRCDIR="$USERSRCDIR" - [[ -z "$VMLINUX" ]] && VMLINUX="$SRCDIR"/vmlinux - [[ ! -e "$VMLINUX" ]] && die "can't find vmlinux" + if [[ -z "$OOT_MODULE" ]]; then + [[ -z "$VMLINUX" ]] && VMLINUX="$SRCDIR"/vmlinux + [[ ! -e "$VMLINUX" ]] && die "can't find vmlinux" - # Extract the target kernel version from vmlinux in this case. - ARCHVERSION="$(strings "$VMLINUX" | grep -m 1 -e "^Linux version" | awk '{ print($3); }')" + # Extract the target kernel version from vmlinux in this case. + ARCHVERSION="$(strings "$VMLINUX" | grep -m 1 -e "^Linux version" | awk '{ print($3); }')" + else + ARCHVERSION="$(modinfo -F vermagic "$OOT_MODULE" | awk '{print $1}')" + fi fi [[ -z "$ARCHVERSION" ]] && ARCHVERSION="$(uname -r)" @@ -516,6 +564,7 @@ KREL="${ARCHVERSION##*-}" KREL="${KREL%.*}" fi +[[ "$ARCHVERSION" =~ .el7a. ]] && ALT="-alt" [[ -z "$TARGETS" ]] && TARGETS="vmlinux modules" @@ -551,8 +600,16 @@ if [[ -n "$USERSRCDIR" ]]; then echo "Using source directory at $USERSRCDIR" - # save vmlinux before it gets removed with mrproper - [[ "$VMLINUX" -ef "$SRCDIR"/vmlinux ]] && cp -f "$VMLINUX" "$TEMPDIR/vmlinux" && VMLINUX="$TEMPDIR/vmlinux" + # save original vmlinux before it gets overwritten by sourcedir build + if [[ -z "$OOT_MODULE" ]] && [[ "$VMLINUX" -ef "$SRCDIR"/vmlinux ]]; then + cp -f "$VMLINUX" "$TEMPDIR/vmlinux" + VMLINUX="$TEMPDIR/vmlinux" + fi + + # For external modules, use the running kernel's config + if [[ -n "$OOT_MODULE" ]] && [[ -z "$CONFIGFILE" ]]; then + CONFIGFILE="/boot/config-${ARCHVERSION}" + fi elif [[ -e "$SRCDIR"/.config ]] && [[ -e "$VERSIONFILE" ]] && [[ "$(cat "$VERSIONFILE")" = "$ARCHVERSION" ]]; then echo "Using cache at $SRCDIR" @@ -561,7 +618,6 @@ if [[ "$DISTRO" = fedora ]] || [[ "$DISTRO" = rhel ]] || [[ "$DISTRO" = ol ]] || [[ "$DISTRO" = centos ]]; then echo "Fedora/Red Hat distribution detected" - rpm -q --quiet rpmdevtools || die "rpmdevtools not installed" clean_cache @@ -570,19 +626,19 @@ if [[ "$DISTRO" = fedora ]]; then wget -P "$TEMPDIR" "http://kojipkgs.fedoraproject.org/packages/kernel/$KVER/$KREL/src/kernel-$KVER-$KREL.src.rpm" 2>&1 | logger || die else - rpm -q --quiet yum-utils || die "yum-utils not installed" - yumdownloader --source --destdir "$TEMPDIR" "kernel-$ARCHVERSION" 2>&1 | logger || die + command -v yumdownloader &>/dev/null || die "yumdownloader (yum-utils or dnf-utils) not installed" + yumdownloader --source --destdir "$TEMPDIR" "kernel$ALT-$KVER-$KREL" 2>&1 | logger || die fi - SRCRPM="$TEMPDIR/kernel-$KVER-$KREL.src.rpm" + SRCRPM="$TEMPDIR/kernel$ALT-$KVER-$KREL.src.rpm" fi echo "Unpacking kernel source" rpm -D "_topdir $RPMTOPDIR" -ivh "$SRCRPM" 2>&1 | logger || die - rpmbuild -D "_topdir $RPMTOPDIR" -bp "--target=$(uname -m)" "$RPMTOPDIR"/SPECS/kernel.spec 2>&1 | logger || + rpmbuild -D "_topdir $RPMTOPDIR" -bp --nodeps "--target=$(uname -m)" "$RPMTOPDIR"/SPECS/kernel$ALT.spec 2>&1 | logger || die "rpmbuild -bp failed. you may need to run 'yum-builddep kernel' first." - mv "$RPMTOPDIR"/BUILD/kernel-*/linux-"${ARCHVERSION%.*}"*"${ARCHVERSION##*.}" "$SRCDIR" 2>&1 | logger || die + mv "$RPMTOPDIR"/BUILD/kernel-*/linux-* "$SRCDIR" 2>&1 | logger || die rm -rf "$RPMTOPDIR" rm -rf "$SRCDIR/.git" @@ -592,6 +648,10 @@ echo "$ARCHVERSION" > "$VERSIONFILE" || die + [[ -z "$CONFIGFILE" ]] && CONFIGFILE="$SRCDIR/configs/kernel$ALT-$KVER-$ARCH.config" + + (cd "$SRCDIR" && make mrproper 2>&1 | logger) || die + elif [[ "$DISTRO" = ubuntu ]] || [[ "$DISTRO" = debian ]]; then echo "Debian/Ubuntu distribution detected" @@ -601,7 +661,6 @@ # url may be changed for a different mirror url="http://archive.ubuntu.com/ubuntu/pool/main/l" sublevel="SUBLEVEL = 0" - UBUNTU_KERNEL=1 elif [[ "$DISTRO" = debian ]]; then @@ -610,7 +669,7 @@ sublevel="SUBLEVEL =" fi - pkgname="$(dpkg-query -W -f='${Source}' "linux-image-$ARCHVERSION")" + pkgname="$(dpkg-query -W -f='${Source}' "linux-image-$ARCHVERSION" | sed s/-signed//)" pkgver="$(dpkg-query -W -f='${Version}' "linux-image-$ARCHVERSION")" dscname="${pkgname}_${pkgver}.dsc" @@ -621,7 +680,7 @@ # Download source deb pkg (dget -u "$url/${pkgname}/${dscname}" 2>&1) | logger || die "dget: Could not fetch/unpack $url/${pkgname}/${dscname}" mv "${pkgname}-$KVER" "$SRCDIR" || die - cp "/boot/config-${ARCHVERSION}" "$SRCDIR/.config" || die + [[ -z "$CONFIGFILE" ]] && CONFIGFILE="/boot/config-${ARCHVERSION}" if [[ "$ARCHVERSION" == *-* ]]; then echo "-${ARCHVERSION#*-}" > "$SRCDIR/localversion" || die fi @@ -635,10 +694,9 @@ fi fi -# save .config before it gets removed with mrproper [[ -z "$CONFIGFILE" ]] && CONFIGFILE="$SRCDIR"/.config [[ ! -e "$CONFIGFILE" ]] && die "can't find config file" -[[ "$CONFIGFILE" -ef "$SRCDIR"/.config ]] && cp -f "$CONFIGFILE" "$TEMPDIR" && CONFIGFILE="$TEMPDIR"/.config +[[ ! "$CONFIGFILE" -ef "$SRCDIR"/.config ]] && cp -f "$CONFIGFILE" "$SRCDIR/.config" # Build variables - Set some defaults, then adjust features # according to .config and kernel version @@ -663,15 +721,27 @@ KBUILD_EXTRA_SYMBOLS="$SYMVERSFILE" fi -# optional kernel configs: CONFIG_PARAVIRT +# optional kernel configs: if grep -q "CONFIG_PARAVIRT=y" "$CONFIGFILE"; then CONFIG_PARAVIRT=1 else CONFIG_PARAVIRT=0 fi +if grep -q "CONFIG_UNWINDER_ORC=y" "$CONFIGFILE"; then + CONFIG_UNWINDER_ORC=1 +else + CONFIG_UNWINDER_ORC=0 +fi +if grep -q "CONFIG_JUMP_LABEL=y" "$CONFIGFILE"; then + CONFIG_JUMP_LABEL=1 +else + CONFIG_JUMP_LABEL=0 +fi -# unsupported kernel option checking: CONFIG_DEBUG_INFO_SPLIT +# unsupported kernel option checking grep -q "CONFIG_DEBUG_INFO_SPLIT=y" "$CONFIGFILE" && die "kernel option 'CONFIG_DEBUG_INFO_SPLIT' not supported" +grep -q "CONFIG_GCC_PLUGIN_LATENT_ENTROPY=y" "$CONFIGFILE" && die "kernel option 'CONFIG_GCC_PLUGIN_LATENT_ENTROPY' not supported" +grep -q "CONFIG_GCC_PLUGIN_RANDSTRUCT=y" "$CONFIGFILE" && die "kernel option 'CONFIG_GCC_PLUGIN_RANDSTRUCT' not supported" echo "Testing patch file(s)" cd "$SRCDIR" || die @@ -684,7 +754,8 @@ ARCH_KCFLAGS="-mcmodel=large -fplugin=$PLUGINDIR/ppc64le-plugin.so" fi -export KCFLAGS="-I$DATADIR/patch -ffunction-sections -fdata-sections $ARCH_KCFLAGS" +export KCFLAGS="-I$DATADIR/patch -ffunction-sections -fdata-sections \ + $ARCH_KCFLAGS $DEBUG_KCFLAGS" echo "Reading special section data" find_special_section_data @@ -693,32 +764,39 @@ export KPATCH_GCC_DEBUG=1 fi -echo "Building original kernel" -./scripts/setlocalversion --save-scmversion || die -make mrproper 2>&1 | logger || die -cp -f "$CONFIGFILE" "$SRCDIR/.config" +echo "Building original source" +[[ -n "$OOT_MODULE" ]] || ./scripts/setlocalversion --save-scmversion || die unset KPATCH_GCC_TEMPDIR # $TARGETS used as list, no quotes. # shellcheck disable=SC2086 CROSS_COMPILE="$TOOLSDIR/kpatch-gcc " make "-j$CPUS" $TARGETS 2>&1 | logger || die -echo "Building patched kernel" +echo "Building patched source" apply_patches mkdir -p "$TEMPDIR/orig" "$TEMPDIR/patched" KPATCH_GCC_TEMPDIR="$TEMPDIR" export KPATCH_GCC_TEMPDIR +KPATCH_GCC_SRCDIR="$SRCDIR" +export KPATCH_GCC_SRCDIR # $TARGETS used as list, no quotes. # shellcheck disable=SC2086 CROSS_COMPILE="$TOOLSDIR/kpatch-gcc " \ KBUILD_MODPOST_WARN=1 \ make "-j$CPUS" $TARGETS 2>&1 | logger || die -grep "undefined reference" "$LOGFILE" | grep -qv kpatch_shadow && die -grep "undefined!" "$LOGFILE" | grep -qv kpatch_shadow && die + +# source.c:(.section+0xFF): undefined reference to `symbol' +grep "undefined reference" "$LOGFILE" | sed -r "s/^.*\`(.*)'$/\\1/" \ + >"${TEMPDIR}"/undefined_references + +# WARNING: "symbol" [path/to/module.ko] undefined! +grep "undefined!" "$LOGFILE" | cut -d\" -f2 >>"${TEMPDIR}"/undefined_references if [[ ! -e "$TEMPDIR/changed_objs" ]]; then die "no changed objects found" fi +[[ -n "$OOT_MODULE" ]] || grep -q vmlinux "$SRCDIR/Module.symvers" || die "truncated $SRCDIR/Module.symvers file" + # Read as words, no quotes. # shellcheck disable=SC2013 for i in $(cat "$TEMPDIR/changed_objs") @@ -768,16 +846,39 @@ mkdir -p "output/$(dirname "$i")" cd "$SRCDIR" || die find_kobj "$i" - if [[ "$KOBJFILE" = vmlinux ]]; then - KOBJFILE="$VMLINUX" - else - KOBJFILE="$TEMPDIR/module/$KOBJFILE" - fi cd "$TEMPDIR" || die if [[ -e "orig/$i" ]]; then - # create-diff-object orig.o patched.o kernel-object output.o Module.symvers patch-mod-name - "$TOOLSDIR"/create-diff-object "orig/$i" "patched/$i" "$KOBJFILE" \ - "output/$i" "$SRCDIR/Module.symvers" "${MODNAME//-/_}" 2>&1 | logger 1 + if [[ "$(basename "$KOBJFILE")" = vmlinux ]]; then + KOBJFILE_NAME=vmlinux + KOBJFILE_PATH="$VMLINUX" + SYMTAB="${TEMPDIR}/${KOBJFILE_NAME}.symtab" + SYMVERS_FILE="$SRCDIR/Module.symvers" + elif [[ "$(basename "$KOBJFILE")" = "$(basename "$OOT_MODULE")" ]]; then + KOBJFILE_NAME="$(basename --suffix=.ko "$OOT_MODULE")" + KOBJFILE_PATH="$OOT_MODULE" + SYMTAB="${TEMPDIR}/module/${KOBJFILE_NAME}.symtab" + SYMVERS_FILE="$TEMPDIR/Module.symvers" + BUILDDIR="/lib/modules/$ARCHVERSION/build/" + cp "$SRCDIR/Module.symvers" "$SYMVERS_FILE" + awk '{ print $1 "\t" $2 "\t" $3 "\t" $4}' "${BUILDDIR}/Module.symvers" >> "$SYMVERS_FILE" + else + KOBJFILE_NAME=$(basename "${KOBJFILE%.ko}") + KOBJFILE_NAME="${KOBJFILE_NAME/-/_}" + KOBJFILE_PATH="${TEMPDIR}/module/$KOBJFILE" + SYMTAB="${KOBJFILE_PATH}.symtab" + SYMVERS_FILE="$SRCDIR/Module.symvers" + fi + + readelf -s --wide "$KOBJFILE_PATH" > "$SYMTAB" + if [[ "$ARCH" = "ppc64le" ]]; then + sed -ri 's/\s+\[: 8\]//' "$SYMTAB" + fi + + # create-diff-object orig.o patched.o parent-name parent-symtab + # Module.symvers patch-mod-name output.o + "$TOOLSDIR"/create-diff-object "orig/$i" "patched/$i" "$KOBJFILE_NAME" \ + "$SYMTAB" "$SYMVERS_FILE" "${MODNAME//-/_}" \ + "output/$i" 2>&1 | logger 1 check_pipe_status create-diff-object # create-diff-object returns 3 if no functional change is found [[ "$rc" -eq 0 ]] || [[ "$rc" -eq 3 ]] || ERROR="$((ERROR + 1))" @@ -803,7 +904,7 @@ echo -n "Patched objects:" for i in $(echo "${objnames[@]}" | tr ' ' '\n' | sort -u | tr '\n' ' ') do - echo -n " $(basename "$i")" + echo -n " $i" done echo @@ -814,7 +915,7 @@ echo "Building patch module: $MODNAME.ko" -if [[ ! -z "$UBUNTU_KERNEL" ]]; then +if [[ -z "$USERSRCDIR" ]] && [[ "$DISTRO" = ubuntu ]]; then # UBUNTU: add UTS_UBUNTU_RELEASE_ABI to utsrelease.h after regenerating it UBUNTU_ABI="${ARCHVERSION#*-}" UBUNTU_ABI="${UBUNTU_ABI%-*}" @@ -838,8 +939,12 @@ fi cd "$TEMPDIR/patch" || die - -KPATCH_BUILD="$SRCDIR" KPATCH_NAME="$MODNAME" \ +if [[ -z "$OOT_MODULE" ]]; then + KPATCH_BUILD="$SRCDIR" +else + KPATCH_BUILD="/lib/modules/$ARCHVERSION/build" +fi +KPATCH_BUILD="$KPATCH_BUILD" KPATCH_NAME="$MODNAME" \ KBUILD_EXTRA_SYMBOLS="$KBUILD_EXTRA_SYMBOLS" \ KPATCH_LDFLAGS="$KPATCH_LDFLAGS" \ make 2>&1 | logger || die @@ -853,6 +958,28 @@ check_pipe_status create-klp-module fi +readelf --wide --symbols "$TEMPDIR/patch/$MODNAME.ko" 2>/dev/null | \ + sed -r 's/\s+\[: 8\]//' | \ + awk '($4=="FUNC" || $4=="OBJECT") && ($5=="GLOBAL" || $5=="WEAK") && $7!="UND" {print $NF}' \ + >"${TEMPDIR}"/new_symbols + +if "$KPATCH_MODULE"; then + cat >>"${TEMPDIR}"/new_symbols <<-EOF + kpatch_shadow_free + kpatch_shadow_alloc + kpatch_register + kpatch_shadow_get + kpatch_unregister + kpatch_root_kobj + EOF +fi + +# Compare undefined_references and new_symbols files and print only the first +# column containing lines unique to first file. +UNDEFINED=$(comm -23 <(sort -u "${TEMPDIR}"/undefined_references) \ + <(sort -u "${TEMPDIR}"/new_symbols) | tr '\n' ' ') +[[ -n "$UNDEFINED" ]] && die "Undefined symbols: $UNDEFINED" + cp -f "$TEMPDIR/patch/$MODNAME.ko" "$BASE" || die [[ "$DEBUG" -eq 0 ]] && rm -f "$LOGFILE" diff -Nru kpatch-0.5.0/kpatch-build/kpatch-elf.c kpatch-0.8.0/kpatch-build/kpatch-elf.c --- kpatch-0.5.0/kpatch-build/kpatch-elf.c 2017-12-21 05:02:48.000000000 +0000 +++ kpatch-0.8.0/kpatch-build/kpatch-elf.c 2019-08-28 17:34:00.000000000 +0000 @@ -263,7 +263,7 @@ { struct section *symtab; struct symbol *sym; - int symbols_nr, index = 0; + unsigned int symbols_nr, index = 0; symtab = find_section_by_name(&kelf->sections, ".symtab"); if (!symtab) @@ -322,7 +322,7 @@ list_for_each_entry(sym, &kelf->symbols, list) { if (sym->type != STT_FUNC || !sym->sec || !sym->sec->rela) continue; -#ifdef __powerpc__ +#ifdef __powerpc64__ list_for_each_entry(rela, &sym->sec->rela->relas, list) { if (!strcmp(rela->sym->name, "_mcount")) { sym->has_func_profiling = 1; @@ -332,7 +332,9 @@ #else rela = list_first_entry(&sym->sec->rela->relas, struct rela, list); - if (rela->type != R_X86_64_NONE || + if ((rela->type != R_X86_64_NONE && + rela->type != R_X86_64_PC32 && + rela->type != R_X86_64_PLT32) || strcmp(rela->sym->name, "__fentry__")) continue; @@ -452,7 +454,7 @@ void print_strtab(char *buf, size_t size) { - int i; + size_t i; for (i = 0; i < size; i++) { if (buf[i] == 0) @@ -565,6 +567,7 @@ void kpatch_create_symtab(struct kpatch_elf *kelf) { struct section *symtab; + struct section *strtab; struct symbol *sym; char *buf; size_t size; @@ -598,7 +601,11 @@ symtab->data->d_size = size; /* update symtab section header */ - symtab->sh.sh_link = find_section_by_name(&kelf->sections, ".strtab")->index; + strtab = find_section_by_name(&kelf->sections, ".strtab"); + if (!strtab) + ERROR("missing .strtab section"); + + symtab->sh.sh_link = strtab->index; symtab->sh.sh_info = nr_local; } @@ -647,6 +654,7 @@ relasec->data = malloc(sizeof(*relasec->data)); if (!relasec->data) ERROR("malloc"); + relasec->data->d_type = ELF_T_RELA; /* set section header */ relasec->sh.sh_type = SHT_RELA; @@ -697,7 +705,7 @@ { struct section *sec; struct symbol *sym; - int index; + unsigned int index; index = 1; /* elf write function handles NULL section 0 */ list_for_each_entry(sec, &kelf->sections, list) @@ -750,6 +758,7 @@ { int fd; struct section *sec; + struct section *shstrtab; Elf *elfout; GElf_Ehdr eh, ehout; Elf_Scn *scn; @@ -765,7 +774,7 @@ if (!elfout) ERROR("elf_begin"); - if (!gelf_newehdr(elfout, gelf_getclass(kelf->elf))) + if (!gelf_newehdr(elfout, gelf_getclass(elf))) ERROR("gelf_newehdr"); if (!gelf_getehdr(elfout, &ehout)) @@ -779,7 +788,12 @@ ehout.e_machine = eh.e_machine; ehout.e_type = eh.e_type; ehout.e_version = EV_CURRENT; - ehout.e_shstrndx = find_section_by_name(&kelf->sections, ".shstrtab")->index; + + shstrtab = find_section_by_name(&kelf->sections, ".shstrtab"); + if (!shstrtab) + ERROR("missing .shstrtab section"); + + ehout.e_shstrndx = shstrtab->index; /* add changed sections */ list_for_each_entry(sec, &kelf->sections, list) { @@ -814,6 +828,9 @@ printf("%s\n",elf_errmsg(-1)); ERROR("elf_update"); } + + elf_end(elfout); + close(fd); } /* diff -Nru kpatch-0.5.0/kpatch-build/kpatch-elf.h kpatch-0.8.0/kpatch-build/kpatch-elf.h --- kpatch-0.5.0/kpatch-build/kpatch-elf.h 2017-12-21 05:02:48.000000000 +0000 +++ kpatch-0.8.0/kpatch-build/kpatch-elf.h 2019-08-28 17:34:00.000000000 +0000 @@ -20,6 +20,7 @@ #ifndef _KPATCH_ELF_H_ #define _KPATCH_ELF_H_ +#include #include #include "list.h" #include "log.h" @@ -49,7 +50,7 @@ GElf_Shdr sh; Elf_Data *data; char *name; - int index; + unsigned int index; enum status status; int include; int ignore; @@ -69,10 +70,12 @@ struct symbol { struct list_head list; struct symbol *twin; + struct symbol *parent; + struct symbol *child; struct section *sec; GElf_Sym sym; char *name; - int index; + unsigned int index; unsigned char bind, type; enum status status; union { @@ -88,8 +91,9 @@ struct symbol *sym; unsigned int type; int addend; - int offset; + unsigned int offset; char *string; + bool need_dynrela; }; struct string { @@ -126,7 +130,8 @@ ERROR("malloc"); \ memset((_new), 0, sizeof(*(_new))); \ INIT_LIST_HEAD(&(_new)->list); \ - list_add_tail(&(_new)->list, (_list)); \ + if (_list) \ + list_add_tail(&(_new)->list, (_list)); \ } int offset_of_string(struct list_head *list, char *name); diff -Nru kpatch-0.5.0/kpatch-build/kpatch-gcc kpatch-0.8.0/kpatch-build/kpatch-gcc --- kpatch-0.5.0/kpatch-build/kpatch-gcc 2017-12-21 05:02:48.000000000 +0000 +++ kpatch-0.8.0/kpatch-build/kpatch-gcc 2019-08-28 17:34:00.000000000 +0000 @@ -13,7 +13,7 @@ declare -a args=("$@") -if [[ "$TOOLCHAINCMD" = "gcc" ]] ; then +if [[ "$TOOLCHAINCMD" =~ "gcc" ]] ; then while [ "$#" -gt 0 ]; do if [ "$1" = "-o" ]; then obj="$2" @@ -23,9 +23,11 @@ [[ "$obj" = */.tmp_mc_*.o ]] && break; [[ "$obj" = */.tmp_*.o ]] && obj="${obj/.tmp_/}" - case "$obj" in + relobj=${obj//$KPATCH_GCC_SRCDIR\//} + case "$relobj" in *.mod.o|\ *built-in.o|\ + *built-in.a|\ vmlinux.o|\ .tmp_kallsyms1.o|\ .tmp_kallsyms2.o|\ @@ -40,14 +42,15 @@ arch/x86/entry/vdso/*|\ drivers/firmware/efi/libstub/*|\ arch/powerpc/kernel/prom_init.o|\ + lib/*|\ .*.o|\ */.lib_exports.o) break ;; *.o) - mkdir -p "$KPATCH_GCC_TEMPDIR/orig/$(dirname "$obj")" - [[ -e "$obj" ]] && cp -f "$obj" "$KPATCH_GCC_TEMPDIR/orig/$obj" - echo "$obj" >> "$KPATCH_GCC_TEMPDIR/changed_objs" + mkdir -p "$KPATCH_GCC_TEMPDIR/orig/$(dirname "$relobj")" + [[ -e "$obj" ]] && cp -f "$obj" "$KPATCH_GCC_TEMPDIR/orig/$relobj" + echo "$relobj" >> "$KPATCH_GCC_TEMPDIR/changed_objs" break ;; *) @@ -61,10 +64,11 @@ while [ "$#" -gt 0 ]; do if [ "$1" = "-o" ]; then obj="$2" + relobj=${obj//$KPATCH_GCC_SRCDIR\//} case "$obj" in *.ko) - mkdir -p "$KPATCH_GCC_TEMPDIR/module/$(dirname "$obj")" - cp -f "$obj" "$KPATCH_GCC_TEMPDIR/module/$obj" + mkdir -p "$KPATCH_GCC_TEMPDIR/module/$(dirname "$relobj")" + cp -f "$obj" "$KPATCH_GCC_TEMPDIR/module/$relobj" break ;; .tmp_vmlinux*|vmlinux) diff -Nru kpatch-0.5.0/kpatch-build/kpatch.h kpatch-0.8.0/kpatch-build/kpatch.h --- kpatch-0.5.0/kpatch-build/kpatch.h 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/kpatch-build/kpatch.h 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1,11 @@ +#ifndef _KPATCH_H_ +#define _KPATCH_H_ + +enum exit_status { + EXIT_STATUS_SUCCESS = 0, + EXIT_STATUS_ERROR = 1, + EXIT_STATUS_DIFF_FATAL = 2, + EXIT_STATUS_NO_CHANGE = 3, +}; + +#endif /* _KPATCH_H_ */ diff -Nru kpatch-0.5.0/kpatch-build/log.h kpatch-0.8.0/kpatch-build/log.h --- kpatch-0.5.0/kpatch-build/log.h 2017-12-21 05:02:48.000000000 +0000 +++ kpatch-0.8.0/kpatch-build/log.h 2019-08-28 17:34:00.000000000 +0000 @@ -2,13 +2,14 @@ #define _LOG_H_ #include +#include "kpatch.h" /* Files that include log.h must define loglevel and childobj */ extern enum loglevel loglevel; extern char *childobj; #define ERROR(format, ...) \ - error(1, 0, "ERROR: %s: %s: %d: " format, childobj, __FUNCTION__, __LINE__, ##__VA_ARGS__) + error(EXIT_STATUS_ERROR, 0, "ERROR: %s: %s: %d: " format, childobj, __FUNCTION__, __LINE__, ##__VA_ARGS__) #define log_debug(format, ...) log(DEBUG, format, ##__VA_ARGS__) #define log_normal(format, ...) log(NORMAL, "%s: " format, childobj, ##__VA_ARGS__) diff -Nru kpatch-0.5.0/kpatch-build/lookup.c kpatch-0.8.0/kpatch-build/lookup.c --- kpatch-0.5.0/kpatch-build/lookup.c 2017-12-21 05:02:48.000000000 +0000 +++ kpatch-0.8.0/kpatch-build/lookup.c 2019-08-28 17:34:00.000000000 +0000 @@ -43,7 +43,7 @@ unsigned long value; unsigned long size; char *name; - int type, bind, skip; + int type, bind; }; struct export_symbol { @@ -56,7 +56,6 @@ struct object_symbol *obj_syms; struct export_symbol *exp_syms; struct object_symbol *local_syms; - int vmlinux; }; #define for_each_obj_symbol(ndx, iter, table) \ @@ -68,13 +67,21 @@ #define for_each_exp_symbol(ndx, iter, table) \ for (ndx = 0, iter = table->exp_syms; ndx < table->exp_nr; ndx++, iter++) -static int discarded_sym(struct lookup_table *table, - struct sym_compare_type *sym) +static int maybe_discarded_sym(const char *name) { - if (table->vmlinux && sym->name && - (!strncmp(sym->name, "__exitcall_", 11) || - !strncmp(sym->name, "__brk_reservation_fn_", 21) || - !strncmp(sym->name, "__func_stack_frame_non_standard_", 32))) + if (!name) + return 0; + + /* + * Sometimes these symbols are discarded during linking, and sometimes + * they're not, depending on whether the parent object is vmlinux or a + * module, and also depending on the kernel version. For simplicity, + * we just always skip them when comparing object symbol tables. + */ + if (!strncmp(name, "__exitcall_", 11) || + !strncmp(name, "__brk_reservation_fn_", 21) || + !strncmp(name, "__func_stack_frame_non_standard_", 32) || + !strncmp(name, "__addressable_", 14)) return 1; return 0; @@ -114,7 +121,7 @@ * Symbols which get discarded at link time are missing from * the lookup table, so skip them. */ - if (discarded_sym(table, child)) + if (maybe_discarded_sym(child->name)) continue; found = 0; @@ -126,6 +133,8 @@ continue; if (sym->type != STT_FUNC && sym->type != STT_OBJECT) continue; + if (maybe_discarded_sym(sym->name)) + continue; if (!strcmp(child->name, sym->name)) { found = 1; @@ -163,105 +172,112 @@ } if (!table->local_syms) - ERROR("find_local_syms for %s: found_none", hint); + ERROR("find_local_syms for %s: couldn't find in vmlinux symbol table", hint); } -static void obj_read(struct lookup_table *table, char *path) +/* Strip the path and replace '-' with '_' */ +static char *make_modname(char *modname) { - Elf *elf; - int fd, i, len; - Elf_Scn *scn; - GElf_Shdr sh; - GElf_Sym sym; - Elf_Data *data; - char *name; - struct object_symbol *mysym; - size_t shstrndx; + char *cur, *name; - if ((fd = open(path, O_RDONLY, 0)) < 0) - ERROR("open"); + if (!modname) + return NULL; - elf_version(EV_CURRENT); + name = strdup(basename(modname)); + if (!name) + ERROR("strdup"); - elf = elf_begin(fd, ELF_C_READ_MMAP, NULL); - if (!elf) { - printf("%s\n", elf_errmsg(-1)); - ERROR("elf_begin"); + cur = name; /* use cur as tmp */ + while (*cur != '\0') { + if (*cur == '-') + *cur = '_'; + cur++; } - if (elf_getshdrstrndx(elf, &shstrndx)) - ERROR("elf_getshdrstrndx"); + return name; +} - scn = NULL; - while ((scn = elf_nextscn(elf, scn))) { - if (!gelf_getshdr(scn, &sh)) - ERROR("gelf_getshdr"); - - name = elf_strptr(elf, shstrndx, sh.sh_name); - if (!name) - ERROR("elf_strptr scn"); +static void symtab_read(struct lookup_table *table, char *path) +{ + FILE *file; + long unsigned int value; + unsigned int i = 0; + int matched; + char line[256], name[256], size[16], type[16], bind[16], ndx[16]; - if (!strcmp(name, ".symtab")) - break; - } + if ((file = fopen(path, "r")) == NULL) + ERROR("fopen"); - if (!scn) - ERROR(".symtab section not found"); + while (fgets(line, 256, file)) { + matched = sscanf(line, "%*s %lx %s %s %s %*s %s %s\n", + &value, size, type, bind, ndx, name); + + if (matched == 5) { + name[0] = '\0'; + matched++; + } - data = elf_getdata(scn, NULL); - if (!data) - ERROR("elf_getdata"); + if (matched != 6 || + !strcmp(ndx, "UND") || + !strcmp(type, "SECTION")) + continue; - len = sh.sh_size / sh.sh_entsize; + table->obj_nr++; + } - table->obj_syms = malloc(len * sizeof(*table->obj_syms)); + table->obj_syms = malloc(table->obj_nr * sizeof(*table->obj_syms)); if (!table->obj_syms) ERROR("malloc table.obj_syms"); - memset(table->obj_syms, 0, len * sizeof(*table->obj_syms)); - table->obj_nr = len; + memset(table->obj_syms, 0, table->obj_nr * sizeof(*table->obj_syms)); - for_each_obj_symbol(i, mysym, table) { - if (!gelf_getsym(data, i, &sym)) - ERROR("gelf_getsym"); + rewind(file); - if (sym.st_shndx == SHN_UNDEF) { - mysym->skip = 1; - continue; + while (fgets(line, 256, file)) { + matched = sscanf(line, "%*s %lx %s %s %s %*s %s %s\n", + &value, size, type, bind, ndx, name); + + if (matched == 5) { + name[0] = '\0'; + matched++; } - name = elf_strptr(elf, sh.sh_link, sym.st_name); - if(!name) - ERROR("elf_strptr sym"); - - mysym->value = sym.st_value; - mysym->size = sym.st_size; - mysym->type = GELF_ST_TYPE(sym.st_info); - mysym->bind = GELF_ST_BIND(sym.st_info); - mysym->name = strdup(name); - if (!mysym->name) - ERROR("strdup"); - } + if (matched != 6 || + !strcmp(ndx, "UND") || + !strcmp(type, "SECTION")) + continue; - close(fd); - elf_end(elf); -} + table->obj_syms[i].value = value; + table->obj_syms[i].size = strtoul(size, NULL, 0); -/* Strip the path and replace '-' with '_' */ -static char *make_modname(char *modname) -{ - char *cur; + if (!strcmp(bind, "LOCAL")) { + table->obj_syms[i].bind = STB_LOCAL; + } else if (!strcmp(bind, "GLOBAL")) { + table->obj_syms[i].bind = STB_GLOBAL; + } else if (!strcmp(bind, "WEAK")) { + table->obj_syms[i].bind = STB_WEAK; + } else { + ERROR("unknown symbol bind %s", bind); + } - if (!modname) - return NULL; + if (!strcmp(type, "NOTYPE")) { + table->obj_syms[i].type = STT_NOTYPE; + } else if (!strcmp(type, "OBJECT")) { + table->obj_syms[i].type = STT_OBJECT; + } else if (!strcmp(type, "FUNC")) { + table->obj_syms[i].type = STT_FUNC; + } else if (!strcmp(type, "FILE")) { + table->obj_syms[i].type = STT_FILE; + } else { + ERROR("unknown symbol type %s", type); + } - cur = modname; - while (*cur != '\0') { - if (*cur == '-') - *cur = '_'; - cur++; + table->obj_syms[i].name = strdup(name); + if (!table->obj_syms[i].name) + ERROR("strdup"); + i++; } - return basename(modname); + fclose(file); } static void symvers_read(struct lookup_table *table, char *path) @@ -271,7 +287,7 @@ char name[256], mod[256], export[256]; char *objname, *symname; - if ((file = fopen(path, "r")) < 0) + if ((file = fopen(path, "r")) == NULL) ERROR("fopen"); while (fscanf(file, "%x %s %s %s\n", @@ -292,11 +308,7 @@ if (!symname) perror("strdup"); - objname = strdup(mod); - if (!objname) - perror("strdup"); - /* Modifies objname in-place */ - objname = make_modname(objname); + objname = make_modname(mod); table->exp_syms[i].name = symname; table->exp_syms[i].objname = objname; @@ -306,7 +318,7 @@ fclose(file); } -struct lookup_table *lookup_open(char *obj_path, char *symvers_path, +struct lookup_table *lookup_open(char *symtab_path, char *symvers_path, char *hint, struct sym_compare_type *locals) { struct lookup_table *table; @@ -316,9 +328,7 @@ ERROR("malloc table"); memset(table, 0, sizeof(*table)); - table->vmlinux = !strncmp(basename(obj_path), "vmlinux", 7); - - obj_read(table, obj_path); + symtab_read(table, symtab_path); symvers_read(table, symvers_path); find_local_syms(table, hint, locals); @@ -327,7 +337,18 @@ void lookup_close(struct lookup_table *table) { + int i; + struct object_symbol *obj_sym; + struct export_symbol *exp_sym; + + for_each_obj_symbol(i, obj_sym, table) + free(obj_sym->name); free(table->obj_syms); + + for_each_exp_symbol(i, exp_sym, table) { + free(exp_sym->name); + free(exp_sym->objname); + } free(table->exp_syms); free(table); } @@ -344,9 +365,6 @@ memset(result, 0, sizeof(*result)); for_each_obj_symbol(i, sym, table) { - if (sym->skip) - continue; - if (sym->bind == STB_LOCAL && !strcmp(sym->name, name)) pos++; @@ -384,7 +402,7 @@ memset(result, 0, sizeof(*result)); for_each_obj_symbol(i, sym, table) { - if (!sym->skip && (sym->bind == STB_GLOBAL || sym->bind == STB_WEAK) && + if ((sym->bind == STB_GLOBAL || sym->bind == STB_WEAK) && !strcmp(sym->name, name)) { result->value = sym->value; result->size = sym->size; diff -Nru kpatch-0.5.0/kpatch-build/lookup.h kpatch-0.8.0/kpatch-build/lookup.h --- kpatch-0.5.0/kpatch-build/lookup.h 2017-12-21 05:02:48.000000000 +0000 +++ kpatch-0.8.0/kpatch-build/lookup.h 2019-08-28 17:34:00.000000000 +0000 @@ -14,7 +14,7 @@ int type; }; -struct lookup_table *lookup_open(char *obj_path, char *symvers_path, +struct lookup_table *lookup_open(char *symtab_path, char *symvers_path, char *hint, struct sym_compare_type *locals); void lookup_close(struct lookup_table *table); int lookup_local_symbol(struct lookup_table *table, char *name, diff -Nru kpatch-0.5.0/kpatch-build/Makefile kpatch-0.8.0/kpatch-build/Makefile --- kpatch-0.5.0/kpatch-build/Makefile 2017-12-21 05:02:48.000000000 +0000 +++ kpatch-0.8.0/kpatch-build/Makefile 2019-08-28 17:34:00.000000000 +0000 @@ -1,6 +1,6 @@ include ../Makefile.inc -CFLAGS += -MMD -MP -I../kmod/patch -Iinsn -Wall -g -Werror +CFLAGS += -MMD -MP -I../kmod/patch -Iinsn -Wall -Wsign-compare -g -Werror LDLIBS = -lelf TARGETS = create-diff-object create-klp-module create-kpatch-module @@ -35,7 +35,7 @@ install: all $(INSTALL) -d $(LIBEXECDIR) - $(INSTALL) $(TARGETS) kpatch-gcc $(PLUGIN) $(LIBEXECDIR) + $(INSTALL) $(TARGETS) kpatch-gcc $(LIBEXECDIR) $(INSTALL) -d $(BINDIR) $(INSTALL) kpatch-build $(BINDIR) diff -Nru kpatch-0.5.0/Makefile kpatch-0.8.0/Makefile --- kpatch-0.5.0/Makefile 2017-12-21 05:02:48.000000000 +0000 +++ kpatch-0.8.0/Makefile 2019-08-28 17:34:00.000000000 +0000 @@ -6,8 +6,15 @@ UNINSTALL_DIRS = $(SUBDIRS:%=uninstall-%) CLEAN_DIRS = $(SUBDIRS:%=clean-%) -.PHONY: all install uninstall clean check +UNITTEST_DIR = test/unit +INTEGRATION_DIR = test/integration +CLEAN_DIRS += clean-$(UNITTEST_DIR) + +.PHONY: all install uninstall clean check unit .PHONY: $(SUBDIRS) $(BUILD_DIRS) $(INSTALL_DIRS) $(CLEAN_DIRS) +.PHONY: integration integration-slow integration-quick +.PHONY: vagrant-integration-slow vagrant-integration-quick vagrant-integration +.PHONY: vagrant-install all: $(BUILD_DIRS) @@ -26,5 +33,33 @@ $(CLEAN_DIRS): $(MAKE) -C $(@:clean-%=%) clean +unit: $(UNITTEST_DIR)/Makefile build-kpatch-build + $(MAKE) -C $(UNITTEST_DIR) + +integration: integration-quick + +integration-slow: $(INTEGRATION_DIR)/Makefile build-kpatch-build build-kpatch build-kmod + $(MAKE) -C $(INTEGRATION_DIR) slow + +integration-quick: $(INTEGRATION_DIR)/Makefile build-kpatch-build build-kpatch build-kmod + $(MAKE) -C $(INTEGRATION_DIR) quick + +vagrant-install: $(INTEGRATION_DIR)/lib.sh +ifneq ($(shell id -u), 0) + @echo "WARNING: This target is intended for use on freshly-installed machines/vms only." && \ + echo "Do not proceed unless you read $(INTEGRATION_DIR)/lib.sh and realise what this target does." && \ + echo "Press ctrl-c to abort, return to proceed." && \ + read +endif + source $(INTEGRATION_DIR)/lib.sh && kpatch_check_install_vagrant + +vagrant-integration: vagrant-integration-quick + +vagrant-integration-slow: + $(MAKE) -C $(INTEGRATION_DIR) vagrant-slow + +vagrant-integration-quick: + $(MAKE) -C $(INTEGRATION_DIR) vagrant-quick + check: shellcheck kpatch/kpatch kpatch-build/kpatch-build kpatch-build/kpatch-gcc diff -Nru kpatch-0.5.0/Makefile.inc kpatch-0.8.0/Makefile.inc --- kpatch-0.5.0/Makefile.inc 2017-12-21 05:02:48.000000000 +0000 +++ kpatch-0.8.0/Makefile.inc 2019-08-28 17:34:00.000000000 +0000 @@ -15,6 +15,7 @@ DATADIR = $(DESTDIR)$(PREFIX)/share/kpatch MANDIR = $(DESTDIR)$(PREFIX)/share/man/man1 SYSTEMDDIR = $(DESTDIR)$(PREFIX)/lib/systemd/system +UPSTARTDIR = $(DESTDIR)/etc/init # The core module is only supported on x86_64 ifeq ($(ARCH),x86_64) diff -Nru kpatch-0.5.0/man/kpatch.1 kpatch-0.8.0/man/kpatch.1 --- kpatch-0.5.0/man/kpatch.1 2017-12-21 05:02:48.000000000 +0000 +++ kpatch-0.8.0/man/kpatch.1 2019-08-28 17:34:00.000000000 +0000 @@ -12,10 +12,10 @@ .SH COMMANDS install [-k|--kernel-version=] - install patch module to the initrd to be loaded at boot + install patch module to be loaded at boot uninstall [-k|--kernel-version=] - uninstall patch module from the initrd + uninstall patch module load --all load all installed patch modules into the running kernel @@ -35,6 +35,9 @@ list list installed patch modules +signal + signal/poke any process stalling the current patch transition + version display the kpatch version diff -Nru kpatch-0.5.0/man/kpatch-build.1 kpatch-0.8.0/man/kpatch-build.1 --- kpatch-0.5.0/man/kpatch-build.1 2017-12-21 05:02:48.000000000 +0000 +++ kpatch-0.8.0/man/kpatch-build.1 2019-08-28 17:34:00.000000000 +0000 @@ -11,14 +11,14 @@ modified functions in the kernel such that the patched code takes effect. -This script currently only works on Fedora and will need to be adapted -to work on other distros. - .SH OPTIONS -h|--help Show this help message +-a|--archversion + Specify the kernel arch version + -r|--sourcerpm Specify kernel source RPM @@ -31,11 +31,28 @@ -v|--vmlinux Specify original vmlinux +-j|--jobs + Specify the number of make jobs + -t|--target Specify custom kernel build targets +-n|--name + Specify the name of the kpatch module + +-o|--output + Specify output folder + -d|--debug Keep scratch files in /tmp + (can be specified multiple times) + +-e|--oot-module + Enable patching out-of-tree module, + specify current version of module + +--skip-cleanup + Skip post-build cleanup --skip-gcc-check Skips check that ensures that the system gcc version and diff -Nru kpatch-0.5.0/README.md kpatch-0.8.0/README.md --- kpatch-0.5.0/README.md 2017-12-21 05:02:48.000000000 +0000 +++ kpatch-0.8.0/README.md 2019-08-28 17:34:00.000000000 +0000 @@ -40,10 +40,13 @@ Install the dependencies for the "kpatch-build" command: ```bash -sudo dnf install rpmdevtools pesign yum-utils openssl wget numactl-devel +sudo dnf install pesign yum-utils openssl wget numactl-devel sudo dnf builddep kernel-${UNAME%.*} sudo dnf debuginfo-install kernel-${UNAME%.*} +# required on ppc64le +sudo dnf install gcc-plugin-devel + # optional, but highly recommended sudo dnf install ccache ccache --max-size=5G @@ -68,19 +71,22 @@ ```bash sudo yum-config-manager --enable rhel-7-server-optional-rpms -sudo yum install rpmdevtools pesign yum-utils zlib-devel \ +sudo yum install pesign yum-utils zlib-devel \ binutils-devel newt-devel python-devel perl-ExtUtils-Embed \ audit-libs-devel numactl-devel pciutils-devel bison ncurses-devel sudo yum-builddep kernel-${UNAME%.*} sudo debuginfo-install kernel-${UNAME%.*} +# required on ppc64le +sudo yum install gcc-plugin-devel + # optional, but highly recommended -sudo yum install https://dl.fedoraproject.org/pub/epel/7/x86_64/c/ccache-3.2.7-3.el7.x86_64.rpm +sudo yum install https://dl.fedoraproject.org/pub/epel/7/x86_64/Packages/c/ccache-3.3.4-1.el7.x86_64.rpm ccache --max-size=5G # optional, for kpatch-test -sudo dnf install patchutils +sudo yum install patchutils ``` #### CentOS 7 @@ -98,7 +104,7 @@ Install the dependencies for the "kpatch-build" command: ```bash -sudo yum install rpmdevtools pesign yum-utils zlib-devel \ +sudo yum install pesign yum-utils zlib-devel \ binutils-devel newt-devel python-devel perl-ExtUtils-Embed \ audit-libs audit-libs-devel numactl-devel pciutils-devel bison @@ -113,7 +119,7 @@ ccache --max-size=5G # optional, for kpatch-test -sudo dnf install patchutils +sudo yum install patchutils ``` #### Oracle Linux 7 @@ -131,7 +137,7 @@ Install the dependencies for the "kpatch-build" command: ```bash -sudo yum install rpmdevtools pesign yum-utils zlib-devel \ +sudo yum install pesign yum-utils zlib-devel \ binutils-devel newt-devel python-devel perl-ExtUtils-Embed \ audit-libs numactl-devel pciutils-devel bison @@ -149,10 +155,10 @@ ccache --max-size=5G # optional, for kpatch-test -sudo dnf install patchutils +sudo yum install patchutils ``` -#### Ubuntu 14.04 +#### Ubuntu *NOTE: You'll need about 15GB of free disk space for the kpatch-build cache in `~/.kpatch` and for ccache.* @@ -166,9 +172,13 @@ Install the dependencies for the "kpatch-build" command: ```bash -apt-get install dpkg-dev devscripts +apt-get install dpkg-dev devscripts elfutils apt-get build-dep linux +# required on ppc64le +# e.g., on Ubuntu 18.04 for gcc-7.3 +apt-get install gcc-7-plugin-dev + # optional, but highly recommended apt-get install ccache ccache --max-size=5G @@ -232,6 +242,10 @@ apt-get install dpkg-dev apt-get build-dep linux + # required on ppc64le + # e.g., on stretch for gcc-6.3 + apt-get install gcc-6-plugin-dev + # optional, but highly recommended apt-get install ccache ccache --max-size=5G @@ -459,11 +473,10 @@ supported. kpatch-build will return an error if the patch attempts to do so. -- Patches which modify statically allocated data are not supported. - kpatch-build will detect that and return an error. (In the future - we will add a facility to support it. It will probably require the - user to write code which runs at patch module loading time which manually - updates the data.) +- Patches which modify statically allocated data are not directly supported. + kpatch-build will detect that and return an error. This limitation can be + overcome by using callbacks or shadow variables, as described in the + [Patch Author Guide](doc/patch-author-guide.md). - Patches which change the way a function interacts with dynamically allocated data might be safe, or might not. It isn't possible for @@ -634,9 +647,27 @@ **Q. Can you patch out-of-tree modules?** -- Yes, though it's currently a bit of a manual process. See this - [message](https://www.redhat.com/archives/kpatch/2015-June/msg00004.html) on - the kpatch mailing list for more information. +Yes! There's a few requirements, and the feature is still in its infancy. + +1. You need to use the `--oot-module` flag to specify the version of the +module that's currently running on the machine. +2. `--sourcedir` has to be passed with a directory containing the same +version of code as the running module, all set up and ready to build with a +`make` command. For example, some modules need `autogen.sh` and +`./configure` to have been run with the appropriate flags to match the +currently-running module. +3. If the `Module.symvers` file for the out-of-tree module doesn't appear +in the root of the provided source directory, a symlink needs to be created +in that directory that points to its actual location. +4. Usually you'll need to pass the `--target` flag as well, to specify the +proper `make` target names. +5. This has only been tested for a single out-of-tree module per patch, and +not for out-of-tree modules with dependencies on other out-of-tree modules +built separately. + +***Sample invocation*** + +`kpatch-build --sourcedir ~/test/ --target default --oot-module /lib/modules/$(uname -r)/extra/test.ko test.patch` Get involved diff -Nru kpatch-0.5.0/test/difftree.sh kpatch-0.8.0/test/difftree.sh --- kpatch-0.5.0/test/difftree.sh 2017-12-21 05:02:48.000000000 +0000 +++ kpatch-0.8.0/test/difftree.sh 2019-08-28 17:34:00.000000000 +0000 @@ -30,6 +30,7 @@ case $i in *.mod.o|\ *built-in.o|\ + *built-in.a|\ vmlinux.o|\ .tmp_kallsyms1.o|\ .tmp_kallsyms2.o|\ @@ -45,7 +46,7 @@ ;; esac # skip objects that are the linked product of more than one object file - [[ $(eu-readelf -s $i | grep FILE | wc -l) -ne 1 ]] && continue + [[ $(readelf -s $i | awk '$4=="FILE" {n++} END {print n}') -ne 1 ]] && continue $SCRIPTDIR/../kpatch-build/create-diff-object $i $i /usr/lib/debug/lib/modules/$(uname -r)/vmlinux "$TEMPDIR/output.o" > "$TEMPDIR/log.txt" 2>&1 RETCODE=$? # expect RETCODE to be 3 indicating no change diff -Nru kpatch-0.5.0/test/integration/centos-7/fixup-section.patch kpatch-0.8.0/test/integration/centos-7/fixup-section.patch --- kpatch-0.5.0/test/integration/centos-7/fixup-section.patch 2017-12-21 05:02:48.000000000 +0000 +++ kpatch-0.8.0/test/integration/centos-7/fixup-section.patch 2019-08-28 17:34:00.000000000 +0000 @@ -1,12 +1,12 @@ -diff -Nupr src.orig/fs/readdir.c src/fs/readdir.c ---- src.orig/fs/readdir.c 2017-09-22 15:27:21.658056010 -0400 -+++ src/fs/readdir.c 2017-09-22 15:27:26.378075555 -0400 -@@ -166,6 +166,8 @@ static int filldir(void * __buf, const c +diff --git a/fs/readdir.c b/fs/readdir.c +index febd02dfbe2d..064db7bd70d0 100644 +--- a/fs/readdir.c ++++ b/fs/readdir.c +@@ -176,6 +176,7 @@ static int filldir(void * __buf, const char * name, int namlen, loff_t offset, goto efault; } dirent = buf->current_dir; -+ if (dirent->d_ino == 12345678) -+ printk("kpatch-test: testing .fixup section changes\n"); ++ asm("nop"); if (__put_user(d_ino, &dirent->d_ino)) goto efault; if (__put_user(reclen, &dirent->d_reclen)) diff -Nru kpatch-0.5.0/test/integration/centos-7/gcc-static-local-var-2.patch kpatch-0.8.0/test/integration/centos-7/gcc-static-local-var-2.patch --- kpatch-0.5.0/test/integration/centos-7/gcc-static-local-var-2.patch 2017-12-21 05:02:48.000000000 +0000 +++ kpatch-0.8.0/test/integration/centos-7/gcc-static-local-var-2.patch 2019-08-28 17:34:00.000000000 +0000 @@ -1,14 +1,6 @@ diff -Nupr src.orig/mm/mmap.c src/mm/mmap.c --- src.orig/mm/mmap.c 2017-09-22 15:27:21.618055844 -0400 +++ src/mm/mmap.c 2017-09-22 15:27:31.024094794 -0400 -@@ -1677,6 +1677,7 @@ static inline int accountable_mapping(st - return (vm_flags & (VM_NORESERVE | VM_SHARED | VM_WRITE)) == VM_WRITE; - } - -+#include "kpatch-macros.h" - unsigned long mmap_region(struct file *file, unsigned long addr, - unsigned long len, vm_flags_t vm_flags, unsigned long pgoff, - struct list_head *uf) @@ -1687,6 +1688,9 @@ unsigned long mmap_region(struct file *f struct rb_node **rb_link, *rb_parent; unsigned long charged = 0; diff -Nru kpatch-0.5.0/test/integration/centos-7/gcc-static-local-var-4.test kpatch-0.8.0/test/integration/centos-7/gcc-static-local-var-4.test --- kpatch-0.5.0/test/integration/centos-7/gcc-static-local-var-4.test 2017-12-21 05:02:48.000000000 +0000 +++ kpatch-0.8.0/test/integration/centos-7/gcc-static-local-var-4.test 2019-08-28 17:34:00.000000000 +0000 @@ -1,6 +1,6 @@ #!/bin/bash -if $(nm kpatch-gcc-static-local-var-4.ko | grep -q free_ioctx); then +if $(nm test-gcc-static-local-var-4.ko | grep -q free_ioctx); then exit 1 else exit 0 diff -Nru kpatch-0.5.0/test/integration/centos-7/gcc-static-local-var-6.patch kpatch-0.8.0/test/integration/centos-7/gcc-static-local-var-6.patch --- kpatch-0.5.0/test/integration/centos-7/gcc-static-local-var-6.patch 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/test/integration/centos-7/gcc-static-local-var-6.patch 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1,23 @@ +diff --git a/net/ipv6/netfilter.c b/net/ipv6/netfilter.c +index a9d587a..23336ed 100644 +--- a/net/ipv6/netfilter.c ++++ b/net/ipv6/netfilter.c +@@ -106,6 +106,8 @@ static int nf_ip6_reroute(struct sk_buff *skb, + return 0; + } + ++#include "kpatch-macros.h" ++ + static int nf_ip6_route(struct net *net, struct dst_entry **dst, + struct flowi *fl, bool strict) + { +@@ -119,6 +121,9 @@ static int nf_ip6_route(struct net *net, struct dst_entry **dst, + struct dst_entry *result; + int err; + ++ if (!jiffies) ++ printk("kpatch nf_ip6_route foo\n"); ++ + result = ip6_route_output(net, sk, &fl->u.ip6); + err = result->error; + if (err) diff -Nru kpatch-0.5.0/test/integration/centos-7/macro-callbacks.patch kpatch-0.8.0/test/integration/centos-7/macro-callbacks.patch --- kpatch-0.5.0/test/integration/centos-7/macro-callbacks.patch 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/test/integration/centos-7/macro-callbacks.patch 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1,160 @@ +kpatch/livepatch callback test patch: + + vmlinux + pcspkr (mod) + joydev (mod) + +Note: update joydev's pre-patch callback to return -ENODEV to test failure path + +--- src.old/fs/aio.c 2018-02-26 11:07:51.522610407 -0500 ++++ src/fs/aio.c 2018-03-05 11:17:21.560015449 -0500 +@@ -42,6 +42,50 @@ + #include + #include + ++#include ++#include "kpatch-macros.h" ++ ++static const char *const module_state[] = { ++ [MODULE_STATE_LIVE] = "[MODULE_STATE_LIVE] Normal state", ++ [MODULE_STATE_COMING] = "[MODULE_STATE_COMING] Full formed, running module_init", ++ [MODULE_STATE_GOING] = "[MODULE_STATE_GOING] Going away", ++ [MODULE_STATE_UNFORMED] = "[MODULE_STATE_UNFORMED] Still setting it up", ++}; ++ ++static void callback_info(const char *callback, patch_object *obj) ++{ ++ if (obj->mod) ++ pr_info("%s: %s -> %s\n", callback, obj->mod->name, ++ module_state[obj->mod->state]); ++ else ++ pr_info("%s: vmlinux\n", callback); ++} ++ ++static int pre_patch_callback(patch_object *obj) ++{ ++ callback_info(__func__, obj); ++ return 0; ++} ++KPATCH_PRE_PATCH_CALLBACK(pre_patch_callback); ++ ++static void post_patch_callback(patch_object *obj) ++{ ++ callback_info(__func__, obj); ++} ++KPATCH_POST_PATCH_CALLBACK(post_patch_callback); ++ ++static void pre_unpatch_callback(patch_object *obj) ++{ ++ callback_info(__func__, obj); ++} ++KPATCH_PRE_UNPATCH_CALLBACK(pre_unpatch_callback); ++ ++static void post_unpatch_callback(patch_object *obj) ++{ ++ callback_info(__func__, obj); ++} ++KPATCH_POST_UNPATCH_CALLBACK(post_unpatch_callback); ++ + #define AIO_RING_MAGIC 0xa10a10a1 + #define AIO_RING_COMPAT_FEATURES 1 + #define AIO_RING_INCOMPAT_FEATURES 0 +--- src.old/drivers/input/joydev.c 2018-02-26 11:07:49.470610407 -0500 ++++ src/drivers/input/joydev.c 2018-03-05 11:18:13.998015449 -0500 +@@ -954,3 +954,47 @@ static void __exit joydev_exit(void) + + module_init(joydev_init); + module_exit(joydev_exit); ++ ++#include ++#include "kpatch-macros.h" ++ ++static const char *const module_state[] = { ++ [MODULE_STATE_LIVE] = "[MODULE_STATE_LIVE] Normal state", ++ [MODULE_STATE_COMING] = "[MODULE_STATE_COMING] Full formed, running module_init", ++ [MODULE_STATE_GOING] = "[MODULE_STATE_GOING] Going away", ++ [MODULE_STATE_UNFORMED] = "[MODULE_STATE_UNFORMED] Still setting it up", ++}; ++ ++static void callback_info(const char *callback, patch_object *obj) ++{ ++ if (obj->mod) ++ pr_info("%s: %s -> %s\n", callback, obj->mod->name, ++ module_state[obj->mod->state]); ++ else ++ pr_info("%s: vmlinux\n", callback); ++} ++ ++static int pre_patch_callback(patch_object *obj) ++{ ++ callback_info(__func__, obj); ++ return 0; /* return -ENODEV; */ ++} ++KPATCH_PRE_PATCH_CALLBACK(pre_patch_callback); ++ ++static void post_patch_callback(patch_object *obj) ++{ ++ callback_info(__func__, obj); ++} ++KPATCH_POST_PATCH_CALLBACK(post_patch_callback); ++ ++static void pre_unpatch_callback(patch_object *obj) ++{ ++ callback_info(__func__, obj); ++} ++KPATCH_PRE_UNPATCH_CALLBACK(pre_unpatch_callback); ++ ++static void post_unpatch_callback(patch_object *obj) ++{ ++ callback_info(__func__, obj); ++} ++KPATCH_POST_UNPATCH_CALLBACK(post_unpatch_callback); +--- src.old/drivers/input/misc/pcspkr.c 2018-02-26 11:07:49.477610407 -0500 ++++ src/drivers/input/misc/pcspkr.c 2018-03-05 11:18:23.411015449 -0500 +@@ -136,3 +136,46 @@ static struct platform_driver pcspkr_pla + }; + module_platform_driver(pcspkr_platform_driver); + ++#include ++#include "kpatch-macros.h" ++ ++static const char *const module_state[] = { ++ [MODULE_STATE_LIVE] = "[MODULE_STATE_LIVE] Normal state", ++ [MODULE_STATE_COMING] = "[MODULE_STATE_COMING] Full formed, running module_init", ++ [MODULE_STATE_GOING] = "[MODULE_STATE_GOING] Going away", ++ [MODULE_STATE_UNFORMED] = "[MODULE_STATE_UNFORMED] Still setting it up", ++}; ++ ++static void callback_info(const char *callback, patch_object *obj) ++{ ++ if (obj->mod) ++ pr_info("%s: %s -> %s\n", callback, obj->mod->name, ++ module_state[obj->mod->state]); ++ else ++ pr_info("%s: vmlinux\n", callback); ++} ++ ++static int pre_patch_callback(patch_object *obj) ++{ ++ callback_info(__func__, obj); ++ return 0; ++} ++KPATCH_PRE_PATCH_CALLBACK(pre_patch_callback); ++ ++static void post_patch_callback(patch_object *obj) ++{ ++ callback_info(__func__, obj); ++} ++KPATCH_POST_PATCH_CALLBACK(post_patch_callback); ++ ++static void pre_unpatch_callback(patch_object *obj) ++{ ++ callback_info(__func__, obj); ++} ++KPATCH_PRE_UNPATCH_CALLBACK(pre_unpatch_callback); ++ ++static void post_unpatch_callback(patch_object *obj) ++{ ++ callback_info(__func__, obj); ++} ++KPATCH_POST_UNPATCH_CALLBACK(post_unpatch_callback); diff -Nru kpatch-0.5.0/test/integration/centos-7/macro-hooks-LOADED.test kpatch-0.8.0/test/integration/centos-7/macro-hooks-LOADED.test --- kpatch-0.5.0/test/integration/centos-7/macro-hooks-LOADED.test 2017-12-21 05:02:48.000000000 +0000 +++ kpatch-0.8.0/test/integration/centos-7/macro-hooks-LOADED.test 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -#!/bin/bash - -[[ $(cat /proc/sys/fs/aio-max-nr) = 262144 ]] diff -Nru kpatch-0.5.0/test/integration/centos-7/macro-hooks.patch kpatch-0.8.0/test/integration/centos-7/macro-hooks.patch --- kpatch-0.5.0/test/integration/centos-7/macro-hooks.patch 2017-12-21 05:02:48.000000000 +0000 +++ kpatch-0.8.0/test/integration/centos-7/macro-hooks.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,24 +0,0 @@ -diff -Nupr src.orig/fs/aio.c src/fs/aio.c ---- src.orig/fs/aio.c 2017-09-22 15:27:21.702056192 -0400 -+++ src/fs/aio.c 2017-09-22 15:27:36.703118311 -0400 -@@ -1683,6 +1683,20 @@ SYSCALL_DEFINE3(io_cancel, aio_context_t - return ret; - } - -+static int aio_max_nr_orig; -+void kpatch_load_aio_max_nr(void) -+{ -+ aio_max_nr_orig = aio_max_nr; -+ aio_max_nr = 0x40000; -+} -+void kpatch_unload_aio_max_nr(void) -+{ -+ aio_max_nr = aio_max_nr_orig; -+} -+#include "kpatch-macros.h" -+KPATCH_LOAD_HOOK(kpatch_load_aio_max_nr); -+KPATCH_UNLOAD_HOOK(kpatch_unload_aio_max_nr); -+ - /* io_getevents: - * Attempts to read at least min_nr events and up to nr events from - * the completion queue for the aio_context specified by ctx_id. If diff -Nru kpatch-0.5.0/test/integration/centos-7/macro-printk.patch kpatch-0.8.0/test/integration/centos-7/macro-printk.patch --- kpatch-0.5.0/test/integration/centos-7/macro-printk.patch 2017-12-21 05:02:48.000000000 +0000 +++ kpatch-0.8.0/test/integration/centos-7/macro-printk.patch 2019-08-28 17:34:00.000000000 +0000 @@ -1,7 +1,8 @@ -diff -Nupr src.orig/net/ipv4/fib_frontend.c src/net/ipv4/fib_frontend.c ---- src.orig/net/ipv4/fib_frontend.c 2017-09-22 16:52:10.646110299 -0400 -+++ src/net/ipv4/fib_frontend.c 2017-09-22 16:55:14.395870305 -0400 -@@ -633,6 +633,7 @@ errout: +Index: src/net/ipv4/fib_frontend.c +=================================================================== +--- src.orig/net/ipv4/fib_frontend.c ++++ src/net/ipv4/fib_frontend.c +@@ -685,6 +685,7 @@ errout: return err; } @@ -9,7 +10,7 @@ static int inet_rtm_newroute(struct sk_buff *skb, struct nlmsghdr *nlh) { struct net *net = sock_net(skb->sk); -@@ -651,6 +652,7 @@ static int inet_rtm_newroute(struct sk_b +@@ -703,6 +704,7 @@ static int inet_rtm_newroute(struct sk_b } err = fib_table_insert(net, tb, &cfg); @@ -17,10 +18,11 @@ errout: return err; } -diff -Nupr src.orig/net/ipv4/fib_semantics.c src/net/ipv4/fib_semantics.c ---- src.orig/net/ipv4/fib_semantics.c 2017-09-22 16:52:10.645110295 -0400 -+++ src/net/ipv4/fib_semantics.c 2017-09-22 16:54:05.175584004 -0400 -@@ -925,6 +925,7 @@ fib_convert_metrics(struct fib_info *fi, +Index: src/net/ipv4/fib_semantics.c +=================================================================== +--- src.orig/net/ipv4/fib_semantics.c ++++ src/net/ipv4/fib_semantics.c +@@ -969,6 +969,7 @@ fib_convert_metrics(struct fib_info *fi, return 0; } @@ -28,7 +30,7 @@ struct fib_info *fib_create_info(struct fib_config *cfg) { int err; -@@ -949,6 +950,7 @@ struct fib_info *fib_create_info(struct +@@ -993,6 +994,7 @@ struct fib_info *fib_create_info(struct #endif err = -ENOBUFS; @@ -36,7 +38,7 @@ if (fib_info_cnt >= fib_info_hash_size) { unsigned int new_size = fib_info_hash_size << 1; struct hlist_head *new_info_hash; -@@ -969,6 +971,7 @@ struct fib_info *fib_create_info(struct +@@ -1013,6 +1015,7 @@ struct fib_info *fib_create_info(struct if (!fib_info_hash_size) goto failure; } @@ -44,15 +46,15 @@ fi = kzalloc(sizeof(*fi)+nhs*sizeof(struct fib_nh), GFP_KERNEL); if (fi == NULL) -@@ -980,6 +983,7 @@ struct fib_info *fib_create_info(struct - } else - fi->fib_metrics = (u32 *) dst_default_metrics; +@@ -1028,6 +1031,7 @@ struct fib_info *fib_create_info(struct + fi->fib_metrics = (struct dst_metrics *)&dst_default_metrics; + } fib_info_cnt++; + KPATCH_PRINTK("[fib_create_info]: 3 create error err is %d\n",err); - fi->fib_net = net; fi->fib_protocol = cfg->fc_protocol; -@@ -996,8 +1000,10 @@ struct fib_info *fib_create_info(struct + fi->fib_scope = cfg->fc_scope; +@@ -1043,8 +1047,10 @@ struct fib_info *fib_create_info(struct if (!nexthop_nh->nh_pcpu_rth_output) goto failure; } endfor_nexthops(fi) @@ -63,7 +65,7 @@ if (err) goto failure; -@@ -1048,6 +1054,7 @@ struct fib_info *fib_create_info(struct +@@ -1095,6 +1101,7 @@ struct fib_info *fib_create_info(struct nh->nh_weight = 1; #endif } @@ -71,7 +73,7 @@ if (fib_props[cfg->fc_type].error) { if (cfg->fc_gw || cfg->fc_oif || cfg->fc_mp) -@@ -1065,6 +1072,7 @@ struct fib_info *fib_create_info(struct +@@ -1112,6 +1119,7 @@ struct fib_info *fib_create_info(struct goto err_inval; } } @@ -79,7 +81,7 @@ if (cfg->fc_scope > RT_SCOPE_HOST) goto err_inval; -@@ -1087,6 +1095,7 @@ struct fib_info *fib_create_info(struct +@@ -1134,6 +1142,7 @@ struct fib_info *fib_create_info(struct goto failure; } endfor_nexthops(fi) } @@ -87,7 +89,7 @@ if (fi->fib_prefsrc) { if (cfg->fc_type != RTN_LOCAL || !cfg->fc_dst || -@@ -1099,6 +1108,7 @@ struct fib_info *fib_create_info(struct +@@ -1146,6 +1155,7 @@ struct fib_info *fib_create_info(struct fib_info_update_nh_saddr(net, nexthop_nh); fib_add_weight(fi, nexthop_nh); } endfor_nexthops(fi) @@ -95,7 +97,7 @@ fib_rebalance(fi); -@@ -1110,6 +1120,7 @@ link_it: +@@ -1157,6 +1167,7 @@ link_it: ofi->fib_treeref++; return ofi; } @@ -103,7 +105,7 @@ fi->fib_treeref++; atomic_inc(&fi->fib_clntref); -@@ -1133,6 +1144,7 @@ link_it: +@@ -1180,6 +1191,7 @@ link_it: hlist_add_head(&nexthop_nh->nh_hash, head); } endfor_nexthops(fi) spin_unlock_bh(&fib_info_lock); @@ -111,7 +113,7 @@ return fi; err_inval: -@@ -1143,6 +1155,7 @@ failure: +@@ -1190,6 +1202,7 @@ failure: fi->fib_dead = 1; free_fib_info(fi); } @@ -119,10 +121,11 @@ return ERR_PTR(err); } -diff -Nupr src.orig/net/ipv4/fib_trie.c src/net/ipv4/fib_trie.c ---- src.orig/net/ipv4/fib_trie.c 2017-09-22 16:52:10.645110295 -0400 -+++ src/net/ipv4/fib_trie.c 2017-09-22 16:55:39.940975963 -0400 -@@ -1191,6 +1191,7 @@ static int fib_insert_alias(struct trie +Index: src/net/ipv4/fib_trie.c +=================================================================== +--- src.orig/net/ipv4/fib_trie.c ++++ src/net/ipv4/fib_trie.c +@@ -1105,6 +1105,7 @@ static int fib_insert_alias(struct trie } /* Caller must hold RTNL. */ @@ -130,7 +133,7 @@ int fib_table_insert(struct net *net, struct fib_table *tb, struct fib_config *cfg) { -@@ -1216,11 +1217,14 @@ int fib_table_insert(struct net *net, st +@@ -1130,11 +1131,14 @@ int fib_table_insert(struct net *net, st if ((plen < KEYLENGTH) && (key << plen)) return -EINVAL; @@ -144,4 +147,4 @@ + KPATCH_PRINTK("[fib_table_insert]: cross\n"); l = fib_find_node(t, &tp, key); - fa = l ? fib_find_alias(&l->leaf, slen, tos, fi->fib_priority) : NULL; + fa = l ? fib_find_alias(&l->leaf, slen, tos, fi->fib_priority, diff -Nru kpatch-0.5.0/test/integration/centos-7/meminfo-cmdline-rebuild-SLOW-LOADED.test kpatch-0.8.0/test/integration/centos-7/meminfo-cmdline-rebuild-SLOW-LOADED.test --- kpatch-0.5.0/test/integration/centos-7/meminfo-cmdline-rebuild-SLOW-LOADED.test 2017-12-21 05:02:48.000000000 +0000 +++ kpatch-0.8.0/test/integration/centos-7/meminfo-cmdline-rebuild-SLOW-LOADED.test 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -#!/bin/bash - -grep VMALLOCCHUNK /proc/meminfo && grep kpatch=1 /proc/cmdline diff -Nru kpatch-0.5.0/test/integration/centos-7/meminfo-cmdline-rebuild-SLOW-LOADED.test.disabled kpatch-0.8.0/test/integration/centos-7/meminfo-cmdline-rebuild-SLOW-LOADED.test.disabled --- kpatch-0.5.0/test/integration/centos-7/meminfo-cmdline-rebuild-SLOW-LOADED.test.disabled 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/test/integration/centos-7/meminfo-cmdline-rebuild-SLOW-LOADED.test.disabled 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1,3 @@ +#!/bin/bash + +grep VMALLOCCHUNK /proc/meminfo && grep kpatch=1 /proc/cmdline diff -Nru kpatch-0.5.0/test/integration/centos-7/meminfo-cmdline-rebuild-SLOW.patch kpatch-0.8.0/test/integration/centos-7/meminfo-cmdline-rebuild-SLOW.patch --- kpatch-0.5.0/test/integration/centos-7/meminfo-cmdline-rebuild-SLOW.patch 2017-12-21 05:02:48.000000000 +0000 +++ kpatch-0.8.0/test/integration/centos-7/meminfo-cmdline-rebuild-SLOW.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,35 +0,0 @@ -diff -Nupr src.orig/fs/proc/cmdline.c src/fs/proc/cmdline.c ---- src.orig/fs/proc/cmdline.c 2017-09-22 15:27:21.698056175 -0400 -+++ src/fs/proc/cmdline.c 2017-09-22 15:27:37.842123028 -0400 -@@ -5,7 +5,7 @@ - - static int cmdline_proc_show(struct seq_file *m, void *v) - { -- seq_printf(m, "%s\n", saved_command_line); -+ seq_printf(m, "%s kpatch=1\n", saved_command_line); - return 0; - } - -diff -Nupr src.orig/fs/proc/meminfo.c src/fs/proc/meminfo.c ---- src.orig/fs/proc/meminfo.c 2017-09-22 15:27:21.699056179 -0400 -+++ src/fs/proc/meminfo.c 2017-09-22 15:27:37.843123032 -0400 -@@ -99,7 +99,7 @@ static int meminfo_proc_show(struct seq_ - "Committed_AS: %8lu kB\n" - "VmallocTotal: %8lu kB\n" - "VmallocUsed: %8lu kB\n" -- "VmallocChunk: %8lu kB\n" -+ "VMALLOCCHUNK: %8lu kB\n" - #ifdef CONFIG_MEMORY_FAILURE - "HardwareCorrupted: %5lu kB\n" - #endif -diff -Nupr src.orig/include/linux/kernel.h src/include/linux/kernel.h ---- src.orig/include/linux/kernel.h 2017-09-22 15:27:20.379050713 -0400 -+++ src/include/linux/kernel.h 2017-09-22 15:27:37.843123032 -0400 -@@ -2,6 +2,7 @@ - #define _LINUX_KERNEL_H - - -+ - #include - #include - #include diff -Nru kpatch-0.5.0/test/integration/centos-7/meminfo-cmdline-rebuild-SLOW.patch.disabled kpatch-0.8.0/test/integration/centos-7/meminfo-cmdline-rebuild-SLOW.patch.disabled --- kpatch-0.5.0/test/integration/centos-7/meminfo-cmdline-rebuild-SLOW.patch.disabled 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/test/integration/centos-7/meminfo-cmdline-rebuild-SLOW.patch.disabled 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1,37 @@ +Disabled due to CSWTITCH issue from https://github.com/dynup/kpatch/issues/876 +--- +diff -Nupr src.orig/fs/proc/cmdline.c src/fs/proc/cmdline.c +--- src.orig/fs/proc/cmdline.c 2017-09-22 15:27:21.698056175 -0400 ++++ src/fs/proc/cmdline.c 2017-09-22 15:27:37.842123028 -0400 +@@ -5,7 +5,7 @@ + + static int cmdline_proc_show(struct seq_file *m, void *v) + { +- seq_printf(m, "%s\n", saved_command_line); ++ seq_printf(m, "%s kpatch=1\n", saved_command_line); + return 0; + } + +diff -Nupr src.orig/fs/proc/meminfo.c src/fs/proc/meminfo.c +--- src.orig/fs/proc/meminfo.c 2017-09-22 15:27:21.699056179 -0400 ++++ src/fs/proc/meminfo.c 2017-09-22 15:27:37.843123032 -0400 +@@ -99,7 +99,7 @@ static int meminfo_proc_show(struct seq_ + "Committed_AS: %8lu kB\n" + "VmallocTotal: %8lu kB\n" + "VmallocUsed: %8lu kB\n" +- "VmallocChunk: %8lu kB\n" ++ "VMALLOCCHUNK: %8lu kB\n" + #ifdef CONFIG_MEMORY_FAILURE + "HardwareCorrupted: %5lu kB\n" + #endif +diff -Nupr src.orig/include/linux/kernel.h src/include/linux/kernel.h +--- src.orig/include/linux/kernel.h 2017-09-22 15:27:20.379050713 -0400 ++++ src/include/linux/kernel.h 2017-09-22 15:27:37.843123032 -0400 +@@ -2,6 +2,7 @@ + #define _LINUX_KERNEL_H + + ++ + #include + #include + #include diff -Nru kpatch-0.5.0/test/integration/centos-7/module-shadow.patch kpatch-0.8.0/test/integration/centos-7/module-shadow.patch --- kpatch-0.5.0/test/integration/centos-7/module-shadow.patch 2017-12-21 05:02:48.000000000 +0000 +++ kpatch-0.8.0/test/integration/centos-7/module-shadow.patch 2019-08-28 17:34:00.000000000 +0000 @@ -1,22 +1,23 @@ -diff -Nupr src.orig/arch/x86/kvm/vmx.c src/arch/x86/kvm/vmx.c ---- src.orig/arch/x86/kvm/vmx.c 2017-09-22 15:27:20.853052676 -0400 -+++ src/arch/x86/kvm/vmx.c 2017-09-22 15:27:44.742151601 -0400 -@@ -10581,10 +10581,20 @@ static void vmx_leave_nested(struct kvm_ +Index: src/arch/x86/kvm/vmx.c +=================================================================== +--- src.orig/arch/x86/kvm/vmx.c ++++ src/arch/x86/kvm/vmx.c +@@ -11406,10 +11406,20 @@ static void vmx_leave_nested(struct kvm_ * It should only be called before L2 actually succeeded to run, and when * vmcs01 is current (it doesn't leave_guest_mode() or switch vmcss). */ -+#include "kpatch.h" ++#include static void nested_vmx_entry_failure(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12, u32 reason, unsigned long qualification) { + int *kpatch; + -+ kpatch = kpatch_shadow_alloc(vcpu, "kpatch", sizeof(*kpatch), -+ GFP_KERNEL); ++ kpatch = klp_shadow_alloc(vcpu, 0, sizeof(*kpatch), ++ GFP_KERNEL, NULL, NULL); + if (kpatch) { -+ kpatch_shadow_get(vcpu, "kpatch"); -+ kpatch_shadow_free(vcpu, "kpatch"); ++ klp_shadow_get(vcpu, 0); ++ klp_shadow_free(vcpu, 0, NULL); + } + load_vmcs12_host_state(vcpu, vmcs12); diff -Nru kpatch-0.5.0/test/integration/centos-7/multiple.test kpatch-0.8.0/test/integration/centos-7/multiple.test --- kpatch-0.5.0/test/integration/centos-7/multiple.test 2017-12-21 05:02:48.000000000 +0000 +++ kpatch-0.8.0/test/integration/centos-7/multiple.test 2019-08-28 17:34:00.000000000 +0000 @@ -4,6 +4,10 @@ ROOTDIR="$(readlink -f $SCRIPTDIR/../../..)" KPATCH="sudo $ROOTDIR/kpatch/kpatch" +MODULE_PREFIX="test-" +MODULE_POSTFIX=".ko" +TEST_POSTFIX="-LOADED.test" + set -o errexit die() { @@ -12,12 +16,27 @@ } ko_to_test() { - tmp=${1%.ko}-LOADED.test - echo ${tmp#kpatch-} + tmp=${1%${MODULE_POSTFIX}}${TEST_POSTFIX} + echo ${tmp#${MODULE_PREFIX}} } # make sure any modules added here are disjoint -declare -a modules=(kpatch-cmdline-string.ko kpatch-meminfo-string.ko) +declare -a modules +declare -a blacklist=(data-new-LOADED.test) + +for file in "${SCRIPTDIR}"/*"${TEST_POSTFIX}"; do + name=$(basename ${file}) + skip=0 + for bname in "${blacklist[@]}"; do + if [ "${bname}" == "${name}" ]; then + skip=1 + break + fi + done + if [ ${skip} -eq 0 ]; then + modules+=(${MODULE_PREFIX}${name%${TEST_POSTFIX}}${MODULE_POSTFIX}) + fi +done for mod in "${modules[@]}"; do testprog=$(ko_to_test $mod) @@ -33,7 +52,8 @@ $SCRIPTDIR/$testprog || die "$SCRIPTDIR/$testprog failed after loading modules" done -for mod in "${modules[@]}"; do +for ((idx=${#modules[@]}-1 ; idx>=0 ; idx--)); do + mod=${modules[idx]} $KPATCH unload $mod done diff -Nru kpatch-0.5.0/test/integration/centos-7/remote-setup kpatch-0.8.0/test/integration/centos-7/remote-setup --- kpatch-0.5.0/test/integration/centos-7/remote-setup 2017-12-21 05:02:48.000000000 +0000 +++ kpatch-0.8.0/test/integration/centos-7/remote-setup 2019-08-28 17:34:00.000000000 +0000 @@ -20,7 +20,7 @@ $sudo dnf install -y $* || $sudo dnf install -y $* } -install_rpms gcc elfutils elfutils-devel rpmdevtools pesign openssl numactl-devel wget patchutils +install_rpms gcc elfutils elfutils-devel pesign openssl numactl-devel wget patchutils $sudo dnf builddep -y kernel || $sudo dnf builddep -y kernel diff -Nru kpatch-0.5.0/test/integration/centos-7/shadow-newpid.patch kpatch-0.8.0/test/integration/centos-7/shadow-newpid.patch --- kpatch-0.5.0/test/integration/centos-7/shadow-newpid.patch 2017-12-21 05:02:48.000000000 +0000 +++ kpatch-0.8.0/test/integration/centos-7/shadow-newpid.patch 2019-08-28 17:34:00.000000000 +0000 @@ -1,11 +1,12 @@ -diff -Nupr src.orig/fs/proc/array.c src/fs/proc/array.c ---- src.orig/fs/proc/array.c 2017-09-22 16:52:10.597110096 -0400 -+++ src/fs/proc/array.c 2017-09-22 16:59:40.799972178 -0400 -@@ -359,13 +359,20 @@ static inline void task_seccomp(struct s - #endif +Index: src/fs/proc/array.c +=================================================================== +--- src.orig/fs/proc/array.c ++++ src/fs/proc/array.c +@@ -394,13 +394,20 @@ static inline void task_seccomp(struct s + seq_putc(m, '\n'); } -+#include "kpatch.h" ++#include static inline void task_context_switch_counts(struct seq_file *m, struct task_struct *p) { @@ -16,52 +17,54 @@ p->nvcsw, p->nivcsw); + -+ newpid = kpatch_shadow_get(p, "newpid"); ++ newpid = klp_shadow_get(p, 0); + if (newpid) + seq_printf(m, "newpid:\t%d\n", *newpid); } static void task_cpus_allowed(struct seq_file *m, struct task_struct *task) -diff -Nupr src.orig/kernel/exit.c src/kernel/exit.c ---- src.orig/kernel/exit.c 2017-09-22 16:52:10.506109720 -0400 -+++ src/kernel/exit.c 2017-09-22 16:59:40.799972178 -0400 -@@ -715,6 +715,7 @@ static void check_stack_usage(void) +Index: src/kernel/exit.c +=================================================================== +--- src.orig/kernel/exit.c ++++ src/kernel/exit.c +@@ -791,6 +791,7 @@ static void check_stack_usage(void) static inline void check_stack_usage(void) {} #endif -+#include "kpatch.h" ++#include void do_exit(long code) { struct task_struct *tsk = current; -@@ -812,6 +813,8 @@ void do_exit(long code) +@@ -888,6 +889,8 @@ void do_exit(long code) check_stack_usage(); exit_thread(); -+ kpatch_shadow_free(tsk, "newpid"); ++ klp_shadow_free(tsk, 0, NULL); + /* * Flush inherited counters to the parent - before the parent * gets woken up by child-exit notifications. -diff -Nupr src.orig/kernel/fork.c src/kernel/fork.c ---- src.orig/kernel/fork.c 2017-09-22 16:52:10.504109711 -0400 -+++ src/kernel/fork.c 2017-09-22 17:00:44.938237460 -0400 -@@ -1700,6 +1700,7 @@ struct task_struct *fork_idle(int cpu) +Index: src/kernel/fork.c +=================================================================== +--- src.orig/kernel/fork.c ++++ src/kernel/fork.c +@@ -1757,6 +1757,7 @@ struct task_struct *fork_idle(int cpu) * It copies the process, and if successful kick-starts * it and waits for it to finish using the VM if required. */ -+#include "kpatch.h" ++#include long do_fork(unsigned long clone_flags, unsigned long stack_start, unsigned long stack_size, -@@ -1737,6 +1738,13 @@ long do_fork(unsigned long clone_flags, +@@ -1794,6 +1795,13 @@ long do_fork(unsigned long clone_flags, if (!IS_ERR(p)) { struct completion vfork; struct pid *pid; + int *newpid; + static int ctr = 0; + -+ newpid = kpatch_shadow_alloc(p, "newpid", sizeof(*newpid), -+ GFP_KERNEL); ++ newpid = klp_shadow_get_or_alloc(p, 0, sizeof(*newpid), ++ GFP_KERNEL, NULL, NULL); + if (newpid) + *newpid = ctr++; diff -Nru kpatch-0.5.0/test/integration/fedora-25/bug-table-section.patch kpatch-0.8.0/test/integration/fedora-25/bug-table-section.patch --- kpatch-0.5.0/test/integration/fedora-25/bug-table-section.patch 2017-12-21 05:02:48.000000000 +0000 +++ kpatch-0.8.0/test/integration/fedora-25/bug-table-section.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,12 +0,0 @@ -diff -Nupr src.orig/fs/proc/proc_sysctl.c src/fs/proc/proc_sysctl.c ---- src.orig/fs/proc/proc_sysctl.c 2016-11-30 19:39:49.316737234 +0000 -+++ src/fs/proc/proc_sysctl.c 2016-11-30 19:39:49.441737234 +0000 -@@ -301,6 +301,8 @@ void sysctl_head_put(struct ctl_table_he - - static struct ctl_table_header *sysctl_head_grab(struct ctl_table_header *head) - { -+ if (jiffies == 0) -+ printk("kpatch-test: testing __bug_table section changes\n"); - BUG_ON(!head); - spin_lock(&sysctl_lock); - if (!use_table(head)) diff -Nru kpatch-0.5.0/test/integration/fedora-25/cmdline-string-LOADED.test kpatch-0.8.0/test/integration/fedora-25/cmdline-string-LOADED.test --- kpatch-0.5.0/test/integration/fedora-25/cmdline-string-LOADED.test 2017-12-21 05:02:48.000000000 +0000 +++ kpatch-0.8.0/test/integration/fedora-25/cmdline-string-LOADED.test 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -#!/bin/bash - -grep kpatch=1 /proc/cmdline diff -Nru kpatch-0.5.0/test/integration/fedora-25/cmdline-string.patch kpatch-0.8.0/test/integration/fedora-25/cmdline-string.patch --- kpatch-0.5.0/test/integration/fedora-25/cmdline-string.patch 2017-12-21 05:02:48.000000000 +0000 +++ kpatch-0.8.0/test/integration/fedora-25/cmdline-string.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,12 +0,0 @@ -diff -Nupr src.orig/fs/proc/cmdline.c src/fs/proc/cmdline.c ---- src.orig/fs/proc/cmdline.c 2016-11-30 19:39:49.317737234 +0000 -+++ src/fs/proc/cmdline.c 2016-11-30 19:39:52.696737234 +0000 -@@ -5,7 +5,7 @@ - - static int cmdline_proc_show(struct seq_file *m, void *v) - { -- seq_printf(m, "%s\n", saved_command_line); -+ seq_printf(m, "%s kpatch=1\n", saved_command_line); - return 0; - } - diff -Nru kpatch-0.5.0/test/integration/fedora-25/convert-global-local.patch kpatch-0.8.0/test/integration/fedora-25/convert-global-local.patch --- kpatch-0.5.0/test/integration/fedora-25/convert-global-local.patch 2017-12-21 05:02:48.000000000 +0000 +++ kpatch-0.8.0/test/integration/fedora-25/convert-global-local.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,16 +0,0 @@ -This is a test for #658: a kernel panic seen when patching an exported -function (e.g., kmalloc) which is used by patch_init(). ---- -diff -Nupr src.orig/mm/slub.c src/mm/slub.c ---- src.orig/mm/slub.c 2016-12-11 14:17:54.000000000 -0500 -+++ src/mm/slub.c 2017-02-08 21:02:17.946870598 -0500 -@@ -3719,6 +3719,9 @@ void *__kmalloc(size_t size, gfp_t flags - struct kmem_cache *s; - void *ret; - -+ if (!jiffies) -+ printk("kpatch kmalloc\n"); -+ - if (unlikely(size > KMALLOC_MAX_CACHE_SIZE)) - return kmalloc_large(size, flags); - diff -Nru kpatch-0.5.0/test/integration/fedora-25/data-new-LOADED.test kpatch-0.8.0/test/integration/fedora-25/data-new-LOADED.test --- kpatch-0.5.0/test/integration/fedora-25/data-new-LOADED.test 2017-12-21 05:02:48.000000000 +0000 +++ kpatch-0.8.0/test/integration/fedora-25/data-new-LOADED.test 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -#!/bin/bash - -grep "kpatch: 5" /proc/meminfo diff -Nru kpatch-0.5.0/test/integration/fedora-25/data-new.patch kpatch-0.8.0/test/integration/fedora-25/data-new.patch --- kpatch-0.5.0/test/integration/fedora-25/data-new.patch 2017-12-21 05:02:48.000000000 +0000 +++ kpatch-0.8.0/test/integration/fedora-25/data-new.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,20 +0,0 @@ -diff -Nupr src.orig/fs/proc/meminfo.c src/fs/proc/meminfo.c ---- src.orig/fs/proc/meminfo.c 2017-02-08 21:06:25.943876606 -0500 -+++ src/fs/proc/meminfo.c 2017-02-08 21:08:07.154879058 -0500 -@@ -42,6 +42,8 @@ static void show_val_kb(struct seq_file - seq_write(m, " kB\n", 4); - } - -+static int foo = 5; -+ - static int meminfo_proc_show(struct seq_file *m, void *v) - { - struct sysinfo i; -@@ -153,6 +155,7 @@ static int meminfo_proc_show(struct seq_ - show_val_kb(m, "CmaFree: ", - global_page_state(NR_FREE_CMA_PAGES)); - #endif -+ seq_printf(m, "kpatch: %d\n", foo); - - hugetlb_report_meminfo(m); - diff -Nru kpatch-0.5.0/test/integration/fedora-25/data-read-mostly.patch kpatch-0.8.0/test/integration/fedora-25/data-read-mostly.patch --- kpatch-0.5.0/test/integration/fedora-25/data-read-mostly.patch 2017-12-21 05:02:48.000000000 +0000 +++ kpatch-0.8.0/test/integration/fedora-25/data-read-mostly.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,11 +0,0 @@ -diff -Nupr src.orig/net/core/dev.c src/net/core/dev.c ---- src.orig/net/core/dev.c 2016-11-30 19:39:45.232737234 +0000 -+++ src/net/core/dev.c 2016-11-30 19:40:02.077737234 +0000 -@@ -4179,6 +4179,7 @@ ncls: - case RX_HANDLER_PASS: - break; - default: -+ printk("BUG!\n"); - BUG(); - } - } diff -Nru kpatch-0.5.0/test/integration/fedora-25/fixup-section.patch kpatch-0.8.0/test/integration/fedora-25/fixup-section.patch --- kpatch-0.5.0/test/integration/fedora-25/fixup-section.patch 2017-12-21 05:02:48.000000000 +0000 +++ kpatch-0.8.0/test/integration/fedora-25/fixup-section.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,12 +0,0 @@ -diff -Nupr src.orig/fs/readdir.c src/fs/readdir.c ---- src.orig/fs/readdir.c 2016-11-30 19:39:49.237737234 +0000 -+++ src/fs/readdir.c 2016-11-30 19:40:05.186737234 +0000 -@@ -188,6 +188,8 @@ static int filldir(struct dir_context *c - goto efault; - } - dirent = buf->current_dir; -+ if (dirent->d_ino == 12345678) -+ printk("kpatch-test: testing .fixup section changes\n"); - if (__put_user(d_ino, &dirent->d_ino)) - goto efault; - if (__put_user(reclen, &dirent->d_reclen)) diff -Nru kpatch-0.5.0/test/integration/fedora-25/gcc-constprop.patch kpatch-0.8.0/test/integration/fedora-25/gcc-constprop.patch --- kpatch-0.5.0/test/integration/fedora-25/gcc-constprop.patch 2017-12-21 05:02:48.000000000 +0000 +++ kpatch-0.8.0/test/integration/fedora-25/gcc-constprop.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,16 +0,0 @@ -ensure timekeeping_forward_now.constprop.8 and -timekeeping_forward_now.constprop.9 are correlated. - -diff -Nupr src.orig/kernel/time/timekeeping.c src/kernel/time/timekeeping.c ---- src.orig/kernel/time/timekeeping.c 2016-11-30 19:39:45.151737234 +0000 -+++ src/kernel/time/timekeeping.c 2016-11-30 19:40:08.035737234 +0000 -@@ -1150,6 +1150,9 @@ void do_gettimeofday(struct timeval *tv) - { - struct timespec64 now; - -+ if (!tv) -+ return; -+ - getnstimeofday64(&now); - tv->tv_sec = now.tv_sec; - tv->tv_usec = now.tv_nsec/1000; diff -Nru kpatch-0.5.0/test/integration/fedora-25/gcc-isra.patch kpatch-0.8.0/test/integration/fedora-25/gcc-isra.patch --- kpatch-0.5.0/test/integration/fedora-25/gcc-isra.patch 2017-12-21 05:02:48.000000000 +0000 +++ kpatch-0.8.0/test/integration/fedora-25/gcc-isra.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,11 +0,0 @@ -diff -Nupr src.orig/fs/proc/proc_sysctl.c src/fs/proc/proc_sysctl.c ---- src.orig/fs/proc/proc_sysctl.c 2016-11-30 19:39:49.316737234 +0000 -+++ src/fs/proc/proc_sysctl.c 2016-11-30 19:40:10.918737234 +0000 -@@ -46,6 +46,7 @@ void proc_sys_poll_notify(struct ctl_tab - if (!poll) - return; - -+ printk("kpatch-test: testing gcc .isra function name mangling\n"); - atomic_inc(&poll->event); - wake_up_interruptible(&poll->wait); - } diff -Nru kpatch-0.5.0/test/integration/fedora-25/gcc-mangled-3.patch kpatch-0.8.0/test/integration/fedora-25/gcc-mangled-3.patch --- kpatch-0.5.0/test/integration/fedora-25/gcc-mangled-3.patch 2017-12-21 05:02:48.000000000 +0000 +++ kpatch-0.8.0/test/integration/fedora-25/gcc-mangled-3.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,16 +0,0 @@ -ensure that __cmpxchg_double_slab.isra.45 and -__cmpxchg_double_slab.isra.45.part.46 aren't correlated. - -diff -Nupr src.orig/mm/slub.c src/mm/slub.c ---- src.orig/mm/slub.c 2016-11-30 19:39:45.200737234 +0000 -+++ src/mm/slub.c 2016-11-30 19:40:13.997737234 +0000 -@@ -5758,6 +5758,9 @@ void get_slabinfo(struct kmem_cache *s, - int node; - struct kmem_cache_node *n; - -+ if (!jiffies) -+ printk("slabinfo\n"); -+ - for_each_kmem_cache_node(s, node, n) { - nr_slabs += node_nr_slabs(n); - nr_objs += node_nr_objs(n); diff -Nru kpatch-0.5.0/test/integration/fedora-25/gcc-static-local-var-2.patch kpatch-0.8.0/test/integration/fedora-25/gcc-static-local-var-2.patch --- kpatch-0.5.0/test/integration/fedora-25/gcc-static-local-var-2.patch 2017-12-21 05:02:48.000000000 +0000 +++ kpatch-0.8.0/test/integration/fedora-25/gcc-static-local-var-2.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,21 +0,0 @@ -diff -Nupr src.orig/mm/mmap.c src/mm/mmap.c ---- src.orig/mm/mmap.c 2017-02-08 20:48:33.821850633 -0500 -+++ src/mm/mmap.c 2017-02-08 20:48:56.682851187 -0500 -@@ -1582,6 +1582,7 @@ static inline int accountable_mapping(st - return (vm_flags & (VM_NORESERVE | VM_SHARED | VM_WRITE)) == VM_WRITE; - } - -+#include "kpatch-macros.h" - unsigned long mmap_region(struct file *file, unsigned long addr, - unsigned long len, vm_flags_t vm_flags, unsigned long pgoff) - { -@@ -1591,6 +1592,9 @@ unsigned long mmap_region(struct file *f - struct rb_node **rb_link, *rb_parent; - unsigned long charged = 0; - -+ if (!jiffies) -+ printk("kpatch mmap foo\n"); -+ - /* Check against address space limit. */ - if (!may_expand_vm(mm, vm_flags, len >> PAGE_SHIFT)) { - unsigned long nr_pages; diff -Nru kpatch-0.5.0/test/integration/fedora-25/gcc-static-local-var-3.patch kpatch-0.8.0/test/integration/fedora-25/gcc-static-local-var-3.patch --- kpatch-0.5.0/test/integration/fedora-25/gcc-static-local-var-3.patch 2017-12-21 05:02:48.000000000 +0000 +++ kpatch-0.8.0/test/integration/fedora-25/gcc-static-local-var-3.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,19 +0,0 @@ -diff -Nupr src.orig/kernel/reboot.c src/kernel/reboot.c ---- src.orig/kernel/reboot.c 2016-11-30 19:39:45.165737234 +0000 -+++ src/kernel/reboot.c 2016-11-30 19:40:19.850737234 +0000 -@@ -366,8 +366,15 @@ SYSCALL_DEFINE4(reboot, int, magic1, int - return ret; - } - -+void kpatch_bar(void) -+{ -+ if (!jiffies) -+ printk("kpatch_foo\n"); -+} -+ - static void deferred_cad(struct work_struct *dummy) - { -+ kpatch_bar(); - kernel_restart(NULL); - } - diff -Nru kpatch-0.5.0/test/integration/fedora-25/gcc-static-local-var-4.patch kpatch-0.8.0/test/integration/fedora-25/gcc-static-local-var-4.patch --- kpatch-0.5.0/test/integration/fedora-25/gcc-static-local-var-4.patch 2017-12-21 05:02:48.000000000 +0000 +++ kpatch-0.8.0/test/integration/fedora-25/gcc-static-local-var-4.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,21 +0,0 @@ -diff -Nupr src.orig/fs/aio.c src/fs/aio.c ---- src.orig/fs/aio.c.orig 2017-02-08 21:10:29.963882517 -0500 -+++ src/fs/aio.c 2017-02-08 21:10:51.501883039 -0500 -@@ -271,10 +271,17 @@ static int __init aio_setup(void) - } - __initcall(aio_setup); - -+void kpatch_aio_foo(void) -+{ -+ if (!jiffies) -+ printk("kpatch aio foo\n"); -+} -+ - static void put_aio_ring_file(struct kioctx *ctx) - { - struct file *aio_ring_file = ctx->aio_ring_file; - struct address_space *i_mapping; -+ kpatch_aio_foo(); - - if (aio_ring_file) { - truncate_setsize(aio_ring_file->f_inode, 0); diff -Nru kpatch-0.5.0/test/integration/fedora-25/gcc-static-local-var-4.test kpatch-0.8.0/test/integration/fedora-25/gcc-static-local-var-4.test --- kpatch-0.5.0/test/integration/fedora-25/gcc-static-local-var-4.test 2017-12-21 05:02:48.000000000 +0000 +++ kpatch-0.8.0/test/integration/fedora-25/gcc-static-local-var-4.test 1970-01-01 00:00:00.000000000 +0000 @@ -1,7 +0,0 @@ -#!/bin/bash - -if $(nm kpatch-gcc-static-local-var-4.ko | grep -q free_ioctx); then - exit 1 -else - exit 0 -fi diff -Nru kpatch-0.5.0/test/integration/fedora-25/gcc-static-local-var-5.patch kpatch-0.8.0/test/integration/fedora-25/gcc-static-local-var-5.patch --- kpatch-0.5.0/test/integration/fedora-25/gcc-static-local-var-5.patch 2017-12-21 05:02:48.000000000 +0000 +++ kpatch-0.8.0/test/integration/fedora-25/gcc-static-local-var-5.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,45 +0,0 @@ -diff -Nupr src.orig/kernel/audit.c src/kernel/audit.c ---- src.orig/kernel/audit.c 2016-11-30 19:39:45.165737234 +0000 -+++ src/kernel/audit.c 2016-11-30 19:40:25.802737234 +0000 -@@ -211,6 +211,12 @@ void audit_panic(const char *message) - } - } - -+void kpatch_audit_foo(void) -+{ -+ if (!jiffies) -+ printk("kpatch audit foo\n"); -+} -+ - static inline int audit_rate_check(void) - { - static unsigned long last_check = 0; -@@ -221,6 +227,7 @@ static inline int audit_rate_check(void) - unsigned long elapsed; - int retval = 0; - -+ kpatch_audit_foo(); - if (!audit_rate_limit) return 1; - - spin_lock_irqsave(&lock, flags); -@@ -240,6 +247,11 @@ static inline int audit_rate_check(void) - return retval; - } - -+noinline void kpatch_audit_check(void) -+{ -+ audit_rate_check(); -+} -+ - /** - * audit_log_lost - conditionally log lost audit message event - * @message: the message stating reason for lost audit message -@@ -286,6 +298,8 @@ static int audit_log_config_change(char - struct audit_buffer *ab; - int rc = 0; - -+ kpatch_audit_check(); -+ - ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE); - if (unlikely(!ab)) - return rc; diff -Nru kpatch-0.5.0/test/integration/fedora-25/gcc-static-local-var.patch kpatch-0.8.0/test/integration/fedora-25/gcc-static-local-var.patch --- kpatch-0.5.0/test/integration/fedora-25/gcc-static-local-var.patch 2017-12-21 05:02:48.000000000 +0000 +++ kpatch-0.8.0/test/integration/fedora-25/gcc-static-local-var.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,25 +0,0 @@ -diff -Nupr src.orig/arch/x86/kernel/ldt.c src/arch/x86/kernel/ldt.c ---- src.orig/arch/x86/kernel/ldt.c 2016-11-30 19:39:46.579737234 +0000 -+++ src/arch/x86/kernel/ldt.c 2016-11-30 19:40:28.658737234 +0000 -@@ -99,6 +99,12 @@ static void free_ldt_struct(struct ldt_s - kfree(ldt); - } - -+void hi_there(void) -+{ -+ if (!jiffies) -+ printk("hi there\n"); -+} -+ - /* - * we do not have to muck with descriptors here, that is - * done in switch_mm() as needed. -@@ -109,6 +115,8 @@ int init_new_context_ldt(struct task_str - struct mm_struct *old_mm; - int retval = 0; - -+ hi_there(); -+ - mutex_init(&mm->context.lock); - old_mm = current->mm; - if (!old_mm) { diff -Nru kpatch-0.5.0/test/integration/fedora-25/macro-hooks-LOADED.test kpatch-0.8.0/test/integration/fedora-25/macro-hooks-LOADED.test --- kpatch-0.5.0/test/integration/fedora-25/macro-hooks-LOADED.test 2017-12-21 05:02:48.000000000 +0000 +++ kpatch-0.8.0/test/integration/fedora-25/macro-hooks-LOADED.test 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -#!/bin/bash - -[[ $(cat /proc/sys/fs/aio-max-nr) = 262144 ]] diff -Nru kpatch-0.5.0/test/integration/fedora-25/macro-hooks.patch kpatch-0.8.0/test/integration/fedora-25/macro-hooks.patch --- kpatch-0.5.0/test/integration/fedora-25/macro-hooks.patch 2017-12-21 05:02:48.000000000 +0000 +++ kpatch-0.8.0/test/integration/fedora-25/macro-hooks.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,24 +0,0 @@ -diff -Nupr src.orig/fs/aio.c src/fs/aio.c ---- src.orig/fs/aio.c 2016-11-30 19:39:49.237737234 +0000 -+++ src/fs/aio.c 2016-11-30 19:40:31.570737234 +0000 -@@ -1719,6 +1719,20 @@ SYSCALL_DEFINE3(io_cancel, aio_context_t - return ret; - } - -+static int aio_max_nr_orig; -+void kpatch_load_aio_max_nr(void) -+{ -+ aio_max_nr_orig = aio_max_nr; -+ aio_max_nr = 0x40000; -+} -+void kpatch_unload_aio_max_nr(void) -+{ -+ aio_max_nr = aio_max_nr_orig; -+} -+#include "kpatch-macros.h" -+KPATCH_LOAD_HOOK(kpatch_load_aio_max_nr); -+KPATCH_UNLOAD_HOOK(kpatch_unload_aio_max_nr); -+ - /* io_getevents: - * Attempts to read at least min_nr events and up to nr events from - * the completion queue for the aio_context specified by ctx_id. If diff -Nru kpatch-0.5.0/test/integration/fedora-25/macro-printk.patch kpatch-0.8.0/test/integration/fedora-25/macro-printk.patch --- kpatch-0.5.0/test/integration/fedora-25/macro-printk.patch 2017-12-21 05:02:48.000000000 +0000 +++ kpatch-0.8.0/test/integration/fedora-25/macro-printk.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,146 +0,0 @@ -diff -Nupr src.orig/net/ipv4/fib_frontend.c src/net/ipv4/fib_frontend.c ---- src.orig/net/ipv4/fib_frontend.c 2017-02-08 21:47:41.895936587 -0500 -+++ src/net/ipv4/fib_frontend.c 2017-02-08 21:48:15.908937411 -0500 -@@ -721,6 +721,7 @@ errout: - return err; - } - -+#include "kpatch-macros.h" - static int inet_rtm_newroute(struct sk_buff *skb, struct nlmsghdr *nlh) - { - struct net *net = sock_net(skb->sk); -@@ -739,6 +740,7 @@ static int inet_rtm_newroute(struct sk_b - } - - err = fib_table_insert(net, tb, &cfg); -+ KPATCH_PRINTK("[inet_rtm_newroute]: err is %d\n", err); - errout: - return err; - } -diff -Nupr src.orig/net/ipv4/fib_semantics.c src/net/ipv4/fib_semantics.c ---- src.orig/net/ipv4/fib_semantics.c 2017-02-08 21:49:22.766939031 -0500 -+++ src/net/ipv4/fib_semantics.c 2017-02-08 21:53:08.628944503 -0500 -@@ -991,6 +991,7 @@ fib_convert_metrics(struct fib_info *fi, - return 0; - } - -+#include "kpatch-macros.h" - struct fib_info *fib_create_info(struct fib_config *cfg) - { - int err; -@@ -1018,6 +1019,7 @@ struct fib_info *fib_create_info(struct - #endif - - err = -ENOBUFS; -+ KPATCH_PRINTK("[fib_create_info]: create error err is %d\n",err); - if (fib_info_cnt >= fib_info_hash_size) { - unsigned int new_size = fib_info_hash_size << 1; - struct hlist_head *new_info_hash; -@@ -1038,6 +1040,7 @@ struct fib_info *fib_create_info(struct - if (!fib_info_hash_size) - goto failure; - } -+ KPATCH_PRINTK("[fib_create_info]: 2 create error err is %d\n",err); - - fi = kzalloc(sizeof(*fi)+nhs*sizeof(struct fib_nh), GFP_KERNEL); - if (!fi) -@@ -1049,6 +1052,7 @@ struct fib_info *fib_create_info(struct - goto failure; - } else - fi->fib_metrics = (u32 *) dst_default_metrics; -+ KPATCH_PRINTK("[fib_create_info]: 3 create error err is %d\n",err); - - fi->fib_net = net; - fi->fib_protocol = cfg->fc_protocol; -@@ -1066,6 +1070,7 @@ struct fib_info *fib_create_info(struct - if (!nexthop_nh->nh_pcpu_rth_output) - goto failure; - } endfor_nexthops(fi) -+ KPATCH_PRINTK("[fib_create_info]: 4 create error err is %d\n",err); - - err = fib_convert_metrics(fi, cfg); - if (err) -@@ -1119,6 +1124,9 @@ struct fib_info *fib_create_info(struct - #endif - } - -+ KPATCH_PRINTK("[fib_create_info]: 5 create error err is %d\n",err); -+ KPATCH_PRINTK("[fib_create_info]: 6 create error err is %d\n",err); -+ - if (fib_props[cfg->fc_type].error) { - if (cfg->fc_gw || cfg->fc_oif || cfg->fc_mp) - goto err_inval; -@@ -1135,6 +1143,7 @@ struct fib_info *fib_create_info(struct - goto err_inval; - } - } -+ KPATCH_PRINTK("[fib_create_info]: 7 create error err is %d\n",err); - - if (cfg->fc_scope > RT_SCOPE_HOST) - goto err_inval; -@@ -1163,6 +1172,7 @@ struct fib_info *fib_create_info(struct - if (linkdown == fi->fib_nhs) - fi->fib_flags |= RTNH_F_LINKDOWN; - } -+ KPATCH_PRINTK("[fib_create_info]: 8 create error err is %d\n",err); - - if (fi->fib_prefsrc && !fib_valid_prefsrc(cfg, fi->fib_prefsrc)) - goto err_inval; -@@ -1171,6 +1181,7 @@ struct fib_info *fib_create_info(struct - fib_info_update_nh_saddr(net, nexthop_nh); - fib_add_weight(fi, nexthop_nh); - } endfor_nexthops(fi) -+ KPATCH_PRINTK("[fib_create_info]: 9 create error err is %d\n",err); - - fib_rebalance(fi); - -@@ -1182,6 +1193,7 @@ link_it: - ofi->fib_treeref++; - return ofi; - } -+ KPATCH_PRINTK("[fib_create_info]: 10 create error err is %d\n",err); - - fi->fib_treeref++; - atomic_inc(&fi->fib_clntref); -@@ -1205,6 +1217,7 @@ link_it: - hlist_add_head(&nexthop_nh->nh_hash, head); - } endfor_nexthops(fi) - spin_unlock_bh(&fib_info_lock); -+ KPATCH_PRINTK("[fib_create_info]: 11 create error err is %d\n",err); - return fi; - - err_inval: -@@ -1215,6 +1228,7 @@ failure: - fi->fib_dead = 1; - free_fib_info(fi); - } -+ KPATCH_PRINTK("[fib_create_info]: 12 create error err is %d\n",err); - - return ERR_PTR(err); - } -diff -Nupr src.orig/net/ipv4/fib_trie.c src/net/ipv4/fib_trie.c ---- src.orig/net/ipv4/fib_trie.c 2017-02-08 21:53:18.182944734 -0500 -+++ src/net/ipv4/fib_trie.c 2017-02-09 16:43:09.835587031 -0500 -@@ -1106,6 +1106,7 @@ static int fib_insert_alias(struct trie - } - - /* Caller must hold RTNL. */ -+#include "kpatch-macros.h" - int fib_table_insert(struct net *net, struct fib_table *tb, - struct fib_config *cfg) - { -@@ -1130,11 +1131,14 @@ int fib_table_insert(struct net *net, st - if ((plen < KEYLENGTH) && (key << plen)) - return -EINVAL; - -+ KPATCH_PRINTK("[fib_table_insert]: start\n"); - fi = fib_create_info(cfg); - if (IS_ERR(fi)) { - err = PTR_ERR(fi); -+ KPATCH_PRINTK("[fib_table_insert]: create error err is %d\n",err); - goto err; - } -+ KPATCH_PRINTK("[fib_table_insert]: cross\n"); - - l = fib_find_node(t, &tp, key); - fa = l ? fib_find_alias(&l->leaf, slen, tos, fi->fib_priority, diff -Nru kpatch-0.5.0/test/integration/fedora-25/meminfo-cmdline-rebuild-SLOW-LOADED.test kpatch-0.8.0/test/integration/fedora-25/meminfo-cmdline-rebuild-SLOW-LOADED.test --- kpatch-0.5.0/test/integration/fedora-25/meminfo-cmdline-rebuild-SLOW-LOADED.test 2017-12-21 05:02:48.000000000 +0000 +++ kpatch-0.8.0/test/integration/fedora-25/meminfo-cmdline-rebuild-SLOW-LOADED.test 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -#!/bin/bash - -grep VMALLOCCHUNK /proc/meminfo && grep kpatch=1 /proc/cmdline diff -Nru kpatch-0.5.0/test/integration/fedora-25/meminfo-cmdline-rebuild-SLOW.patch kpatch-0.8.0/test/integration/fedora-25/meminfo-cmdline-rebuild-SLOW.patch --- kpatch-0.5.0/test/integration/fedora-25/meminfo-cmdline-rebuild-SLOW.patch 2017-12-21 05:02:48.000000000 +0000 +++ kpatch-0.8.0/test/integration/fedora-25/meminfo-cmdline-rebuild-SLOW.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,35 +0,0 @@ -diff -Nupr src.orig/fs/proc/cmdline.c src/fs/proc/cmdline.c ---- src.orig/fs/proc/cmdline.c 2017-02-08 21:31:22.297912856 -0500 -+++ src/fs/proc/cmdline.c 2017-02-08 21:39:53.633925243 -0500 -@@ -5,7 +5,7 @@ - - static int cmdline_proc_show(struct seq_file *m, void *v) - { -- seq_printf(m, "%s\n", saved_command_line); -+ seq_printf(m, "%s kpatch=1\n", saved_command_line); - return 0; - } - -diff -Nupr src.orig/fs/proc/meminfo.c src/fs/proc/meminfo.c ---- src.orig/fs/proc/meminfo.c 2017-02-08 21:06:25.943876606 -0500 -+++ src/fs/proc/meminfo.c 2017-02-08 21:40:25.550926017 -0500 -@@ -132,7 +132,7 @@ static int meminfo_proc_show(struct seq_ - seq_printf(m, "VmallocTotal: %8lu kB\n", - (unsigned long)VMALLOC_TOTAL >> 10); - show_val_kb(m, "VmallocUsed: ", 0ul); -- show_val_kb(m, "VmallocChunk: ", 0ul); -+ show_val_kb(m, "VMALLOCCHUNK: ", 0ul); - - #ifdef CONFIG_MEMORY_FAILURE - seq_printf(m, "HardwareCorrupted: %5lu kB\n", -diff -Nupr src.orig/include/linux/kernel.h src/include/linux/kernel.h ---- src.orig/include/linux/kernel.h 2017-02-08 21:42:09.228928528 -0500 -+++ src/include/linux/kernel.h 2017-02-08 21:42:10.994928571 -0500 -@@ -2,6 +2,7 @@ - #define _LINUX_KERNEL_H - - -+ - #include - #include - #include diff -Nru kpatch-0.5.0/test/integration/fedora-25/meminfo-init2-FAIL.patch kpatch-0.8.0/test/integration/fedora-25/meminfo-init2-FAIL.patch --- kpatch-0.5.0/test/integration/fedora-25/meminfo-init2-FAIL.patch 2017-12-21 05:02:48.000000000 +0000 +++ kpatch-0.8.0/test/integration/fedora-25/meminfo-init2-FAIL.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,20 +0,0 @@ -diff -Nupr src.orig/fs/proc/meminfo.c src/fs/proc/meminfo.c ---- src.orig/fs/proc/meminfo.c 2017-02-08 21:06:25.943876606 -0500 -+++ src/fs/proc/meminfo.c 2017-02-08 21:37:44.992922127 -0500 -@@ -51,6 +51,8 @@ static int meminfo_proc_show(struct seq_ - unsigned long pages[NR_LRU_LISTS]; - int lru; - -+ printk("a\n"); -+ - si_meminfo(&i); - si_swapinfo(&i); - committed = percpu_counter_read_positive(&vm_committed_as); -@@ -175,6 +177,7 @@ static const struct file_operations memi - - static int __init proc_meminfo_init(void) - { -+ printk("a\n"); - proc_create("meminfo", 0, NULL, &meminfo_proc_fops); - return 0; - } diff -Nru kpatch-0.5.0/test/integration/fedora-25/meminfo-init-FAIL.patch kpatch-0.8.0/test/integration/fedora-25/meminfo-init-FAIL.patch --- kpatch-0.5.0/test/integration/fedora-25/meminfo-init-FAIL.patch 2017-12-21 05:02:48.000000000 +0000 +++ kpatch-0.8.0/test/integration/fedora-25/meminfo-init-FAIL.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,11 +0,0 @@ -diff -Nupr src.orig/fs/proc/meminfo.c src/fs/proc/meminfo.c ---- src.orig/fs/proc/meminfo.c 2016-11-30 19:39:49.317737234 +0000 -+++ src/fs/proc/meminfo.c 2016-11-30 19:40:43.833737234 +0000 -@@ -196,6 +196,7 @@ static const struct file_operations memi - - static int __init proc_meminfo_init(void) - { -+ printk("a\n"); - proc_create("meminfo", 0, NULL, &meminfo_proc_fops); - return 0; - } diff -Nru kpatch-0.5.0/test/integration/fedora-25/meminfo-string-LOADED.test kpatch-0.8.0/test/integration/fedora-25/meminfo-string-LOADED.test --- kpatch-0.5.0/test/integration/fedora-25/meminfo-string-LOADED.test 2017-12-21 05:02:48.000000000 +0000 +++ kpatch-0.8.0/test/integration/fedora-25/meminfo-string-LOADED.test 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -#!/bin/bash - -grep VMALLOCCHUNK /proc/meminfo diff -Nru kpatch-0.5.0/test/integration/fedora-25/meminfo-string.patch kpatch-0.8.0/test/integration/fedora-25/meminfo-string.patch --- kpatch-0.5.0/test/integration/fedora-25/meminfo-string.patch 2017-12-21 05:02:48.000000000 +0000 +++ kpatch-0.8.0/test/integration/fedora-25/meminfo-string.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,12 +0,0 @@ -diff -Nupr src.orig/fs/proc/meminfo.c src/fs/proc/meminfo.c ---- src.orig/fs/proc/meminfo.c 2017-02-08 21:06:25.943876606 -0500 -+++ fs/proc/meminfo.c 2017-02-08 21:35:26.574918774 -0500 -@@ -132,7 +132,7 @@ static int meminfo_proc_show(struct seq_ - seq_printf(m, "VmallocTotal: %8lu kB\n", - (unsigned long)VMALLOC_TOTAL >> 10); - show_val_kb(m, "VmallocUsed: ", 0ul); -- show_val_kb(m, "VmallocChunk: ", 0ul); -+ show_val_kb(m, "VMALLOCCHUNK: ", 0ul); - - #ifdef CONFIG_MEMORY_FAILURE - seq_printf(m, "HardwareCorrupted: %5lu kB\n", diff -Nru kpatch-0.5.0/test/integration/fedora-25/module-call-external.patch kpatch-0.8.0/test/integration/fedora-25/module-call-external.patch --- kpatch-0.5.0/test/integration/fedora-25/module-call-external.patch 2017-12-21 05:02:48.000000000 +0000 +++ kpatch-0.8.0/test/integration/fedora-25/module-call-external.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,33 +0,0 @@ -diff -Nupr src.orig/fs/nfsd/export.c src/fs/nfsd/export.c ---- src.orig/fs/nfsd/export.c 2016-11-30 19:39:49.284737234 +0000 -+++ src/fs/nfsd/export.c 2016-11-30 19:40:50.089737234 +0000 -@@ -1193,6 +1193,8 @@ static void exp_flags(struct seq_file *m - } - } - -+extern char *kpatch_string(void); -+ - static int e_show(struct seq_file *m, void *p) - { - struct cache_head *cp = p; -@@ -1202,6 +1204,7 @@ static int e_show(struct seq_file *m, vo - if (p == SEQ_START_TOKEN) { - seq_puts(m, "# Version 1.1\n"); - seq_puts(m, "# Path Client(Flags) # IPs\n"); -+ seq_puts(m, kpatch_string()); - return 0; - } - -diff -Nupr src.orig/net/netlink/af_netlink.c src/net/netlink/af_netlink.c ---- src.orig/net/netlink/af_netlink.c 2016-11-30 19:39:45.299737234 +0000 -+++ src/net/netlink/af_netlink.c 2016-11-30 19:40:50.090737234 +0000 -@@ -2619,4 +2619,9 @@ panic: - panic("netlink_init: Cannot allocate nl_table\n"); - } - -+char *kpatch_string(void) -+{ -+ return "# kpatch\n"; -+} -+ - core_initcall(netlink_proto_init); diff -Nru kpatch-0.5.0/test/integration/fedora-25/module-kvm-fixup.patch kpatch-0.8.0/test/integration/fedora-25/module-kvm-fixup.patch --- kpatch-0.5.0/test/integration/fedora-25/module-kvm-fixup.patch 2017-12-21 05:02:48.000000000 +0000 +++ kpatch-0.8.0/test/integration/fedora-25/module-kvm-fixup.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,12 +0,0 @@ -diff -Nupr src.orig/arch/x86/kvm/vmx.c src/arch/x86/kvm/vmx.c ---- src.orig/arch/x86/kvm/vmx.c 2016-11-30 19:39:46.591737234 +0000 -+++ src/arch/x86/kvm/vmx.c 2016-11-30 19:40:53.182737234 +0000 -@@ -10845,6 +10845,8 @@ static int vmx_check_intercept(struct kv - struct x86_instruction_info *info, - enum x86_intercept_stage stage) - { -+ if (!jiffies) -+ printk("kpatch vmx_check_intercept\n"); - return X86EMUL_CONTINUE; - } - diff -Nru kpatch-0.5.0/test/integration/fedora-25/module-shadow.patch kpatch-0.8.0/test/integration/fedora-25/module-shadow.patch --- kpatch-0.5.0/test/integration/fedora-25/module-shadow.patch 2017-12-21 05:02:48.000000000 +0000 +++ kpatch-0.8.0/test/integration/fedora-25/module-shadow.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,24 +0,0 @@ -diff -Nupr src.orig/arch/x86/kvm/vmx.c src/arch/x86/kvm/vmx.c ---- src.orig/arch/x86/kvm/vmx.c 2016-11-30 19:39:46.591737234 +0000 -+++ src/arch/x86/kvm/vmx.c 2016-11-30 19:40:56.291737234 +0000 -@@ -10829,10 +10829,20 @@ static void vmx_leave_nested(struct kvm_ - * It should only be called before L2 actually succeeded to run, and when - * vmcs01 is current (it doesn't leave_guest_mode() or switch vmcss). - */ -+#include "kpatch.h" - static void nested_vmx_entry_failure(struct kvm_vcpu *vcpu, - struct vmcs12 *vmcs12, - u32 reason, unsigned long qualification) - { -+ int *kpatch; -+ -+ kpatch = kpatch_shadow_alloc(vcpu, "kpatch", sizeof(*kpatch), -+ GFP_KERNEL); -+ if (kpatch) { -+ kpatch_shadow_get(vcpu, "kpatch"); -+ kpatch_shadow_free(vcpu, "kpatch"); -+ } -+ - load_vmcs12_host_state(vcpu, vmcs12); - vmcs12->vm_exit_reason = reason | VMX_EXIT_REASONS_FAILED_VMENTRY; - vmcs12->exit_qualification = qualification; diff -Nru kpatch-0.5.0/test/integration/fedora-25/multiple.test kpatch-0.8.0/test/integration/fedora-25/multiple.test --- kpatch-0.5.0/test/integration/fedora-25/multiple.test 2017-12-21 05:02:48.000000000 +0000 +++ kpatch-0.8.0/test/integration/fedora-25/multiple.test 1970-01-01 00:00:00.000000000 +0000 @@ -1,45 +0,0 @@ -#!/bin/bash - -SCRIPTDIR="$(readlink -f $(dirname $(type -p $0)))" -ROOTDIR="$(readlink -f $SCRIPTDIR/../../..)" -KPATCH="sudo $ROOTDIR/kpatch/kpatch" - -set -o errexit - -die() { - echo "ERROR: $@" >&2 - exit 1 -} - -ko_to_test() { - tmp=${1%.ko}-LOADED.test - echo ${tmp#kpatch-} -} - -# make sure any modules added here are disjoint -declare -a modules=(kpatch-cmdline-string.ko kpatch-meminfo-string.ko) - -for mod in "${modules[@]}"; do - testprog=$(ko_to_test $mod) - $SCRIPTDIR/$testprog && die "$SCRIPTDIR/$testprog succeeded before loading any modules" -done - -for mod in "${modules[@]}"; do - $KPATCH load $mod -done - -for mod in "${modules[@]}"; do - testprog=$(ko_to_test $mod) - $SCRIPTDIR/$testprog || die "$SCRIPTDIR/$testprog failed after loading modules" -done - -for mod in "${modules[@]}"; do - $KPATCH unload $mod -done - -for mod in "${modules[@]}"; do - testprog=$(ko_to_test $mod) - $SCRIPTDIR/$testprog && die "$SCRIPTDIR/$testprog succeeded after unloading modules" -done - -exit 0 diff -Nru kpatch-0.5.0/test/integration/fedora-25/new-function.patch kpatch-0.8.0/test/integration/fedora-25/new-function.patch --- kpatch-0.5.0/test/integration/fedora-25/new-function.patch 2017-12-21 05:02:48.000000000 +0000 +++ kpatch-0.8.0/test/integration/fedora-25/new-function.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,25 +0,0 @@ -diff -Nupr src.orig/drivers/tty/n_tty.c src/drivers/tty/n_tty.c ---- src.orig/drivers/tty/n_tty.c 2016-11-30 19:39:48.532737234 +0000 -+++ src/drivers/tty/n_tty.c 2016-11-30 19:40:59.432737234 +0000 -@@ -2269,7 +2269,7 @@ static ssize_t n_tty_read(struct tty_str - * lock themselves) - */ - --static ssize_t n_tty_write(struct tty_struct *tty, struct file *file, -+static ssize_t noinline kpatch_n_tty_write(struct tty_struct *tty, struct file *file, - const unsigned char *buf, size_t nr) - { - const unsigned char *b = buf; -@@ -2356,6 +2356,12 @@ break_out: - return (b - buf) ? b - buf : retval; - } - -+static ssize_t n_tty_write(struct tty_struct *tty, struct file *file, -+ const unsigned char *buf, size_t nr) -+{ -+ return kpatch_n_tty_write(tty, file, buf, nr); -+} -+ - /** - * n_tty_poll - poll method for N_TTY - * @tty: terminal device diff -Nru kpatch-0.5.0/test/integration/fedora-25/new-globals.patch kpatch-0.8.0/test/integration/fedora-25/new-globals.patch --- kpatch-0.5.0/test/integration/fedora-25/new-globals.patch 2017-12-21 05:02:48.000000000 +0000 +++ kpatch-0.8.0/test/integration/fedora-25/new-globals.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,34 +0,0 @@ -diff -Nupr src.orig/fs/proc/cmdline.c src/fs/proc/cmdline.c ---- src.orig/fs/proc/cmdline.c 2017-02-08 21:31:22.297912856 -0500 -+++ src/fs/proc/cmdline.c 2017-02-08 21:32:08.510913975 -0500 -@@ -27,3 +27,10 @@ static int __init proc_cmdline_init(void - return 0; - } - fs_initcall(proc_cmdline_init); -+ -+#include -+void kpatch_print_message(void) -+{ -+ if (!jiffies) -+ printk("hello there!\n"); -+} -diff -Nupr src.orig/fs/proc/meminfo.c src/fs/proc/meminfo.c ---- src.orig/fs/proc/meminfo.c 2017-02-08 21:06:25.943876606 -0500 -+++ src/fs/proc/meminfo.c 2017-02-08 21:33:26.498915865 -0500 -@@ -19,6 +19,8 @@ - #include - #include "internal.h" - -+void kpatch_print_message(void); -+ - void __attribute__((weak)) arch_report_meminfo(struct seq_file *m) - { - } -@@ -65,6 +67,7 @@ static int meminfo_proc_show(struct seq_ - - available = si_mem_available(); - -+ kpatch_print_message(); - show_val_kb(m, "MemTotal: ", i.totalram); - show_val_kb(m, "MemFree: ", i.freeram); - show_val_kb(m, "MemAvailable: ", available); diff -Nru kpatch-0.5.0/test/integration/fedora-25/parainstructions-section.patch kpatch-0.8.0/test/integration/fedora-25/parainstructions-section.patch --- kpatch-0.5.0/test/integration/fedora-25/parainstructions-section.patch 2017-12-21 05:02:48.000000000 +0000 +++ kpatch-0.8.0/test/integration/fedora-25/parainstructions-section.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,11 +0,0 @@ -diff -Nupr src.orig/fs/proc/generic.c src/fs/proc/generic.c ---- src.orig/fs/proc/generic.c 2016-11-30 19:39:49.317737234 +0000 -+++ src/fs/proc/generic.c 2016-11-30 19:41:05.659737234 +0000 -@@ -192,6 +192,7 @@ int proc_alloc_inum(unsigned int *inum) - unsigned int i; - int error; - -+ printk("kpatch-test: testing change to .parainstructions section\n"); - retry: - if (!ida_pre_get(&proc_inum_ida, GFP_KERNEL)) - return -ENOMEM; diff -Nru kpatch-0.5.0/test/integration/fedora-25/README kpatch-0.8.0/test/integration/fedora-25/README --- kpatch-0.5.0/test/integration/fedora-25/README 2017-12-21 05:02:48.000000000 +0000 +++ kpatch-0.8.0/test/integration/fedora-25/README 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -4.9.7-201.fc25.x86_64 diff -Nru kpatch-0.5.0/test/integration/fedora-25/remote-setup kpatch-0.8.0/test/integration/fedora-25/remote-setup --- kpatch-0.5.0/test/integration/fedora-25/remote-setup 2017-12-21 05:02:48.000000000 +0000 +++ kpatch-0.8.0/test/integration/fedora-25/remote-setup 1970-01-01 00:00:00.000000000 +0000 @@ -1,45 +0,0 @@ -#!/bin/bash -x - -# install rpms on a Fedora 22 system to prepare it for kpatch integration tests - -set -o errexit - -[[ $UID != 0 ]] && sudo=sudo - -warn() { - echo "ERROR: $1" >&2 -} - -die() { - warn "$@" - exit 1 -} - -install_rpms() { - # crude workaround for a weird dnf bug where it fails to download - $sudo dnf install -y $* || $sudo dnf install -y $* -} - -install_rpms gcc elfutils elfutils-devel rpmdevtools pesign openssl numactl-devel wget patchutils - -$sudo dnf builddep -y kernel || $sudo dnf builddep -y kernel - -# install kernel debuginfo and devel RPMs for target kernel -kverrel=$(uname -r) -kverrel=${kverrel%.x86_64} -kver=${kverrel%%-*} -krel=${kverrel#*-} -install_rpms https://kojipkgs.fedoraproject.org/packages/kernel/$kver/$krel/x86_64/kernel-debuginfo-$kver-$krel.x86_64.rpm https://kojipkgs.fedoraproject.org/packages/kernel/$kver/$krel/x86_64/kernel-debuginfo-common-x86_64-$kver-$krel.x86_64.rpm https://kojipkgs.fedoraproject.org/packages/kernel/$kver/$krel/x86_64/kernel-devel-$kver-$krel.x86_64.rpm - -# install version of gcc which was used to build the target kernel -gccver=$(gcc --version |head -n1 |cut -d' ' -f3-) -kgccver=$(readelf -p .comment /usr/lib/debug/lib/modules/$(uname -r)/vmlinux |grep GCC: | tr -s ' ' | cut -d ' ' -f6-) -if [[ $gccver != $kgccver ]]; then - gver=$(echo $kgccver | awk '{print $1}') - grel=$(echo $kgccver | sed 's/.*-\(.*\))/\1/') - grel=$grel.$(rpm -q gcc |sed 's/.*\.\(.*\)\.x86_64/\1/') - install_rpms https://kojipkgs.fedoraproject.org/packages/gcc/$gver/$grel/x86_64/cpp-$gver-$grel.x86_64.rpm https://kojipkgs.fedoraproject.org/packages/gcc/$gver/$grel/x86_64/gcc-$gver-$grel.x86_64.rpm https://kojipkgs.fedoraproject.org/packages/gcc/$gver/$grel/x86_64/libgomp-$gver-$grel.x86_64.rpm -fi - -install_rpms ccache -ccache -M 5G diff -Nru kpatch-0.5.0/test/integration/fedora-25/replace-section-references.patch kpatch-0.8.0/test/integration/fedora-25/replace-section-references.patch --- kpatch-0.5.0/test/integration/fedora-25/replace-section-references.patch 2017-12-21 05:02:48.000000000 +0000 +++ kpatch-0.8.0/test/integration/fedora-25/replace-section-references.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,12 +0,0 @@ -diff -Nupr src.orig/arch/x86/kvm/x86.c src/arch/x86/kvm/x86.c ---- src.orig/arch/x86/kvm/x86.c 2017-02-08 20:48:33.312850621 -0500 -+++ src/arch/x86/kvm/x86.c 2017-02-08 20:49:15.030851631 -0500 -@@ -250,6 +250,8 @@ static void shared_msr_update(unsigned s - - void kvm_define_shared_msr(unsigned slot, u32 msr) - { -+ if (!jiffies) -+ printk("kpatch kvm define shared msr\n"); - BUG_ON(slot >= KVM_NR_SHARED_MSRS); - shared_msrs_global.msrs[slot] = msr; - if (slot >= shared_msrs_global.nr) diff -Nru kpatch-0.5.0/test/integration/fedora-25/shadow-newpid-LOADED.test kpatch-0.8.0/test/integration/fedora-25/shadow-newpid-LOADED.test --- kpatch-0.5.0/test/integration/fedora-25/shadow-newpid-LOADED.test 2017-12-21 05:02:48.000000000 +0000 +++ kpatch-0.8.0/test/integration/fedora-25/shadow-newpid-LOADED.test 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -#!/bin/bash - -grep -q newpid: /proc/$$/status diff -Nru kpatch-0.5.0/test/integration/fedora-25/shadow-newpid.patch kpatch-0.8.0/test/integration/fedora-25/shadow-newpid.patch --- kpatch-0.5.0/test/integration/fedora-25/shadow-newpid.patch 2017-12-21 05:02:48.000000000 +0000 +++ kpatch-0.8.0/test/integration/fedora-25/shadow-newpid.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,68 +0,0 @@ -diff -Nupr src.orig/fs/proc/array.c src/fs/proc/array.c ---- src.orig/fs/proc/array.c 2017-02-08 21:17:58.244893377 -0500 -+++ src/fs/proc/array.c 2017-02-08 21:26:21.670905573 -0500 -@@ -348,12 +348,19 @@ static inline void task_seccomp(struct s - #endif - } - -+#include "kpatch.h" - static inline void task_context_switch_counts(struct seq_file *m, - struct task_struct *p) - { -+ int *newpid; -+ - seq_put_decimal_ull(m, "voluntary_ctxt_switches:\t", p->nvcsw); - seq_put_decimal_ull(m, "\nnonvoluntary_ctxt_switches:\t", p->nivcsw); - seq_putc(m, '\n'); -+ -+ newpid = kpatch_shadow_get(p, "newpid"); -+ if (newpid) -+ seq_printf(m, "newpid:\t%d\n", *newpid); - } - - static void task_cpus_allowed(struct seq_file *m, struct task_struct *task) -diff -Nupr src.orig/kernel/exit.c src/kernel/exit.c ---- src.orig/kernel/exit.c 2017-02-08 21:26:31.119905802 -0500 -+++ src/kernel/exit.c 2017-02-08 21:27:11.347906776 -0500 -@@ -725,6 +725,7 @@ static void check_stack_usage(void) - static inline void check_stack_usage(void) {} - #endif - -+#include "kpatch.h" - void __noreturn do_exit(long code) - { - struct task_struct *tsk = current; -@@ -828,6 +829,8 @@ void __noreturn do_exit(long code) - exit_task_work(tsk); - exit_thread(tsk); - -+ kpatch_shadow_free(tsk, "newpid"); -+ - /* - * Flush inherited counters to the parent - before the parent - * gets woken up by child-exit notifications. -diff -Nupr src.orig/kernel/fork.c src/kernel/fork.c ---- src.orig/kernel/fork.c 2017-02-08 21:27:34.629907340 -0500 -+++ src/kernel/fork.c 2017-02-08 21:28:31.182908710 -0500 -@@ -1904,6 +1904,7 @@ struct task_struct *fork_idle(int cpu) - * It copies the process, and if successful kick-starts - * it and waits for it to finish using the VM if required. - */ -+#include "kpatch.h" - long _do_fork(unsigned long clone_flags, - unsigned long stack_start, - unsigned long stack_size, -@@ -1943,6 +1944,13 @@ long _do_fork(unsigned long clone_flags, - if (!IS_ERR(p)) { - struct completion vfork; - struct pid *pid; -+ int *newpid; -+ static int ctr = 0; -+ -+ newpid = kpatch_shadow_alloc(p, "newpid", sizeof(*newpid), -+ GFP_KERNEL); -+ if (newpid) -+ *newpid = ctr++; - - trace_sched_process_fork(current, p); - diff -Nru kpatch-0.5.0/test/integration/fedora-25/smp-locks-section.patch kpatch-0.8.0/test/integration/fedora-25/smp-locks-section.patch --- kpatch-0.5.0/test/integration/fedora-25/smp-locks-section.patch 2017-12-21 05:02:48.000000000 +0000 +++ kpatch-0.8.0/test/integration/fedora-25/smp-locks-section.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,12 +0,0 @@ -diff -Nupr src.orig/drivers/tty/tty_buffer.c src/drivers/tty/tty_buffer.c ---- src.orig/drivers/tty/tty_buffer.c 2016-11-30 19:39:48.532737234 +0000 -+++ src/drivers/tty/tty_buffer.c 2016-11-30 19:41:15.067737234 +0000 -@@ -255,6 +255,8 @@ static int __tty_buffer_request_room(str - struct tty_buffer *b, *n; - int left, change; - -+ if (!size) -+ printk("kpatch-test: testing .smp_locks section changes\n"); - b = buf->tail; - if (b->flags & TTYB_NORMAL) - left = 2 * b->size - b->used; diff -Nru kpatch-0.5.0/test/integration/fedora-25/special-static-2.patch kpatch-0.8.0/test/integration/fedora-25/special-static-2.patch --- kpatch-0.5.0/test/integration/fedora-25/special-static-2.patch 2017-12-21 05:02:48.000000000 +0000 +++ kpatch-0.8.0/test/integration/fedora-25/special-static-2.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,24 +0,0 @@ -diff -Nupr src.orig/arch/x86/kvm/x86.c src/arch/x86/kvm/x86.c ---- src.orig/arch/x86/kvm/x86.c 2016-11-30 19:39:46.590737234 +0000 -+++ src/arch/x86/kvm/x86.c 2016-11-30 19:41:18.201737234 +0000 -@@ -2039,12 +2039,20 @@ static void record_steal_time(struct kvm - &vcpu->arch.st.steal, sizeof(struct kvm_steal_time)); - } - -+void kpatch_kvm_x86_foo(void) -+{ -+ if (!jiffies) -+ printk("kpatch kvm x86 foo\n"); -+} -+ - int kvm_set_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info) - { - bool pr = false; - u32 msr = msr_info->index; - u64 data = msr_info->data; - -+ kpatch_kvm_x86_foo(); -+ - switch (msr) { - case MSR_AMD64_NB_CFG: - case MSR_IA32_UCODE_REV: diff -Nru kpatch-0.5.0/test/integration/fedora-25/special-static.patch kpatch-0.8.0/test/integration/fedora-25/special-static.patch --- kpatch-0.5.0/test/integration/fedora-25/special-static.patch 2017-12-21 05:02:48.000000000 +0000 +++ kpatch-0.8.0/test/integration/fedora-25/special-static.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,22 +0,0 @@ -diff -Nupr src.orig/kernel/fork.c src/kernel/fork.c ---- src.orig/kernel/fork.c 2016-11-30 19:39:45.165737234 +0000 -+++ src/kernel/fork.c 2016-11-30 19:41:21.329737234 +0000 -@@ -1169,10 +1169,18 @@ static void posix_cpu_timers_init_group( - INIT_LIST_HEAD(&sig->cpu_timers[2]); - } - -+void kpatch_foo(void) -+{ -+ if (!jiffies) -+ printk("kpatch copy signal\n"); -+} -+ - static int copy_signal(unsigned long clone_flags, struct task_struct *tsk) - { - struct signal_struct *sig; - -+ kpatch_foo(); -+ - if (clone_flags & CLONE_THREAD) - return 0; - diff -Nru kpatch-0.5.0/test/integration/fedora-25/tracepoints-section.patch kpatch-0.8.0/test/integration/fedora-25/tracepoints-section.patch --- kpatch-0.5.0/test/integration/fedora-25/tracepoints-section.patch 2017-12-21 05:02:48.000000000 +0000 +++ kpatch-0.8.0/test/integration/fedora-25/tracepoints-section.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,15 +0,0 @@ -ensure __jump_table is parsed and we can tell that it effectively didn't change - -diff -Nupr src.orig/kernel/time/timer.c src/kernel/time/timer.c ---- src.orig/kernel/time/timer.c 2016-11-30 19:39:45.150737234 +0000 -+++ src/kernel/time/timer.c 2016-11-30 20:02:08.254737234 +0000 -@@ -1637,6 +1637,9 @@ static void run_timer_softirq(struct sof - { - struct timer_base *base = this_cpu_ptr(&timer_bases[BASE_STD]); - -+ if (!base) -+ printk("kpatch-test: testing __tracepoints section changes\n"); -+ - __run_timers(base); - if (IS_ENABLED(CONFIG_NO_HZ_COMMON) && base->nohz_active) - __run_timers(this_cpu_ptr(&timer_bases[BASE_DEF])); diff -Nru kpatch-0.5.0/test/integration/fedora-25/warn-detect-FAIL.patch kpatch-0.8.0/test/integration/fedora-25/warn-detect-FAIL.patch --- kpatch-0.5.0/test/integration/fedora-25/warn-detect-FAIL.patch 2017-12-21 05:02:48.000000000 +0000 +++ kpatch-0.8.0/test/integration/fedora-25/warn-detect-FAIL.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,8 +0,0 @@ -diff -Nupr src.orig/arch/x86/kvm/x86.c src/arch/x86/kvm/x86.c ---- src.orig/arch/x86/kvm/x86.c 2016-11-30 19:39:46.590737234 +0000 -+++ src/arch/x86/kvm/x86.c 2016-11-30 19:41:24.482737234 +0000 -@@ -1,3 +1,4 @@ -+ - /* - * Kernel-based Virtual Machine driver for Linux - * diff -Nru kpatch-0.5.0/test/integration/fedora-27/data-new-LOADED.test kpatch-0.8.0/test/integration/fedora-27/data-new-LOADED.test --- kpatch-0.5.0/test/integration/fedora-27/data-new-LOADED.test 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/test/integration/fedora-27/data-new-LOADED.test 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1,3 @@ +#!/bin/bash + +grep "kpatch: 5" /proc/meminfo diff -Nru kpatch-0.5.0/test/integration/fedora-27/data-new.patch kpatch-0.8.0/test/integration/fedora-27/data-new.patch --- kpatch-0.5.0/test/integration/fedora-27/data-new.patch 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/test/integration/fedora-27/data-new.patch 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1,20 @@ +diff -Nupr src.orig/fs/proc/meminfo.c src/fs/proc/meminfo.c +--- src.orig/fs/proc/meminfo.c 2017-11-17 15:58:41.113211972 -0500 ++++ src/fs/proc/meminfo.c 2017-11-17 15:58:58.554211972 -0500 +@@ -42,6 +42,8 @@ static void show_val_kb(struct seq_file + seq_write(m, " kB\n", 4); + } + ++static int foo = 5; ++ + static int meminfo_proc_show(struct seq_file *m, void *v) + { + struct sysinfo i; +@@ -153,6 +155,7 @@ static int meminfo_proc_show(struct seq_ + show_val_kb(m, "CmaFree: ", + global_page_state(NR_FREE_CMA_PAGES)); + #endif ++ seq_printf(m, "kpatch: %d\n", foo); + + hugetlb_report_meminfo(m); + diff -Nru kpatch-0.5.0/test/integration/fedora-27/gcc-static-local-var-6.patch kpatch-0.8.0/test/integration/fedora-27/gcc-static-local-var-6.patch --- kpatch-0.5.0/test/integration/fedora-27/gcc-static-local-var-6.patch 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/test/integration/fedora-27/gcc-static-local-var-6.patch 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1,23 @@ +diff --git a/net/ipv6/netfilter.c b/net/ipv6/netfilter.c +index 9bf2604..026ac6c 100644 +--- a/net/ipv6/netfilter.c ++++ b/net/ipv6/netfilter.c +@@ -109,6 +109,8 @@ static int nf_ip6_reroute(struct net *net, struct sk_buff *skb, + return 0; + } + ++#include "kpatch-macros.h" ++ + static int nf_ip6_route(struct net *net, struct dst_entry **dst, + struct flowi *fl, bool strict) + { +@@ -122,6 +124,9 @@ static int nf_ip6_route(struct net *net, struct dst_entry **dst, + struct dst_entry *result; + int err; + ++ if (!jiffies) ++ printk("kpatch nf_ip6_route foo\n"); ++ + result = ip6_route_output(net, sk, &fl->u.ip6); + err = result->error; + if (err) diff -Nru kpatch-0.5.0/test/integration/fedora-27/macro-callbacks.patch kpatch-0.8.0/test/integration/fedora-27/macro-callbacks.patch --- kpatch-0.5.0/test/integration/fedora-27/macro-callbacks.patch 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/test/integration/fedora-27/macro-callbacks.patch 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1,163 @@ +kpatch/livepatch callback test patch: + + vmlinux + pcspkr (mod) + joydev (mod) + +Note: update joydev's pre-patch callback to return -ENODEV to test failure path + +diff -Nupr src.old/drivers/input/joydev.c src/drivers/input/joydev.c +--- src.old/drivers/input/joydev.c 2017-09-03 16:56:17.000000000 -0400 ++++ src/drivers/input/joydev.c 2018-03-22 16:32:40.963082354 -0400 +@@ -1010,3 +1010,47 @@ static void __exit joydev_exit(void) + + module_init(joydev_init); + module_exit(joydev_exit); ++ ++#include ++#include "kpatch-macros.h" ++ ++static const char *const module_state[] = { ++ [MODULE_STATE_LIVE] = "[MODULE_STATE_LIVE] Normal state", ++ [MODULE_STATE_COMING] = "[MODULE_STATE_COMING] Full formed, running module_init", ++ [MODULE_STATE_GOING] = "[MODULE_STATE_GOING] Going away", ++ [MODULE_STATE_UNFORMED] = "[MODULE_STATE_UNFORMED] Still setting it up", ++}; ++ ++static void callback_info(const char *callback, patch_object *obj) ++{ ++ if (obj->mod) ++ pr_info("%s: %s -> %s\n", callback, obj->mod->name, ++ module_state[obj->mod->state]); ++ else ++ pr_info("%s: vmlinux\n", callback); ++} ++ ++static int pre_patch_callback(patch_object *obj) ++{ ++ callback_info(__func__, obj); ++ return 0; /* return -ENODEV; */ ++} ++KPATCH_PRE_PATCH_CALLBACK(pre_patch_callback); ++ ++static void post_patch_callback(patch_object *obj) ++{ ++ callback_info(__func__, obj); ++} ++KPATCH_POST_PATCH_CALLBACK(post_patch_callback); ++ ++static void pre_unpatch_callback(patch_object *obj) ++{ ++ callback_info(__func__, obj); ++} ++KPATCH_PRE_UNPATCH_CALLBACK(pre_unpatch_callback); ++ ++static void post_unpatch_callback(patch_object *obj) ++{ ++ callback_info(__func__, obj); ++} ++KPATCH_POST_UNPATCH_CALLBACK(post_unpatch_callback); +diff -Nupr src.old/drivers/input/misc/pcspkr.c src/drivers/input/misc/pcspkr.c +--- src.old/drivers/input/misc/pcspkr.c 2018-03-22 16:29:27.716082354 -0400 ++++ src/drivers/input/misc/pcspkr.c 2018-03-22 16:32:40.963082354 -0400 +@@ -132,3 +132,46 @@ static struct platform_driver pcspkr_pla + }; + module_platform_driver(pcspkr_platform_driver); + ++#include ++#include "kpatch-macros.h" ++ ++static const char *const module_state[] = { ++ [MODULE_STATE_LIVE] = "[MODULE_STATE_LIVE] Normal state", ++ [MODULE_STATE_COMING] = "[MODULE_STATE_COMING] Full formed, running module_init", ++ [MODULE_STATE_GOING] = "[MODULE_STATE_GOING] Going away", ++ [MODULE_STATE_UNFORMED] = "[MODULE_STATE_UNFORMED] Still setting it up", ++}; ++ ++static void callback_info(const char *callback, patch_object *obj) ++{ ++ if (obj->mod) ++ pr_info("%s: %s -> %s\n", callback, obj->mod->name, ++ module_state[obj->mod->state]); ++ else ++ pr_info("%s: vmlinux\n", callback); ++} ++ ++static int pre_patch_callback(patch_object *obj) ++{ ++ callback_info(__func__, obj); ++ return 0; ++} ++KPATCH_PRE_PATCH_CALLBACK(pre_patch_callback); ++ ++static void post_patch_callback(patch_object *obj) ++{ ++ callback_info(__func__, obj); ++} ++KPATCH_POST_PATCH_CALLBACK(post_patch_callback); ++ ++static void pre_unpatch_callback(patch_object *obj) ++{ ++ callback_info(__func__, obj); ++} ++KPATCH_PRE_UNPATCH_CALLBACK(pre_unpatch_callback); ++ ++static void post_unpatch_callback(patch_object *obj) ++{ ++ callback_info(__func__, obj); ++} ++KPATCH_POST_UNPATCH_CALLBACK(post_unpatch_callback); +diff -Nupr src.old/fs/aio.c src/fs/aio.c +--- src.old/fs/aio.c 2017-09-03 16:56:17.000000000 -0400 ++++ src/fs/aio.c 2018-03-22 16:32:40.962082354 -0400 +@@ -46,6 +46,50 @@ + + #include "internal.h" + ++#include ++#include "kpatch-macros.h" ++ ++static const char *const module_state[] = { ++ [MODULE_STATE_LIVE] = "[MODULE_STATE_LIVE] Normal state", ++ [MODULE_STATE_COMING] = "[MODULE_STATE_COMING] Full formed, running module_init", ++ [MODULE_STATE_GOING] = "[MODULE_STATE_GOING] Going away", ++ [MODULE_STATE_UNFORMED] = "[MODULE_STATE_UNFORMED] Still setting it up", ++}; ++ ++static void callback_info(const char *callback, patch_object *obj) ++{ ++ if (obj->mod) ++ pr_info("%s: %s -> %s\n", callback, obj->mod->name, ++ module_state[obj->mod->state]); ++ else ++ pr_info("%s: vmlinux\n", callback); ++} ++ ++static int pre_patch_callback(patch_object *obj) ++{ ++ callback_info(__func__, obj); ++ return 0; ++} ++KPATCH_PRE_PATCH_CALLBACK(pre_patch_callback); ++ ++static void post_patch_callback(patch_object *obj) ++{ ++ callback_info(__func__, obj); ++} ++KPATCH_POST_PATCH_CALLBACK(post_patch_callback); ++ ++static void pre_unpatch_callback(patch_object *obj) ++{ ++ callback_info(__func__, obj); ++} ++KPATCH_PRE_UNPATCH_CALLBACK(pre_unpatch_callback); ++ ++static void post_unpatch_callback(patch_object *obj) ++{ ++ callback_info(__func__, obj); ++} ++KPATCH_POST_UNPATCH_CALLBACK(post_unpatch_callback); ++ + #define AIO_RING_MAGIC 0xa10a10a1 + #define AIO_RING_COMPAT_FEATURES 1 + #define AIO_RING_INCOMPAT_FEATURES 0 diff -Nru kpatch-0.5.0/test/integration/fedora-27/meminfo-cmdline-rebuild-SLOW-LOADED.test.disabled kpatch-0.8.0/test/integration/fedora-27/meminfo-cmdline-rebuild-SLOW-LOADED.test.disabled --- kpatch-0.5.0/test/integration/fedora-27/meminfo-cmdline-rebuild-SLOW-LOADED.test.disabled 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/test/integration/fedora-27/meminfo-cmdline-rebuild-SLOW-LOADED.test.disabled 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1,3 @@ +#!/bin/bash + +grep VMALLOCCHUNK /proc/meminfo && grep kpatch=1 /proc/cmdline diff -Nru kpatch-0.5.0/test/integration/fedora-27/meminfo-cmdline-rebuild-SLOW.patch.disabled kpatch-0.8.0/test/integration/fedora-27/meminfo-cmdline-rebuild-SLOW.patch.disabled --- kpatch-0.5.0/test/integration/fedora-27/meminfo-cmdline-rebuild-SLOW.patch.disabled 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/test/integration/fedora-27/meminfo-cmdline-rebuild-SLOW.patch.disabled 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1,40 @@ +Disabled due to https://github.com/dynup/kpatch/issues/767 +--- +Index: src/fs/proc/cmdline.c +=================================================================== +--- src.orig/fs/proc/cmdline.c ++++ src/fs/proc/cmdline.c +@@ -7,7 +7,7 @@ + static int cmdline_proc_show(struct seq_file *m, void *v) + { + seq_puts(m, saved_command_line); +- seq_putc(m, '\n'); ++ seq_puts(m, " kpatch=1\n"); + return 0; + } + +Index: src/fs/proc/meminfo.c +=================================================================== +--- src.orig/fs/proc/meminfo.c ++++ src/fs/proc/meminfo.c +@@ -120,7 +120,7 @@ static int meminfo_proc_show(struct seq_ + seq_printf(m, "VmallocTotal: %8lu kB\n", + (unsigned long)VMALLOC_TOTAL >> 10); + show_val_kb(m, "VmallocUsed: ", 0ul); +- show_val_kb(m, "VmallocChunk: ", 0ul); ++ show_val_kb(m, "VMALLOCCHUNK: ", 0ul); + + #ifdef CONFIG_MEMORY_FAILURE + seq_printf(m, "HardwareCorrupted: %5lu kB\n", +Index: src/include/linux/kernel.h +=================================================================== +--- src.orig/include/linux/kernel.h ++++ src/include/linux/kernel.h +@@ -3,6 +3,7 @@ + #define _LINUX_KERNEL_H + + ++ + #include + #include + #include diff -Nru kpatch-0.5.0/test/integration/fedora-27/module-call-external.patch kpatch-0.8.0/test/integration/fedora-27/module-call-external.patch --- kpatch-0.5.0/test/integration/fedora-27/module-call-external.patch 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/test/integration/fedora-27/module-call-external.patch 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1,33 @@ +diff -Nupr src.orig/fs/nfsd/export.c src/fs/nfsd/export.c +--- src.orig/fs/nfsd/export.c 2017-11-17 15:58:26.667211972 -0500 ++++ src/fs/nfsd/export.c 2017-11-17 15:59:26.338211972 -0500 +@@ -1194,6 +1194,8 @@ static void exp_flags(struct seq_file *m + } + } + ++extern char *kpatch_string(void); ++ + static int e_show(struct seq_file *m, void *p) + { + struct cache_head *cp = p; +@@ -1203,6 +1205,7 @@ static int e_show(struct seq_file *m, vo + if (p == SEQ_START_TOKEN) { + seq_puts(m, "# Version 1.1\n"); + seq_puts(m, "# Path Client(Flags) # IPs\n"); ++ seq_puts(m, kpatch_string()); + return 0; + } + +diff -Nupr src.orig/net/netlink/af_netlink.c src/net/netlink/af_netlink.c +--- src.orig/net/netlink/af_netlink.c 2017-11-17 15:58:49.333211972 -0500 ++++ src/net/netlink/af_netlink.c 2017-11-17 15:59:26.338211972 -0500 +@@ -2739,4 +2739,9 @@ panic: + panic("netlink_init: Cannot allocate nl_table\n"); + } + ++char *kpatch_string(void) ++{ ++ return "# kpatch\n"; ++} ++ + core_initcall(netlink_proto_init); diff -Nru kpatch-0.5.0/test/integration/fedora-27/module-shadow.patch kpatch-0.8.0/test/integration/fedora-27/module-shadow.patch --- kpatch-0.5.0/test/integration/fedora-27/module-shadow.patch 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/test/integration/fedora-27/module-shadow.patch 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1,24 @@ +diff -Nupr src.orig/arch/x86/kvm/vmx.c src/arch/x86/kvm/vmx.c +--- src.orig/arch/x86/kvm/vmx.c 2017-11-17 15:58:19.369211972 -0500 ++++ src/arch/x86/kvm/vmx.c 2017-11-17 15:59:29.615211972 -0500 +@@ -11259,10 +11259,20 @@ static void vmx_leave_nested(struct kvm_ + * It should only be called before L2 actually succeeded to run, and when + * vmcs01 is current (it doesn't leave_guest_mode() or switch vmcss). + */ ++#include "kpatch.h" + static void nested_vmx_entry_failure(struct kvm_vcpu *vcpu, + struct vmcs12 *vmcs12, + u32 reason, unsigned long qualification) + { ++ int *kpatch; ++ ++ kpatch = kpatch_shadow_alloc(vcpu, "kpatch", sizeof(*kpatch), ++ GFP_KERNEL); ++ if (kpatch) { ++ kpatch_shadow_get(vcpu, "kpatch"); ++ kpatch_shadow_free(vcpu, "kpatch"); ++ } ++ + load_vmcs12_host_state(vcpu, vmcs12); + vmcs12->vm_exit_reason = reason | VMX_EXIT_REASONS_FAILED_VMENTRY; + vmcs12->exit_qualification = qualification; diff -Nru kpatch-0.5.0/test/integration/fedora-27/multiple.test kpatch-0.8.0/test/integration/fedora-27/multiple.test --- kpatch-0.5.0/test/integration/fedora-27/multiple.test 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/test/integration/fedora-27/multiple.test 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1,64 @@ +#!/bin/bash + +SCRIPTDIR="$(readlink -f $(dirname $(type -p $0)))" +ROOTDIR="$(readlink -f $SCRIPTDIR/../../..)" +KPATCH="sudo $ROOTDIR/kpatch/kpatch" + +MODULE_PREFIX="test-" +MODULE_POSTFIX=".ko" +TEST_POSTFIX="-LOADED.test" + +set -o errexit + +die() { + echo "ERROR: $@" >&2 + exit 1 +} + +ko_to_test() { + tmp=${1%${MODULE_POSTFIX}}${TEST_POSTFIX} + echo ${tmp#${MODULE_PREFIX}} +} + +# make sure any modules added here are disjoint +declare -a modules +declare -a blacklist=(meminfo-cmdline-rebuild-SLOW-LOADED.test) + +for file in "${SCRIPTDIR}"/*"${TEST_POSTFIX}"; do + name=$(basename ${file}) + skip=0 + for bname in "${blacklist[@]}"; do + if [ "${bname}" == "${name}" ]; then + skip=1 + break + fi + done + if [ ${skip} -eq 0 ]; then + modules+=(${MODULE_PREFIX}${name%${TEST_POSTFIX}}${MODULE_POSTFIX}) + fi +done + +for mod in "${modules[@]}"; do + testprog=$(ko_to_test $mod) + $SCRIPTDIR/$testprog && die "$SCRIPTDIR/$testprog succeeded before loading any modules" +done + +for mod in "${modules[@]}"; do + $KPATCH load $mod +done + +for mod in "${modules[@]}"; do + testprog=$(ko_to_test $mod) + $SCRIPTDIR/$testprog || die "$SCRIPTDIR/$testprog failed after loading modules" +done + +for mod in "${modules[@]}"; do + $KPATCH unload $mod +done + +for mod in "${modules[@]}"; do + testprog=$(ko_to_test $mod) + $SCRIPTDIR/$testprog && die "$SCRIPTDIR/$testprog succeeded after unloading modules" +done + +exit 0 diff -Nru kpatch-0.5.0/test/integration/fedora-27/new-function.patch kpatch-0.8.0/test/integration/fedora-27/new-function.patch --- kpatch-0.5.0/test/integration/fedora-27/new-function.patch 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/test/integration/fedora-27/new-function.patch 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1,25 @@ +diff -Nupr src.orig/drivers/tty/n_tty.c src/drivers/tty/n_tty.c +--- src.orig/drivers/tty/n_tty.c 2017-11-17 15:58:00.462211972 -0500 ++++ src/drivers/tty/n_tty.c 2017-11-17 15:59:31.240211972 -0500 +@@ -2269,7 +2269,7 @@ static ssize_t n_tty_read(struct tty_str + * lock themselves) + */ + +-static ssize_t n_tty_write(struct tty_struct *tty, struct file *file, ++static ssize_t noinline kpatch_n_tty_write(struct tty_struct *tty, struct file *file, + const unsigned char *buf, size_t nr) + { + const unsigned char *b = buf; +@@ -2356,6 +2356,12 @@ break_out: + return (b - buf) ? b - buf : retval; + } + ++static ssize_t n_tty_write(struct tty_struct *tty, struct file *file, ++ const unsigned char *buf, size_t nr) ++{ ++ return kpatch_n_tty_write(tty, file, buf, nr); ++} ++ + /** + * n_tty_poll - poll method for N_TTY + * @tty: terminal device diff -Nru kpatch-0.5.0/test/integration/fedora-27/new-globals.patch kpatch-0.8.0/test/integration/fedora-27/new-globals.patch --- kpatch-0.5.0/test/integration/fedora-27/new-globals.patch 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/test/integration/fedora-27/new-globals.patch 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1,34 @@ +diff -Nupr src.orig/fs/proc/cmdline.c src/fs/proc/cmdline.c +--- src.orig/fs/proc/cmdline.c 2017-11-17 15:58:41.126211972 -0500 ++++ src/fs/proc/cmdline.c 2017-11-17 15:59:32.886211972 -0500 +@@ -27,3 +27,10 @@ static int __init proc_cmdline_init(void + return 0; + } + fs_initcall(proc_cmdline_init); ++ ++#include ++void kpatch_print_message(void) ++{ ++ if (!jiffies) ++ printk("hello there!\n"); ++} +diff -Nupr src.orig/fs/proc/meminfo.c src/fs/proc/meminfo.c +--- src.orig/fs/proc/meminfo.c 2017-11-17 15:59:24.724211972 -0500 ++++ src/fs/proc/meminfo.c 2017-11-17 15:59:32.887211972 -0500 +@@ -19,6 +19,8 @@ + #include + #include "internal.h" + ++void kpatch_print_message(void); ++ + void __attribute__((weak)) arch_report_meminfo(struct seq_file *m) + { + } +@@ -65,6 +67,7 @@ static int meminfo_proc_show(struct seq_ + + available = si_mem_available(); + ++ kpatch_print_message(); + show_val_kb(m, "MemTotal: ", i.totalram); + show_val_kb(m, "MemFree: ", i.freeram); + show_val_kb(m, "MemAvailable: ", available); diff -Nru kpatch-0.5.0/test/integration/fedora-27/README kpatch-0.8.0/test/integration/fedora-27/README --- kpatch-0.5.0/test/integration/fedora-27/README 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/test/integration/fedora-27/README 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1 @@ +4.13.9-300.fc27.x86_64 diff -Nru kpatch-0.5.0/test/integration/fedora-27/remote-setup kpatch-0.8.0/test/integration/fedora-27/remote-setup --- kpatch-0.5.0/test/integration/fedora-27/remote-setup 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/test/integration/fedora-27/remote-setup 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1,45 @@ +#!/bin/bash -x + +# install rpms on a Fedora 22 system to prepare it for kpatch integration tests + +set -o errexit + +[[ $UID != 0 ]] && sudo=sudo + +warn() { + echo "ERROR: $1" >&2 +} + +die() { + warn "$@" + exit 1 +} + +install_rpms() { + # crude workaround for a weird dnf bug where it fails to download + $sudo dnf install -y $* || $sudo dnf install -y $* +} + +install_rpms gcc elfutils elfutils-devel pesign openssl numactl-devel wget patchutils + +$sudo dnf builddep -y kernel || $sudo dnf builddep -y kernel + +# install kernel debuginfo and devel RPMs for target kernel +kverrel=$(uname -r) +kverrel=${kverrel%.x86_64} +kver=${kverrel%%-*} +krel=${kverrel#*-} +install_rpms https://kojipkgs.fedoraproject.org/packages/kernel/$kver/$krel/x86_64/kernel-debuginfo-$kver-$krel.x86_64.rpm https://kojipkgs.fedoraproject.org/packages/kernel/$kver/$krel/x86_64/kernel-debuginfo-common-x86_64-$kver-$krel.x86_64.rpm https://kojipkgs.fedoraproject.org/packages/kernel/$kver/$krel/x86_64/kernel-devel-$kver-$krel.x86_64.rpm + +# install version of gcc which was used to build the target kernel +gccver=$(gcc --version |head -n1 |cut -d' ' -f3-) +kgccver=$(readelf -p .comment /usr/lib/debug/lib/modules/$(uname -r)/vmlinux |grep GCC: | tr -s ' ' | cut -d ' ' -f6-) +if [[ $gccver != $kgccver ]]; then + gver=$(echo $kgccver | awk '{print $1}') + grel=$(echo $kgccver | sed 's/.*-\(.*\))/\1/') + grel=$grel.$(rpm -q gcc |sed 's/.*\.\(.*\)\.x86_64/\1/') + install_rpms https://kojipkgs.fedoraproject.org/packages/gcc/$gver/$grel/x86_64/cpp-$gver-$grel.x86_64.rpm https://kojipkgs.fedoraproject.org/packages/gcc/$gver/$grel/x86_64/gcc-$gver-$grel.x86_64.rpm https://kojipkgs.fedoraproject.org/packages/gcc/$gver/$grel/x86_64/libgomp-$gver-$grel.x86_64.rpm +fi + +install_rpms ccache +ccache -M 5G diff -Nru kpatch-0.5.0/test/integration/fedora-27/shadow-newpid-LOADED.test kpatch-0.8.0/test/integration/fedora-27/shadow-newpid-LOADED.test --- kpatch-0.5.0/test/integration/fedora-27/shadow-newpid-LOADED.test 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/test/integration/fedora-27/shadow-newpid-LOADED.test 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1,3 @@ +#!/bin/bash + +grep -q newpid: /proc/$$/status diff -Nru kpatch-0.5.0/test/integration/fedora-27/shadow-newpid.patch kpatch-0.8.0/test/integration/fedora-27/shadow-newpid.patch --- kpatch-0.5.0/test/integration/fedora-27/shadow-newpid.patch 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/test/integration/fedora-27/shadow-newpid.patch 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1,78 @@ +Index: src/fs/proc/array.c +=================================================================== +--- src.orig/fs/proc/array.c ++++ src/fs/proc/array.c +@@ -363,12 +363,19 @@ static inline void task_seccomp(struct s + seq_putc(m, '\n'); + } + ++#include "kpatch.h" + static inline void task_context_switch_counts(struct seq_file *m, + struct task_struct *p) + { ++ int *newpid; ++ + seq_put_decimal_ull(m, "voluntary_ctxt_switches:\t", p->nvcsw); + seq_put_decimal_ull(m, "\nnonvoluntary_ctxt_switches:\t", p->nivcsw); + seq_putc(m, '\n'); ++ ++ newpid = kpatch_shadow_get(p, "newpid"); ++ if (newpid) ++ seq_printf(m, "newpid:\t%d\n", *newpid); + } + + static void task_cpus_allowed(struct seq_file *m, struct task_struct *task) +Index: src/kernel/exit.c +=================================================================== +--- src.orig/kernel/exit.c ++++ src/kernel/exit.c +@@ -760,6 +760,7 @@ static void check_stack_usage(void) + static inline void check_stack_usage(void) {} + #endif + ++#include "kpatch.h" + void __noreturn do_exit(long code) + { + struct task_struct *tsk = current; +@@ -865,6 +866,8 @@ void __noreturn do_exit(long code) + exit_task_work(tsk); + exit_thread(tsk); + ++ kpatch_shadow_free(tsk, "newpid"); ++ + /* + * Flush inherited counters to the parent - before the parent + * gets woken up by child-exit notifications. +Index: src/kernel/fork.c +=================================================================== +--- src.orig/kernel/fork.c ++++ src/kernel/fork.c +@@ -2062,6 +2062,7 @@ struct task_struct *fork_idle(int cpu) + * It copies the process, and if successful kick-starts + * it and waits for it to finish using the VM if required. + */ ++#include "kpatch.h" + long _do_fork(unsigned long clone_flags, + unsigned long stack_start, + unsigned long stack_size, +@@ -2074,6 +2075,8 @@ long _do_fork(unsigned long clone_flags, + struct task_struct *p; + int trace = 0; + long nr; ++ int *newpid; ++ static int ctr = 0; + + /* + * Determine whether and which event to report to ptracer. When +@@ -2100,6 +2103,11 @@ long _do_fork(unsigned long clone_flags, + if (IS_ERR(p)) + return PTR_ERR(p); + ++ newpid = kpatch_shadow_alloc(p, "newpid", sizeof(*newpid), ++ GFP_KERNEL); ++ if (newpid) ++ *newpid = ctr++; ++ + /* + * Do this prior waking up the new thread - the thread pointer + * might get invalid after that point, if the thread exits quickly. diff -Nru kpatch-0.5.0/test/integration/fedora-27/warn-detect-FAIL.patch kpatch-0.8.0/test/integration/fedora-27/warn-detect-FAIL.patch --- kpatch-0.5.0/test/integration/fedora-27/warn-detect-FAIL.patch 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/test/integration/fedora-27/warn-detect-FAIL.patch 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1,9 @@ +diff --git a/net/core/dev.c b/net/core/dev.c +index ef0cc6ea5f8d..9a840ec54270 100644 +--- a/net/core/dev.c ++++ b/net/core/dev.c +@@ -1,3 +1,4 @@ ++ + /* + * NET3 Protocol independent device support routines. + * diff -Nru kpatch-0.5.0/test/integration/kpatch-test kpatch-0.8.0/test/integration/kpatch-test --- kpatch-0.5.0/test/integration/kpatch-test 2017-12-21 05:02:48.000000000 +0000 +++ kpatch-0.8.0/test/integration/kpatch-test 2019-08-28 17:34:00.000000000 +0000 @@ -28,8 +28,6 @@ # # - foo.patch: patch that should build successfully # -# - foo-SLOW.patch: patch that should be skipped in the quick test -# # - bar-FAIL.patch: patch that should fail to build # # - foo-LOADED.test: executable which tests whether the foo.patch module is @@ -51,7 +49,7 @@ KPATCHBUILD="$ROOTDIR"/kpatch-build/kpatch-build ERROR=0 LOG=test.log -rm -f $LOG +rm -f *.log PATCHDIR="${PATCHDIR:-$PWD}" declare -a PATCH_LIST @@ -63,7 +61,7 @@ echo " -h, --help Show this help message" >&2 echo " -c, --cached Don't rebuild patch modules" >&2 echo " -d, --directory Patch directory" >&2 - echo " -q, --quick Just combine all patches into one module for testing" >&2 + echo " -q, --quick Test combined patch and -FAIL patches only" >&2 } options=$(getopt -o hcd:q -l "help,cached,directory,quick" -- "$@") || exit 1 @@ -106,7 +104,6 @@ prefix=${file%%.patch} [[ -e "$prefix-FAIL.test" ]] && TEST_LIST+=("$prefix-FAIL.test") [[ -e "$prefix-LOADED.test" ]] && TEST_LIST+=("$prefix-LOADED.test") - [[ -e "$prefix-SLOW.test" ]] && TEST_LIST+=("$prefix-SLOW.test") done fi @@ -133,7 +130,8 @@ build_module() { file=$1 prefix=$(basename ${file%%.patch}) - module=kpatch-$prefix.ko + modname="test-$prefix" + module="${modname}.ko" if [[ $prefix =~ -FAIL ]]; then shouldfail=1 @@ -150,8 +148,11 @@ log "build: $prefix" - if ! $KPATCHBUILD $file >> $LOG 2>&1; then - [[ $shouldfail -eq 0 ]] && error "$prefix: build failed" + if ! $KPATCHBUILD -n $modname $file >> $LOG 2>&1; then + if [[ $shouldfail -eq 0 ]]; then + error "$prefix: build failed" + cp $HOME/.kpatch/build.log $prefix.log + fi else [[ $shouldfail -eq 1 ]] && error "$prefix: build succeeded when it should have failed" fi @@ -160,7 +161,8 @@ run_load_test() { file=$1 prefix=$(basename ${file%%.patch}) - module=kpatch-$prefix.ko + modname="test-$prefix" + module="${modname}.ko" testprog="$(dirname $1)/$prefix-LOADED.test" [[ $prefix =~ -FAIL ]] && return @@ -204,7 +206,7 @@ run_custom_test() { testprog=$1 - prefix=$(basename ${file%%.test}) + prefix=$(basename ${testprog%%.test}) [[ $testprog = *-LOADED.test ]] && return @@ -217,7 +219,7 @@ build_combined_module() { - if [[ $SKIPBUILD -eq 1 ]] && [[ -e kpatch-COMBINED.ko ]]; then + if [[ $SKIPBUILD -eq 1 ]] && [[ -e test-COMBINED.ko ]]; then log "skipping build: combined" return fi @@ -225,7 +227,6 @@ declare -a COMBINED_LIST for file in "${PATCH_LIST[@]}"; do [[ $file =~ -FAIL ]] && log "combine: skipping $file" && continue - [[ $file =~ -SLOW ]] && log "combine: skipping $file" && continue COMBINED_LIST+=($file) done if [[ ${#COMBINED_LIST[@]} -le 1 ]]; then @@ -235,14 +236,15 @@ log "build: combined module" - if ! $KPATCHBUILD -n kpatch-COMBINED "${COMBINED_LIST[@]}" >> $LOG 2>&1; then + if ! $KPATCHBUILD -n test-COMBINED "${COMBINED_LIST[@]}" >> $LOG 2>&1; then error "combined build failed" + cp $HOME/.kpatch/build.log combined.log fi } run_combined_test() { - if [[ ! -e kpatch-COMBINED.ko ]]; then - log "can't find kpatch-COMBINED.ko, skipping" + if [[ ! -e test-COMBINED.ko ]]; then + log "can't find test-COMBINED.ko, skipping" return fi @@ -258,7 +260,7 @@ fi done - if ! $KPATCH load kpatch-COMBINED.ko >> $LOG 2>&1; then + if ! $KPATCH load test-COMBINED.ko >> $LOG 2>&1; then error "combined: kpatch load failed" return fi @@ -270,7 +272,7 @@ fi done - if ! $KPATCH unload kpatch-COMBINED.ko >> $LOG 2>&1; then + if ! $KPATCH unload test-COMBINED.ko >> $LOG 2>&1; then error "combined: kpatch unload failed" return fi @@ -288,11 +290,11 @@ echo "clearing printk buffer" sudo dmesg -C -if [[ $QUICK != 1 ]]; then - for file in "${PATCH_LIST[@]}"; do +for file in "${PATCH_LIST[@]}"; do + if [[ $QUICK != 1 || $file =~ -FAIL ]]; then build_module $file - done -fi + fi +done build_combined_module @@ -308,15 +310,20 @@ if [[ $QUICK != 1 ]]; then for testprog in "${TEST_LIST[@]}"; do - unload_all - run_custom_test $testprog + if [[ ! $testprog =~ -FAIL ]]; then + unload_all + run_custom_test $testprog + fi done fi unload_all -dmesg |grep -q "Call Trace" && error "kernel error detected in printk buffer" +if dmesg | grep -q "Call Trace"; then + dmesg > dmesg.log + error "kernel error detected in printk buffer" +fi if [[ $ERROR -gt 0 ]]; then log "$ERROR errors encountered" diff -Nru kpatch-0.5.0/test/integration/lib.sh kpatch-0.8.0/test/integration/lib.sh --- kpatch-0.5.0/test/integration/lib.sh 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/test/integration/lib.sh 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1,300 @@ +#!/bin/bash + +kpatch_set_ccache_max_size() +{ + local ccache_max_size=${1:-10G} + + ccache --max-size="${ccache_max_size}" +} + +kpatch_fedora_dependencies() +{ + local kernel_version + kernel_version=$(uname -r) + + sudo dnf install -y gcc "kernel-devel-${kernel_version%.*}" elfutils elfutils-devel + sudo dnf install -y pesign yum-utils openssl wget numactl-devel + sudo dnf builddep -y "kernel-${kernel_version%.*}" + sudo dnf debuginfo-install -y "kernel-${kernel_version%.*}" + + sudo dnf install -y ccache +} + +kpatch_ubuntu_dependencies() +{ + sudo sed -i 's/# deb-src/deb-src/' /etc/apt/sources.list + sudo apt-get update + + sudo apt-get install -y make gcc libelf-dev elfutils + sudo apt-get install -y dpkg-dev devscripts + sudo apt-get build-dep -y linux + + sudo apt-get install -y ccache + + # Add ddebs repository + if ! grep -q 'ddebs.ubuntu.com' /etc/apt/sources.list.d/ddebs.list; then + local codename + codename=$(lsb_release -sc) + sudo tee /etc/apt/sources.list.d/ddebs.list <<-EOF + deb http://ddebs.ubuntu.com/ ${codename} main restricted universe multiverse + deb http://ddebs.ubuntu.com/ ${codename}-security main restricted universe multiverse + deb http://ddebs.ubuntu.com/ ${codename}-updates main restricted universe multiverse + deb http://ddebs.ubuntu.com/ ${codename}-proposed main restricted universe multiverse + EOF + + # add APT key + wget -Nq http://ddebs.ubuntu.com/dbgsym-release-key.asc -O- | sudo apt-key add - + sudo apt-get update + fi + sudo apt-get install -y "linux-image-$(uname -r)-dbgsym" +} + +kpatch_rhel_dependencies() +{ + local kernel_version + local arch + kernel_version=$(uname -r) + arch=$(uname -m) + + sudo yum install -y git gcc gcc-c++ "kernel-devel-${kernel_version%.*}" elfutils elfutils-devel + sudo yum install -y yum-utils zlib-devel binutils-devel newt-devel \ + python-devel perl-ExtUtils-Embed audit-libs-devel numactl-devel \ + pciutils-devel bison ncurses-devel rpm-build java-devel + sudo yum-builddep -y "kernel-${kernel_version%.*}" + sudo debuginfo-install -y "kernel-${kernel_version%.*}" + + [ "${arch}" == "x86_64" ] && sudo yum install -y pesign + [ "${arch}" == "ppc64le" ] && sudo yum install -y gcc-plugin-devel + + sudo yum install -y "https://dl.fedoraproject.org/pub/epel/7/${arch}/Packages/c/ccache-3.3.4-1.el7.${arch}.rpm" +} + +kpatch_centos_dependencies() +{ + local kernel_version + local arch + kernel_version=$(uname -r) + arch=$(uname -m) + + sudo yum install -y gcc gcc-c++ "kernel-devel-${kernel_version%.*}" elfutils elfutils-devel + sudo yum install -y yum-utils zlib-devel binutils-devel newt-devel \ + python-devel perl-ExtUtils-Embed audit-libs-devel numactl-devel \ + pciutils-devel bison ncurses-devel rpm-build java-devel pesign + sudo yum-config-manager --enable debug + sudo yum-builddep -y "kernel-${kernel_version%.*}" + sudo debuginfo-install -y "kernel-${kernel_version%.*}" + + sudo yum install -y "https://dl.fedoraproject.org/pub/epel/7/${arch}/Packages/c/ccache-3.3.4-1.el7.${arch}.rpm" +} + +kpatch_dependencies() +{ + # shellcheck disable=SC1091 + source /etc/os-release + + eval "kpatch_${ID}_dependencies" || { echo "Unsupported distro: ${ID}"; exit 1; } +} + +kpatch_separate_partition_cache() +{ + local partition=${1} + local mountpoint=${2} + local reformat=${3} + local owner=${USER} + + if [[ "${reformat}" == "y" ]]; then + sudo mkfs.xfs -f "${partition}" + fi + + sudo mkdir -p "${mountpoint}" + sudo mount "${partition}" "${mountpoint}" + sudo chown "${owner}":"${owner}" "${mountpoint}" + + rm -rf "${mountpoint}/.ccache" + rm -rf "${mountpoint}/.kpatch" + mkdir "${mountpoint}/.ccache" + mkdir "${mountpoint}/.kpatch" + + rm -rf "${HOME}/.ccache" + rm -rf "${HOME}/.kpatch" + + ln -sv "${mountpoint}/.ccache" "${HOME}/.ccache" + ln -sv "${mountpoint}/.kpatch" "${HOME}/.kpatch" +} + +kpatch_separate_disk_cache() +{ + local device=${1} + local mountpoint=${2} + local partition="${device}1" + + echo -e "o\\nn\\np\\n1\\n\\n\\nw\\n" | sudo fdisk "${device}" + kpatch_separate_partition_cache "${partition}" "${mountpoint}" y +} + +kpatch_install_vagrant_centos() +{ + local image_path=${1} + + sudo yum group install -y "Development Tools" + sudo yum -y install qemu-kvm libvirt virt-install bridge-utils libvirt-devel libxslt-devel libxml2-devel libvirt-devel libguestfs-tools-c libvirt-client + + echo "net.ipv4.ip_forward = 1" | sudo tee /etc/sysctl.d/99-ipforward.conf + sudo sysctl -p /etc/sysctl.d/99-ipforward.conf + + sudo systemctl enable libvirtd + sudo systemctl start libvirtd || exit 1 + + if [[ -n "${image_path}" ]]; then + mkdir -p "${image_path}/libvirt/images" + virsh pool-define-as --target "${image_path}/libvirt/images" default dir || exit 1 + virsh pool-start default || exit 1 + fi + + sudo yum install -y https://releases.hashicorp.com/vagrant/2.1.2/vagrant_2.1.2_x86_64.rpm || exit 1 + + vagrant plugin install vagrant-libvirt +} + +kpatch_install_vagrant_rhel() +{ + local image_path=${1} + + kpatch_install_vagrant_centos "${image_path}" + + sudo systemctl enable nfs + sudo systemctl start nfs || exit 1 + +} + +kpatch_install_vagrant_fedora() +{ + local image_path=${1} + + echo "net.ipv4.ip_forward = 1" | sudo tee /etc/sysctl.d/99-ipforward.conf + sudo sysctl -p /etc/sysctl.d/99-ipforward.conf + + sudo dnf install -y libvirt virt-install libvirt-client nfs-utils vagrant vagrant-libvirt + + echo "[nfsd]" | sudo tee -a /etc/nfs.conf + echo "udp=y" | sudo tee -a /etc/nfs.conf + echo "vers3=y" | sudo tee -a /etc/nfs.conf + sudo systemctl restart nfs + + sudo systemctl enable libvirtd + sudo systemctl start libvirtd || exit 1 + + if [[ -n "${image_path}" ]]; then + mkdir -p "${image_path}/libvirt/images" + virsh pool-define-as --target "${image_path}/libvirt/images" default dir || exit 1 + virsh pool-start default || exit 1 + fi +} + +kpatch_install_vagrant() +{ + local image_path=${1} + + # shellcheck disable=SC1091 + source /etc/os-release + + eval "kpatch_install_vagrant_${ID} ${image_path}" || { echo "Unsupported distro: ${ID}"; exit 1; } +} + +kpatch_check_install_vagrant() +{ + local image_path=${1} + [ "$(which vagrant)" == "" ] && kpatch_install_vagrant "${image_path}" + return 0 +} + +kpatch_write_vagrantfile_template() +{ + local target_distro=${1} + + local box_prefix="kpatch" + + cat >Vagrantfile < '40G' + libvirt.cpus = $(getconf _NPROCESSORS_ONLN) + libvirt.memory = $(awk '/MemTotal/ {printf("%d\n", ($2*0.8)/1024)}' /proc/meminfo) + libvirt.graphics_type = "none" + libvirt.disk_bus = 'virtio' + libvirt.disk_device = 'vda' + end + config.vm.box = "${box_prefix}/${target_distro}" + config.vm.synced_folder ".", "/vagrant", type: "nfs" +EOF +} + +kpatch_write_vagrantfile_centos_provision() +{ + cat >>Vagrantfile <>Vagrantfile +} + +kpatch_integration_tests_vagrant_distro() +{ + local target_distro=${1} + local test_script=${2} + local slowtest=${3} + + local testdir + local workdir + local logdir + + testdir="$(pwd)" + workdir="${target_distro}.vagrant" + rm -rf "${workdir}" + mkdir -p "${workdir}" + cd "${workdir}" || exit 1 + + kpatch_write_vagrantfile "${target_distro}" + + vagrant up || { vagrant destroy -f; exit 1; } + + local test_cmd="bash /vagrant/runtest.sh" + if [ "${slowtest}" == "1" ]; then + test_cmd="${test_cmd} --slow" + fi + + cp "${test_script}" ./runtest.sh + vagrant ssh -c "${test_cmd}" + local rc=$? + + if [ $rc -eq 0 ]; then + echo "${target_distro} PASS" + else + echo "${target_distro} FAIL" + fi + + logdir="${testdir}/${target_distro}_log" + rm -rf "${logdir}" + mkdir -p "${logdir}" + cp logs/* "${logdir}" + + vagrant destroy -f + + cd "${testdir}" || exit 1 + if [ $rc -eq 0 ]; then + rm -rf "${workdir}" + fi + + return "${rc}" +} diff -Nru kpatch-0.5.0/test/integration/Makefile kpatch-0.8.0/test/integration/Makefile --- kpatch-0.5.0/test/integration/Makefile 2017-12-21 05:02:48.000000000 +0000 +++ kpatch-0.8.0/test/integration/Makefile 2019-08-28 17:34:00.000000000 +0000 @@ -18,6 +18,14 @@ cached: ./kpatch-test -d $(PATCH_DIR) --cached $(PATCHES) +vagrant: vagrant_quick + +vagrant-quick: + ./test-vagrant + +vagrant-slow: + ./test-vagrant --slow + clean: rm -f *.ko *.log COMBINED.patch diff -Nru kpatch-0.5.0/test/integration/rhel-7.4/bug-table-section.patch kpatch-0.8.0/test/integration/rhel-7.4/bug-table-section.patch --- kpatch-0.5.0/test/integration/rhel-7.4/bug-table-section.patch 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/test/integration/rhel-7.4/bug-table-section.patch 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1,12 @@ +diff -Nupr src.orig/fs/proc/proc_sysctl.c src/fs/proc/proc_sysctl.c +--- src.orig/fs/proc/proc_sysctl.c 2017-09-22 15:27:21.698056175 -0400 ++++ src/fs/proc/proc_sysctl.c 2017-09-22 15:27:21.769056469 -0400 +@@ -266,6 +266,8 @@ void sysctl_head_put(struct ctl_table_he + + static struct ctl_table_header *sysctl_head_grab(struct ctl_table_header *head) + { ++ if (jiffies == 0) ++ printk("kpatch-test: testing __bug_table section changes\n"); + BUG_ON(!head); + spin_lock(&sysctl_lock); + if (!use_table(head)) diff -Nru kpatch-0.5.0/test/integration/rhel-7.4/cmdline-string-LOADED.test kpatch-0.8.0/test/integration/rhel-7.4/cmdline-string-LOADED.test --- kpatch-0.5.0/test/integration/rhel-7.4/cmdline-string-LOADED.test 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/test/integration/rhel-7.4/cmdline-string-LOADED.test 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1,3 @@ +#!/bin/bash + +grep kpatch=1 /proc/cmdline diff -Nru kpatch-0.5.0/test/integration/rhel-7.4/cmdline-string.patch kpatch-0.8.0/test/integration/rhel-7.4/cmdline-string.patch --- kpatch-0.5.0/test/integration/rhel-7.4/cmdline-string.patch 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/test/integration/rhel-7.4/cmdline-string.patch 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1,12 @@ +diff -Nupr src.orig/fs/proc/cmdline.c src/fs/proc/cmdline.c +--- src.orig/fs/proc/cmdline.c 2017-09-22 15:27:21.698056175 -0400 ++++ src/fs/proc/cmdline.c 2017-09-22 15:27:22.955061380 -0400 +@@ -5,7 +5,7 @@ + + static int cmdline_proc_show(struct seq_file *m, void *v) + { +- seq_printf(m, "%s\n", saved_command_line); ++ seq_printf(m, "%s kpatch=1\n", saved_command_line); + return 0; + } + diff -Nru kpatch-0.5.0/test/integration/rhel-7.4/data-new-LOADED.test kpatch-0.8.0/test/integration/rhel-7.4/data-new-LOADED.test --- kpatch-0.5.0/test/integration/rhel-7.4/data-new-LOADED.test 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/test/integration/rhel-7.4/data-new-LOADED.test 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1,3 @@ +#!/bin/bash + +grep "kpatch: 5" /proc/meminfo diff -Nru kpatch-0.5.0/test/integration/rhel-7.4/data-new.patch kpatch-0.8.0/test/integration/rhel-7.4/data-new.patch --- kpatch-0.5.0/test/integration/rhel-7.4/data-new.patch 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/test/integration/rhel-7.4/data-new.patch 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1,28 @@ +diff -Nupr src.orig/fs/proc/meminfo.c src/fs/proc/meminfo.c +--- src.orig/fs/proc/meminfo.c 2017-09-22 15:27:21.699056179 -0400 ++++ src/fs/proc/meminfo.c 2017-09-22 15:27:24.102066130 -0400 +@@ -20,6 +20,8 @@ void __attribute__((weak)) arch_report_m + { + } + ++static int foo = 5; ++ + static int meminfo_proc_show(struct seq_file *m, void *v) + { + struct sysinfo i; +@@ -106,6 +108,7 @@ static int meminfo_proc_show(struct seq_ + #ifdef CONFIG_TRANSPARENT_HUGEPAGE + "AnonHugePages: %8lu kB\n" + #endif ++ "kpatch: %d" + , + K(i.totalram), + K(i.freeram), +@@ -167,6 +170,7 @@ static int meminfo_proc_show(struct seq_ + ,K(global_page_state(NR_ANON_TRANSPARENT_HUGEPAGES) * + HPAGE_PMD_NR) + #endif ++ ,foo + ); + + hugetlb_report_meminfo(m); diff -Nru kpatch-0.5.0/test/integration/rhel-7.4/data-read-mostly.patch kpatch-0.8.0/test/integration/rhel-7.4/data-read-mostly.patch --- kpatch-0.5.0/test/integration/rhel-7.4/data-read-mostly.patch 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/test/integration/rhel-7.4/data-read-mostly.patch 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1,11 @@ +diff -Nupr src.orig/net/core/dev.c src/net/core/dev.c +--- src.orig/net/core/dev.c 2017-09-22 15:27:21.759056428 -0400 ++++ src/net/core/dev.c 2017-09-22 15:27:25.244070859 -0400 +@@ -4012,6 +4012,7 @@ ncls: + case RX_HANDLER_PASS: + break; + default: ++ printk("BUG!\n"); + BUG(); + } + } diff -Nru kpatch-0.5.0/test/integration/rhel-7.4/fixup-section.patch kpatch-0.8.0/test/integration/rhel-7.4/fixup-section.patch --- kpatch-0.5.0/test/integration/rhel-7.4/fixup-section.patch 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/test/integration/rhel-7.4/fixup-section.patch 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1,12 @@ +diff --git a/fs/readdir.c b/fs/readdir.c +index fee38e04fae4..bce1e5ce74e5 100644 +--- a/fs/readdir.c ++++ b/fs/readdir.c +@@ -166,6 +166,7 @@ static int filldir(void * __buf, const char * name, int namlen, loff_t offset, + goto efault; + } + dirent = buf->current_dir; ++ asm("nop"); + if (__put_user(d_ino, &dirent->d_ino)) + goto efault; + if (__put_user(reclen, &dirent->d_reclen)) diff -Nru kpatch-0.5.0/test/integration/rhel-7.4/gcc-constprop.patch kpatch-0.8.0/test/integration/rhel-7.4/gcc-constprop.patch --- kpatch-0.5.0/test/integration/rhel-7.4/gcc-constprop.patch 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/test/integration/rhel-7.4/gcc-constprop.patch 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1,13 @@ +diff -Nupr src.orig/kernel/time/timekeeping.c src/kernel/time/timekeeping.c +--- src.orig/kernel/time/timekeeping.c 2017-09-22 15:27:21.602055778 -0400 ++++ src/kernel/time/timekeeping.c 2017-09-22 15:27:27.522080292 -0400 +@@ -877,6 +877,9 @@ void do_gettimeofday(struct timeval *tv) + { + struct timespec64 now; + ++ if (!tv) ++ return; ++ + getnstimeofday64(&now); + tv->tv_sec = now.tv_sec; + tv->tv_usec = now.tv_nsec/1000; diff -Nru kpatch-0.5.0/test/integration/rhel-7.4/gcc-isra.patch kpatch-0.8.0/test/integration/rhel-7.4/gcc-isra.patch --- kpatch-0.5.0/test/integration/rhel-7.4/gcc-isra.patch 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/test/integration/rhel-7.4/gcc-isra.patch 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1,11 @@ +diff -Nupr src.orig/fs/proc/proc_sysctl.c src/fs/proc/proc_sysctl.c +--- src.orig/fs/proc/proc_sysctl.c 2017-09-22 15:27:21.698056175 -0400 ++++ src/fs/proc/proc_sysctl.c 2017-09-22 15:27:28.670085046 -0400 +@@ -24,6 +24,7 @@ void proc_sys_poll_notify(struct ctl_tab + if (!poll) + return; + ++ printk("kpatch-test: testing gcc .isra function name mangling\n"); + atomic_inc(&poll->event); + wake_up_interruptible(&poll->wait); + } diff -Nru kpatch-0.5.0/test/integration/rhel-7.4/gcc-mangled-3.patch kpatch-0.8.0/test/integration/rhel-7.4/gcc-mangled-3.patch --- kpatch-0.5.0/test/integration/rhel-7.4/gcc-mangled-3.patch 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/test/integration/rhel-7.4/gcc-mangled-3.patch 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1,13 @@ +diff -Nupr src.orig/mm/slub.c src/mm/slub.c +--- src.orig/mm/slub.c 2017-09-22 15:27:21.618055844 -0400 ++++ src/mm/slub.c 2017-09-22 15:27:29.830089850 -0400 +@@ -5528,6 +5528,9 @@ void get_slabinfo(struct kmem_cache *s, + unsigned long nr_free = 0; + int node; + ++ if (!jiffies) ++ printk("slabinfo\n"); ++ + for_each_online_node(node) { + struct kmem_cache_node *n = get_node(s, node); + diff -Nru kpatch-0.5.0/test/integration/rhel-7.4/gcc-static-local-var-2.patch kpatch-0.8.0/test/integration/rhel-7.4/gcc-static-local-var-2.patch --- kpatch-0.5.0/test/integration/rhel-7.4/gcc-static-local-var-2.patch 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/test/integration/rhel-7.4/gcc-static-local-var-2.patch 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1,13 @@ +diff -Nupr src.orig/mm/mmap.c src/mm/mmap.c +--- src.orig/mm/mmap.c 2017-09-22 15:27:21.618055844 -0400 ++++ src/mm/mmap.c 2017-09-22 15:27:31.024094794 -0400 +@@ -1687,6 +1688,9 @@ unsigned long mmap_region(struct file *f + struct rb_node **rb_link, *rb_parent; + unsigned long charged = 0; + ++ if (!jiffies) ++ printk("kpatch mmap foo\n"); ++ + /* Check against address space limit. */ + if (!may_expand_vm(mm, len >> PAGE_SHIFT)) { + unsigned long nr_pages; diff -Nru kpatch-0.5.0/test/integration/rhel-7.4/gcc-static-local-var-3.patch kpatch-0.8.0/test/integration/rhel-7.4/gcc-static-local-var-3.patch --- kpatch-0.5.0/test/integration/rhel-7.4/gcc-static-local-var-3.patch 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/test/integration/rhel-7.4/gcc-static-local-var-3.patch 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1,19 @@ +diff -Nupr src.orig/kernel/sys.c src/kernel/sys.c +--- src.orig/kernel/sys.c 2017-09-22 15:27:21.601055773 -0400 ++++ src/kernel/sys.c 2017-09-22 15:27:32.170099540 -0400 +@@ -554,8 +554,15 @@ SYSCALL_DEFINE4(reboot, int, magic1, int + return ret; + } + ++void kpatch_bar(void) ++{ ++ if (!jiffies) ++ printk("kpatch_foo\n"); ++} ++ + static void deferred_cad(struct work_struct *dummy) + { ++ kpatch_bar(); + kernel_restart(NULL); + } + diff -Nru kpatch-0.5.0/test/integration/rhel-7.4/gcc-static-local-var-4.patch kpatch-0.8.0/test/integration/rhel-7.4/gcc-static-local-var-4.patch --- kpatch-0.5.0/test/integration/rhel-7.4/gcc-static-local-var-4.patch 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/test/integration/rhel-7.4/gcc-static-local-var-4.patch 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1,20 @@ +diff -Nupr src.orig/fs/aio.c src/fs/aio.c +--- src.orig/fs/aio.c 2017-09-22 15:27:21.702056192 -0400 ++++ src/fs/aio.c 2017-09-22 15:27:33.299104215 -0400 +@@ -219,9 +219,16 @@ static int __init aio_setup(void) + } + __initcall(aio_setup); + ++void kpatch_aio_foo(void) ++{ ++ if (!jiffies) ++ printk("kpatch aio foo\n"); ++} ++ + static void put_aio_ring_file(struct kioctx *ctx) + { + struct file *aio_ring_file = ctx->aio_ring_file; ++ kpatch_aio_foo(); + if (aio_ring_file) { + truncate_setsize(aio_ring_file->f_inode, 0); + diff -Nru kpatch-0.5.0/test/integration/rhel-7.4/gcc-static-local-var-4.test kpatch-0.8.0/test/integration/rhel-7.4/gcc-static-local-var-4.test --- kpatch-0.5.0/test/integration/rhel-7.4/gcc-static-local-var-4.test 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/test/integration/rhel-7.4/gcc-static-local-var-4.test 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1,7 @@ +#!/bin/bash + +if $(nm test-gcc-static-local-var-4.ko | grep -q free_ioctx); then + exit 1 +else + exit 0 +fi diff -Nru kpatch-0.5.0/test/integration/rhel-7.4/gcc-static-local-var-5.patch kpatch-0.8.0/test/integration/rhel-7.4/gcc-static-local-var-5.patch --- kpatch-0.5.0/test/integration/rhel-7.4/gcc-static-local-var-5.patch 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/test/integration/rhel-7.4/gcc-static-local-var-5.patch 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1,45 @@ +diff -Nupr src.orig/kernel/audit.c src/kernel/audit.c +--- src.orig/kernel/audit.c 2017-09-22 15:27:21.602055778 -0400 ++++ src/kernel/audit.c 2017-09-22 15:27:34.429108894 -0400 +@@ -205,6 +205,12 @@ void audit_panic(const char *message) + } + } + ++void kpatch_audit_foo(void) ++{ ++ if (!jiffies) ++ printk("kpatch audit foo\n"); ++} ++ + static inline int audit_rate_check(void) + { + static unsigned long last_check = 0; +@@ -215,6 +221,7 @@ static inline int audit_rate_check(void) + unsigned long elapsed; + int retval = 0; + ++ kpatch_audit_foo(); + if (!audit_rate_limit) return 1; + + spin_lock_irqsave(&lock, flags); +@@ -234,6 +241,11 @@ static inline int audit_rate_check(void) + return retval; + } + ++noinline void kpatch_audit_check(void) ++{ ++ audit_rate_check(); ++} ++ + /** + * audit_log_lost - conditionally log lost audit message event + * @message: the message stating reason for lost audit message +@@ -282,6 +294,8 @@ static int audit_log_config_change(char + struct audit_buffer *ab; + int rc = 0; + ++ kpatch_audit_check(); ++ + ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE); + if (unlikely(!ab)) + return rc; diff -Nru kpatch-0.5.0/test/integration/rhel-7.4/gcc-static-local-var-6.patch kpatch-0.8.0/test/integration/rhel-7.4/gcc-static-local-var-6.patch --- kpatch-0.5.0/test/integration/rhel-7.4/gcc-static-local-var-6.patch 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/test/integration/rhel-7.4/gcc-static-local-var-6.patch 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1,23 @@ +diff --git a/net/ipv6/netfilter.c b/net/ipv6/netfilter.c +index a9d587a..23336ed 100644 +--- a/net/ipv6/netfilter.c ++++ b/net/ipv6/netfilter.c +@@ -106,6 +106,8 @@ static int nf_ip6_reroute(struct sk_buff *skb, + return 0; + } + ++#include "kpatch-macros.h" ++ + static int nf_ip6_route(struct net *net, struct dst_entry **dst, + struct flowi *fl, bool strict) + { +@@ -119,6 +121,9 @@ static int nf_ip6_route(struct net *net, struct dst_entry **dst, + struct dst_entry *result; + int err; + ++ if (!jiffies) ++ printk("kpatch nf_ip6_route foo\n"); ++ + result = ip6_route_output(net, sk, &fl->u.ip6); + err = result->error; + if (err) diff -Nru kpatch-0.5.0/test/integration/rhel-7.4/gcc-static-local-var.patch kpatch-0.8.0/test/integration/rhel-7.4/gcc-static-local-var.patch --- kpatch-0.5.0/test/integration/rhel-7.4/gcc-static-local-var.patch 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/test/integration/rhel-7.4/gcc-static-local-var.patch 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1,25 @@ +diff -Nupr src.orig/arch/x86/kernel/ldt.c src/arch/x86/kernel/ldt.c +--- src.orig/arch/x86/kernel/ldt.c 2017-09-22 15:27:20.847052651 -0400 ++++ src/arch/x86/kernel/ldt.c 2017-09-22 15:27:35.573113632 -0400 +@@ -98,6 +98,12 @@ static inline int copy_ldt(mm_context_t + return 0; + } + ++void hi_there(void) ++{ ++ if (!jiffies) ++ printk("hi there\n"); ++} ++ + /* + * we do not have to muck with descriptors here, that is + * done in switch_mm() as needed. +@@ -107,6 +113,8 @@ int init_new_context(struct task_struct + struct mm_struct *old_mm; + int retval = 0; + ++ hi_there(); ++ + mutex_init(&mm->context.lock); + mm->context.size = 0; + old_mm = current->mm; diff -Nru kpatch-0.5.0/test/integration/rhel-7.4/macro-callbacks.patch kpatch-0.8.0/test/integration/rhel-7.4/macro-callbacks.patch --- kpatch-0.5.0/test/integration/rhel-7.4/macro-callbacks.patch 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/test/integration/rhel-7.4/macro-callbacks.patch 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1,160 @@ +kpatch/livepatch callback test patch: + + vmlinux + pcspkr (mod) + joydev (mod) + +Note: update joydev's pre-patch callback to return -ENODEV to test failure path + +--- src.old/fs/aio.c 2018-02-26 11:07:51.522610407 -0500 ++++ src/fs/aio.c 2018-03-05 11:17:21.560015449 -0500 +@@ -42,6 +42,50 @@ + #include + #include + ++#include ++#include "kpatch-macros.h" ++ ++static const char *const module_state[] = { ++ [MODULE_STATE_LIVE] = "[MODULE_STATE_LIVE] Normal state", ++ [MODULE_STATE_COMING] = "[MODULE_STATE_COMING] Full formed, running module_init", ++ [MODULE_STATE_GOING] = "[MODULE_STATE_GOING] Going away", ++ [MODULE_STATE_UNFORMED] = "[MODULE_STATE_UNFORMED] Still setting it up", ++}; ++ ++static void callback_info(const char *callback, patch_object *obj) ++{ ++ if (obj->mod) ++ pr_info("%s: %s -> %s\n", callback, obj->mod->name, ++ module_state[obj->mod->state]); ++ else ++ pr_info("%s: vmlinux\n", callback); ++} ++ ++static int pre_patch_callback(patch_object *obj) ++{ ++ callback_info(__func__, obj); ++ return 0; ++} ++KPATCH_PRE_PATCH_CALLBACK(pre_patch_callback); ++ ++static void post_patch_callback(patch_object *obj) ++{ ++ callback_info(__func__, obj); ++} ++KPATCH_POST_PATCH_CALLBACK(post_patch_callback); ++ ++static void pre_unpatch_callback(patch_object *obj) ++{ ++ callback_info(__func__, obj); ++} ++KPATCH_PRE_UNPATCH_CALLBACK(pre_unpatch_callback); ++ ++static void post_unpatch_callback(patch_object *obj) ++{ ++ callback_info(__func__, obj); ++} ++KPATCH_POST_UNPATCH_CALLBACK(post_unpatch_callback); ++ + #define AIO_RING_MAGIC 0xa10a10a1 + #define AIO_RING_COMPAT_FEATURES 1 + #define AIO_RING_INCOMPAT_FEATURES 0 +--- src.old/drivers/input/joydev.c 2018-02-26 11:07:49.470610407 -0500 ++++ src/drivers/input/joydev.c 2018-03-05 11:18:13.998015449 -0500 +@@ -954,3 +954,47 @@ static void __exit joydev_exit(void) + + module_init(joydev_init); + module_exit(joydev_exit); ++ ++#include ++#include "kpatch-macros.h" ++ ++static const char *const module_state[] = { ++ [MODULE_STATE_LIVE] = "[MODULE_STATE_LIVE] Normal state", ++ [MODULE_STATE_COMING] = "[MODULE_STATE_COMING] Full formed, running module_init", ++ [MODULE_STATE_GOING] = "[MODULE_STATE_GOING] Going away", ++ [MODULE_STATE_UNFORMED] = "[MODULE_STATE_UNFORMED] Still setting it up", ++}; ++ ++static void callback_info(const char *callback, patch_object *obj) ++{ ++ if (obj->mod) ++ pr_info("%s: %s -> %s\n", callback, obj->mod->name, ++ module_state[obj->mod->state]); ++ else ++ pr_info("%s: vmlinux\n", callback); ++} ++ ++static int pre_patch_callback(patch_object *obj) ++{ ++ callback_info(__func__, obj); ++ return 0; /* return -ENODEV; */ ++} ++KPATCH_PRE_PATCH_CALLBACK(pre_patch_callback); ++ ++static void post_patch_callback(patch_object *obj) ++{ ++ callback_info(__func__, obj); ++} ++KPATCH_POST_PATCH_CALLBACK(post_patch_callback); ++ ++static void pre_unpatch_callback(patch_object *obj) ++{ ++ callback_info(__func__, obj); ++} ++KPATCH_PRE_UNPATCH_CALLBACK(pre_unpatch_callback); ++ ++static void post_unpatch_callback(patch_object *obj) ++{ ++ callback_info(__func__, obj); ++} ++KPATCH_POST_UNPATCH_CALLBACK(post_unpatch_callback); +--- src.old/drivers/input/misc/pcspkr.c 2018-02-26 11:07:49.477610407 -0500 ++++ src/drivers/input/misc/pcspkr.c 2018-03-05 11:18:23.411015449 -0500 +@@ -136,3 +136,46 @@ static struct platform_driver pcspkr_pla + }; + module_platform_driver(pcspkr_platform_driver); + ++#include ++#include "kpatch-macros.h" ++ ++static const char *const module_state[] = { ++ [MODULE_STATE_LIVE] = "[MODULE_STATE_LIVE] Normal state", ++ [MODULE_STATE_COMING] = "[MODULE_STATE_COMING] Full formed, running module_init", ++ [MODULE_STATE_GOING] = "[MODULE_STATE_GOING] Going away", ++ [MODULE_STATE_UNFORMED] = "[MODULE_STATE_UNFORMED] Still setting it up", ++}; ++ ++static void callback_info(const char *callback, patch_object *obj) ++{ ++ if (obj->mod) ++ pr_info("%s: %s -> %s\n", callback, obj->mod->name, ++ module_state[obj->mod->state]); ++ else ++ pr_info("%s: vmlinux\n", callback); ++} ++ ++static int pre_patch_callback(patch_object *obj) ++{ ++ callback_info(__func__, obj); ++ return 0; ++} ++KPATCH_PRE_PATCH_CALLBACK(pre_patch_callback); ++ ++static void post_patch_callback(patch_object *obj) ++{ ++ callback_info(__func__, obj); ++} ++KPATCH_POST_PATCH_CALLBACK(post_patch_callback); ++ ++static void pre_unpatch_callback(patch_object *obj) ++{ ++ callback_info(__func__, obj); ++} ++KPATCH_PRE_UNPATCH_CALLBACK(pre_unpatch_callback); ++ ++static void post_unpatch_callback(patch_object *obj) ++{ ++ callback_info(__func__, obj); ++} ++KPATCH_POST_UNPATCH_CALLBACK(post_unpatch_callback); diff -Nru kpatch-0.5.0/test/integration/rhel-7.4/macro-printk.patch kpatch-0.8.0/test/integration/rhel-7.4/macro-printk.patch --- kpatch-0.5.0/test/integration/rhel-7.4/macro-printk.patch 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/test/integration/rhel-7.4/macro-printk.patch 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1,147 @@ +diff -Nupr src.orig/net/ipv4/fib_frontend.c src/net/ipv4/fib_frontend.c +--- src.orig/net/ipv4/fib_frontend.c 2017-09-22 16:52:10.646110299 -0400 ++++ src/net/ipv4/fib_frontend.c 2017-09-22 16:55:14.395870305 -0400 +@@ -633,6 +633,7 @@ errout: + return err; + } + ++#include "kpatch-macros.h" + static int inet_rtm_newroute(struct sk_buff *skb, struct nlmsghdr *nlh) + { + struct net *net = sock_net(skb->sk); +@@ -651,6 +652,7 @@ static int inet_rtm_newroute(struct sk_b + } + + err = fib_table_insert(net, tb, &cfg); ++ KPATCH_PRINTK("[inet_rtm_newroute]: err is %d\n", err); + errout: + return err; + } +diff -Nupr src.orig/net/ipv4/fib_semantics.c src/net/ipv4/fib_semantics.c +--- src.orig/net/ipv4/fib_semantics.c 2017-09-22 16:52:10.645110295 -0400 ++++ src/net/ipv4/fib_semantics.c 2017-09-22 16:54:05.175584004 -0400 +@@ -925,6 +925,7 @@ fib_convert_metrics(struct fib_info *fi, + return 0; + } + ++#include "kpatch-macros.h" + struct fib_info *fib_create_info(struct fib_config *cfg) + { + int err; +@@ -949,6 +950,7 @@ struct fib_info *fib_create_info(struct + #endif + + err = -ENOBUFS; ++ KPATCH_PRINTK("[fib_create_info]: create error err is %d\n",err); + if (fib_info_cnt >= fib_info_hash_size) { + unsigned int new_size = fib_info_hash_size << 1; + struct hlist_head *new_info_hash; +@@ -969,6 +971,7 @@ struct fib_info *fib_create_info(struct + if (!fib_info_hash_size) + goto failure; + } ++ KPATCH_PRINTK("[fib_create_info]: 2 create error err is %d\n",err); + + fi = kzalloc(sizeof(*fi)+nhs*sizeof(struct fib_nh), GFP_KERNEL); + if (fi == NULL) +@@ -980,6 +983,7 @@ struct fib_info *fib_create_info(struct + } else + fi->fib_metrics = (u32 *) dst_default_metrics; + fib_info_cnt++; ++ KPATCH_PRINTK("[fib_create_info]: 3 create error err is %d\n",err); + + fi->fib_net = net; + fi->fib_protocol = cfg->fc_protocol; +@@ -996,8 +1000,10 @@ struct fib_info *fib_create_info(struct + if (!nexthop_nh->nh_pcpu_rth_output) + goto failure; + } endfor_nexthops(fi) ++ KPATCH_PRINTK("[fib_create_info]: 4 create error err is %d\n",err); + + err = fib_convert_metrics(fi, cfg); ++ KPATCH_PRINTK("[fib_create_info]: 5 create error err is %d\n",err); + if (err) + goto failure; + +@@ -1048,6 +1054,7 @@ struct fib_info *fib_create_info(struct + nh->nh_weight = 1; + #endif + } ++ KPATCH_PRINTK("[fib_create_info]: 6 create error err is %d\n",err); + + if (fib_props[cfg->fc_type].error) { + if (cfg->fc_gw || cfg->fc_oif || cfg->fc_mp) +@@ -1065,6 +1072,7 @@ struct fib_info *fib_create_info(struct + goto err_inval; + } + } ++ KPATCH_PRINTK("[fib_create_info]: 7 create error err is %d\n",err); + + if (cfg->fc_scope > RT_SCOPE_HOST) + goto err_inval; +@@ -1087,6 +1095,7 @@ struct fib_info *fib_create_info(struct + goto failure; + } endfor_nexthops(fi) + } ++ KPATCH_PRINTK("[fib_create_info]: 8 create error err is %d\n",err); + + if (fi->fib_prefsrc) { + if (cfg->fc_type != RTN_LOCAL || !cfg->fc_dst || +@@ -1099,6 +1108,7 @@ struct fib_info *fib_create_info(struct + fib_info_update_nh_saddr(net, nexthop_nh); + fib_add_weight(fi, nexthop_nh); + } endfor_nexthops(fi) ++ KPATCH_PRINTK("[fib_create_info]: 9 create error err is %d\n",err); + + fib_rebalance(fi); + +@@ -1110,6 +1120,7 @@ link_it: + ofi->fib_treeref++; + return ofi; + } ++ KPATCH_PRINTK("[fib_create_info]: 10 create error err is %d\n",err); + + fi->fib_treeref++; + atomic_inc(&fi->fib_clntref); +@@ -1133,6 +1144,7 @@ link_it: + hlist_add_head(&nexthop_nh->nh_hash, head); + } endfor_nexthops(fi) + spin_unlock_bh(&fib_info_lock); ++ KPATCH_PRINTK("[fib_create_info]: 11 create error err is %d\n",err); + return fi; + + err_inval: +@@ -1143,6 +1155,7 @@ failure: + fi->fib_dead = 1; + free_fib_info(fi); + } ++ KPATCH_PRINTK("[fib_create_info]: 12 create error err is %d\n",err); + + return ERR_PTR(err); + } +diff -Nupr src.orig/net/ipv4/fib_trie.c src/net/ipv4/fib_trie.c +--- src.orig/net/ipv4/fib_trie.c 2017-09-22 16:52:10.645110295 -0400 ++++ src/net/ipv4/fib_trie.c 2017-09-22 16:55:39.940975963 -0400 +@@ -1191,6 +1191,7 @@ static int fib_insert_alias(struct trie + } + + /* Caller must hold RTNL. */ ++#include "kpatch-macros.h" + int fib_table_insert(struct net *net, struct fib_table *tb, + struct fib_config *cfg) + { +@@ -1216,11 +1217,14 @@ int fib_table_insert(struct net *net, st + if ((plen < KEYLENGTH) && (key << plen)) + return -EINVAL; + ++ KPATCH_PRINTK("[fib_table_insert]: start\n"); + fi = fib_create_info(cfg); + if (IS_ERR(fi)) { + err = PTR_ERR(fi); ++ KPATCH_PRINTK("[fib_table_insert]: create error err is %d\n",err); + goto err; + } ++ KPATCH_PRINTK("[fib_table_insert]: cross\n"); + + l = fib_find_node(t, &tp, key); + fa = l ? fib_find_alias(&l->leaf, slen, tos, fi->fib_priority) : NULL; diff -Nru kpatch-0.5.0/test/integration/rhel-7.4/meminfo-init2-FAIL.patch kpatch-0.8.0/test/integration/rhel-7.4/meminfo-init2-FAIL.patch --- kpatch-0.5.0/test/integration/rhel-7.4/meminfo-init2-FAIL.patch 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/test/integration/rhel-7.4/meminfo-init2-FAIL.patch 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1,19 @@ +diff -Nupr src.orig/fs/proc/meminfo.c src/fs/proc/meminfo.c +--- src.orig/fs/proc/meminfo.c 2017-09-22 15:27:21.699056179 -0400 ++++ src/fs/proc/meminfo.c 2017-09-22 15:27:38.972127707 -0400 +@@ -30,6 +30,7 @@ static int meminfo_proc_show(struct seq_ + unsigned long pages[NR_LRU_LISTS]; + int lru; + ++ printk("a\n"); + /* + * display in kilobytes. + */ +@@ -191,6 +192,7 @@ static const struct file_operations memi + + static int __init proc_meminfo_init(void) + { ++ printk("a\n"); + proc_create("meminfo", 0, NULL, &meminfo_proc_fops); + return 0; + } diff -Nru kpatch-0.5.0/test/integration/rhel-7.4/meminfo-init-FAIL.patch kpatch-0.8.0/test/integration/rhel-7.4/meminfo-init-FAIL.patch --- kpatch-0.5.0/test/integration/rhel-7.4/meminfo-init-FAIL.patch 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/test/integration/rhel-7.4/meminfo-init-FAIL.patch 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1,11 @@ +diff -Nupr src.orig/fs/proc/meminfo.c src/fs/proc/meminfo.c +--- src.orig/fs/proc/meminfo.c 2017-09-22 15:27:21.699056179 -0400 ++++ src/fs/proc/meminfo.c 2017-09-22 15:27:40.130132502 -0400 +@@ -191,6 +191,7 @@ static const struct file_operations memi + + static int __init proc_meminfo_init(void) + { ++ printk("a\n"); + proc_create("meminfo", 0, NULL, &meminfo_proc_fops); + return 0; + } diff -Nru kpatch-0.5.0/test/integration/rhel-7.4/meminfo-string-LOADED.test kpatch-0.8.0/test/integration/rhel-7.4/meminfo-string-LOADED.test --- kpatch-0.5.0/test/integration/rhel-7.4/meminfo-string-LOADED.test 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/test/integration/rhel-7.4/meminfo-string-LOADED.test 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1,3 @@ +#!/bin/bash + +grep VMALLOCCHUNK /proc/meminfo diff -Nru kpatch-0.5.0/test/integration/rhel-7.4/meminfo-string.patch kpatch-0.8.0/test/integration/rhel-7.4/meminfo-string.patch --- kpatch-0.5.0/test/integration/rhel-7.4/meminfo-string.patch 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/test/integration/rhel-7.4/meminfo-string.patch 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1,12 @@ +diff -Nupr src.orig/fs/proc/meminfo.c src/fs/proc/meminfo.c +--- src.orig/fs/proc/meminfo.c 2017-09-22 15:27:21.699056179 -0400 ++++ src/fs/proc/meminfo.c 2017-09-22 15:27:41.274137239 -0400 +@@ -99,7 +99,7 @@ static int meminfo_proc_show(struct seq_ + "Committed_AS: %8lu kB\n" + "VmallocTotal: %8lu kB\n" + "VmallocUsed: %8lu kB\n" +- "VmallocChunk: %8lu kB\n" ++ "VMALLOCCHUNK: %8lu kB\n" + #ifdef CONFIG_MEMORY_FAILURE + "HardwareCorrupted: %5lu kB\n" + #endif diff -Nru kpatch-0.5.0/test/integration/rhel-7.4/module-call-external.patch kpatch-0.8.0/test/integration/rhel-7.4/module-call-external.patch --- kpatch-0.5.0/test/integration/rhel-7.4/module-call-external.patch 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/test/integration/rhel-7.4/module-call-external.patch 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1,33 @@ +diff -Nupr src.orig/fs/nfsd/export.c src/fs/nfsd/export.c +--- src.orig/fs/nfsd/export.c 2017-09-22 15:27:21.705056204 -0400 ++++ src/fs/nfsd/export.c 2017-09-22 15:27:42.411141948 -0400 +@@ -1184,6 +1184,8 @@ static void exp_flags(struct seq_file *m + } + } + ++extern char *kpatch_string(void); ++ + static int e_show(struct seq_file *m, void *p) + { + struct cache_head *cp = p; +@@ -1193,6 +1195,7 @@ static int e_show(struct seq_file *m, vo + if (p == SEQ_START_TOKEN) { + seq_puts(m, "# Version 1.1\n"); + seq_puts(m, "# Path Client(Flags) # IPs\n"); ++ seq_puts(m, kpatch_string()); + return 0; + } + +diff -Nupr src.orig/net/netlink/af_netlink.c src/net/netlink/af_netlink.c +--- src.orig/net/netlink/af_netlink.c 2017-09-22 15:27:21.754056407 -0400 ++++ src/net/netlink/af_netlink.c 2017-09-22 15:27:42.412141952 -0400 +@@ -3260,4 +3260,9 @@ panic: + panic("netlink_init: Cannot allocate nl_table\n"); + } + ++char *kpatch_string(void) ++{ ++ return "# kpatch\n"; ++} ++ + core_initcall(netlink_proto_init); diff -Nru kpatch-0.5.0/test/integration/rhel-7.4/module-kvm-fixup.patch kpatch-0.8.0/test/integration/rhel-7.4/module-kvm-fixup.patch --- kpatch-0.5.0/test/integration/rhel-7.4/module-kvm-fixup.patch 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/test/integration/rhel-7.4/module-kvm-fixup.patch 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1,12 @@ +diff -Nupr src.orig/arch/x86/kvm/vmx.c src/arch/x86/kvm/vmx.c +--- src.orig/arch/x86/kvm/vmx.c 2017-09-22 15:27:20.853052676 -0400 ++++ src/arch/x86/kvm/vmx.c 2017-09-22 15:27:43.583146801 -0400 +@@ -10597,6 +10597,8 @@ static int vmx_check_intercept(struct kv + struct x86_instruction_info *info, + enum x86_intercept_stage stage) + { ++ if (!jiffies) ++ printk("kpatch vmx_check_intercept\n"); + return X86EMUL_CONTINUE; + } + diff -Nru kpatch-0.5.0/test/integration/rhel-7.4/module-shadow.patch kpatch-0.8.0/test/integration/rhel-7.4/module-shadow.patch --- kpatch-0.5.0/test/integration/rhel-7.4/module-shadow.patch 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/test/integration/rhel-7.4/module-shadow.patch 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1,24 @@ +diff -Nupr src.orig/arch/x86/kvm/vmx.c src/arch/x86/kvm/vmx.c +--- src.orig/arch/x86/kvm/vmx.c 2017-09-22 15:27:20.853052676 -0400 ++++ src/arch/x86/kvm/vmx.c 2017-09-22 15:27:44.742151601 -0400 +@@ -10581,10 +10581,20 @@ static void vmx_leave_nested(struct kvm_ + * It should only be called before L2 actually succeeded to run, and when + * vmcs01 is current (it doesn't leave_guest_mode() or switch vmcss). + */ ++#include "kpatch.h" + static void nested_vmx_entry_failure(struct kvm_vcpu *vcpu, + struct vmcs12 *vmcs12, + u32 reason, unsigned long qualification) + { ++ int *kpatch; ++ ++ kpatch = kpatch_shadow_alloc(vcpu, "kpatch", sizeof(*kpatch), ++ GFP_KERNEL); ++ if (kpatch) { ++ kpatch_shadow_get(vcpu, "kpatch"); ++ kpatch_shadow_free(vcpu, "kpatch"); ++ } ++ + load_vmcs12_host_state(vcpu, vmcs12); + vmcs12->vm_exit_reason = reason | VMX_EXIT_REASONS_FAILED_VMENTRY; + vmcs12->exit_qualification = qualification; diff -Nru kpatch-0.5.0/test/integration/rhel-7.4/multiple.test kpatch-0.8.0/test/integration/rhel-7.4/multiple.test --- kpatch-0.5.0/test/integration/rhel-7.4/multiple.test 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/test/integration/rhel-7.4/multiple.test 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1,64 @@ +#!/bin/bash + +SCRIPTDIR="$(readlink -f $(dirname $(type -p $0)))" +ROOTDIR="$(readlink -f $SCRIPTDIR/../..)" +KPATCH="sudo $ROOTDIR/kpatch/kpatch" + +MODULE_PREFIX="test-" +MODULE_POSTFIX=".ko" +TEST_POSTFIX="-LOADED.test" + +set -o errexit + +die() { + echo "ERROR: $@" >&2 + exit 1 +} + +ko_to_test() { + tmp=${1%${MODULE_POSTFIX}}${TEST_POSTFIX} + echo ${tmp#${MODULE_PREFIX}} +} + +# make sure any modules added here are disjoint +declare -a modules +declare -a blacklist=(meminfo-string-LOADED.test) + +for file in "${SCRIPTDIR}"/*"${TEST_POSTFIX}"; do + name=$(basename ${file}) + skip=0 + for bname in "${blacklist[@]}"; do + if [ "${bname}" == "${name}" ]; then + skip=1 + break + fi + done + if [ ${skip} -eq 0 ]; then + modules+=(${MODULE_PREFIX}${name%${TEST_POSTFIX}}${MODULE_POSTFIX}) + fi +done + +for mod in "${modules[@]}"; do + testprog=$(ko_to_test $mod) + $SCRIPTDIR/$testprog && die "$SCRIPTDIR/$testprog succeeded before loading any modules" +done + +for mod in "${modules[@]}"; do + $KPATCH load $mod +done + +for mod in "${modules[@]}"; do + testprog=$(ko_to_test $mod) + $SCRIPTDIR/$testprog || die "$SCRIPTDIR/$testprog failed after loading modules" +done + +for mod in "${modules[@]}"; do + $KPATCH unload $mod +done + +for mod in "${modules[@]}"; do + testprog=$(ko_to_test $mod) + $SCRIPTDIR/$testprog && die "$SCRIPTDIR/$testprog succeeded after unloading modules" +done + +exit 0 diff -Nru kpatch-0.5.0/test/integration/rhel-7.4/new-function.patch kpatch-0.8.0/test/integration/rhel-7.4/new-function.patch --- kpatch-0.5.0/test/integration/rhel-7.4/new-function.patch 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/test/integration/rhel-7.4/new-function.patch 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1,25 @@ +diff -Nupr src.orig/drivers/tty/n_tty.c src/drivers/tty/n_tty.c +--- src.orig/drivers/tty/n_tty.c 2017-09-22 15:27:21.084053633 -0400 ++++ src/drivers/tty/n_tty.c 2017-09-22 15:27:45.888156346 -0400 +@@ -2016,7 +2016,7 @@ do_it_again: + * lock themselves) + */ + +-static ssize_t n_tty_write(struct tty_struct *tty, struct file *file, ++static ssize_t noinline kpatch_n_tty_write(struct tty_struct *tty, struct file *file, + const unsigned char *buf, size_t nr) + { + const unsigned char *b = buf; +@@ -2098,6 +2098,12 @@ break_out: + return (b - buf) ? b - buf : retval; + } + ++static ssize_t n_tty_write(struct tty_struct *tty, struct file *file, ++ const unsigned char *buf, size_t nr) ++{ ++ return kpatch_n_tty_write(tty, file, buf, nr); ++} ++ + /** + * n_tty_poll - poll method for N_TTY + * @tty: terminal device diff -Nru kpatch-0.5.0/test/integration/rhel-7.4/new-globals.patch kpatch-0.8.0/test/integration/rhel-7.4/new-globals.patch --- kpatch-0.5.0/test/integration/rhel-7.4/new-globals.patch 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/test/integration/rhel-7.4/new-globals.patch 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1,34 @@ +diff -Nupr src.orig/fs/proc/cmdline.c src/fs/proc/cmdline.c +--- src.orig/fs/proc/cmdline.c 2017-09-22 15:27:21.698056175 -0400 ++++ src/fs/proc/cmdline.c 2017-09-22 15:27:47.028161067 -0400 +@@ -27,3 +27,10 @@ static int __init proc_cmdline_init(void + return 0; + } + module_init(proc_cmdline_init); ++ ++#include ++void kpatch_print_message(void) ++{ ++ if (!jiffies) ++ printk("hello there!\n"); ++} +diff -Nupr src.orig/fs/proc/meminfo.c src/fs/proc/meminfo.c +--- src.orig/fs/proc/meminfo.c 2017-09-22 15:27:21.699056179 -0400 ++++ src/fs/proc/meminfo.c 2017-09-22 15:27:47.029161071 -0400 +@@ -16,6 +16,8 @@ + #include + #include "internal.h" + ++void kpatch_print_message(void); ++ + void __attribute__((weak)) arch_report_meminfo(struct seq_file *m) + { + } +@@ -53,6 +55,7 @@ static int meminfo_proc_show(struct seq_ + /* + * Tagged format, for easy grepping and expansion. + */ ++ kpatch_print_message(); + seq_printf(m, + "MemTotal: %8lu kB\n" + "MemFree: %8lu kB\n" diff -Nru kpatch-0.5.0/test/integration/rhel-7.4/parainstructions-section.patch kpatch-0.8.0/test/integration/rhel-7.4/parainstructions-section.patch --- kpatch-0.5.0/test/integration/rhel-7.4/parainstructions-section.patch 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/test/integration/rhel-7.4/parainstructions-section.patch 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1,11 @@ +diff -Nupr src.orig/fs/proc/generic.c src/fs/proc/generic.c +--- src.orig/fs/proc/generic.c 2017-09-22 15:27:21.698056175 -0400 ++++ src/fs/proc/generic.c 2017-09-22 15:27:48.190165879 -0400 +@@ -194,6 +194,7 @@ int proc_alloc_inum(unsigned int *inum) + unsigned int i; + int error; + ++ printk("kpatch-test: testing change to .parainstructions section\n"); + retry: + if (!ida_pre_get(&proc_inum_ida, GFP_KERNEL)) + return -ENOMEM; diff -Nru kpatch-0.5.0/test/integration/rhel-7.4/replace-section-references.patch kpatch-0.8.0/test/integration/rhel-7.4/replace-section-references.patch --- kpatch-0.5.0/test/integration/rhel-7.4/replace-section-references.patch 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/test/integration/rhel-7.4/replace-section-references.patch 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1,12 @@ +diff -Nupr src.orig/arch/x86/kvm/x86.c src/arch/x86/kvm/x86.c +--- src.orig/arch/x86/kvm/x86.c 2017-09-22 15:27:20.852052672 -0400 ++++ src/arch/x86/kvm/x86.c 2017-09-22 15:27:49.362170732 -0400 +@@ -248,6 +248,8 @@ static void shared_msr_update(unsigned s + + void kvm_define_shared_msr(unsigned slot, u32 msr) + { ++ if (!jiffies) ++ printk("kpatch kvm define shared msr\n"); + BUG_ON(slot >= KVM_NR_SHARED_MSRS); + shared_msrs_global.msrs[slot] = msr; + if (slot >= shared_msrs_global.nr) diff -Nru kpatch-0.5.0/test/integration/rhel-7.4/shadow-newpid-LOADED.test kpatch-0.8.0/test/integration/rhel-7.4/shadow-newpid-LOADED.test --- kpatch-0.5.0/test/integration/rhel-7.4/shadow-newpid-LOADED.test 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/test/integration/rhel-7.4/shadow-newpid-LOADED.test 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1,3 @@ +#!/bin/bash + +grep -q newpid: /proc/$$/status diff -Nru kpatch-0.5.0/test/integration/rhel-7.4/shadow-newpid.patch kpatch-0.8.0/test/integration/rhel-7.4/shadow-newpid.patch --- kpatch-0.5.0/test/integration/rhel-7.4/shadow-newpid.patch 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/test/integration/rhel-7.4/shadow-newpid.patch 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1,69 @@ +diff -Nupr src.orig/fs/proc/array.c src/fs/proc/array.c +--- src.orig/fs/proc/array.c 2017-09-22 16:52:10.597110096 -0400 ++++ src/fs/proc/array.c 2017-09-22 16:59:40.799972178 -0400 +@@ -359,13 +359,20 @@ static inline void task_seccomp(struct s + #endif + } + ++#include "kpatch.h" + static inline void task_context_switch_counts(struct seq_file *m, + struct task_struct *p) + { ++ int *newpid; ++ + seq_printf(m, "voluntary_ctxt_switches:\t%lu\n" + "nonvoluntary_ctxt_switches:\t%lu\n", + p->nvcsw, + p->nivcsw); ++ ++ newpid = kpatch_shadow_get(p, "newpid"); ++ if (newpid) ++ seq_printf(m, "newpid:\t%d\n", *newpid); + } + + static void task_cpus_allowed(struct seq_file *m, struct task_struct *task) +diff -Nupr src.orig/kernel/exit.c src/kernel/exit.c +--- src.orig/kernel/exit.c 2017-09-22 16:52:10.506109720 -0400 ++++ src/kernel/exit.c 2017-09-22 16:59:40.799972178 -0400 +@@ -715,6 +715,7 @@ static void check_stack_usage(void) + static inline void check_stack_usage(void) {} + #endif + ++#include "kpatch.h" + void do_exit(long code) + { + struct task_struct *tsk = current; +@@ -812,6 +813,8 @@ void do_exit(long code) + check_stack_usage(); + exit_thread(); + ++ kpatch_shadow_free(tsk, "newpid"); ++ + /* + * Flush inherited counters to the parent - before the parent + * gets woken up by child-exit notifications. +diff -Nupr src.orig/kernel/fork.c src/kernel/fork.c +--- src.orig/kernel/fork.c 2017-09-22 16:52:10.504109711 -0400 ++++ src/kernel/fork.c 2017-09-22 17:00:44.938237460 -0400 +@@ -1700,6 +1700,7 @@ struct task_struct *fork_idle(int cpu) + * It copies the process, and if successful kick-starts + * it and waits for it to finish using the VM if required. + */ ++#include "kpatch.h" + long do_fork(unsigned long clone_flags, + unsigned long stack_start, + unsigned long stack_size, +@@ -1737,6 +1738,13 @@ long do_fork(unsigned long clone_flags, + if (!IS_ERR(p)) { + struct completion vfork; + struct pid *pid; ++ int *newpid; ++ static int ctr = 0; ++ ++ newpid = kpatch_shadow_alloc(p, "newpid", sizeof(*newpid), ++ GFP_KERNEL); ++ if (newpid) ++ *newpid = ctr++; + + trace_sched_process_fork(current, p); + diff -Nru kpatch-0.5.0/test/integration/rhel-7.4/smp-locks-section.patch kpatch-0.8.0/test/integration/rhel-7.4/smp-locks-section.patch --- kpatch-0.5.0/test/integration/rhel-7.4/smp-locks-section.patch 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/test/integration/rhel-7.4/smp-locks-section.patch 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1,14 @@ +diff -Nupr src.orig/drivers/tty/tty_buffer.c src/drivers/tty/tty_buffer.c +--- src.orig/drivers/tty/tty_buffer.c 2017-09-22 15:27:21.077053604 -0400 ++++ src/drivers/tty/tty_buffer.c 2017-09-22 15:27:50.542175618 -0400 +@@ -217,6 +217,10 @@ int tty_buffer_request_room(struct tty_p + /* OPTIMISATION: We could keep a per tty "zero" sized buffer to + remove this conditional if its worth it. This would be invisible + to the callers */ ++ ++ if (!size) ++ printk("kpatch-test: testing .smp_locks section changes\n"); ++ + b = buf->tail; + if (b != NULL) + left = b->size - b->used; diff -Nru kpatch-0.5.0/test/integration/rhel-7.4/special-static-2.patch kpatch-0.8.0/test/integration/rhel-7.4/special-static-2.patch --- kpatch-0.5.0/test/integration/rhel-7.4/special-static-2.patch 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/test/integration/rhel-7.4/special-static-2.patch 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1,24 @@ +diff -Nupr src.orig/arch/x86/kvm/x86.c src/arch/x86/kvm/x86.c +--- src.orig/arch/x86/kvm/x86.c 2017-09-22 15:27:20.852052672 -0400 ++++ src/arch/x86/kvm/x86.c 2017-09-22 15:27:51.744180596 -0400 +@@ -2093,12 +2093,20 @@ static void record_steal_time(struct kvm + &vcpu->arch.st.steal, sizeof(struct kvm_steal_time)); + } + ++void kpatch_kvm_x86_foo(void) ++{ ++ if (!jiffies) ++ printk("kpatch kvm x86 foo\n"); ++} ++ + int kvm_set_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info) + { + bool pr = false; + u32 msr = msr_info->index; + u64 data = msr_info->data; + ++ kpatch_kvm_x86_foo(); ++ + switch (msr) { + case MSR_AMD64_NB_CFG: + case MSR_IA32_UCODE_REV: diff -Nru kpatch-0.5.0/test/integration/rhel-7.4/special-static.patch kpatch-0.8.0/test/integration/rhel-7.4/special-static.patch --- kpatch-0.5.0/test/integration/rhel-7.4/special-static.patch 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/test/integration/rhel-7.4/special-static.patch 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1,22 @@ +diff -Nupr src.orig/kernel/fork.c src/kernel/fork.c +--- src.orig/kernel/fork.c 2017-09-22 15:27:21.600055769 -0400 ++++ src/kernel/fork.c 2017-09-22 15:27:53.052186012 -0400 +@@ -1129,10 +1129,18 @@ static void posix_cpu_timers_init_group( + INIT_LIST_HEAD(&sig->cpu_timers[2]); + } + ++void kpatch_foo(void) ++{ ++ if (!jiffies) ++ printk("kpatch copy signal\n"); ++} ++ + static int copy_signal(unsigned long clone_flags, struct task_struct *tsk) + { + struct signal_struct *sig; + ++ kpatch_foo(); ++ + if (clone_flags & CLONE_THREAD) + return 0; + diff -Nru kpatch-0.5.0/test/integration/rhel-7.4/tracepoints-section.patch kpatch-0.8.0/test/integration/rhel-7.4/tracepoints-section.patch --- kpatch-0.5.0/test/integration/rhel-7.4/tracepoints-section.patch 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/test/integration/rhel-7.4/tracepoints-section.patch 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1,13 @@ +diff -Nupr src.orig/kernel/timer.c src/kernel/timer.c +--- src.orig/kernel/timer.c 2017-09-22 15:27:21.600055769 -0400 ++++ src/kernel/timer.c 2017-09-22 15:27:54.288191131 -0400 +@@ -1390,6 +1390,9 @@ static void run_timer_softirq(struct sof + { + struct tvec_base *base = __this_cpu_read(tvec_bases); + ++ if (!base) ++ printk("kpatch-test: testing __tracepoints section changes\n"); ++ + if (time_after_eq(jiffies, base->timer_jiffies)) + __run_timers(base); + } diff -Nru kpatch-0.5.0/test/integration/rhel-7.4/warn-detect-FAIL.patch kpatch-0.8.0/test/integration/rhel-7.4/warn-detect-FAIL.patch --- kpatch-0.5.0/test/integration/rhel-7.4/warn-detect-FAIL.patch 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/test/integration/rhel-7.4/warn-detect-FAIL.patch 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1,8 @@ +diff -Nupr src.orig/arch/x86/kvm/x86.c src/arch/x86/kvm/x86.c +--- src.orig/arch/x86/kvm/x86.c 2017-09-22 15:27:20.852052672 -0400 ++++ src/arch/x86/kvm/x86.c 2017-09-22 15:27:55.489196104 -0400 +@@ -1,3 +1,4 @@ ++ + /* + * Kernel-based Virtual Machine driver for Linux + * diff -Nru kpatch-0.5.0/test/integration/rhel-7.5/bug-table-section.patch kpatch-0.8.0/test/integration/rhel-7.5/bug-table-section.patch --- kpatch-0.5.0/test/integration/rhel-7.5/bug-table-section.patch 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/test/integration/rhel-7.5/bug-table-section.patch 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1,12 @@ +diff -Nupr src.orig/fs/proc/proc_sysctl.c src/fs/proc/proc_sysctl.c +--- src.orig/fs/proc/proc_sysctl.c 2017-09-22 15:27:21.698056175 -0400 ++++ src/fs/proc/proc_sysctl.c 2017-09-22 15:27:21.769056469 -0400 +@@ -266,6 +266,8 @@ void sysctl_head_put(struct ctl_table_he + + static struct ctl_table_header *sysctl_head_grab(struct ctl_table_header *head) + { ++ if (jiffies == 0) ++ printk("kpatch-test: testing __bug_table section changes\n"); + BUG_ON(!head); + spin_lock(&sysctl_lock); + if (!use_table(head)) diff -Nru kpatch-0.5.0/test/integration/rhel-7.5/cmdline-string-LOADED.test kpatch-0.8.0/test/integration/rhel-7.5/cmdline-string-LOADED.test --- kpatch-0.5.0/test/integration/rhel-7.5/cmdline-string-LOADED.test 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/test/integration/rhel-7.5/cmdline-string-LOADED.test 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1,3 @@ +#!/bin/bash + +grep kpatch=1 /proc/cmdline diff -Nru kpatch-0.5.0/test/integration/rhel-7.5/cmdline-string.patch kpatch-0.8.0/test/integration/rhel-7.5/cmdline-string.patch --- kpatch-0.5.0/test/integration/rhel-7.5/cmdline-string.patch 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/test/integration/rhel-7.5/cmdline-string.patch 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1,12 @@ +diff -Nupr src.orig/fs/proc/cmdline.c src/fs/proc/cmdline.c +--- src.orig/fs/proc/cmdline.c 2017-09-22 15:27:21.698056175 -0400 ++++ src/fs/proc/cmdline.c 2017-09-22 15:27:22.955061380 -0400 +@@ -5,7 +5,7 @@ + + static int cmdline_proc_show(struct seq_file *m, void *v) + { +- seq_printf(m, "%s\n", saved_command_line); ++ seq_printf(m, "%s kpatch=1\n", saved_command_line); + return 0; + } + diff -Nru kpatch-0.5.0/test/integration/rhel-7.5/data-new-LOADED.test kpatch-0.8.0/test/integration/rhel-7.5/data-new-LOADED.test --- kpatch-0.5.0/test/integration/rhel-7.5/data-new-LOADED.test 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/test/integration/rhel-7.5/data-new-LOADED.test 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1,3 @@ +#!/bin/bash + +grep "kpatch: 5" /proc/meminfo diff -Nru kpatch-0.5.0/test/integration/rhel-7.5/data-new.patch kpatch-0.8.0/test/integration/rhel-7.5/data-new.patch --- kpatch-0.5.0/test/integration/rhel-7.5/data-new.patch 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/test/integration/rhel-7.5/data-new.patch 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1,28 @@ +diff -Nupr src.orig/fs/proc/meminfo.c src/fs/proc/meminfo.c +--- src.orig/fs/proc/meminfo.c 2017-09-22 15:27:21.699056179 -0400 ++++ src/fs/proc/meminfo.c 2017-09-22 15:27:24.102066130 -0400 +@@ -20,6 +20,8 @@ void __attribute__((weak)) arch_report_m + { + } + ++static int foo = 5; ++ + static int meminfo_proc_show(struct seq_file *m, void *v) + { + struct sysinfo i; +@@ -106,6 +108,7 @@ static int meminfo_proc_show(struct seq_ + #ifdef CONFIG_TRANSPARENT_HUGEPAGE + "AnonHugePages: %8lu kB\n" + #endif ++ "kpatch: %d" + , + K(i.totalram), + K(i.freeram), +@@ -167,6 +170,7 @@ static int meminfo_proc_show(struct seq_ + ,K(global_page_state(NR_ANON_TRANSPARENT_HUGEPAGES) * + HPAGE_PMD_NR) + #endif ++ ,foo + ); + + hugetlb_report_meminfo(m); diff -Nru kpatch-0.5.0/test/integration/rhel-7.5/data-read-mostly.patch kpatch-0.8.0/test/integration/rhel-7.5/data-read-mostly.patch --- kpatch-0.5.0/test/integration/rhel-7.5/data-read-mostly.patch 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/test/integration/rhel-7.5/data-read-mostly.patch 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1,11 @@ +diff -Nupr src.orig/net/core/dev.c src/net/core/dev.c +--- src.orig/net/core/dev.c 2017-09-22 15:27:21.759056428 -0400 ++++ src/net/core/dev.c 2017-09-22 15:27:25.244070859 -0400 +@@ -4012,6 +4012,7 @@ ncls: + case RX_HANDLER_PASS: + break; + default: ++ printk("BUG!\n"); + BUG(); + } + } diff -Nru kpatch-0.5.0/test/integration/rhel-7.5/fixup-section.patch kpatch-0.8.0/test/integration/rhel-7.5/fixup-section.patch --- kpatch-0.5.0/test/integration/rhel-7.5/fixup-section.patch 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/test/integration/rhel-7.5/fixup-section.patch 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1,12 @@ +diff --git a/fs/readdir.c b/fs/readdir.c +index febd02dfbe2d..064db7bd70d0 100644 +--- a/fs/readdir.c ++++ b/fs/readdir.c +@@ -176,6 +176,7 @@ static int filldir(void * __buf, const char * name, int namlen, loff_t offset, + goto efault; + } + dirent = buf->current_dir; ++ asm("nop"); + if (__put_user(d_ino, &dirent->d_ino)) + goto efault; + if (__put_user(reclen, &dirent->d_reclen)) diff -Nru kpatch-0.5.0/test/integration/rhel-7.5/gcc-constprop.patch kpatch-0.8.0/test/integration/rhel-7.5/gcc-constprop.patch --- kpatch-0.5.0/test/integration/rhel-7.5/gcc-constprop.patch 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/test/integration/rhel-7.5/gcc-constprop.patch 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1,13 @@ +diff -Nupr src.orig/kernel/time/timekeeping.c src/kernel/time/timekeeping.c +--- src.orig/kernel/time/timekeeping.c 2017-09-22 15:27:21.602055778 -0400 ++++ src/kernel/time/timekeeping.c 2017-09-22 15:27:27.522080292 -0400 +@@ -877,6 +877,9 @@ void do_gettimeofday(struct timeval *tv) + { + struct timespec64 now; + ++ if (!tv) ++ return; ++ + getnstimeofday64(&now); + tv->tv_sec = now.tv_sec; + tv->tv_usec = now.tv_nsec/1000; diff -Nru kpatch-0.5.0/test/integration/rhel-7.5/gcc-isra.patch kpatch-0.8.0/test/integration/rhel-7.5/gcc-isra.patch --- kpatch-0.5.0/test/integration/rhel-7.5/gcc-isra.patch 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/test/integration/rhel-7.5/gcc-isra.patch 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1,11 @@ +diff -Nupr src.orig/fs/proc/proc_sysctl.c src/fs/proc/proc_sysctl.c +--- src.orig/fs/proc/proc_sysctl.c 2017-09-22 15:27:21.698056175 -0400 ++++ src/fs/proc/proc_sysctl.c 2017-09-22 15:27:28.670085046 -0400 +@@ -24,6 +24,7 @@ void proc_sys_poll_notify(struct ctl_tab + if (!poll) + return; + ++ printk("kpatch-test: testing gcc .isra function name mangling\n"); + atomic_inc(&poll->event); + wake_up_interruptible(&poll->wait); + } diff -Nru kpatch-0.5.0/test/integration/rhel-7.5/gcc-mangled-3.patch kpatch-0.8.0/test/integration/rhel-7.5/gcc-mangled-3.patch --- kpatch-0.5.0/test/integration/rhel-7.5/gcc-mangled-3.patch 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/test/integration/rhel-7.5/gcc-mangled-3.patch 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1,13 @@ +diff -Nupr src.orig/mm/slub.c src/mm/slub.c +--- src.orig/mm/slub.c 2017-09-22 15:27:21.618055844 -0400 ++++ src/mm/slub.c 2017-09-22 15:27:29.830089850 -0400 +@@ -5528,6 +5528,9 @@ void get_slabinfo(struct kmem_cache *s, + unsigned long nr_free = 0; + int node; + ++ if (!jiffies) ++ printk("slabinfo\n"); ++ + for_each_online_node(node) { + struct kmem_cache_node *n = get_node(s, node); + diff -Nru kpatch-0.5.0/test/integration/rhel-7.5/gcc-static-local-var-2.patch kpatch-0.8.0/test/integration/rhel-7.5/gcc-static-local-var-2.patch --- kpatch-0.5.0/test/integration/rhel-7.5/gcc-static-local-var-2.patch 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/test/integration/rhel-7.5/gcc-static-local-var-2.patch 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1,13 @@ +diff -Nupr src.orig/mm/mmap.c src/mm/mmap.c +--- src.orig/mm/mmap.c 2017-09-22 15:27:21.618055844 -0400 ++++ src/mm/mmap.c 2017-09-22 15:27:31.024094794 -0400 +@@ -1687,6 +1688,9 @@ unsigned long mmap_region(struct file *f + struct rb_node **rb_link, *rb_parent; + unsigned long charged = 0; + ++ if (!jiffies) ++ printk("kpatch mmap foo\n"); ++ + /* Check against address space limit. */ + if (!may_expand_vm(mm, len >> PAGE_SHIFT)) { + unsigned long nr_pages; diff -Nru kpatch-0.5.0/test/integration/rhel-7.5/gcc-static-local-var-3.patch kpatch-0.8.0/test/integration/rhel-7.5/gcc-static-local-var-3.patch --- kpatch-0.5.0/test/integration/rhel-7.5/gcc-static-local-var-3.patch 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/test/integration/rhel-7.5/gcc-static-local-var-3.patch 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1,19 @@ +diff -Nupr src.orig/kernel/sys.c src/kernel/sys.c +--- src.orig/kernel/sys.c 2017-09-22 15:27:21.601055773 -0400 ++++ src/kernel/sys.c 2017-09-22 15:27:32.170099540 -0400 +@@ -554,8 +554,15 @@ SYSCALL_DEFINE4(reboot, int, magic1, int + return ret; + } + ++void kpatch_bar(void) ++{ ++ if (!jiffies) ++ printk("kpatch_foo\n"); ++} ++ + static void deferred_cad(struct work_struct *dummy) + { ++ kpatch_bar(); + kernel_restart(NULL); + } + diff -Nru kpatch-0.5.0/test/integration/rhel-7.5/gcc-static-local-var-4.patch kpatch-0.8.0/test/integration/rhel-7.5/gcc-static-local-var-4.patch --- kpatch-0.5.0/test/integration/rhel-7.5/gcc-static-local-var-4.patch 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/test/integration/rhel-7.5/gcc-static-local-var-4.patch 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1,20 @@ +diff -Nupr src.orig/fs/aio.c src/fs/aio.c +--- src.orig/fs/aio.c 2017-09-22 15:27:21.702056192 -0400 ++++ src/fs/aio.c 2017-09-22 15:27:33.299104215 -0400 +@@ -219,9 +219,16 @@ static int __init aio_setup(void) + } + __initcall(aio_setup); + ++void kpatch_aio_foo(void) ++{ ++ if (!jiffies) ++ printk("kpatch aio foo\n"); ++} ++ + static void put_aio_ring_file(struct kioctx *ctx) + { + struct file *aio_ring_file = ctx->aio_ring_file; ++ kpatch_aio_foo(); + if (aio_ring_file) { + truncate_setsize(aio_ring_file->f_inode, 0); + diff -Nru kpatch-0.5.0/test/integration/rhel-7.5/gcc-static-local-var-4.test kpatch-0.8.0/test/integration/rhel-7.5/gcc-static-local-var-4.test --- kpatch-0.5.0/test/integration/rhel-7.5/gcc-static-local-var-4.test 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/test/integration/rhel-7.5/gcc-static-local-var-4.test 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1,7 @@ +#!/bin/bash + +if $(nm test-gcc-static-local-var-4.ko | grep -q free_ioctx); then + exit 1 +else + exit 0 +fi diff -Nru kpatch-0.5.0/test/integration/rhel-7.5/gcc-static-local-var-5.patch kpatch-0.8.0/test/integration/rhel-7.5/gcc-static-local-var-5.patch --- kpatch-0.5.0/test/integration/rhel-7.5/gcc-static-local-var-5.patch 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/test/integration/rhel-7.5/gcc-static-local-var-5.patch 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1,45 @@ +diff -Nupr src.orig/kernel/audit.c src/kernel/audit.c +--- src.orig/kernel/audit.c 2017-09-22 15:27:21.602055778 -0400 ++++ src/kernel/audit.c 2017-09-22 15:27:34.429108894 -0400 +@@ -205,6 +205,12 @@ void audit_panic(const char *message) + } + } + ++void kpatch_audit_foo(void) ++{ ++ if (!jiffies) ++ printk("kpatch audit foo\n"); ++} ++ + static inline int audit_rate_check(void) + { + static unsigned long last_check = 0; +@@ -215,6 +221,7 @@ static inline int audit_rate_check(void) + unsigned long elapsed; + int retval = 0; + ++ kpatch_audit_foo(); + if (!audit_rate_limit) return 1; + + spin_lock_irqsave(&lock, flags); +@@ -234,6 +241,11 @@ static inline int audit_rate_check(void) + return retval; + } + ++noinline void kpatch_audit_check(void) ++{ ++ audit_rate_check(); ++} ++ + /** + * audit_log_lost - conditionally log lost audit message event + * @message: the message stating reason for lost audit message +@@ -282,6 +294,8 @@ static int audit_log_config_change(char + struct audit_buffer *ab; + int rc = 0; + ++ kpatch_audit_check(); ++ + ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE); + if (unlikely(!ab)) + return rc; diff -Nru kpatch-0.5.0/test/integration/rhel-7.5/gcc-static-local-var-6.patch kpatch-0.8.0/test/integration/rhel-7.5/gcc-static-local-var-6.patch --- kpatch-0.5.0/test/integration/rhel-7.5/gcc-static-local-var-6.patch 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/test/integration/rhel-7.5/gcc-static-local-var-6.patch 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1,23 @@ +diff --git a/net/ipv6/netfilter.c b/net/ipv6/netfilter.c +index a9d587a..23336ed 100644 +--- a/net/ipv6/netfilter.c ++++ b/net/ipv6/netfilter.c +@@ -106,6 +106,8 @@ static int nf_ip6_reroute(struct sk_buff *skb, + return 0; + } + ++#include "kpatch-macros.h" ++ + static int nf_ip6_route(struct net *net, struct dst_entry **dst, + struct flowi *fl, bool strict) + { +@@ -119,6 +121,9 @@ static int nf_ip6_route(struct net *net, struct dst_entry **dst, + struct dst_entry *result; + int err; + ++ if (!jiffies) ++ printk("kpatch nf_ip6_route foo\n"); ++ + result = ip6_route_output(net, sk, &fl->u.ip6); + err = result->error; + if (err) diff -Nru kpatch-0.5.0/test/integration/rhel-7.5/gcc-static-local-var.patch kpatch-0.8.0/test/integration/rhel-7.5/gcc-static-local-var.patch --- kpatch-0.5.0/test/integration/rhel-7.5/gcc-static-local-var.patch 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/test/integration/rhel-7.5/gcc-static-local-var.patch 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1,25 @@ +diff -Nupr src.orig/arch/x86/kernel/ldt.c src/arch/x86/kernel/ldt.c +--- src.orig/arch/x86/kernel/ldt.c 2017-09-22 15:27:20.847052651 -0400 ++++ src/arch/x86/kernel/ldt.c 2017-09-22 15:27:35.573113632 -0400 +@@ -98,6 +98,12 @@ static inline int copy_ldt(mm_context_t + return 0; + } + ++void hi_there(void) ++{ ++ if (!jiffies) ++ printk("hi there\n"); ++} ++ + /* + * we do not have to muck with descriptors here, that is + * done in switch_mm() as needed. +@@ -107,6 +113,8 @@ int init_new_context(struct task_struct + struct mm_struct *old_mm; + int retval = 0; + ++ hi_there(); ++ + mutex_init(&mm->context.lock); + mm->context.size = 0; + old_mm = current->mm; diff -Nru kpatch-0.5.0/test/integration/rhel-7.5/macro-callbacks.patch kpatch-0.8.0/test/integration/rhel-7.5/macro-callbacks.patch --- kpatch-0.5.0/test/integration/rhel-7.5/macro-callbacks.patch 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/test/integration/rhel-7.5/macro-callbacks.patch 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1,160 @@ +kpatch/livepatch callback test patch: + + vmlinux + pcspkr (mod) + joydev (mod) + +Note: update joydev's pre-patch callback to return -ENODEV to test failure path + +--- src.old/fs/aio.c 2018-02-26 11:07:51.522610407 -0500 ++++ src/fs/aio.c 2018-03-05 11:17:21.560015449 -0500 +@@ -42,6 +42,50 @@ + #include + #include + ++#include ++#include "kpatch-macros.h" ++ ++static const char *const module_state[] = { ++ [MODULE_STATE_LIVE] = "[MODULE_STATE_LIVE] Normal state", ++ [MODULE_STATE_COMING] = "[MODULE_STATE_COMING] Full formed, running module_init", ++ [MODULE_STATE_GOING] = "[MODULE_STATE_GOING] Going away", ++ [MODULE_STATE_UNFORMED] = "[MODULE_STATE_UNFORMED] Still setting it up", ++}; ++ ++static void callback_info(const char *callback, patch_object *obj) ++{ ++ if (obj->mod) ++ pr_info("%s: %s -> %s\n", callback, obj->mod->name, ++ module_state[obj->mod->state]); ++ else ++ pr_info("%s: vmlinux\n", callback); ++} ++ ++static int pre_patch_callback(patch_object *obj) ++{ ++ callback_info(__func__, obj); ++ return 0; ++} ++KPATCH_PRE_PATCH_CALLBACK(pre_patch_callback); ++ ++static void post_patch_callback(patch_object *obj) ++{ ++ callback_info(__func__, obj); ++} ++KPATCH_POST_PATCH_CALLBACK(post_patch_callback); ++ ++static void pre_unpatch_callback(patch_object *obj) ++{ ++ callback_info(__func__, obj); ++} ++KPATCH_PRE_UNPATCH_CALLBACK(pre_unpatch_callback); ++ ++static void post_unpatch_callback(patch_object *obj) ++{ ++ callback_info(__func__, obj); ++} ++KPATCH_POST_UNPATCH_CALLBACK(post_unpatch_callback); ++ + #define AIO_RING_MAGIC 0xa10a10a1 + #define AIO_RING_COMPAT_FEATURES 1 + #define AIO_RING_INCOMPAT_FEATURES 0 +--- src.old/drivers/input/joydev.c 2018-02-26 11:07:49.470610407 -0500 ++++ src/drivers/input/joydev.c 2018-03-05 11:18:13.998015449 -0500 +@@ -954,3 +954,47 @@ static void __exit joydev_exit(void) + + module_init(joydev_init); + module_exit(joydev_exit); ++ ++#include ++#include "kpatch-macros.h" ++ ++static const char *const module_state[] = { ++ [MODULE_STATE_LIVE] = "[MODULE_STATE_LIVE] Normal state", ++ [MODULE_STATE_COMING] = "[MODULE_STATE_COMING] Full formed, running module_init", ++ [MODULE_STATE_GOING] = "[MODULE_STATE_GOING] Going away", ++ [MODULE_STATE_UNFORMED] = "[MODULE_STATE_UNFORMED] Still setting it up", ++}; ++ ++static void callback_info(const char *callback, patch_object *obj) ++{ ++ if (obj->mod) ++ pr_info("%s: %s -> %s\n", callback, obj->mod->name, ++ module_state[obj->mod->state]); ++ else ++ pr_info("%s: vmlinux\n", callback); ++} ++ ++static int pre_patch_callback(patch_object *obj) ++{ ++ callback_info(__func__, obj); ++ return 0; /* return -ENODEV; */ ++} ++KPATCH_PRE_PATCH_CALLBACK(pre_patch_callback); ++ ++static void post_patch_callback(patch_object *obj) ++{ ++ callback_info(__func__, obj); ++} ++KPATCH_POST_PATCH_CALLBACK(post_patch_callback); ++ ++static void pre_unpatch_callback(patch_object *obj) ++{ ++ callback_info(__func__, obj); ++} ++KPATCH_PRE_UNPATCH_CALLBACK(pre_unpatch_callback); ++ ++static void post_unpatch_callback(patch_object *obj) ++{ ++ callback_info(__func__, obj); ++} ++KPATCH_POST_UNPATCH_CALLBACK(post_unpatch_callback); +--- src.old/drivers/input/misc/pcspkr.c 2018-02-26 11:07:49.477610407 -0500 ++++ src/drivers/input/misc/pcspkr.c 2018-03-05 11:18:23.411015449 -0500 +@@ -136,3 +136,46 @@ static struct platform_driver pcspkr_pla + }; + module_platform_driver(pcspkr_platform_driver); + ++#include ++#include "kpatch-macros.h" ++ ++static const char *const module_state[] = { ++ [MODULE_STATE_LIVE] = "[MODULE_STATE_LIVE] Normal state", ++ [MODULE_STATE_COMING] = "[MODULE_STATE_COMING] Full formed, running module_init", ++ [MODULE_STATE_GOING] = "[MODULE_STATE_GOING] Going away", ++ [MODULE_STATE_UNFORMED] = "[MODULE_STATE_UNFORMED] Still setting it up", ++}; ++ ++static void callback_info(const char *callback, patch_object *obj) ++{ ++ if (obj->mod) ++ pr_info("%s: %s -> %s\n", callback, obj->mod->name, ++ module_state[obj->mod->state]); ++ else ++ pr_info("%s: vmlinux\n", callback); ++} ++ ++static int pre_patch_callback(patch_object *obj) ++{ ++ callback_info(__func__, obj); ++ return 0; ++} ++KPATCH_PRE_PATCH_CALLBACK(pre_patch_callback); ++ ++static void post_patch_callback(patch_object *obj) ++{ ++ callback_info(__func__, obj); ++} ++KPATCH_POST_PATCH_CALLBACK(post_patch_callback); ++ ++static void pre_unpatch_callback(patch_object *obj) ++{ ++ callback_info(__func__, obj); ++} ++KPATCH_PRE_UNPATCH_CALLBACK(pre_unpatch_callback); ++ ++static void post_unpatch_callback(patch_object *obj) ++{ ++ callback_info(__func__, obj); ++} ++KPATCH_POST_UNPATCH_CALLBACK(post_unpatch_callback); diff -Nru kpatch-0.5.0/test/integration/rhel-7.5/macro-printk.patch kpatch-0.8.0/test/integration/rhel-7.5/macro-printk.patch --- kpatch-0.5.0/test/integration/rhel-7.5/macro-printk.patch 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/test/integration/rhel-7.5/macro-printk.patch 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1,147 @@ +diff -Nupr src.orig/net/ipv4/fib_frontend.c src/net/ipv4/fib_frontend.c +--- src.orig/net/ipv4/fib_frontend.c 2017-09-22 16:52:10.646110299 -0400 ++++ src/net/ipv4/fib_frontend.c 2017-09-22 16:55:14.395870305 -0400 +@@ -633,6 +633,7 @@ errout: + return err; + } + ++#include "kpatch-macros.h" + static int inet_rtm_newroute(struct sk_buff *skb, struct nlmsghdr *nlh) + { + struct net *net = sock_net(skb->sk); +@@ -651,6 +652,7 @@ static int inet_rtm_newroute(struct sk_b + } + + err = fib_table_insert(net, tb, &cfg); ++ KPATCH_PRINTK("[inet_rtm_newroute]: err is %d\n", err); + errout: + return err; + } +diff -Nupr src.orig/net/ipv4/fib_semantics.c src/net/ipv4/fib_semantics.c +--- src.orig/net/ipv4/fib_semantics.c 2017-09-22 16:52:10.645110295 -0400 ++++ src/net/ipv4/fib_semantics.c 2017-09-22 16:54:05.175584004 -0400 +@@ -925,6 +925,7 @@ fib_convert_metrics(struct fib_info *fi, + return 0; + } + ++#include "kpatch-macros.h" + struct fib_info *fib_create_info(struct fib_config *cfg) + { + int err; +@@ -949,6 +950,7 @@ struct fib_info *fib_create_info(struct + #endif + + err = -ENOBUFS; ++ KPATCH_PRINTK("[fib_create_info]: create error err is %d\n",err); + if (fib_info_cnt >= fib_info_hash_size) { + unsigned int new_size = fib_info_hash_size << 1; + struct hlist_head *new_info_hash; +@@ -969,6 +971,7 @@ struct fib_info *fib_create_info(struct + if (!fib_info_hash_size) + goto failure; + } ++ KPATCH_PRINTK("[fib_create_info]: 2 create error err is %d\n",err); + + fi = kzalloc(sizeof(*fi)+nhs*sizeof(struct fib_nh), GFP_KERNEL); + if (fi == NULL) +@@ -980,6 +983,7 @@ struct fib_info *fib_create_info(struct + } else + fi->fib_metrics = (u32 *) dst_default_metrics; + fib_info_cnt++; ++ KPATCH_PRINTK("[fib_create_info]: 3 create error err is %d\n",err); + + fi->fib_net = net; + fi->fib_protocol = cfg->fc_protocol; +@@ -996,8 +1000,10 @@ struct fib_info *fib_create_info(struct + if (!nexthop_nh->nh_pcpu_rth_output) + goto failure; + } endfor_nexthops(fi) ++ KPATCH_PRINTK("[fib_create_info]: 4 create error err is %d\n",err); + + err = fib_convert_metrics(fi, cfg); ++ KPATCH_PRINTK("[fib_create_info]: 5 create error err is %d\n",err); + if (err) + goto failure; + +@@ -1048,6 +1054,7 @@ struct fib_info *fib_create_info(struct + nh->nh_weight = 1; + #endif + } ++ KPATCH_PRINTK("[fib_create_info]: 6 create error err is %d\n",err); + + if (fib_props[cfg->fc_type].error) { + if (cfg->fc_gw || cfg->fc_oif || cfg->fc_mp) +@@ -1065,6 +1072,7 @@ struct fib_info *fib_create_info(struct + goto err_inval; + } + } ++ KPATCH_PRINTK("[fib_create_info]: 7 create error err is %d\n",err); + + if (cfg->fc_scope > RT_SCOPE_HOST) + goto err_inval; +@@ -1087,6 +1095,7 @@ struct fib_info *fib_create_info(struct + goto failure; + } endfor_nexthops(fi) + } ++ KPATCH_PRINTK("[fib_create_info]: 8 create error err is %d\n",err); + + if (fi->fib_prefsrc) { + if (cfg->fc_type != RTN_LOCAL || !cfg->fc_dst || +@@ -1099,6 +1108,7 @@ struct fib_info *fib_create_info(struct + fib_info_update_nh_saddr(net, nexthop_nh); + fib_add_weight(fi, nexthop_nh); + } endfor_nexthops(fi) ++ KPATCH_PRINTK("[fib_create_info]: 9 create error err is %d\n",err); + + fib_rebalance(fi); + +@@ -1110,6 +1120,7 @@ link_it: + ofi->fib_treeref++; + return ofi; + } ++ KPATCH_PRINTK("[fib_create_info]: 10 create error err is %d\n",err); + + fi->fib_treeref++; + atomic_inc(&fi->fib_clntref); +@@ -1133,6 +1144,7 @@ link_it: + hlist_add_head(&nexthop_nh->nh_hash, head); + } endfor_nexthops(fi) + spin_unlock_bh(&fib_info_lock); ++ KPATCH_PRINTK("[fib_create_info]: 11 create error err is %d\n",err); + return fi; + + err_inval: +@@ -1143,6 +1155,7 @@ failure: + fi->fib_dead = 1; + free_fib_info(fi); + } ++ KPATCH_PRINTK("[fib_create_info]: 12 create error err is %d\n",err); + + return ERR_PTR(err); + } +diff -Nupr src.orig/net/ipv4/fib_trie.c src/net/ipv4/fib_trie.c +--- src.orig/net/ipv4/fib_trie.c 2017-09-22 16:52:10.645110295 -0400 ++++ src/net/ipv4/fib_trie.c 2017-09-22 16:55:39.940975963 -0400 +@@ -1191,6 +1191,7 @@ static int fib_insert_alias(struct trie + } + + /* Caller must hold RTNL. */ ++#include "kpatch-macros.h" + int fib_table_insert(struct net *net, struct fib_table *tb, + struct fib_config *cfg) + { +@@ -1216,11 +1217,14 @@ int fib_table_insert(struct net *net, st + if ((plen < KEYLENGTH) && (key << plen)) + return -EINVAL; + ++ KPATCH_PRINTK("[fib_table_insert]: start\n"); + fi = fib_create_info(cfg); + if (IS_ERR(fi)) { + err = PTR_ERR(fi); ++ KPATCH_PRINTK("[fib_table_insert]: create error err is %d\n",err); + goto err; + } ++ KPATCH_PRINTK("[fib_table_insert]: cross\n"); + + l = fib_find_node(t, &tp, key); + fa = l ? fib_find_alias(&l->leaf, slen, tos, fi->fib_priority) : NULL; diff -Nru kpatch-0.5.0/test/integration/rhel-7.5/meminfo-init2-FAIL.patch kpatch-0.8.0/test/integration/rhel-7.5/meminfo-init2-FAIL.patch --- kpatch-0.5.0/test/integration/rhel-7.5/meminfo-init2-FAIL.patch 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/test/integration/rhel-7.5/meminfo-init2-FAIL.patch 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1,19 @@ +diff -Nupr src.orig/fs/proc/meminfo.c src/fs/proc/meminfo.c +--- src.orig/fs/proc/meminfo.c 2017-09-22 15:27:21.699056179 -0400 ++++ src/fs/proc/meminfo.c 2017-09-22 15:27:38.972127707 -0400 +@@ -30,6 +30,7 @@ static int meminfo_proc_show(struct seq_ + unsigned long pages[NR_LRU_LISTS]; + int lru; + ++ printk("a\n"); + /* + * display in kilobytes. + */ +@@ -191,6 +192,7 @@ static const struct file_operations memi + + static int __init proc_meminfo_init(void) + { ++ printk("a\n"); + proc_create("meminfo", 0, NULL, &meminfo_proc_fops); + return 0; + } diff -Nru kpatch-0.5.0/test/integration/rhel-7.5/meminfo-init-FAIL.patch kpatch-0.8.0/test/integration/rhel-7.5/meminfo-init-FAIL.patch --- kpatch-0.5.0/test/integration/rhel-7.5/meminfo-init-FAIL.patch 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/test/integration/rhel-7.5/meminfo-init-FAIL.patch 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1,11 @@ +diff -Nupr src.orig/fs/proc/meminfo.c src/fs/proc/meminfo.c +--- src.orig/fs/proc/meminfo.c 2017-09-22 15:27:21.699056179 -0400 ++++ src/fs/proc/meminfo.c 2017-09-22 15:27:40.130132502 -0400 +@@ -191,6 +191,7 @@ static const struct file_operations memi + + static int __init proc_meminfo_init(void) + { ++ printk("a\n"); + proc_create("meminfo", 0, NULL, &meminfo_proc_fops); + return 0; + } diff -Nru kpatch-0.5.0/test/integration/rhel-7.5/meminfo-string-LOADED.test kpatch-0.8.0/test/integration/rhel-7.5/meminfo-string-LOADED.test --- kpatch-0.5.0/test/integration/rhel-7.5/meminfo-string-LOADED.test 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/test/integration/rhel-7.5/meminfo-string-LOADED.test 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1,3 @@ +#!/bin/bash + +grep VMALLOCCHUNK /proc/meminfo diff -Nru kpatch-0.5.0/test/integration/rhel-7.5/meminfo-string.patch kpatch-0.8.0/test/integration/rhel-7.5/meminfo-string.patch --- kpatch-0.5.0/test/integration/rhel-7.5/meminfo-string.patch 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/test/integration/rhel-7.5/meminfo-string.patch 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1,12 @@ +diff -Nupr src.orig/fs/proc/meminfo.c src/fs/proc/meminfo.c +--- src.orig/fs/proc/meminfo.c 2017-09-22 15:27:21.699056179 -0400 ++++ src/fs/proc/meminfo.c 2017-09-22 15:27:41.274137239 -0400 +@@ -99,7 +99,7 @@ static int meminfo_proc_show(struct seq_ + "Committed_AS: %8lu kB\n" + "VmallocTotal: %8lu kB\n" + "VmallocUsed: %8lu kB\n" +- "VmallocChunk: %8lu kB\n" ++ "VMALLOCCHUNK: %8lu kB\n" + #ifdef CONFIG_MEMORY_FAILURE + "HardwareCorrupted: %5lu kB\n" + #endif diff -Nru kpatch-0.5.0/test/integration/rhel-7.5/module-call-external.patch kpatch-0.8.0/test/integration/rhel-7.5/module-call-external.patch --- kpatch-0.5.0/test/integration/rhel-7.5/module-call-external.patch 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/test/integration/rhel-7.5/module-call-external.patch 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1,33 @@ +diff -Nupr src.orig/fs/nfsd/export.c src/fs/nfsd/export.c +--- src.orig/fs/nfsd/export.c 2017-09-22 15:27:21.705056204 -0400 ++++ src/fs/nfsd/export.c 2017-09-22 15:27:42.411141948 -0400 +@@ -1184,6 +1184,8 @@ static void exp_flags(struct seq_file *m + } + } + ++extern char *kpatch_string(void); ++ + static int e_show(struct seq_file *m, void *p) + { + struct cache_head *cp = p; +@@ -1193,6 +1195,7 @@ static int e_show(struct seq_file *m, vo + if (p == SEQ_START_TOKEN) { + seq_puts(m, "# Version 1.1\n"); + seq_puts(m, "# Path Client(Flags) # IPs\n"); ++ seq_puts(m, kpatch_string()); + return 0; + } + +diff -Nupr src.orig/net/netlink/af_netlink.c src/net/netlink/af_netlink.c +--- src.orig/net/netlink/af_netlink.c 2017-09-22 15:27:21.754056407 -0400 ++++ src/net/netlink/af_netlink.c 2017-09-22 15:27:42.412141952 -0400 +@@ -3260,4 +3260,9 @@ panic: + panic("netlink_init: Cannot allocate nl_table\n"); + } + ++char *kpatch_string(void) ++{ ++ return "# kpatch\n"; ++} ++ + core_initcall(netlink_proto_init); diff -Nru kpatch-0.5.0/test/integration/rhel-7.5/module-kvm-fixup.patch kpatch-0.8.0/test/integration/rhel-7.5/module-kvm-fixup.patch --- kpatch-0.5.0/test/integration/rhel-7.5/module-kvm-fixup.patch 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/test/integration/rhel-7.5/module-kvm-fixup.patch 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1,12 @@ +diff -Nupr src.orig/arch/x86/kvm/vmx.c src/arch/x86/kvm/vmx.c +--- src.orig/arch/x86/kvm/vmx.c 2017-09-22 15:27:20.853052676 -0400 ++++ src/arch/x86/kvm/vmx.c 2017-09-22 15:27:43.583146801 -0400 +@@ -10597,6 +10597,8 @@ static int vmx_check_intercept(struct kv + struct x86_instruction_info *info, + enum x86_intercept_stage stage) + { ++ if (!jiffies) ++ printk("kpatch vmx_check_intercept\n"); + return X86EMUL_CONTINUE; + } + diff -Nru kpatch-0.5.0/test/integration/rhel-7.5/module-shadow.patch kpatch-0.8.0/test/integration/rhel-7.5/module-shadow.patch --- kpatch-0.5.0/test/integration/rhel-7.5/module-shadow.patch 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/test/integration/rhel-7.5/module-shadow.patch 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1,25 @@ +Index: src/arch/x86/kvm/vmx.c +=================================================================== +--- src.orig/arch/x86/kvm/vmx.c ++++ src/arch/x86/kvm/vmx.c +@@ -11168,10 +11168,20 @@ static void vmx_leave_nested(struct kvm_ + * It should only be called before L2 actually succeeded to run, and when + * vmcs01 is current (it doesn't leave_guest_mode() or switch vmcss). + */ ++#include + static void nested_vmx_entry_failure(struct kvm_vcpu *vcpu, + struct vmcs12 *vmcs12, + u32 reason, unsigned long qualification) + { ++ int *kpatch; ++ ++ kpatch = klp_shadow_alloc(vcpu, 0, NULL, sizeof(*kpatch), ++ GFP_KERNEL); ++ if (kpatch) { ++ klp_shadow_get(vcpu, 0); ++ klp_shadow_free(vcpu, 0); ++ } ++ + load_vmcs12_host_state(vcpu, vmcs12); + vmcs12->vm_exit_reason = reason | VMX_EXIT_REASONS_FAILED_VMENTRY; + vmcs12->exit_qualification = qualification; diff -Nru kpatch-0.5.0/test/integration/rhel-7.5/multiple.test kpatch-0.8.0/test/integration/rhel-7.5/multiple.test --- kpatch-0.5.0/test/integration/rhel-7.5/multiple.test 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/test/integration/rhel-7.5/multiple.test 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1,65 @@ +#!/bin/bash + +SCRIPTDIR="$(readlink -f $(dirname $(type -p $0)))" +ROOTDIR="$(readlink -f $SCRIPTDIR/../..)" +KPATCH="sudo $ROOTDIR/kpatch/kpatch" + +MODULE_PREFIX="test-" +MODULE_POSTFIX=".ko" +TEST_POSTFIX="-LOADED.test" + +set -o errexit + +die() { + echo "ERROR: $@" >&2 + exit 1 +} + +ko_to_test() { + tmp=${1%${MODULE_POSTFIX}}${TEST_POSTFIX} + echo ${tmp#${MODULE_PREFIX}} +} + +# make sure any modules added here are disjoint +declare -a modules +declare -a blacklist=(meminfo-string-LOADED.test) + +for file in "${SCRIPTDIR}"/*"${TEST_POSTFIX}"; do + name=$(basename ${file}) + skip=0 + for bname in "${blacklist[@]}"; do + if [ "${bname}" == "${name}" ]; then + skip=1 + break + fi + done + if [ ${skip} -eq 0 ]; then + modules+=(${MODULE_PREFIX}${name%${TEST_POSTFIX}}${MODULE_POSTFIX}) + fi +done + +for mod in "${modules[@]}"; do + testprog=$(ko_to_test $mod) + $SCRIPTDIR/$testprog && die "$SCRIPTDIR/$testprog succeeded before loading any modules" +done + +for mod in "${modules[@]}"; do + $KPATCH load $mod +done + +for mod in "${modules[@]}"; do + testprog=$(ko_to_test $mod) + $SCRIPTDIR/$testprog || die "$SCRIPTDIR/$testprog failed after loading modules" +done + +for ((idx=${#modules[@]}-1 ; idx>=0 ; idx--)); do + mod=${modules[idx]} + $KPATCH unload $mod +done + +for mod in "${modules[@]}"; do + testprog=$(ko_to_test $mod) + $SCRIPTDIR/$testprog && die "$SCRIPTDIR/$testprog succeeded after unloading modules" +done + +exit 0 diff -Nru kpatch-0.5.0/test/integration/rhel-7.5/new-function.patch kpatch-0.8.0/test/integration/rhel-7.5/new-function.patch --- kpatch-0.5.0/test/integration/rhel-7.5/new-function.patch 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/test/integration/rhel-7.5/new-function.patch 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1,25 @@ +diff -Nupr src.orig/drivers/tty/n_tty.c src/drivers/tty/n_tty.c +--- src.orig/drivers/tty/n_tty.c 2017-09-22 15:27:21.084053633 -0400 ++++ src/drivers/tty/n_tty.c 2017-09-22 15:27:45.888156346 -0400 +@@ -2016,7 +2016,7 @@ do_it_again: + * lock themselves) + */ + +-static ssize_t n_tty_write(struct tty_struct *tty, struct file *file, ++static ssize_t noinline kpatch_n_tty_write(struct tty_struct *tty, struct file *file, + const unsigned char *buf, size_t nr) + { + const unsigned char *b = buf; +@@ -2098,6 +2098,12 @@ break_out: + return (b - buf) ? b - buf : retval; + } + ++static ssize_t __attribute__((optimize("-fno-optimize-sibling-calls"))) n_tty_write(struct tty_struct *tty, struct file *file, ++ const unsigned char *buf, size_t nr) ++{ ++ return kpatch_n_tty_write(tty, file, buf, nr); ++} ++ + /** + * n_tty_poll - poll method for N_TTY + * @tty: terminal device diff -Nru kpatch-0.5.0/test/integration/rhel-7.5/new-globals.patch kpatch-0.8.0/test/integration/rhel-7.5/new-globals.patch --- kpatch-0.5.0/test/integration/rhel-7.5/new-globals.patch 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/test/integration/rhel-7.5/new-globals.patch 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1,34 @@ +diff -Nupr src.orig/fs/proc/cmdline.c src/fs/proc/cmdline.c +--- src.orig/fs/proc/cmdline.c 2017-09-22 15:27:21.698056175 -0400 ++++ src/fs/proc/cmdline.c 2017-09-22 15:27:47.028161067 -0400 +@@ -27,3 +27,10 @@ static int __init proc_cmdline_init(void + return 0; + } + module_init(proc_cmdline_init); ++ ++#include ++void kpatch_print_message(void) ++{ ++ if (!jiffies) ++ printk("hello there!\n"); ++} +diff -Nupr src.orig/fs/proc/meminfo.c src/fs/proc/meminfo.c +--- src.orig/fs/proc/meminfo.c 2017-09-22 15:27:21.699056179 -0400 ++++ src/fs/proc/meminfo.c 2017-09-22 15:27:47.029161071 -0400 +@@ -16,6 +16,8 @@ + #include + #include "internal.h" + ++void kpatch_print_message(void); ++ + void __attribute__((weak)) arch_report_meminfo(struct seq_file *m) + { + } +@@ -53,6 +55,7 @@ static int meminfo_proc_show(struct seq_ + /* + * Tagged format, for easy grepping and expansion. + */ ++ kpatch_print_message(); + seq_printf(m, + "MemTotal: %8lu kB\n" + "MemFree: %8lu kB\n" diff -Nru kpatch-0.5.0/test/integration/rhel-7.5/parainstructions-section.patch kpatch-0.8.0/test/integration/rhel-7.5/parainstructions-section.patch --- kpatch-0.5.0/test/integration/rhel-7.5/parainstructions-section.patch 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/test/integration/rhel-7.5/parainstructions-section.patch 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1,11 @@ +diff -Nupr src.orig/fs/proc/generic.c src/fs/proc/generic.c +--- src.orig/fs/proc/generic.c 2017-09-22 15:27:21.698056175 -0400 ++++ src/fs/proc/generic.c 2017-09-22 15:27:48.190165879 -0400 +@@ -194,6 +194,7 @@ int proc_alloc_inum(unsigned int *inum) + unsigned int i; + int error; + ++ printk("kpatch-test: testing change to .parainstructions section\n"); + retry: + if (!ida_pre_get(&proc_inum_ida, GFP_KERNEL)) + return -ENOMEM; diff -Nru kpatch-0.5.0/test/integration/rhel-7.5/replace-section-references.patch kpatch-0.8.0/test/integration/rhel-7.5/replace-section-references.patch --- kpatch-0.5.0/test/integration/rhel-7.5/replace-section-references.patch 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/test/integration/rhel-7.5/replace-section-references.patch 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1,12 @@ +diff -Nupr src.orig/arch/x86/kvm/x86.c src/arch/x86/kvm/x86.c +--- src.orig/arch/x86/kvm/x86.c 2017-09-22 15:27:20.852052672 -0400 ++++ src/arch/x86/kvm/x86.c 2017-09-22 15:27:49.362170732 -0400 +@@ -248,6 +248,8 @@ static void shared_msr_update(unsigned s + + void kvm_define_shared_msr(unsigned slot, u32 msr) + { ++ if (!jiffies) ++ printk("kpatch kvm define shared msr\n"); + BUG_ON(slot >= KVM_NR_SHARED_MSRS); + shared_msrs_global.msrs[slot] = msr; + if (slot >= shared_msrs_global.nr) diff -Nru kpatch-0.5.0/test/integration/rhel-7.5/shadow-newpid-LOADED.test kpatch-0.8.0/test/integration/rhel-7.5/shadow-newpid-LOADED.test --- kpatch-0.5.0/test/integration/rhel-7.5/shadow-newpid-LOADED.test 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/test/integration/rhel-7.5/shadow-newpid-LOADED.test 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1,3 @@ +#!/bin/bash + +grep -q newpid: /proc/$$/status diff -Nru kpatch-0.5.0/test/integration/rhel-7.5/shadow-newpid.patch kpatch-0.8.0/test/integration/rhel-7.5/shadow-newpid.patch --- kpatch-0.5.0/test/integration/rhel-7.5/shadow-newpid.patch 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/test/integration/rhel-7.5/shadow-newpid.patch 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1,72 @@ +Index: src/fs/proc/array.c +=================================================================== +--- src.orig/fs/proc/array.c ++++ src/fs/proc/array.c +@@ -394,13 +394,20 @@ static inline void task_seccomp(struct s + seq_putc(m, '\n'); + } + ++#include + static inline void task_context_switch_counts(struct seq_file *m, + struct task_struct *p) + { ++ int *newpid; ++ + seq_printf(m, "voluntary_ctxt_switches:\t%lu\n" + "nonvoluntary_ctxt_switches:\t%lu\n", + p->nvcsw, + p->nivcsw); ++ ++ newpid = klp_shadow_get(p, 0); ++ if (newpid) ++ seq_printf(m, "newpid:\t%d\n", *newpid); + } + + static void task_cpus_allowed(struct seq_file *m, struct task_struct *task) +Index: src/kernel/exit.c +=================================================================== +--- src.orig/kernel/exit.c ++++ src/kernel/exit.c +@@ -715,6 +715,7 @@ static void check_stack_usage(void) + static inline void check_stack_usage(void) {} + #endif + ++#include + void do_exit(long code) + { + struct task_struct *tsk = current; +@@ -812,6 +813,8 @@ void do_exit(long code) + check_stack_usage(); + exit_thread(); + ++ klp_shadow_free(tsk, 0); ++ + /* + * Flush inherited counters to the parent - before the parent + * gets woken up by child-exit notifications. +Index: src/kernel/fork.c +=================================================================== +--- src.orig/kernel/fork.c ++++ src/kernel/fork.c +@@ -1751,6 +1751,7 @@ struct task_struct *fork_idle(int cpu) + * It copies the process, and if successful kick-starts + * it and waits for it to finish using the VM if required. + */ ++#include + long do_fork(unsigned long clone_flags, + unsigned long stack_start, + unsigned long stack_size, +@@ -1788,6 +1789,13 @@ long do_fork(unsigned long clone_flags, + if (!IS_ERR(p)) { + struct completion vfork; + struct pid *pid; ++ int *newpid; ++ static int ctr = 0; ++ ++ newpid = klp_shadow_get_or_alloc(p, 0, NULL, sizeof(*newpid), ++ GFP_KERNEL); ++ if (newpid) ++ *newpid = ctr++; + + trace_sched_process_fork(current, p); + diff -Nru kpatch-0.5.0/test/integration/rhel-7.5/smp-locks-section.patch kpatch-0.8.0/test/integration/rhel-7.5/smp-locks-section.patch --- kpatch-0.5.0/test/integration/rhel-7.5/smp-locks-section.patch 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/test/integration/rhel-7.5/smp-locks-section.patch 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1,14 @@ +diff -Nupr src.orig/drivers/tty/tty_buffer.c src/drivers/tty/tty_buffer.c +--- src.orig/drivers/tty/tty_buffer.c 2017-09-22 15:27:21.077053604 -0400 ++++ src/drivers/tty/tty_buffer.c 2017-09-22 15:27:50.542175618 -0400 +@@ -217,6 +217,10 @@ int tty_buffer_request_room(struct tty_p + /* OPTIMISATION: We could keep a per tty "zero" sized buffer to + remove this conditional if its worth it. This would be invisible + to the callers */ ++ ++ if (!size) ++ printk("kpatch-test: testing .smp_locks section changes\n"); ++ + b = buf->tail; + if (b != NULL) + left = b->size - b->used; diff -Nru kpatch-0.5.0/test/integration/rhel-7.5/special-static-2.patch kpatch-0.8.0/test/integration/rhel-7.5/special-static-2.patch --- kpatch-0.5.0/test/integration/rhel-7.5/special-static-2.patch 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/test/integration/rhel-7.5/special-static-2.patch 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1,24 @@ +diff -Nupr src.orig/arch/x86/kvm/x86.c src/arch/x86/kvm/x86.c +--- src.orig/arch/x86/kvm/x86.c 2017-09-22 15:27:20.852052672 -0400 ++++ src/arch/x86/kvm/x86.c 2017-09-22 15:27:51.744180596 -0400 +@@ -2093,12 +2093,20 @@ static void record_steal_time(struct kvm + &vcpu->arch.st.steal, sizeof(struct kvm_steal_time)); + } + ++void kpatch_kvm_x86_foo(void) ++{ ++ if (!jiffies) ++ printk("kpatch kvm x86 foo\n"); ++} ++ + int kvm_set_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info) + { + bool pr = false; + u32 msr = msr_info->index; + u64 data = msr_info->data; + ++ kpatch_kvm_x86_foo(); ++ + switch (msr) { + case MSR_AMD64_NB_CFG: + case MSR_IA32_UCODE_REV: diff -Nru kpatch-0.5.0/test/integration/rhel-7.5/special-static.patch kpatch-0.8.0/test/integration/rhel-7.5/special-static.patch --- kpatch-0.5.0/test/integration/rhel-7.5/special-static.patch 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/test/integration/rhel-7.5/special-static.patch 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1,22 @@ +diff -Nupr src.orig/kernel/fork.c src/kernel/fork.c +--- src.orig/kernel/fork.c 2017-09-22 15:27:21.600055769 -0400 ++++ src/kernel/fork.c 2017-09-22 15:27:53.052186012 -0400 +@@ -1129,10 +1129,18 @@ static void posix_cpu_timers_init_group( + INIT_LIST_HEAD(&sig->cpu_timers[2]); + } + ++void kpatch_foo(void) ++{ ++ if (!jiffies) ++ printk("kpatch copy signal\n"); ++} ++ + static int copy_signal(unsigned long clone_flags, struct task_struct *tsk) + { + struct signal_struct *sig; + ++ kpatch_foo(); ++ + if (clone_flags & CLONE_THREAD) + return 0; + diff -Nru kpatch-0.5.0/test/integration/rhel-7.5/tracepoints-section.patch kpatch-0.8.0/test/integration/rhel-7.5/tracepoints-section.patch --- kpatch-0.5.0/test/integration/rhel-7.5/tracepoints-section.patch 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/test/integration/rhel-7.5/tracepoints-section.patch 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1,13 @@ +diff -Nupr src.orig/kernel/timer.c src/kernel/timer.c +--- src.orig/kernel/timer.c 2017-09-22 15:27:21.600055769 -0400 ++++ src/kernel/timer.c 2017-09-22 15:27:54.288191131 -0400 +@@ -1390,6 +1390,9 @@ static void run_timer_softirq(struct sof + { + struct tvec_base *base = __this_cpu_read(tvec_bases); + ++ if (!base) ++ printk("kpatch-test: testing __tracepoints section changes\n"); ++ + if (time_after_eq(jiffies, base->timer_jiffies)) + __run_timers(base); + } diff -Nru kpatch-0.5.0/test/integration/rhel-7.5/warn-detect-FAIL.patch kpatch-0.8.0/test/integration/rhel-7.5/warn-detect-FAIL.patch --- kpatch-0.5.0/test/integration/rhel-7.5/warn-detect-FAIL.patch 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/test/integration/rhel-7.5/warn-detect-FAIL.patch 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1,8 @@ +diff -Nupr src.orig/arch/x86/kvm/x86.c src/arch/x86/kvm/x86.c +--- src.orig/arch/x86/kvm/x86.c 2017-09-22 15:27:20.852052672 -0400 ++++ src/arch/x86/kvm/x86.c 2017-09-22 15:27:55.489196104 -0400 +@@ -1,3 +1,4 @@ ++ + /* + * Kernel-based Virtual Machine driver for Linux + * diff -Nru kpatch-0.5.0/test/integration/rhel-7.6/bug-table-section.patch kpatch-0.8.0/test/integration/rhel-7.6/bug-table-section.patch --- kpatch-0.5.0/test/integration/rhel-7.6/bug-table-section.patch 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/test/integration/rhel-7.6/bug-table-section.patch 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1,13 @@ +Index: kernel-rhel7/fs/proc/proc_sysctl.c +=================================================================== +--- kernel-rhel7.orig/fs/proc/proc_sysctl.c ++++ kernel-rhel7/fs/proc/proc_sysctl.c +@@ -301,6 +301,8 @@ void sysctl_head_put(struct ctl_table_he + + static struct ctl_table_header *sysctl_head_grab(struct ctl_table_header *head) + { ++ if (jiffies == 0) ++ printk("kpatch-test: testing __bug_table section changes\n"); + BUG_ON(!head); + spin_lock(&sysctl_lock); + if (!use_table(head)) diff -Nru kpatch-0.5.0/test/integration/rhel-7.6/cmdline-string-LOADED.test kpatch-0.8.0/test/integration/rhel-7.6/cmdline-string-LOADED.test --- kpatch-0.5.0/test/integration/rhel-7.6/cmdline-string-LOADED.test 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/test/integration/rhel-7.6/cmdline-string-LOADED.test 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1,3 @@ +#!/bin/bash + +grep kpatch=1 /proc/cmdline diff -Nru kpatch-0.5.0/test/integration/rhel-7.6/cmdline-string.patch kpatch-0.8.0/test/integration/rhel-7.6/cmdline-string.patch --- kpatch-0.5.0/test/integration/rhel-7.6/cmdline-string.patch 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/test/integration/rhel-7.6/cmdline-string.patch 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1,12 @@ +diff -Nupr src.orig/fs/proc/cmdline.c src/fs/proc/cmdline.c +--- src.orig/fs/proc/cmdline.c 2017-09-22 15:27:21.698056175 -0400 ++++ src/fs/proc/cmdline.c 2017-09-22 15:27:22.955061380 -0400 +@@ -5,7 +5,7 @@ + + static int cmdline_proc_show(struct seq_file *m, void *v) + { +- seq_printf(m, "%s\n", saved_command_line); ++ seq_printf(m, "%s kpatch=1\n", saved_command_line); + return 0; + } + diff -Nru kpatch-0.5.0/test/integration/rhel-7.6/data-new-LOADED.test kpatch-0.8.0/test/integration/rhel-7.6/data-new-LOADED.test --- kpatch-0.5.0/test/integration/rhel-7.6/data-new-LOADED.test 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/test/integration/rhel-7.6/data-new-LOADED.test 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1,3 @@ +#!/bin/bash + +grep "kpatch: 5" /proc/meminfo diff -Nru kpatch-0.5.0/test/integration/rhel-7.6/data-new.patch kpatch-0.8.0/test/integration/rhel-7.6/data-new.patch --- kpatch-0.5.0/test/integration/rhel-7.6/data-new.patch 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/test/integration/rhel-7.6/data-new.patch 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1,29 @@ +Index: kernel-rhel7/fs/proc/meminfo.c +=================================================================== +--- kernel-rhel7.orig/fs/proc/meminfo.c ++++ kernel-rhel7/fs/proc/meminfo.c +@@ -20,6 +20,8 @@ void __attribute__((weak)) arch_report_m + { + } + ++static int foo = 5; ++ + static int meminfo_proc_show(struct seq_file *m, void *v) + { + struct sysinfo i; +@@ -110,6 +112,7 @@ static int meminfo_proc_show(struct seq_ + "CmaTotal: %8lu kB\n" + "CmaFree: %8lu kB\n" + #endif ++ "kpatch: %d" + , + K(i.totalram), + K(i.freeram), +@@ -175,6 +178,7 @@ static int meminfo_proc_show(struct seq_ + , K(totalcma_pages) + , K(global_page_state(NR_FREE_CMA_PAGES)) + #endif ++ ,foo + ); + + hugetlb_report_meminfo(m); diff -Nru kpatch-0.5.0/test/integration/rhel-7.6/data-read-mostly.patch kpatch-0.8.0/test/integration/rhel-7.6/data-read-mostly.patch --- kpatch-0.5.0/test/integration/rhel-7.6/data-read-mostly.patch 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/test/integration/rhel-7.6/data-read-mostly.patch 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1,12 @@ +Index: kernel-rhel7/net/core/dev.c +=================================================================== +--- kernel-rhel7.orig/net/core/dev.c ++++ kernel-rhel7/net/core/dev.c +@@ -4199,6 +4199,7 @@ skip_classify: + case RX_HANDLER_PASS: + break; + default: ++ printk("BUG!\n"); + BUG(); + } + } diff -Nru kpatch-0.5.0/test/integration/rhel-7.6/fixup-section.patch kpatch-0.8.0/test/integration/rhel-7.6/fixup-section.patch --- kpatch-0.5.0/test/integration/rhel-7.6/fixup-section.patch 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/test/integration/rhel-7.6/fixup-section.patch 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1,12 @@ +diff --git a/fs/readdir.c b/fs/readdir.c +index febd02dfbe2d..064db7bd70d0 100644 +--- a/fs/readdir.c ++++ b/fs/readdir.c +@@ -176,6 +176,7 @@ static int filldir(void * __buf, const char * name, int namlen, loff_t offset, + goto efault; + } + dirent = buf->current_dir; ++ asm("nop"); + if (__put_user(d_ino, &dirent->d_ino)) + goto efault; + if (__put_user(reclen, &dirent->d_reclen)) diff -Nru kpatch-0.5.0/test/integration/rhel-7.6/gcc-constprop.patch.disabled kpatch-0.8.0/test/integration/rhel-7.6/gcc-constprop.patch.disabled --- kpatch-0.5.0/test/integration/rhel-7.6/gcc-constprop.patch.disabled 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/test/integration/rhel-7.6/gcc-constprop.patch.disabled 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1,13 @@ +diff -Nupr src.orig/kernel/time/timekeeping.c src/kernel/time/timekeeping.c +--- src.orig/kernel/time/timekeeping.c 2017-09-22 15:27:21.602055778 -0400 ++++ src/kernel/time/timekeeping.c 2017-09-22 15:27:27.522080292 -0400 +@@ -877,6 +877,9 @@ void do_gettimeofday(struct timeval *tv) + { + struct timespec64 now; + ++ if (!tv) ++ return; ++ + getnstimeofday64(&now); + tv->tv_sec = now.tv_sec; + tv->tv_usec = now.tv_nsec/1000; diff -Nru kpatch-0.5.0/test/integration/rhel-7.6/gcc-isra.patch kpatch-0.8.0/test/integration/rhel-7.6/gcc-isra.patch --- kpatch-0.5.0/test/integration/rhel-7.6/gcc-isra.patch 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/test/integration/rhel-7.6/gcc-isra.patch 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1,12 @@ +Index: kernel-rhel7/fs/proc/proc_sysctl.c +=================================================================== +--- kernel-rhel7.orig/fs/proc/proc_sysctl.c ++++ kernel-rhel7/fs/proc/proc_sysctl.c +@@ -46,6 +46,7 @@ void proc_sys_poll_notify(struct ctl_tab + if (!poll) + return; + ++ printk("kpatch-test: testing gcc .isra function name mangling\n"); + atomic_inc(&poll->event); + wake_up_interruptible(&poll->wait); + } diff -Nru kpatch-0.5.0/test/integration/rhel-7.6/gcc-mangled-3.patch kpatch-0.8.0/test/integration/rhel-7.6/gcc-mangled-3.patch --- kpatch-0.5.0/test/integration/rhel-7.6/gcc-mangled-3.patch 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/test/integration/rhel-7.6/gcc-mangled-3.patch 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1,14 @@ +Index: kernel-rhel7/mm/slub.c +=================================================================== +--- kernel-rhel7.orig/mm/slub.c ++++ kernel-rhel7/mm/slub.c +@@ -5611,6 +5611,9 @@ void get_slabinfo(struct kmem_cache *s, + unsigned long nr_free = 0; + int node; + ++ if (!jiffies) ++ printk("slabinfo\n"); ++ + for_each_online_node(node) { + struct kmem_cache_node *n = get_node(s, node); + diff -Nru kpatch-0.5.0/test/integration/rhel-7.6/gcc-static-local-var-2.patch kpatch-0.8.0/test/integration/rhel-7.6/gcc-static-local-var-2.patch --- kpatch-0.5.0/test/integration/rhel-7.6/gcc-static-local-var-2.patch 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/test/integration/rhel-7.6/gcc-static-local-var-2.patch 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1,14 @@ +Index: kernel-rhel7/mm/mmap.c +=================================================================== +--- kernel-rhel7.orig/mm/mmap.c ++++ kernel-rhel7/mm/mmap.c +@@ -1715,6 +1715,9 @@ unsigned long mmap_region(struct file *f + struct rb_node **rb_link, *rb_parent; + unsigned long charged = 0; + ++ if (!jiffies) ++ printk("kpatch mmap foo\n"); ++ + /* Check against address space limit. */ + if (!may_expand_vm(mm, len >> PAGE_SHIFT)) { + unsigned long nr_pages; diff -Nru kpatch-0.5.0/test/integration/rhel-7.6/gcc-static-local-var-3.patch kpatch-0.8.0/test/integration/rhel-7.6/gcc-static-local-var-3.patch --- kpatch-0.5.0/test/integration/rhel-7.6/gcc-static-local-var-3.patch 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/test/integration/rhel-7.6/gcc-static-local-var-3.patch 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1,20 @@ +Index: kernel-rhel7/kernel/sys.c +=================================================================== +--- kernel-rhel7.orig/kernel/sys.c ++++ kernel-rhel7/kernel/sys.c +@@ -559,8 +559,15 @@ SYSCALL_DEFINE4(reboot, int, magic1, int + return ret; + } + ++void kpatch_bar(void) ++{ ++ if (!jiffies) ++ printk("kpatch_foo\n"); ++} ++ + static void deferred_cad(struct work_struct *dummy) + { ++ kpatch_bar(); + kernel_restart(NULL); + } + diff -Nru kpatch-0.5.0/test/integration/rhel-7.6/gcc-static-local-var-4.patch kpatch-0.8.0/test/integration/rhel-7.6/gcc-static-local-var-4.patch --- kpatch-0.5.0/test/integration/rhel-7.6/gcc-static-local-var-4.patch 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/test/integration/rhel-7.6/gcc-static-local-var-4.patch 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1,21 @@ +Index: kernel-rhel7/fs/aio.c +=================================================================== +--- kernel-rhel7.orig/fs/aio.c ++++ kernel-rhel7/fs/aio.c +@@ -223,9 +223,16 @@ static int __init aio_setup(void) + } + __initcall(aio_setup); + ++void kpatch_aio_foo(void) ++{ ++ if (!jiffies) ++ printk("kpatch aio foo\n"); ++} ++ + static void put_aio_ring_file(struct kioctx *ctx) + { + struct file *aio_ring_file = ctx->aio_ring_file; ++ kpatch_aio_foo(); + if (aio_ring_file) { + truncate_setsize(aio_ring_file->f_inode, 0); + diff -Nru kpatch-0.5.0/test/integration/rhel-7.6/gcc-static-local-var-4.test kpatch-0.8.0/test/integration/rhel-7.6/gcc-static-local-var-4.test --- kpatch-0.5.0/test/integration/rhel-7.6/gcc-static-local-var-4.test 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/test/integration/rhel-7.6/gcc-static-local-var-4.test 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1,7 @@ +#!/bin/bash + +if $(nm test-gcc-static-local-var-4.ko | grep -q free_ioctx); then + exit 1 +else + exit 0 +fi diff -Nru kpatch-0.5.0/test/integration/rhel-7.6/gcc-static-local-var-5.patch kpatch-0.8.0/test/integration/rhel-7.6/gcc-static-local-var-5.patch --- kpatch-0.5.0/test/integration/rhel-7.6/gcc-static-local-var-5.patch 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/test/integration/rhel-7.6/gcc-static-local-var-5.patch 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1,45 @@ +diff -Nupr src.orig/kernel/audit.c src/kernel/audit.c +--- src.orig/kernel/audit.c 2017-09-22 15:27:21.602055778 -0400 ++++ src/kernel/audit.c 2017-09-22 15:27:34.429108894 -0400 +@@ -205,6 +205,12 @@ void audit_panic(const char *message) + } + } + ++void kpatch_audit_foo(void) ++{ ++ if (!jiffies) ++ printk("kpatch audit foo\n"); ++} ++ + static inline int audit_rate_check(void) + { + static unsigned long last_check = 0; +@@ -215,6 +221,7 @@ static inline int audit_rate_check(void) + unsigned long elapsed; + int retval = 0; + ++ kpatch_audit_foo(); + if (!audit_rate_limit) return 1; + + spin_lock_irqsave(&lock, flags); +@@ -234,6 +241,11 @@ static inline int audit_rate_check(void) + return retval; + } + ++noinline void kpatch_audit_check(void) ++{ ++ audit_rate_check(); ++} ++ + /** + * audit_log_lost - conditionally log lost audit message event + * @message: the message stating reason for lost audit message +@@ -282,6 +294,8 @@ static int audit_log_config_change(char + struct audit_buffer *ab; + int rc = 0; + ++ kpatch_audit_check(); ++ + ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE); + if (unlikely(!ab)) + return rc; diff -Nru kpatch-0.5.0/test/integration/rhel-7.6/gcc-static-local-var-6.patch kpatch-0.8.0/test/integration/rhel-7.6/gcc-static-local-var-6.patch --- kpatch-0.5.0/test/integration/rhel-7.6/gcc-static-local-var-6.patch 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/test/integration/rhel-7.6/gcc-static-local-var-6.patch 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1,23 @@ +diff --git a/net/ipv6/netfilter.c b/net/ipv6/netfilter.c +index a9d587a..23336ed 100644 +--- a/net/ipv6/netfilter.c ++++ b/net/ipv6/netfilter.c +@@ -106,6 +106,8 @@ static int nf_ip6_reroute(struct sk_buff *skb, + return 0; + } + ++#include "kpatch-macros.h" ++ + static int nf_ip6_route(struct net *net, struct dst_entry **dst, + struct flowi *fl, bool strict) + { +@@ -119,6 +121,9 @@ static int nf_ip6_route(struct net *net, struct dst_entry **dst, + struct dst_entry *result; + int err; + ++ if (!jiffies) ++ printk("kpatch nf_ip6_route foo\n"); ++ + result = ip6_route_output(net, sk, &fl->u.ip6); + err = result->error; + if (err) diff -Nru kpatch-0.5.0/test/integration/rhel-7.6/macro-callbacks.patch kpatch-0.8.0/test/integration/rhel-7.6/macro-callbacks.patch --- kpatch-0.5.0/test/integration/rhel-7.6/macro-callbacks.patch 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/test/integration/rhel-7.6/macro-callbacks.patch 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1,160 @@ +kpatch/livepatch callback test patch: + + vmlinux + pcspkr (mod) + joydev (mod) + +Note: update joydev's pre-patch callback to return -ENODEV to test failure path + +--- src.old/fs/aio.c 2018-02-26 11:07:51.522610407 -0500 ++++ src/fs/aio.c 2018-03-05 11:17:21.560015449 -0500 +@@ -42,6 +42,50 @@ + #include + #include + ++#include ++#include "kpatch-macros.h" ++ ++static const char *const module_state[] = { ++ [MODULE_STATE_LIVE] = "[MODULE_STATE_LIVE] Normal state", ++ [MODULE_STATE_COMING] = "[MODULE_STATE_COMING] Full formed, running module_init", ++ [MODULE_STATE_GOING] = "[MODULE_STATE_GOING] Going away", ++ [MODULE_STATE_UNFORMED] = "[MODULE_STATE_UNFORMED] Still setting it up", ++}; ++ ++static void callback_info(const char *callback, patch_object *obj) ++{ ++ if (obj->mod) ++ pr_info("%s: %s -> %s\n", callback, obj->mod->name, ++ module_state[obj->mod->state]); ++ else ++ pr_info("%s: vmlinux\n", callback); ++} ++ ++static int pre_patch_callback(patch_object *obj) ++{ ++ callback_info(__func__, obj); ++ return 0; ++} ++KPATCH_PRE_PATCH_CALLBACK(pre_patch_callback); ++ ++static void post_patch_callback(patch_object *obj) ++{ ++ callback_info(__func__, obj); ++} ++KPATCH_POST_PATCH_CALLBACK(post_patch_callback); ++ ++static void pre_unpatch_callback(patch_object *obj) ++{ ++ callback_info(__func__, obj); ++} ++KPATCH_PRE_UNPATCH_CALLBACK(pre_unpatch_callback); ++ ++static void post_unpatch_callback(patch_object *obj) ++{ ++ callback_info(__func__, obj); ++} ++KPATCH_POST_UNPATCH_CALLBACK(post_unpatch_callback); ++ + #define AIO_RING_MAGIC 0xa10a10a1 + #define AIO_RING_COMPAT_FEATURES 1 + #define AIO_RING_INCOMPAT_FEATURES 0 +--- src.old/drivers/input/joydev.c 2018-02-26 11:07:49.470610407 -0500 ++++ src/drivers/input/joydev.c 2018-03-05 11:18:13.998015449 -0500 +@@ -954,3 +954,47 @@ static void __exit joydev_exit(void) + + module_init(joydev_init); + module_exit(joydev_exit); ++ ++#include ++#include "kpatch-macros.h" ++ ++static const char *const module_state[] = { ++ [MODULE_STATE_LIVE] = "[MODULE_STATE_LIVE] Normal state", ++ [MODULE_STATE_COMING] = "[MODULE_STATE_COMING] Full formed, running module_init", ++ [MODULE_STATE_GOING] = "[MODULE_STATE_GOING] Going away", ++ [MODULE_STATE_UNFORMED] = "[MODULE_STATE_UNFORMED] Still setting it up", ++}; ++ ++static void callback_info(const char *callback, patch_object *obj) ++{ ++ if (obj->mod) ++ pr_info("%s: %s -> %s\n", callback, obj->mod->name, ++ module_state[obj->mod->state]); ++ else ++ pr_info("%s: vmlinux\n", callback); ++} ++ ++static int pre_patch_callback(patch_object *obj) ++{ ++ callback_info(__func__, obj); ++ return 0; /* return -ENODEV; */ ++} ++KPATCH_PRE_PATCH_CALLBACK(pre_patch_callback); ++ ++static void post_patch_callback(patch_object *obj) ++{ ++ callback_info(__func__, obj); ++} ++KPATCH_POST_PATCH_CALLBACK(post_patch_callback); ++ ++static void pre_unpatch_callback(patch_object *obj) ++{ ++ callback_info(__func__, obj); ++} ++KPATCH_PRE_UNPATCH_CALLBACK(pre_unpatch_callback); ++ ++static void post_unpatch_callback(patch_object *obj) ++{ ++ callback_info(__func__, obj); ++} ++KPATCH_POST_UNPATCH_CALLBACK(post_unpatch_callback); +--- src.old/drivers/input/misc/pcspkr.c 2018-02-26 11:07:49.477610407 -0500 ++++ src/drivers/input/misc/pcspkr.c 2018-03-05 11:18:23.411015449 -0500 +@@ -136,3 +136,46 @@ static struct platform_driver pcspkr_pla + }; + module_platform_driver(pcspkr_platform_driver); + ++#include ++#include "kpatch-macros.h" ++ ++static const char *const module_state[] = { ++ [MODULE_STATE_LIVE] = "[MODULE_STATE_LIVE] Normal state", ++ [MODULE_STATE_COMING] = "[MODULE_STATE_COMING] Full formed, running module_init", ++ [MODULE_STATE_GOING] = "[MODULE_STATE_GOING] Going away", ++ [MODULE_STATE_UNFORMED] = "[MODULE_STATE_UNFORMED] Still setting it up", ++}; ++ ++static void callback_info(const char *callback, patch_object *obj) ++{ ++ if (obj->mod) ++ pr_info("%s: %s -> %s\n", callback, obj->mod->name, ++ module_state[obj->mod->state]); ++ else ++ pr_info("%s: vmlinux\n", callback); ++} ++ ++static int pre_patch_callback(patch_object *obj) ++{ ++ callback_info(__func__, obj); ++ return 0; ++} ++KPATCH_PRE_PATCH_CALLBACK(pre_patch_callback); ++ ++static void post_patch_callback(patch_object *obj) ++{ ++ callback_info(__func__, obj); ++} ++KPATCH_POST_PATCH_CALLBACK(post_patch_callback); ++ ++static void pre_unpatch_callback(patch_object *obj) ++{ ++ callback_info(__func__, obj); ++} ++KPATCH_PRE_UNPATCH_CALLBACK(pre_unpatch_callback); ++ ++static void post_unpatch_callback(patch_object *obj) ++{ ++ callback_info(__func__, obj); ++} ++KPATCH_POST_UNPATCH_CALLBACK(post_unpatch_callback); diff -Nru kpatch-0.5.0/test/integration/rhel-7.6/macro-printk.patch kpatch-0.8.0/test/integration/rhel-7.6/macro-printk.patch --- kpatch-0.5.0/test/integration/rhel-7.6/macro-printk.patch 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/test/integration/rhel-7.6/macro-printk.patch 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1,151 @@ +Index: kernel-rhel7/net/ipv4/fib_frontend.c +=================================================================== +--- kernel-rhel7.orig/net/ipv4/fib_frontend.c ++++ kernel-rhel7/net/ipv4/fib_frontend.c +@@ -685,6 +685,7 @@ errout: + return err; + } + ++#include "kpatch-macros.h" + static int inet_rtm_newroute(struct sk_buff *skb, struct nlmsghdr *nlh) + { + struct net *net = sock_net(skb->sk); +@@ -703,6 +704,7 @@ static int inet_rtm_newroute(struct sk_b + } + + err = fib_table_insert(net, tb, &cfg); ++ KPATCH_PRINTK("[inet_rtm_newroute]: err is %d\n", err); + errout: + return err; + } +Index: kernel-rhel7/net/ipv4/fib_semantics.c +=================================================================== +--- kernel-rhel7.orig/net/ipv4/fib_semantics.c ++++ kernel-rhel7/net/ipv4/fib_semantics.c +@@ -969,6 +969,7 @@ fib_convert_metrics(struct fib_info *fi, + return 0; + } + ++#include "kpatch-macros.h" + struct fib_info *fib_create_info(struct fib_config *cfg) + { + int err; +@@ -993,6 +994,7 @@ struct fib_info *fib_create_info(struct + #endif + + err = -ENOBUFS; ++ KPATCH_PRINTK("[fib_create_info]: create error err is %d\n",err); + if (fib_info_cnt >= fib_info_hash_size) { + unsigned int new_size = fib_info_hash_size << 1; + struct hlist_head *new_info_hash; +@@ -1013,6 +1015,7 @@ struct fib_info *fib_create_info(struct + if (!fib_info_hash_size) + goto failure; + } ++ KPATCH_PRINTK("[fib_create_info]: 2 create error err is %d\n",err); + + fi = kzalloc(sizeof(*fi)+nhs*sizeof(struct fib_nh), GFP_KERNEL); + if (fi == NULL) +@@ -1028,6 +1031,8 @@ struct fib_info *fib_create_info(struct + fi->fib_metrics = (struct dst_metrics *)&dst_default_metrics; + } + fib_info_cnt++; ++ KPATCH_PRINTK("[fib_create_info]: 3 create error err is %d\n",err); ++ + fi->fib_net = net; + fi->fib_protocol = cfg->fc_protocol; + fi->fib_scope = cfg->fc_scope; +@@ -1043,8 +1048,10 @@ struct fib_info *fib_create_info(struct + if (!nexthop_nh->nh_pcpu_rth_output) + goto failure; + } endfor_nexthops(fi) ++ KPATCH_PRINTK("[fib_create_info]: 4 create error err is %d\n",err); + + err = fib_convert_metrics(fi, cfg); ++ KPATCH_PRINTK("[fib_create_info]: 5 create error err is %d\n",err); + if (err) + goto failure; + +@@ -1095,6 +1102,7 @@ struct fib_info *fib_create_info(struct + nh->nh_weight = 1; + #endif + } ++ KPATCH_PRINTK("[fib_create_info]: 6 create error err is %d\n",err); + + if (fib_props[cfg->fc_type].error) { + if (cfg->fc_gw || cfg->fc_oif || cfg->fc_mp) +@@ -1112,6 +1120,7 @@ struct fib_info *fib_create_info(struct + goto err_inval; + } + } ++ KPATCH_PRINTK("[fib_create_info]: 7 create error err is %d\n",err); + + if (cfg->fc_scope > RT_SCOPE_HOST) + goto err_inval; +@@ -1134,6 +1143,7 @@ struct fib_info *fib_create_info(struct + goto failure; + } endfor_nexthops(fi) + } ++ KPATCH_PRINTK("[fib_create_info]: 8 create error err is %d\n",err); + + if (fi->fib_prefsrc) { + if (cfg->fc_type != RTN_LOCAL || !cfg->fc_dst || +@@ -1146,6 +1156,7 @@ struct fib_info *fib_create_info(struct + fib_info_update_nh_saddr(net, nexthop_nh); + fib_add_weight(fi, nexthop_nh); + } endfor_nexthops(fi) ++ KPATCH_PRINTK("[fib_create_info]: 9 create error err is %d\n",err); + + fib_rebalance(fi); + +@@ -1157,6 +1168,7 @@ link_it: + ofi->fib_treeref++; + return ofi; + } ++ KPATCH_PRINTK("[fib_create_info]: 10 create error err is %d\n",err); + + fi->fib_treeref++; + atomic_inc(&fi->fib_clntref); +@@ -1180,6 +1192,7 @@ link_it: + hlist_add_head(&nexthop_nh->nh_hash, head); + } endfor_nexthops(fi) + spin_unlock_bh(&fib_info_lock); ++ KPATCH_PRINTK("[fib_create_info]: 11 create error err is %d\n",err); + return fi; + + err_inval: +@@ -1190,6 +1203,7 @@ failure: + fi->fib_dead = 1; + free_fib_info(fi); + } ++ KPATCH_PRINTK("[fib_create_info]: 12 create error err is %d\n",err); + + return ERR_PTR(err); + } +Index: kernel-rhel7/net/ipv4/fib_trie.c +=================================================================== +--- kernel-rhel7.orig/net/ipv4/fib_trie.c ++++ kernel-rhel7/net/ipv4/fib_trie.c +@@ -1105,6 +1105,7 @@ static int fib_insert_alias(struct trie + } + + /* Caller must hold RTNL. */ ++#include "kpatch-macros.h" + int fib_table_insert(struct net *net, struct fib_table *tb, + struct fib_config *cfg) + { +@@ -1130,11 +1131,14 @@ int fib_table_insert(struct net *net, st + if ((plen < KEYLENGTH) && (key << plen)) + return -EINVAL; + ++ KPATCH_PRINTK("[fib_table_insert]: start\n"); + fi = fib_create_info(cfg); + if (IS_ERR(fi)) { + err = PTR_ERR(fi); ++ KPATCH_PRINTK("[fib_table_insert]: create error err is %d\n",err); + goto err; + } ++ KPATCH_PRINTK("[fib_table_insert]: cross\n"); + + l = fib_find_node(t, &tp, key); + fa = l ? fib_find_alias(&l->leaf, slen, tos, fi->fib_priority, diff -Nru kpatch-0.5.0/test/integration/rhel-7.6/meminfo-init2-FAIL.patch kpatch-0.8.0/test/integration/rhel-7.6/meminfo-init2-FAIL.patch --- kpatch-0.5.0/test/integration/rhel-7.6/meminfo-init2-FAIL.patch 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/test/integration/rhel-7.6/meminfo-init2-FAIL.patch 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1,20 @@ +Index: kernel-rhel7/fs/proc/meminfo.c +=================================================================== +--- kernel-rhel7.orig/fs/proc/meminfo.c ++++ kernel-rhel7/fs/proc/meminfo.c +@@ -30,6 +30,7 @@ static int meminfo_proc_show(struct seq_ + unsigned long pages[NR_LRU_LISTS]; + int lru; + ++ printk("a\n"); + /* + * display in kilobytes. + */ +@@ -199,6 +200,7 @@ static const struct file_operations memi + + static int __init proc_meminfo_init(void) + { ++ printk("a\n"); + proc_create("meminfo", 0, NULL, &meminfo_proc_fops); + return 0; + } diff -Nru kpatch-0.5.0/test/integration/rhel-7.6/meminfo-init-FAIL.patch kpatch-0.8.0/test/integration/rhel-7.6/meminfo-init-FAIL.patch --- kpatch-0.5.0/test/integration/rhel-7.6/meminfo-init-FAIL.patch 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/test/integration/rhel-7.6/meminfo-init-FAIL.patch 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1,12 @@ +Index: kernel-rhel7/fs/proc/meminfo.c +=================================================================== +--- kernel-rhel7.orig/fs/proc/meminfo.c ++++ kernel-rhel7/fs/proc/meminfo.c +@@ -199,6 +199,7 @@ static const struct file_operations memi + + static int __init proc_meminfo_init(void) + { ++ printk("a\n"); + proc_create("meminfo", 0, NULL, &meminfo_proc_fops); + return 0; + } diff -Nru kpatch-0.5.0/test/integration/rhel-7.6/meminfo-string-LOADED.test kpatch-0.8.0/test/integration/rhel-7.6/meminfo-string-LOADED.test --- kpatch-0.5.0/test/integration/rhel-7.6/meminfo-string-LOADED.test 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/test/integration/rhel-7.6/meminfo-string-LOADED.test 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1,3 @@ +#!/bin/bash + +grep VMALLOCCHUNK /proc/meminfo diff -Nru kpatch-0.5.0/test/integration/rhel-7.6/meminfo-string.patch kpatch-0.8.0/test/integration/rhel-7.6/meminfo-string.patch --- kpatch-0.5.0/test/integration/rhel-7.6/meminfo-string.patch 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/test/integration/rhel-7.6/meminfo-string.patch 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1,12 @@ +diff -Nupr src.orig/fs/proc/meminfo.c src/fs/proc/meminfo.c +--- src.orig/fs/proc/meminfo.c 2017-09-22 15:27:21.699056179 -0400 ++++ src/fs/proc/meminfo.c 2017-09-22 15:27:41.274137239 -0400 +@@ -99,7 +99,7 @@ static int meminfo_proc_show(struct seq_ + "Committed_AS: %8lu kB\n" + "VmallocTotal: %8lu kB\n" + "VmallocUsed: %8lu kB\n" +- "VmallocChunk: %8lu kB\n" ++ "VMALLOCCHUNK: %8lu kB\n" + #ifdef CONFIG_MEMORY_FAILURE + "HardwareCorrupted: %5lu kB\n" + #endif diff -Nru kpatch-0.5.0/test/integration/rhel-7.6/module-call-external.patch kpatch-0.8.0/test/integration/rhel-7.6/module-call-external.patch --- kpatch-0.5.0/test/integration/rhel-7.6/module-call-external.patch 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/test/integration/rhel-7.6/module-call-external.patch 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1,35 @@ +Index: kernel-rhel7/fs/nfsd/export.c +=================================================================== +--- kernel-rhel7.orig/fs/nfsd/export.c ++++ kernel-rhel7/fs/nfsd/export.c +@@ -1184,6 +1184,8 @@ static void exp_flags(struct seq_file *m + } + } + ++extern char *kpatch_string(void); ++ + static int e_show(struct seq_file *m, void *p) + { + struct cache_head *cp = p; +@@ -1193,6 +1195,7 @@ static int e_show(struct seq_file *m, vo + if (p == SEQ_START_TOKEN) { + seq_puts(m, "# Version 1.1\n"); + seq_puts(m, "# Path Client(Flags) # IPs\n"); ++ seq_puts(m, kpatch_string()); + return 0; + } + +Index: kernel-rhel7/net/netlink/af_netlink.c +=================================================================== +--- kernel-rhel7.orig/net/netlink/af_netlink.c ++++ kernel-rhel7/net/netlink/af_netlink.c +@@ -2568,4 +2568,9 @@ panic: + panic("netlink_init: Cannot allocate nl_table\n"); + } + ++char *kpatch_string(void) ++{ ++ return "# kpatch\n"; ++} ++ + core_initcall(netlink_proto_init); diff -Nru kpatch-0.5.0/test/integration/rhel-7.6/multiple.test kpatch-0.8.0/test/integration/rhel-7.6/multiple.test --- kpatch-0.5.0/test/integration/rhel-7.6/multiple.test 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/test/integration/rhel-7.6/multiple.test 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1,65 @@ +#!/bin/bash + +SCRIPTDIR="$(readlink -f $(dirname $(type -p $0)))" +ROOTDIR="$(readlink -f $SCRIPTDIR/../..)" +KPATCH="sudo $ROOTDIR/kpatch/kpatch" + +MODULE_PREFIX="test-" +MODULE_POSTFIX=".ko" +TEST_POSTFIX="-LOADED.test" + +set -o errexit + +die() { + echo "ERROR: $@" >&2 + exit 1 +} + +ko_to_test() { + tmp=${1%${MODULE_POSTFIX}}${TEST_POSTFIX} + echo ${tmp#${MODULE_PREFIX}} +} + +# make sure any modules added here are disjoint +declare -a modules +declare -a blacklist=(meminfo-string-LOADED.test) + +for file in "${SCRIPTDIR}"/*"${TEST_POSTFIX}"; do + name=$(basename ${file}) + skip=0 + for bname in "${blacklist[@]}"; do + if [ "${bname}" == "${name}" ]; then + skip=1 + break + fi + done + if [ ${skip} -eq 0 ]; then + modules+=(${MODULE_PREFIX}${name%${TEST_POSTFIX}}${MODULE_POSTFIX}) + fi +done + +for mod in "${modules[@]}"; do + testprog=$(ko_to_test $mod) + $SCRIPTDIR/$testprog && die "$SCRIPTDIR/$testprog succeeded before loading any modules" +done + +for mod in "${modules[@]}"; do + $KPATCH load $mod +done + +for mod in "${modules[@]}"; do + testprog=$(ko_to_test $mod) + $SCRIPTDIR/$testprog || die "$SCRIPTDIR/$testprog failed after loading modules" +done + +for ((idx=${#modules[@]}-1 ; idx>=0 ; idx--)); do + mod=${modules[idx]} + $KPATCH unload $mod +done + +for mod in "${modules[@]}"; do + testprog=$(ko_to_test $mod) + $SCRIPTDIR/$testprog && die "$SCRIPTDIR/$testprog succeeded after unloading modules" +done + +exit 0 diff -Nru kpatch-0.5.0/test/integration/rhel-7.6/new-function.patch kpatch-0.8.0/test/integration/rhel-7.6/new-function.patch --- kpatch-0.5.0/test/integration/rhel-7.6/new-function.patch 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/test/integration/rhel-7.6/new-function.patch 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1,26 @@ +Index: kernel-rhel7/drivers/tty/n_tty.c +=================================================================== +--- kernel-rhel7.orig/drivers/tty/n_tty.c ++++ kernel-rhel7/drivers/tty/n_tty.c +@@ -2128,7 +2128,7 @@ do_it_again: + * lock themselves) + */ + +-static ssize_t n_tty_write(struct tty_struct *tty, struct file *file, ++static ssize_t noinline kpatch_n_tty_write(struct tty_struct *tty, struct file *file, + const unsigned char *buf, size_t nr) + { + const unsigned char *b = buf; +@@ -2210,6 +2210,12 @@ break_out: + return (b - buf) ? b - buf : retval; + } + ++static ssize_t __attribute__((optimize("-fno-optimize-sibling-calls"))) n_tty_write(struct tty_struct *tty, struct file *file, ++ const unsigned char *buf, size_t nr) ++{ ++ return kpatch_n_tty_write(tty, file, buf, nr); ++} ++ + /** + * n_tty_poll - poll method for N_TTY + * @tty: terminal device diff -Nru kpatch-0.5.0/test/integration/rhel-7.6/new-globals.patch kpatch-0.8.0/test/integration/rhel-7.6/new-globals.patch --- kpatch-0.5.0/test/integration/rhel-7.6/new-globals.patch 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/test/integration/rhel-7.6/new-globals.patch 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1,34 @@ +diff -Nupr src.orig/fs/proc/cmdline.c src/fs/proc/cmdline.c +--- src.orig/fs/proc/cmdline.c 2017-09-22 15:27:21.698056175 -0400 ++++ src/fs/proc/cmdline.c 2017-09-22 15:27:47.028161067 -0400 +@@ -27,3 +27,10 @@ static int __init proc_cmdline_init(void + return 0; + } + module_init(proc_cmdline_init); ++ ++#include ++void kpatch_print_message(void) ++{ ++ if (!jiffies) ++ printk("hello there!\n"); ++} +diff -Nupr src.orig/fs/proc/meminfo.c src/fs/proc/meminfo.c +--- src.orig/fs/proc/meminfo.c 2017-09-22 15:27:21.699056179 -0400 ++++ src/fs/proc/meminfo.c 2017-09-22 15:27:47.029161071 -0400 +@@ -16,6 +16,8 @@ + #include + #include "internal.h" + ++void kpatch_print_message(void); ++ + void __attribute__((weak)) arch_report_meminfo(struct seq_file *m) + { + } +@@ -53,6 +55,7 @@ static int meminfo_proc_show(struct seq_ + /* + * Tagged format, for easy grepping and expansion. + */ ++ kpatch_print_message(); + seq_printf(m, + "MemTotal: %8lu kB\n" + "MemFree: %8lu kB\n" diff -Nru kpatch-0.5.0/test/integration/rhel-7.6/parainstructions-section.patch kpatch-0.8.0/test/integration/rhel-7.6/parainstructions-section.patch --- kpatch-0.5.0/test/integration/rhel-7.6/parainstructions-section.patch 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/test/integration/rhel-7.6/parainstructions-section.patch 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1,11 @@ +diff -Nupr src.orig/fs/proc/generic.c src/fs/proc/generic.c +--- src.orig/fs/proc/generic.c 2017-09-22 15:27:21.698056175 -0400 ++++ src/fs/proc/generic.c 2017-09-22 15:27:48.190165879 -0400 +@@ -194,6 +194,7 @@ int proc_alloc_inum(unsigned int *inum) + unsigned int i; + int error; + ++ printk("kpatch-test: testing change to .parainstructions section\n"); + retry: + if (!ida_pre_get(&proc_inum_ida, GFP_KERNEL)) + return -ENOMEM; diff -Nru kpatch-0.5.0/test/integration/rhel-7.6/shadow-newpid-LOADED.test kpatch-0.8.0/test/integration/rhel-7.6/shadow-newpid-LOADED.test --- kpatch-0.5.0/test/integration/rhel-7.6/shadow-newpid-LOADED.test 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/test/integration/rhel-7.6/shadow-newpid-LOADED.test 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1,3 @@ +#!/bin/bash + +grep -q newpid: /proc/$$/status diff -Nru kpatch-0.5.0/test/integration/rhel-7.6/shadow-newpid.patch kpatch-0.8.0/test/integration/rhel-7.6/shadow-newpid.patch --- kpatch-0.5.0/test/integration/rhel-7.6/shadow-newpid.patch 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/test/integration/rhel-7.6/shadow-newpid.patch 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1,72 @@ +diff --git a/fs/proc/array.c b/fs/proc/array.c +index 39684c79e8e2..138b60d1314d 100644 +--- a/fs/proc/array.c ++++ b/fs/proc/array.c +@@ -394,13 +394,20 @@ static inline void task_seccomp(struct seq_file *m, struct task_struct *p) + seq_putc(m, '\n'); + } + ++#include + static inline void task_context_switch_counts(struct seq_file *m, + struct task_struct *p) + { ++ int *newpid; ++ + seq_printf(m, "voluntary_ctxt_switches:\t%lu\n" + "nonvoluntary_ctxt_switches:\t%lu\n", + p->nvcsw, + p->nivcsw); ++ ++ newpid = klp_shadow_get(p, 0); ++ if (newpid) ++ seq_printf(m, "newpid:\t%d\n", *newpid); + } + + static void task_cpus_allowed(struct seq_file *m, struct task_struct *task) +diff --git a/kernel/exit.c b/kernel/exit.c +index 148a7842928d..e1dbab71b37d 100644 +--- a/kernel/exit.c ++++ b/kernel/exit.c +@@ -791,6 +791,7 @@ static void check_stack_usage(void) + static inline void check_stack_usage(void) {} + #endif + ++#include + void do_exit(long code) + { + struct task_struct *tsk = current; +@@ -888,6 +889,8 @@ void do_exit(long code) + check_stack_usage(); + exit_thread(); + ++ klp_shadow_free(tsk, 0, NULL); ++ + /* + * Flush inherited counters to the parent - before the parent + * gets woken up by child-exit notifications. +diff --git a/kernel/fork.c b/kernel/fork.c +index 9bff3b28c357..529a2c943d7c 100644 +--- a/kernel/fork.c ++++ b/kernel/fork.c +@@ -1757,6 +1757,7 @@ struct task_struct *fork_idle(int cpu) + * It copies the process, and if successful kick-starts + * it and waits for it to finish using the VM if required. + */ ++#include + long do_fork(unsigned long clone_flags, + unsigned long stack_start, + unsigned long stack_size, +@@ -1794,6 +1795,13 @@ long do_fork(unsigned long clone_flags, + if (!IS_ERR(p)) { + struct completion vfork; + struct pid *pid; ++ int *newpid; ++ static int ctr = 0; ++ ++ newpid = klp_shadow_get_or_alloc(p, 0, sizeof(*newpid), GFP_KERNEL, ++ NULL, NULL); ++ if (newpid) ++ *newpid = ctr++; + + trace_sched_process_fork(current, p); + diff -Nru kpatch-0.5.0/test/integration/rhel-7.6/smp-locks-section.patch kpatch-0.8.0/test/integration/rhel-7.6/smp-locks-section.patch --- kpatch-0.5.0/test/integration/rhel-7.6/smp-locks-section.patch 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/test/integration/rhel-7.6/smp-locks-section.patch 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1,14 @@ +diff -Nupr src.orig/drivers/tty/tty_buffer.c src/drivers/tty/tty_buffer.c +--- src.orig/drivers/tty/tty_buffer.c 2017-09-22 15:27:21.077053604 -0400 ++++ src/drivers/tty/tty_buffer.c 2017-09-22 15:27:50.542175618 -0400 +@@ -217,6 +217,10 @@ int tty_buffer_request_room(struct tty_p + /* OPTIMISATION: We could keep a per tty "zero" sized buffer to + remove this conditional if its worth it. This would be invisible + to the callers */ ++ ++ if (!size) ++ printk("kpatch-test: testing .smp_locks section changes\n"); ++ + b = buf->tail; + if (b != NULL) + left = b->size - b->used; diff -Nru kpatch-0.5.0/test/integration/rhel-7.6/special-static.patch kpatch-0.8.0/test/integration/rhel-7.6/special-static.patch --- kpatch-0.5.0/test/integration/rhel-7.6/special-static.patch 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/test/integration/rhel-7.6/special-static.patch 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1,23 @@ +Index: kernel-rhel7/kernel/fork.c +=================================================================== +--- kernel-rhel7.orig/kernel/fork.c ++++ kernel-rhel7/kernel/fork.c +@@ -1146,10 +1146,18 @@ static void posix_cpu_timers_init_group( + INIT_LIST_HEAD(&sig->cpu_timers[2]); + } + ++void kpatch_foo(void) ++{ ++ if (!jiffies) ++ printk("kpatch copy signal\n"); ++} ++ + static int copy_signal(unsigned long clone_flags, struct task_struct *tsk) + { + struct signal_struct *sig; + ++ kpatch_foo(); ++ + if (clone_flags & CLONE_THREAD) + return 0; + diff -Nru kpatch-0.5.0/test/integration/rhel-7.6/tracepoints-section.patch kpatch-0.8.0/test/integration/rhel-7.6/tracepoints-section.patch --- kpatch-0.5.0/test/integration/rhel-7.6/tracepoints-section.patch 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/test/integration/rhel-7.6/tracepoints-section.patch 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1,14 @@ +Index: kernel-rhel7/kernel/timer.c +=================================================================== +--- kernel-rhel7.orig/kernel/timer.c ++++ kernel-rhel7/kernel/timer.c +@@ -1454,6 +1454,9 @@ static void run_timer_softirq(struct sof + { + struct tvec_base *base = __this_cpu_read(tvec_bases); + ++ if (!base) ++ printk("kpatch-test: testing __tracepoints section changes\n"); ++ + if (time_after_eq(jiffies, base->timer_jiffies)) + __run_timers(base); + } diff -Nru kpatch-0.5.0/test/integration/rhel-7.6/warn-detect-FAIL.patch kpatch-0.8.0/test/integration/rhel-7.6/warn-detect-FAIL.patch --- kpatch-0.5.0/test/integration/rhel-7.6/warn-detect-FAIL.patch 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/test/integration/rhel-7.6/warn-detect-FAIL.patch 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1,8 @@ +diff -Nupr src.orig/arch/x86/kvm/x86.c src/arch/x86/kvm/x86.c +--- src.orig/arch/x86/kvm/x86.c 2017-09-22 15:27:20.852052672 -0400 ++++ src/arch/x86/kvm/x86.c 2017-09-22 15:27:55.489196104 -0400 +@@ -1,3 +1,4 @@ ++ + /* + * Kernel-based Virtual Machine driver for Linux + * diff -Nru kpatch-0.5.0/test/integration/rhel-7.7/bug-table-section.patch kpatch-0.8.0/test/integration/rhel-7.7/bug-table-section.patch --- kpatch-0.5.0/test/integration/rhel-7.7/bug-table-section.patch 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/test/integration/rhel-7.7/bug-table-section.patch 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1,13 @@ +Index: kernel/fs/proc/proc_sysctl.c +=================================================================== +--- kernel.orig/fs/proc/proc_sysctl.c ++++ kernel/fs/proc/proc_sysctl.c +@@ -301,6 +301,8 @@ void sysctl_head_put(struct ctl_table_he + + static struct ctl_table_header *sysctl_head_grab(struct ctl_table_header *head) + { ++ if (jiffies == 0) ++ printk("kpatch-test: testing __bug_table section changes\n"); + BUG_ON(!head); + spin_lock(&sysctl_lock); + if (!use_table(head)) diff -Nru kpatch-0.5.0/test/integration/rhel-7.7/cmdline-string-LOADED.test kpatch-0.8.0/test/integration/rhel-7.7/cmdline-string-LOADED.test --- kpatch-0.5.0/test/integration/rhel-7.7/cmdline-string-LOADED.test 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/test/integration/rhel-7.7/cmdline-string-LOADED.test 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1,3 @@ +#!/bin/bash + +grep kpatch=1 /proc/cmdline diff -Nru kpatch-0.5.0/test/integration/rhel-7.7/cmdline-string.patch kpatch-0.8.0/test/integration/rhel-7.7/cmdline-string.patch --- kpatch-0.5.0/test/integration/rhel-7.7/cmdline-string.patch 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/test/integration/rhel-7.7/cmdline-string.patch 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1,13 @@ +Index: kernel/fs/proc/cmdline.c +=================================================================== +--- kernel.orig/fs/proc/cmdline.c ++++ kernel/fs/proc/cmdline.c +@@ -5,7 +5,7 @@ + + static int cmdline_proc_show(struct seq_file *m, void *v) + { +- seq_printf(m, "%s\n", saved_command_line); ++ seq_printf(m, "%s kpatch=1\n", saved_command_line); + return 0; + } + diff -Nru kpatch-0.5.0/test/integration/rhel-7.7/data-new-LOADED.test kpatch-0.8.0/test/integration/rhel-7.7/data-new-LOADED.test --- kpatch-0.5.0/test/integration/rhel-7.7/data-new-LOADED.test 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/test/integration/rhel-7.7/data-new-LOADED.test 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1,3 @@ +#!/bin/bash + +grep "kpatch: 5" /proc/meminfo diff -Nru kpatch-0.5.0/test/integration/rhel-7.7/data-new.patch kpatch-0.8.0/test/integration/rhel-7.7/data-new.patch --- kpatch-0.5.0/test/integration/rhel-7.7/data-new.patch 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/test/integration/rhel-7.7/data-new.patch 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1,29 @@ +Index: kernel/fs/proc/meminfo.c +=================================================================== +--- kernel.orig/fs/proc/meminfo.c ++++ kernel/fs/proc/meminfo.c +@@ -20,6 +20,8 @@ void __attribute__((weak)) arch_report_m + { + } + ++static int foo = 5; ++ + static int meminfo_proc_show(struct seq_file *m, void *v) + { + struct sysinfo i; +@@ -110,6 +112,7 @@ static int meminfo_proc_show(struct seq_ + "CmaTotal: %8lu kB\n" + "CmaFree: %8lu kB\n" + #endif ++ "kpatch: %d" + , + K(i.totalram), + K(i.freeram), +@@ -175,6 +178,7 @@ static int meminfo_proc_show(struct seq_ + , K(totalcma_pages) + , K(global_page_state(NR_FREE_CMA_PAGES)) + #endif ++ ,foo + ); + + hugetlb_report_meminfo(m); diff -Nru kpatch-0.5.0/test/integration/rhel-7.7/data-read-mostly.patch kpatch-0.8.0/test/integration/rhel-7.7/data-read-mostly.patch --- kpatch-0.5.0/test/integration/rhel-7.7/data-read-mostly.patch 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/test/integration/rhel-7.7/data-read-mostly.patch 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1,12 @@ +Index: kernel/net/core/dev.c +=================================================================== +--- kernel.orig/net/core/dev.c ++++ kernel/net/core/dev.c +@@ -4327,6 +4327,7 @@ skip_classify: + case RX_HANDLER_PASS: + break; + default: ++ printk("BUG!\n"); + BUG(); + } + } diff -Nru kpatch-0.5.0/test/integration/rhel-7.7/fixup-section.patch kpatch-0.8.0/test/integration/rhel-7.7/fixup-section.patch --- kpatch-0.5.0/test/integration/rhel-7.7/fixup-section.patch 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/test/integration/rhel-7.7/fixup-section.patch 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1,12 @@ +Index: kernel/fs/readdir.c +=================================================================== +--- kernel.orig/fs/readdir.c ++++ kernel/fs/readdir.c +@@ -176,6 +176,7 @@ static int filldir(void * __buf, const c + goto efault; + } + dirent = buf->current_dir; ++ asm("nop"); + if (__put_user(d_ino, &dirent->d_ino)) + goto efault; + if (__put_user(reclen, &dirent->d_reclen)) diff -Nru kpatch-0.5.0/test/integration/rhel-7.7/gcc-constprop.patch.disabled kpatch-0.8.0/test/integration/rhel-7.7/gcc-constprop.patch.disabled --- kpatch-0.5.0/test/integration/rhel-7.7/gcc-constprop.patch.disabled 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/test/integration/rhel-7.7/gcc-constprop.patch.disabled 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1,13 @@ +diff -Nupr src.orig/kernel/time/timekeeping.c src/kernel/time/timekeeping.c +--- src.orig/kernel/time/timekeeping.c 2017-09-22 15:27:21.602055778 -0400 ++++ src/kernel/time/timekeeping.c 2017-09-22 15:27:27.522080292 -0400 +@@ -877,6 +877,9 @@ void do_gettimeofday(struct timeval *tv) + { + struct timespec64 now; + ++ if (!tv) ++ return; ++ + getnstimeofday64(&now); + tv->tv_sec = now.tv_sec; + tv->tv_usec = now.tv_nsec/1000; diff -Nru kpatch-0.5.0/test/integration/rhel-7.7/gcc-isra.patch kpatch-0.8.0/test/integration/rhel-7.7/gcc-isra.patch --- kpatch-0.5.0/test/integration/rhel-7.7/gcc-isra.patch 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/test/integration/rhel-7.7/gcc-isra.patch 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1,12 @@ +Index: kernel/fs/proc/proc_sysctl.c +=================================================================== +--- kernel.orig/fs/proc/proc_sysctl.c ++++ kernel/fs/proc/proc_sysctl.c +@@ -46,6 +46,7 @@ void proc_sys_poll_notify(struct ctl_tab + if (!poll) + return; + ++ printk("kpatch-test: testing gcc .isra function name mangling\n"); + atomic_inc(&poll->event); + wake_up_interruptible(&poll->wait); + } diff -Nru kpatch-0.5.0/test/integration/rhel-7.7/gcc-mangled-3.patch kpatch-0.8.0/test/integration/rhel-7.7/gcc-mangled-3.patch --- kpatch-0.5.0/test/integration/rhel-7.7/gcc-mangled-3.patch 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/test/integration/rhel-7.7/gcc-mangled-3.patch 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1,14 @@ +Index: kernel/mm/slub.c +=================================================================== +--- kernel.orig/mm/slub.c ++++ kernel/mm/slub.c +@@ -5675,6 +5675,9 @@ void get_slabinfo(struct kmem_cache *s, + unsigned long nr_free = 0; + int node; + ++ if (!jiffies) ++ printk("slabinfo\n"); ++ + for_each_online_node(node) { + struct kmem_cache_node *n = get_node(s, node); + diff -Nru kpatch-0.5.0/test/integration/rhel-7.7/gcc-static-local-var-2.patch kpatch-0.8.0/test/integration/rhel-7.7/gcc-static-local-var-2.patch --- kpatch-0.5.0/test/integration/rhel-7.7/gcc-static-local-var-2.patch 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/test/integration/rhel-7.7/gcc-static-local-var-2.patch 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1,14 @@ +Index: kernel/mm/mmap.c +=================================================================== +--- kernel.orig/mm/mmap.c ++++ kernel/mm/mmap.c +@@ -1716,6 +1716,9 @@ unsigned long mmap_region(struct file *f + struct rb_node **rb_link, *rb_parent; + unsigned long charged = 0; + ++ if (!jiffies) ++ printk("kpatch mmap foo\n"); ++ + /* Check against address space limit. */ + if (!may_expand_vm(mm, len >> PAGE_SHIFT)) { + unsigned long nr_pages; diff -Nru kpatch-0.5.0/test/integration/rhel-7.7/gcc-static-local-var-3.patch kpatch-0.8.0/test/integration/rhel-7.7/gcc-static-local-var-3.patch --- kpatch-0.5.0/test/integration/rhel-7.7/gcc-static-local-var-3.patch 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/test/integration/rhel-7.7/gcc-static-local-var-3.patch 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1,20 @@ +Index: kernel/kernel/sys.c +=================================================================== +--- kernel.orig/kernel/sys.c ++++ kernel/kernel/sys.c +@@ -559,8 +559,15 @@ SYSCALL_DEFINE4(reboot, int, magic1, int + return ret; + } + ++void kpatch_bar(void) ++{ ++ if (!jiffies) ++ printk("kpatch_foo\n"); ++} ++ + static void deferred_cad(struct work_struct *dummy) + { ++ kpatch_bar(); + kernel_restart(NULL); + } + diff -Nru kpatch-0.5.0/test/integration/rhel-7.7/gcc-static-local-var-4.patch kpatch-0.8.0/test/integration/rhel-7.7/gcc-static-local-var-4.patch --- kpatch-0.5.0/test/integration/rhel-7.7/gcc-static-local-var-4.patch 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/test/integration/rhel-7.7/gcc-static-local-var-4.patch 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1,21 @@ +Index: kernel/fs/aio.c +=================================================================== +--- kernel.orig/fs/aio.c ++++ kernel/fs/aio.c +@@ -223,9 +223,16 @@ static int __init aio_setup(void) + } + __initcall(aio_setup); + ++void kpatch_aio_foo(void) ++{ ++ if (!jiffies) ++ printk("kpatch aio foo\n"); ++} ++ + static void put_aio_ring_file(struct kioctx *ctx) + { + struct file *aio_ring_file = ctx->aio_ring_file; ++ kpatch_aio_foo(); + if (aio_ring_file) { + truncate_setsize(aio_ring_file->f_inode, 0); + diff -Nru kpatch-0.5.0/test/integration/rhel-7.7/gcc-static-local-var-4.test kpatch-0.8.0/test/integration/rhel-7.7/gcc-static-local-var-4.test --- kpatch-0.5.0/test/integration/rhel-7.7/gcc-static-local-var-4.test 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/test/integration/rhel-7.7/gcc-static-local-var-4.test 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1,7 @@ +#!/bin/bash + +if $(nm test-gcc-static-local-var-4.ko | grep -q free_ioctx); then + exit 1 +else + exit 0 +fi diff -Nru kpatch-0.5.0/test/integration/rhel-7.7/gcc-static-local-var-5.patch kpatch-0.8.0/test/integration/rhel-7.7/gcc-static-local-var-5.patch --- kpatch-0.5.0/test/integration/rhel-7.7/gcc-static-local-var-5.patch 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/test/integration/rhel-7.7/gcc-static-local-var-5.patch 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1,46 @@ +Index: kernel/kernel/audit.c +=================================================================== +--- kernel.orig/kernel/audit.c ++++ kernel/kernel/audit.c +@@ -205,6 +205,12 @@ void audit_panic(const char *message) + } + } + ++void kpatch_audit_foo(void) ++{ ++ if (!jiffies) ++ printk("kpatch audit foo\n"); ++} ++ + static inline int audit_rate_check(void) + { + static unsigned long last_check = 0; +@@ -215,6 +221,7 @@ static inline int audit_rate_check(void) + unsigned long elapsed; + int retval = 0; + ++ kpatch_audit_foo(); + if (!audit_rate_limit) return 1; + + spin_lock_irqsave(&lock, flags); +@@ -234,6 +241,11 @@ static inline int audit_rate_check(void) + return retval; + } + ++noinline void kpatch_audit_check(void) ++{ ++ audit_rate_check(); ++} ++ + /** + * audit_log_lost - conditionally log lost audit message event + * @message: the message stating reason for lost audit message +@@ -282,6 +294,8 @@ static int audit_log_config_change(char + struct audit_buffer *ab; + int rc = 0; + ++ kpatch_audit_check(); ++ + ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE); + if (unlikely(!ab)) + return rc; diff -Nru kpatch-0.5.0/test/integration/rhel-7.7/gcc-static-local-var-6.patch kpatch-0.8.0/test/integration/rhel-7.7/gcc-static-local-var-6.patch --- kpatch-0.5.0/test/integration/rhel-7.7/gcc-static-local-var-6.patch 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/test/integration/rhel-7.7/gcc-static-local-var-6.patch 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1,23 @@ +Index: kernel/net/ipv6/netfilter.c +=================================================================== +--- kernel.orig/net/ipv6/netfilter.c ++++ kernel/net/ipv6/netfilter.c +@@ -112,6 +112,8 @@ static int nf_ip6_reroute(struct sk_buff + return 0; + } + ++#include "kpatch-macros.h" ++ + static int nf_ip6_route(struct net *net, struct dst_entry **dst, + struct flowi *fl, bool strict) + { +@@ -125,6 +127,9 @@ static int nf_ip6_route(struct net *net, + struct dst_entry *result; + int err; + ++ if (!jiffies) ++ printk("kpatch nf_ip6_route foo\n"); ++ + result = ip6_route_output(net, sk, &fl->u.ip6); + err = result->error; + if (err) diff -Nru kpatch-0.5.0/test/integration/rhel-7.7/macro-callbacks.patch kpatch-0.8.0/test/integration/rhel-7.7/macro-callbacks.patch --- kpatch-0.5.0/test/integration/rhel-7.7/macro-callbacks.patch 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/test/integration/rhel-7.7/macro-callbacks.patch 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1,166 @@ +kpatch/livepatch callback test patch: + + vmlinux + pcspkr (mod) + joydev (mod) + +Note: update joydev's pre-patch callback to return -ENODEV to test failure path + +Index: kernel/fs/aio.c +=================================================================== +--- kernel.orig/fs/aio.c ++++ kernel/fs/aio.c +@@ -42,6 +42,50 @@ + #include + #include + ++#include ++#include "kpatch-macros.h" ++ ++static const char *const module_state[] = { ++ [MODULE_STATE_LIVE] = "[MODULE_STATE_LIVE] Normal state", ++ [MODULE_STATE_COMING] = "[MODULE_STATE_COMING] Full formed, running module_init", ++ [MODULE_STATE_GOING] = "[MODULE_STATE_GOING] Going away", ++ [MODULE_STATE_UNFORMED] = "[MODULE_STATE_UNFORMED] Still setting it up", ++}; ++ ++static void callback_info(const char *callback, patch_object *obj) ++{ ++ if (obj->mod) ++ pr_info("%s: %s -> %s\n", callback, obj->mod->name, ++ module_state[obj->mod->state]); ++ else ++ pr_info("%s: vmlinux\n", callback); ++} ++ ++static int pre_patch_callback(patch_object *obj) ++{ ++ callback_info(__func__, obj); ++ return 0; ++} ++KPATCH_PRE_PATCH_CALLBACK(pre_patch_callback); ++ ++static void post_patch_callback(patch_object *obj) ++{ ++ callback_info(__func__, obj); ++} ++KPATCH_POST_PATCH_CALLBACK(post_patch_callback); ++ ++static void pre_unpatch_callback(patch_object *obj) ++{ ++ callback_info(__func__, obj); ++} ++KPATCH_PRE_UNPATCH_CALLBACK(pre_unpatch_callback); ++ ++static void post_unpatch_callback(patch_object *obj) ++{ ++ callback_info(__func__, obj); ++} ++KPATCH_POST_UNPATCH_CALLBACK(post_unpatch_callback); ++ + #define AIO_RING_MAGIC 0xa10a10a1 + #define AIO_RING_COMPAT_FEATURES 1 + #define AIO_RING_INCOMPAT_FEATURES 0 +Index: kernel/drivers/input/joydev.c +=================================================================== +--- kernel.orig/drivers/input/joydev.c ++++ kernel/drivers/input/joydev.c +@@ -954,3 +954,47 @@ static void __exit joydev_exit(void) + + module_init(joydev_init); + module_exit(joydev_exit); ++ ++#include ++#include "kpatch-macros.h" ++ ++static const char *const module_state[] = { ++ [MODULE_STATE_LIVE] = "[MODULE_STATE_LIVE] Normal state", ++ [MODULE_STATE_COMING] = "[MODULE_STATE_COMING] Full formed, running module_init", ++ [MODULE_STATE_GOING] = "[MODULE_STATE_GOING] Going away", ++ [MODULE_STATE_UNFORMED] = "[MODULE_STATE_UNFORMED] Still setting it up", ++}; ++ ++static void callback_info(const char *callback, patch_object *obj) ++{ ++ if (obj->mod) ++ pr_info("%s: %s -> %s\n", callback, obj->mod->name, ++ module_state[obj->mod->state]); ++ else ++ pr_info("%s: vmlinux\n", callback); ++} ++ ++static int pre_patch_callback(patch_object *obj) ++{ ++ callback_info(__func__, obj); ++ return 0; /* return -ENODEV; */ ++} ++KPATCH_PRE_PATCH_CALLBACK(pre_patch_callback); ++ ++static void post_patch_callback(patch_object *obj) ++{ ++ callback_info(__func__, obj); ++} ++KPATCH_POST_PATCH_CALLBACK(post_patch_callback); ++ ++static void pre_unpatch_callback(patch_object *obj) ++{ ++ callback_info(__func__, obj); ++} ++KPATCH_PRE_UNPATCH_CALLBACK(pre_unpatch_callback); ++ ++static void post_unpatch_callback(patch_object *obj) ++{ ++ callback_info(__func__, obj); ++} ++KPATCH_POST_UNPATCH_CALLBACK(post_unpatch_callback); +Index: kernel/drivers/input/misc/pcspkr.c +=================================================================== +--- kernel.orig/drivers/input/misc/pcspkr.c ++++ kernel/drivers/input/misc/pcspkr.c +@@ -136,3 +136,46 @@ static struct platform_driver pcspkr_pla + }; + module_platform_driver(pcspkr_platform_driver); + ++#include ++#include "kpatch-macros.h" ++ ++static const char *const module_state[] = { ++ [MODULE_STATE_LIVE] = "[MODULE_STATE_LIVE] Normal state", ++ [MODULE_STATE_COMING] = "[MODULE_STATE_COMING] Full formed, running module_init", ++ [MODULE_STATE_GOING] = "[MODULE_STATE_GOING] Going away", ++ [MODULE_STATE_UNFORMED] = "[MODULE_STATE_UNFORMED] Still setting it up", ++}; ++ ++static void callback_info(const char *callback, patch_object *obj) ++{ ++ if (obj->mod) ++ pr_info("%s: %s -> %s\n", callback, obj->mod->name, ++ module_state[obj->mod->state]); ++ else ++ pr_info("%s: vmlinux\n", callback); ++} ++ ++static int pre_patch_callback(patch_object *obj) ++{ ++ callback_info(__func__, obj); ++ return 0; ++} ++KPATCH_PRE_PATCH_CALLBACK(pre_patch_callback); ++ ++static void post_patch_callback(patch_object *obj) ++{ ++ callback_info(__func__, obj); ++} ++KPATCH_POST_PATCH_CALLBACK(post_patch_callback); ++ ++static void pre_unpatch_callback(patch_object *obj) ++{ ++ callback_info(__func__, obj); ++} ++KPATCH_PRE_UNPATCH_CALLBACK(pre_unpatch_callback); ++ ++static void post_unpatch_callback(patch_object *obj) ++{ ++ callback_info(__func__, obj); ++} ++KPATCH_POST_UNPATCH_CALLBACK(post_unpatch_callback); diff -Nru kpatch-0.5.0/test/integration/rhel-7.7/macro-printk.patch kpatch-0.8.0/test/integration/rhel-7.7/macro-printk.patch --- kpatch-0.5.0/test/integration/rhel-7.7/macro-printk.patch 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/test/integration/rhel-7.7/macro-printk.patch 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1,151 @@ +Index: kernel/net/ipv4/fib_frontend.c +=================================================================== +--- kernel.orig/net/ipv4/fib_frontend.c ++++ kernel/net/ipv4/fib_frontend.c +@@ -686,6 +686,7 @@ errout: + return err; + } + ++#include "kpatch-macros.h" + static int inet_rtm_newroute(struct sk_buff *skb, struct nlmsghdr *nlh) + { + struct net *net = sock_net(skb->sk); +@@ -704,6 +705,7 @@ static int inet_rtm_newroute(struct sk_b + } + + err = fib_table_insert(net, tb, &cfg); ++ KPATCH_PRINTK("[inet_rtm_newroute]: err is %d\n", err); + errout: + return err; + } +Index: kernel/net/ipv4/fib_semantics.c +=================================================================== +--- kernel.orig/net/ipv4/fib_semantics.c ++++ kernel/net/ipv4/fib_semantics.c +@@ -985,6 +985,7 @@ fib_convert_metrics(struct fib_info *fi, + return 0; + } + ++#include "kpatch-macros.h" + struct fib_info *fib_create_info(struct fib_config *cfg) + { + int err; +@@ -1009,6 +1010,7 @@ struct fib_info *fib_create_info(struct + #endif + + err = -ENOBUFS; ++ KPATCH_PRINTK("[fib_create_info]: create error err is %d\n",err); + if (fib_info_cnt >= fib_info_hash_size) { + unsigned int new_size = fib_info_hash_size << 1; + struct hlist_head *new_info_hash; +@@ -1029,6 +1031,7 @@ struct fib_info *fib_create_info(struct + if (!fib_info_hash_size) + goto failure; + } ++ KPATCH_PRINTK("[fib_create_info]: 2 create error err is %d\n",err); + + fi = kzalloc(sizeof(*fi)+nhs*sizeof(struct fib_nh), GFP_KERNEL); + if (fi == NULL) +@@ -1044,6 +1047,8 @@ struct fib_info *fib_create_info(struct + fi->fib_metrics = (struct dst_metrics *)&dst_default_metrics; + } + fib_info_cnt++; ++ KPATCH_PRINTK("[fib_create_info]: 3 create error err is %d\n",err); ++ + fi->fib_net = net; + fi->fib_protocol = cfg->fc_protocol; + fi->fib_scope = cfg->fc_scope; +@@ -1059,8 +1064,10 @@ struct fib_info *fib_create_info(struct + if (!nexthop_nh->nh_pcpu_rth_output) + goto failure; + } endfor_nexthops(fi) ++ KPATCH_PRINTK("[fib_create_info]: 4 create error err is %d\n",err); + + err = fib_convert_metrics(fi, cfg); ++ KPATCH_PRINTK("[fib_create_info]: 5 create error err is %d\n",err); + if (err) + goto failure; + +@@ -1111,6 +1118,7 @@ struct fib_info *fib_create_info(struct + nh->nh_weight = 1; + #endif + } ++ KPATCH_PRINTK("[fib_create_info]: 6 create error err is %d\n",err); + + if (fib_props[cfg->fc_type].error) { + if (cfg->fc_gw || cfg->fc_oif || cfg->fc_mp) +@@ -1128,6 +1136,7 @@ struct fib_info *fib_create_info(struct + goto err_inval; + } + } ++ KPATCH_PRINTK("[fib_create_info]: 7 create error err is %d\n",err); + + if (cfg->fc_scope > RT_SCOPE_HOST) + goto err_inval; +@@ -1150,6 +1159,7 @@ struct fib_info *fib_create_info(struct + goto failure; + } endfor_nexthops(fi) + } ++ KPATCH_PRINTK("[fib_create_info]: 8 create error err is %d\n",err); + + if (fi->fib_prefsrc) { + if (cfg->fc_type != RTN_LOCAL || !cfg->fc_dst || +@@ -1162,6 +1172,7 @@ struct fib_info *fib_create_info(struct + fib_info_update_nh_saddr(net, nexthop_nh); + fib_add_weight(fi, nexthop_nh); + } endfor_nexthops(fi) ++ KPATCH_PRINTK("[fib_create_info]: 9 create error err is %d\n",err); + + fib_rebalance(fi); + +@@ -1173,6 +1184,7 @@ link_it: + ofi->fib_treeref++; + return ofi; + } ++ KPATCH_PRINTK("[fib_create_info]: 10 create error err is %d\n",err); + + fi->fib_treeref++; + atomic_inc(&fi->fib_clntref); +@@ -1196,6 +1208,7 @@ link_it: + hlist_add_head(&nexthop_nh->nh_hash, head); + } endfor_nexthops(fi) + spin_unlock_bh(&fib_info_lock); ++ KPATCH_PRINTK("[fib_create_info]: 11 create error err is %d\n",err); + return fi; + + err_inval: +@@ -1206,6 +1219,7 @@ failure: + fi->fib_dead = 1; + free_fib_info(fi); + } ++ KPATCH_PRINTK("[fib_create_info]: 12 create error err is %d\n",err); + + return ERR_PTR(err); + } +Index: kernel/net/ipv4/fib_trie.c +=================================================================== +--- kernel.orig/net/ipv4/fib_trie.c ++++ kernel/net/ipv4/fib_trie.c +@@ -1105,6 +1105,7 @@ static int fib_insert_alias(struct trie + } + + /* Caller must hold RTNL. */ ++#include "kpatch-macros.h" + int fib_table_insert(struct net *net, struct fib_table *tb, + struct fib_config *cfg) + { +@@ -1130,11 +1131,14 @@ int fib_table_insert(struct net *net, st + if ((plen < KEYLENGTH) && (key << plen)) + return -EINVAL; + ++ KPATCH_PRINTK("[fib_table_insert]: start\n"); + fi = fib_create_info(cfg); + if (IS_ERR(fi)) { + err = PTR_ERR(fi); ++ KPATCH_PRINTK("[fib_table_insert]: create error err is %d\n",err); + goto err; + } ++ KPATCH_PRINTK("[fib_table_insert]: cross\n"); + + l = fib_find_node(t, &tp, key); + fa = l ? fib_find_alias(&l->leaf, slen, tos, fi->fib_priority, diff -Nru kpatch-0.5.0/test/integration/rhel-7.7/meminfo-init2-FAIL.patch kpatch-0.8.0/test/integration/rhel-7.7/meminfo-init2-FAIL.patch --- kpatch-0.5.0/test/integration/rhel-7.7/meminfo-init2-FAIL.patch 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/test/integration/rhel-7.7/meminfo-init2-FAIL.patch 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1,20 @@ +Index: kernel/fs/proc/meminfo.c +=================================================================== +--- kernel.orig/fs/proc/meminfo.c ++++ kernel/fs/proc/meminfo.c +@@ -30,6 +30,7 @@ static int meminfo_proc_show(struct seq_ + unsigned long pages[NR_LRU_LISTS]; + int lru; + ++ printk("a\n"); + /* + * display in kilobytes. + */ +@@ -199,6 +200,7 @@ static const struct file_operations memi + + static int __init proc_meminfo_init(void) + { ++ printk("a\n"); + proc_create("meminfo", 0, NULL, &meminfo_proc_fops); + return 0; + } diff -Nru kpatch-0.5.0/test/integration/rhel-7.7/meminfo-init-FAIL.patch kpatch-0.8.0/test/integration/rhel-7.7/meminfo-init-FAIL.patch --- kpatch-0.5.0/test/integration/rhel-7.7/meminfo-init-FAIL.patch 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/test/integration/rhel-7.7/meminfo-init-FAIL.patch 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1,12 @@ +Index: kernel/fs/proc/meminfo.c +=================================================================== +--- kernel.orig/fs/proc/meminfo.c ++++ kernel/fs/proc/meminfo.c +@@ -199,6 +199,7 @@ static const struct file_operations memi + + static int __init proc_meminfo_init(void) + { ++ printk("a\n"); + proc_create("meminfo", 0, NULL, &meminfo_proc_fops); + return 0; + } diff -Nru kpatch-0.5.0/test/integration/rhel-7.7/meminfo-string-LOADED.test kpatch-0.8.0/test/integration/rhel-7.7/meminfo-string-LOADED.test --- kpatch-0.5.0/test/integration/rhel-7.7/meminfo-string-LOADED.test 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/test/integration/rhel-7.7/meminfo-string-LOADED.test 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1,3 @@ +#!/bin/bash + +grep VMALLOCCHUNK /proc/meminfo diff -Nru kpatch-0.5.0/test/integration/rhel-7.7/meminfo-string.patch kpatch-0.8.0/test/integration/rhel-7.7/meminfo-string.patch --- kpatch-0.5.0/test/integration/rhel-7.7/meminfo-string.patch 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/test/integration/rhel-7.7/meminfo-string.patch 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1,13 @@ +Index: kernel/fs/proc/meminfo.c +=================================================================== +--- kernel.orig/fs/proc/meminfo.c ++++ kernel/fs/proc/meminfo.c +@@ -99,7 +99,7 @@ static int meminfo_proc_show(struct seq_ + "Committed_AS: %8lu kB\n" + "VmallocTotal: %8lu kB\n" + "VmallocUsed: %8lu kB\n" +- "VmallocChunk: %8lu kB\n" ++ "VMALLOCCHUNK: %8lu kB\n" + #ifdef CONFIG_MEMORY_FAILURE + "HardwareCorrupted: %5lu kB\n" + #endif diff -Nru kpatch-0.5.0/test/integration/rhel-7.7/module-call-external.patch kpatch-0.8.0/test/integration/rhel-7.7/module-call-external.patch --- kpatch-0.5.0/test/integration/rhel-7.7/module-call-external.patch 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/test/integration/rhel-7.7/module-call-external.patch 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1,35 @@ +Index: kernel/fs/nfsd/export.c +=================================================================== +--- kernel.orig/fs/nfsd/export.c ++++ kernel/fs/nfsd/export.c +@@ -1184,6 +1184,8 @@ static void exp_flags(struct seq_file *m + } + } + ++extern char *kpatch_string(void); ++ + static int e_show(struct seq_file *m, void *p) + { + struct cache_head *cp = p; +@@ -1193,6 +1195,7 @@ static int e_show(struct seq_file *m, vo + if (p == SEQ_START_TOKEN) { + seq_puts(m, "# Version 1.1\n"); + seq_puts(m, "# Path Client(Flags) # IPs\n"); ++ seq_puts(m, kpatch_string()); + return 0; + } + +Index: kernel/net/netlink/af_netlink.c +=================================================================== +--- kernel.orig/net/netlink/af_netlink.c ++++ kernel/net/netlink/af_netlink.c +@@ -2568,4 +2568,9 @@ panic: + panic("netlink_init: Cannot allocate nl_table\n"); + } + ++char *kpatch_string(void) ++{ ++ return "# kpatch\n"; ++} ++ + core_initcall(netlink_proto_init); diff -Nru kpatch-0.5.0/test/integration/rhel-7.7/multiple.test kpatch-0.8.0/test/integration/rhel-7.7/multiple.test --- kpatch-0.5.0/test/integration/rhel-7.7/multiple.test 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/test/integration/rhel-7.7/multiple.test 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1,65 @@ +#!/bin/bash + +SCRIPTDIR="$(readlink -f $(dirname $(type -p $0)))" +ROOTDIR="$(readlink -f $SCRIPTDIR/../..)" +KPATCH="sudo $ROOTDIR/kpatch/kpatch" + +MODULE_PREFIX="test-" +MODULE_POSTFIX=".ko" +TEST_POSTFIX="-LOADED.test" + +set -o errexit + +die() { + echo "ERROR: $@" >&2 + exit 1 +} + +ko_to_test() { + tmp=${1%${MODULE_POSTFIX}}${TEST_POSTFIX} + echo ${tmp#${MODULE_PREFIX}} +} + +# make sure any modules added here are disjoint +declare -a modules +declare -a blacklist=(meminfo-string-LOADED.test) + +for file in "${SCRIPTDIR}"/*"${TEST_POSTFIX}"; do + name=$(basename ${file}) + skip=0 + for bname in "${blacklist[@]}"; do + if [ "${bname}" == "${name}" ]; then + skip=1 + break + fi + done + if [ ${skip} -eq 0 ]; then + modules+=(${MODULE_PREFIX}${name%${TEST_POSTFIX}}${MODULE_POSTFIX}) + fi +done + +for mod in "${modules[@]}"; do + testprog=$(ko_to_test $mod) + $SCRIPTDIR/$testprog && die "$SCRIPTDIR/$testprog succeeded before loading any modules" +done + +for mod in "${modules[@]}"; do + $KPATCH load $mod +done + +for mod in "${modules[@]}"; do + testprog=$(ko_to_test $mod) + $SCRIPTDIR/$testprog || die "$SCRIPTDIR/$testprog failed after loading modules" +done + +for ((idx=${#modules[@]}-1 ; idx>=0 ; idx--)); do + mod=${modules[idx]} + $KPATCH unload $mod +done + +for mod in "${modules[@]}"; do + testprog=$(ko_to_test $mod) + $SCRIPTDIR/$testprog && die "$SCRIPTDIR/$testprog succeeded after unloading modules" +done + +exit 0 diff -Nru kpatch-0.5.0/test/integration/rhel-7.7/new-function.patch kpatch-0.8.0/test/integration/rhel-7.7/new-function.patch --- kpatch-0.5.0/test/integration/rhel-7.7/new-function.patch 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/test/integration/rhel-7.7/new-function.patch 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1,26 @@ +Index: kernel/drivers/tty/n_tty.c +=================================================================== +--- kernel.orig/drivers/tty/n_tty.c ++++ kernel/drivers/tty/n_tty.c +@@ -2175,7 +2175,7 @@ do_it_again: + * lock themselves) + */ + +-static ssize_t n_tty_write(struct tty_struct *tty, struct file *file, ++static ssize_t noinline kpatch_n_tty_write(struct tty_struct *tty, struct file *file, + const unsigned char *buf, size_t nr) + { + const unsigned char *b = buf; +@@ -2264,6 +2264,12 @@ break_out: + return (b - buf) ? b - buf : retval; + } + ++static ssize_t __attribute__((optimize("-fno-optimize-sibling-calls"))) n_tty_write(struct tty_struct *tty, struct file *file, ++ const unsigned char *buf, size_t nr) ++{ ++ return kpatch_n_tty_write(tty, file, buf, nr); ++} ++ + /** + * n_tty_poll - poll method for N_TTY + * @tty: terminal device diff -Nru kpatch-0.5.0/test/integration/rhel-7.7/new-globals.patch kpatch-0.8.0/test/integration/rhel-7.7/new-globals.patch --- kpatch-0.5.0/test/integration/rhel-7.7/new-globals.patch 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/test/integration/rhel-7.7/new-globals.patch 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1,36 @@ +Index: kernel/fs/proc/cmdline.c +=================================================================== +--- kernel.orig/fs/proc/cmdline.c ++++ kernel/fs/proc/cmdline.c +@@ -27,3 +27,10 @@ static int __init proc_cmdline_init(void + return 0; + } + module_init(proc_cmdline_init); ++ ++#include ++void kpatch_print_message(void) ++{ ++ if (!jiffies) ++ printk("hello there!\n"); ++} +Index: kernel/fs/proc/meminfo.c +=================================================================== +--- kernel.orig/fs/proc/meminfo.c ++++ kernel/fs/proc/meminfo.c +@@ -16,6 +16,8 @@ + #include + #include "internal.h" + ++void kpatch_print_message(void); ++ + void __attribute__((weak)) arch_report_meminfo(struct seq_file *m) + { + } +@@ -53,6 +55,7 @@ static int meminfo_proc_show(struct seq_ + /* + * Tagged format, for easy grepping and expansion. + */ ++ kpatch_print_message(); + seq_printf(m, + "MemTotal: %8lu kB\n" + "MemFree: %8lu kB\n" diff -Nru kpatch-0.5.0/test/integration/rhel-7.7/parainstructions-section.patch kpatch-0.8.0/test/integration/rhel-7.7/parainstructions-section.patch --- kpatch-0.5.0/test/integration/rhel-7.7/parainstructions-section.patch 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/test/integration/rhel-7.7/parainstructions-section.patch 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1,12 @@ +Index: kernel/fs/proc/generic.c +=================================================================== +--- kernel.orig/fs/proc/generic.c ++++ kernel/fs/proc/generic.c +@@ -194,6 +194,7 @@ int proc_alloc_inum(unsigned int *inum) + unsigned int i; + int error; + ++ printk("kpatch-test: testing change to .parainstructions section\n"); + retry: + if (!ida_pre_get(&proc_inum_ida, GFP_KERNEL)) + return -ENOMEM; diff -Nru kpatch-0.5.0/test/integration/rhel-7.7/shadow-newpid-LOADED.test kpatch-0.8.0/test/integration/rhel-7.7/shadow-newpid-LOADED.test --- kpatch-0.5.0/test/integration/rhel-7.7/shadow-newpid-LOADED.test 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/test/integration/rhel-7.7/shadow-newpid-LOADED.test 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1,3 @@ +#!/bin/bash + +grep -q newpid: /proc/$$/status diff -Nru kpatch-0.5.0/test/integration/rhel-7.7/shadow-newpid.patch kpatch-0.8.0/test/integration/rhel-7.7/shadow-newpid.patch --- kpatch-0.5.0/test/integration/rhel-7.7/shadow-newpid.patch 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/test/integration/rhel-7.7/shadow-newpid.patch 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1,72 @@ +Index: kernel/fs/proc/array.c +=================================================================== +--- kernel.orig/fs/proc/array.c ++++ kernel/fs/proc/array.c +@@ -395,13 +395,20 @@ static inline void task_seccomp(struct s + seq_putc(m, '\n'); + } + ++#include + static inline void task_context_switch_counts(struct seq_file *m, + struct task_struct *p) + { ++ int *newpid; ++ + seq_printf(m, "voluntary_ctxt_switches:\t%lu\n" + "nonvoluntary_ctxt_switches:\t%lu\n", + p->nvcsw, + p->nivcsw); ++ ++ newpid = klp_shadow_get(p, 0); ++ if (newpid) ++ seq_printf(m, "newpid:\t%d\n", *newpid); + } + + static void task_cpus_allowed(struct seq_file *m, struct task_struct *task) +Index: kernel/kernel/exit.c +=================================================================== +--- kernel.orig/kernel/exit.c ++++ kernel/kernel/exit.c +@@ -791,6 +791,7 @@ static void check_stack_usage(void) + static inline void check_stack_usage(void) {} + #endif + ++#include + void do_exit(long code) + { + struct task_struct *tsk = current; +@@ -888,6 +889,8 @@ void do_exit(long code) + check_stack_usage(); + exit_thread(); + ++ klp_shadow_free(tsk, 0, NULL); ++ + /* + * Flush inherited counters to the parent - before the parent + * gets woken up by child-exit notifications. +Index: kernel/kernel/fork.c +=================================================================== +--- kernel.orig/kernel/fork.c ++++ kernel/kernel/fork.c +@@ -1760,6 +1760,7 @@ struct task_struct *fork_idle(int cpu) + * It copies the process, and if successful kick-starts + * it and waits for it to finish using the VM if required. + */ ++#include + long do_fork(unsigned long clone_flags, + unsigned long stack_start, + unsigned long stack_size, +@@ -1797,6 +1798,13 @@ long do_fork(unsigned long clone_flags, + if (!IS_ERR(p)) { + struct completion vfork; + struct pid *pid; ++ int *newpid; ++ static int ctr = 0; ++ ++ newpid = klp_shadow_get_or_alloc(p, 0, sizeof(*newpid), GFP_KERNEL, ++ NULL, NULL); ++ if (newpid) ++ *newpid = ctr++; + + trace_sched_process_fork(current, p); + diff -Nru kpatch-0.5.0/test/integration/rhel-7.7/smp-locks-section.patch kpatch-0.8.0/test/integration/rhel-7.7/smp-locks-section.patch --- kpatch-0.5.0/test/integration/rhel-7.7/smp-locks-section.patch 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/test/integration/rhel-7.7/smp-locks-section.patch 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1,15 @@ +Index: kernel/drivers/tty/tty_buffer.c +=================================================================== +--- kernel.orig/drivers/tty/tty_buffer.c ++++ kernel/drivers/tty/tty_buffer.c +@@ -217,6 +217,10 @@ int tty_buffer_request_room(struct tty_p + /* OPTIMISATION: We could keep a per tty "zero" sized buffer to + remove this conditional if its worth it. This would be invisible + to the callers */ ++ ++ if (!size) ++ printk("kpatch-test: testing .smp_locks section changes\n"); ++ + b = buf->tail; + if (b != NULL) + left = b->size - b->used; diff -Nru kpatch-0.5.0/test/integration/rhel-7.7/special-static.patch kpatch-0.8.0/test/integration/rhel-7.7/special-static.patch --- kpatch-0.5.0/test/integration/rhel-7.7/special-static.patch 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/test/integration/rhel-7.7/special-static.patch 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1,23 @@ +Index: kernel/kernel/fork.c +=================================================================== +--- kernel.orig/kernel/fork.c ++++ kernel/kernel/fork.c +@@ -1146,10 +1146,18 @@ static void posix_cpu_timers_init_group( + INIT_LIST_HEAD(&sig->cpu_timers[2]); + } + ++void kpatch_foo(void) ++{ ++ if (!jiffies) ++ printk("kpatch copy signal\n"); ++} ++ + static int copy_signal(unsigned long clone_flags, struct task_struct *tsk) + { + struct signal_struct *sig; + ++ kpatch_foo(); ++ + if (clone_flags & CLONE_THREAD) + return 0; + diff -Nru kpatch-0.5.0/test/integration/rhel-7.7/tracepoints-section.patch kpatch-0.8.0/test/integration/rhel-7.7/tracepoints-section.patch --- kpatch-0.5.0/test/integration/rhel-7.7/tracepoints-section.patch 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/test/integration/rhel-7.7/tracepoints-section.patch 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1,14 @@ +Index: kernel/kernel/timer.c +=================================================================== +--- kernel.orig/kernel/timer.c ++++ kernel/kernel/timer.c +@@ -1454,6 +1454,9 @@ static void run_timer_softirq(struct sof + { + struct tvec_base *base = __this_cpu_read(tvec_bases); + ++ if (!base) ++ printk("kpatch-test: testing __tracepoints section changes\n"); ++ + if (time_after_eq(jiffies, base->timer_jiffies)) + __run_timers(base); + } diff -Nru kpatch-0.5.0/test/integration/rhel-7.7/warn-detect-FAIL.patch kpatch-0.8.0/test/integration/rhel-7.7/warn-detect-FAIL.patch --- kpatch-0.5.0/test/integration/rhel-7.7/warn-detect-FAIL.patch 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/test/integration/rhel-7.7/warn-detect-FAIL.patch 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1,9 @@ +Index: kernel/arch/x86/kvm/x86.c +=================================================================== +--- kernel.orig/arch/x86/kvm/x86.c ++++ kernel/arch/x86/kvm/x86.c +@@ -1,3 +1,4 @@ ++ + /* + * Kernel-based Virtual Machine driver for Linux + * diff -Nru kpatch-0.5.0/test/integration/test-vagrant kpatch-0.8.0/test/integration/test-vagrant --- kpatch-0.5.0/test/integration/test-vagrant 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/test/integration/test-vagrant 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1,42 @@ +#!/bin/bash + +SCRIPTDIR=$(readlink -f "$(dirname "$(type -p "${0}")")") +ROOTDIR=$(readlink -f "${SCRIPTDIR}/../..") +SLOWTEST=0 + +# shellcheck disable=SC1090 +source "${ROOTDIR}/test/integration/lib.sh" + +usage() +{ + echo "usage: $(basename "${0}") [options]" >&2 + echo "-h, --help This message" >&2 + echo "-s, --slow Run all of the tests" >&2 +} + +options="$(getopt -o hs -l "help,slow" -- "$@")" || "getopt failed" + +eval set -- "${options}" + +while [[ $# -gt 0 ]]; do + case "$1" in + -s|--slow) + SLOWTEST=1 + ;; + -h|--help) + usage + exit 0 + ;; + esac + shift +done + +declare -a distros=("fedora27" "centos7") + +ret=0 +for distro in "${distros[@]}"; do + kpatch_integration_tests_vagrant_distro "${distro}" "${ROOTDIR}/test/integration/vm-integration-run" "${SLOWTEST}" + rc=$? + ret=$((ret + rc)) +done +exit ${ret} diff -Nru kpatch-0.5.0/test/integration/ubuntu-16.04/fixup-section.patch kpatch-0.8.0/test/integration/ubuntu-16.04/fixup-section.patch --- kpatch-0.5.0/test/integration/ubuntu-16.04/fixup-section.patch 2017-12-21 05:02:48.000000000 +0000 +++ kpatch-0.8.0/test/integration/ubuntu-16.04/fixup-section.patch 2019-08-28 17:34:00.000000000 +0000 @@ -1,12 +1,12 @@ -diff -Nupr src.orig/fs/readdir.c src/fs/readdir.c ---- src.orig/fs/readdir.c 2016-12-15 19:55:39.196000000 +0000 -+++ src/fs/readdir.c 2016-12-15 19:56:25.868000000 +0000 -@@ -173,6 +173,8 @@ static int filldir(struct dir_context *c +diff --git a/fs/readdir.c b/fs/readdir.c +index ced679179cac..7fb338324582 100644 +--- a/fs/readdir.c ++++ b/fs/readdir.c +@@ -173,6 +173,7 @@ static int filldir(struct dir_context *ctx, const char *name, int namlen, goto efault; } dirent = buf->current_dir; -+ if (dirent->d_ino == 12345678) -+ printk("kpatch-test: testing .fixup section changes\n"); ++ asm("nop"); if (__put_user(d_ino, &dirent->d_ino)) goto efault; if (__put_user(reclen, &dirent->d_reclen)) diff -Nru kpatch-0.5.0/test/integration/ubuntu-16.04/gcc-mangled-3.patch kpatch-0.8.0/test/integration/ubuntu-16.04/gcc-mangled-3.patch --- kpatch-0.5.0/test/integration/ubuntu-16.04/gcc-mangled-3.patch 2017-12-21 05:02:48.000000000 +0000 +++ kpatch-0.8.0/test/integration/ubuntu-16.04/gcc-mangled-3.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,16 +0,0 @@ -ensure that __cmpxchg_double_slab.isra.45 and -__cmpxchg_double_slab.isra.45.part.46 aren't correlated. - -diff -Nupr src.orig/mm/slub.c src/mm/slub.c ---- src.orig/mm/slub.c 2016-12-15 19:55:38.988000000 +0000 -+++ src/mm/slub.c 2016-12-15 19:56:39.068000000 +0000 -@@ -5531,6 +5531,9 @@ void get_slabinfo(struct kmem_cache *s, - int node; - struct kmem_cache_node *n; - -+ if (!jiffies) -+ printk("slabinfo\n"); -+ - for_each_kmem_cache_node(s, node, n) { - nr_slabs += node_nr_slabs(n); - nr_objs += node_nr_objs(n); diff -Nru kpatch-0.5.0/test/integration/ubuntu-16.04/gcc-mangled-3.patch.disabled kpatch-0.8.0/test/integration/ubuntu-16.04/gcc-mangled-3.patch.disabled --- kpatch-0.5.0/test/integration/ubuntu-16.04/gcc-mangled-3.patch.disabled 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/test/integration/ubuntu-16.04/gcc-mangled-3.patch.disabled 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1,19 @@ +ensure that __cmpxchg_double_slab.isra.45 and +__cmpxchg_double_slab.isra.45.part.46 aren't correlated. + +Disabled: __flush_cpu_slab() is present in vmlinux.symtab but is optimized +out during kpatch builds + +diff -Nupr src.orig/mm/slub.c src/mm/slub.c +--- src.orig/mm/slub.c 2016-12-15 19:55:38.988000000 +0000 ++++ src/mm/slub.c 2016-12-15 19:56:39.068000000 +0000 +@@ -5531,6 +5531,9 @@ void get_slabinfo(struct kmem_cache *s, + int node; + struct kmem_cache_node *n; + ++ if (!jiffies) ++ printk("slabinfo\n"); ++ + for_each_kmem_cache_node(s, node, n) { + nr_slabs += node_nr_slabs(n); + nr_objs += node_nr_objs(n); diff -Nru kpatch-0.5.0/test/integration/ubuntu-16.04/gcc-static-local-var-2.patch kpatch-0.8.0/test/integration/ubuntu-16.04/gcc-static-local-var-2.patch --- kpatch-0.5.0/test/integration/ubuntu-16.04/gcc-static-local-var-2.patch 2017-12-21 05:02:48.000000000 +0000 +++ kpatch-0.8.0/test/integration/ubuntu-16.04/gcc-static-local-var-2.patch 2019-08-28 17:34:00.000000000 +0000 @@ -1,14 +1,6 @@ diff -Nupr src.orig/mm/mmap.c src/mm/mmap.c --- src.orig/mm/mmap.c 2016-12-15 19:55:38.992000000 +0000 +++ src/mm/mmap.c 2016-12-15 19:56:43.684000000 +0000 -@@ -1538,6 +1538,7 @@ static inline int accountable_mapping(st - return (vm_flags & (VM_NORESERVE | VM_SHARED | VM_WRITE)) == VM_WRITE; - } - -+#include "kpatch-macros.h" - unsigned long mmap_region(struct file *file, unsigned long addr, - unsigned long len, vm_flags_t vm_flags, unsigned long pgoff) - { @@ -1547,6 +1548,9 @@ unsigned long mmap_region(struct file *f struct rb_node **rb_link, *rb_parent; unsigned long charged = 0; diff -Nru kpatch-0.5.0/test/integration/ubuntu-16.04/gcc-static-local-var-4.test kpatch-0.8.0/test/integration/ubuntu-16.04/gcc-static-local-var-4.test --- kpatch-0.5.0/test/integration/ubuntu-16.04/gcc-static-local-var-4.test 2017-12-21 05:02:48.000000000 +0000 +++ kpatch-0.8.0/test/integration/ubuntu-16.04/gcc-static-local-var-4.test 2019-08-28 17:34:00.000000000 +0000 @@ -1,6 +1,6 @@ #!/bin/bash -if $(nm kpatch-gcc-static-local-var-4.ko | grep -q free_ioctx); then +if $(nm test-gcc-static-local-var-4.ko | grep -q free_ioctx); then exit 1 else exit 0 diff -Nru kpatch-0.5.0/test/integration/ubuntu-16.04/gcc-static-local-var-6.patch kpatch-0.8.0/test/integration/ubuntu-16.04/gcc-static-local-var-6.patch --- kpatch-0.5.0/test/integration/ubuntu-16.04/gcc-static-local-var-6.patch 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/test/integration/ubuntu-16.04/gcc-static-local-var-6.patch 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1,23 @@ +diff --git a/net/ipv6/netfilter.c b/net/ipv6/netfilter.c +index 39970e2..85e750d 100644 +--- a/net/ipv6/netfilter.c ++++ b/net/ipv6/netfilter.c +@@ -108,6 +108,8 @@ static int nf_ip6_reroute(struct net *net, struct sk_buff *skb, + return 0; + } + ++#include "kpatch-macros.h" ++ + static int nf_ip6_route(struct net *net, struct dst_entry **dst, + struct flowi *fl, bool strict) + { +@@ -121,6 +123,9 @@ static int nf_ip6_route(struct net *net, struct dst_entry **dst, + struct dst_entry *result; + int err; + ++ if (!jiffies) ++ printk("kpatch nf_ip6_route foo\n"); ++ + result = ip6_route_output(net, sk, &fl->u.ip6); + err = result->error; + if (err) diff -Nru kpatch-0.5.0/test/integration/ubuntu-16.04/macro-callbacks.patch kpatch-0.8.0/test/integration/ubuntu-16.04/macro-callbacks.patch --- kpatch-0.5.0/test/integration/ubuntu-16.04/macro-callbacks.patch 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/test/integration/ubuntu-16.04/macro-callbacks.patch 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1,163 @@ +kpatch/livepatch callback test patch: + + vmlinux + pcspkr (mod) + joydev (mod) + +Note: update joydev's pre-patch callback to return -ENODEV to test failure path + +diff -Nupr src.old/drivers/input/joydev.c src/drivers/input/joydev.c +--- src.old/drivers/input/joydev.c 2017-09-03 16:56:17.000000000 -0400 ++++ src/drivers/input/joydev.c 2018-03-22 16:32:40.963082354 -0400 +@@ -1010,3 +1010,47 @@ static void __exit joydev_exit(void) + + module_init(joydev_init); + module_exit(joydev_exit); ++ ++#include ++#include "kpatch-macros.h" ++ ++static const char *const module_state[] = { ++ [MODULE_STATE_LIVE] = "[MODULE_STATE_LIVE] Normal state", ++ [MODULE_STATE_COMING] = "[MODULE_STATE_COMING] Full formed, running module_init", ++ [MODULE_STATE_GOING] = "[MODULE_STATE_GOING] Going away", ++ [MODULE_STATE_UNFORMED] = "[MODULE_STATE_UNFORMED] Still setting it up", ++}; ++ ++static void callback_info(const char *callback, patch_object *obj) ++{ ++ if (obj->mod) ++ pr_info("%s: %s -> %s\n", callback, obj->mod->name, ++ module_state[obj->mod->state]); ++ else ++ pr_info("%s: vmlinux\n", callback); ++} ++ ++static int pre_patch_callback(patch_object *obj) ++{ ++ callback_info(__func__, obj); ++ return 0; /* return -ENODEV; */ ++} ++KPATCH_PRE_PATCH_CALLBACK(pre_patch_callback); ++ ++static void post_patch_callback(patch_object *obj) ++{ ++ callback_info(__func__, obj); ++} ++KPATCH_POST_PATCH_CALLBACK(post_patch_callback); ++ ++static void pre_unpatch_callback(patch_object *obj) ++{ ++ callback_info(__func__, obj); ++} ++KPATCH_PRE_UNPATCH_CALLBACK(pre_unpatch_callback); ++ ++static void post_unpatch_callback(patch_object *obj) ++{ ++ callback_info(__func__, obj); ++} ++KPATCH_POST_UNPATCH_CALLBACK(post_unpatch_callback); +diff -Nupr src.old/drivers/input/misc/pcspkr.c src/drivers/input/misc/pcspkr.c +--- src.old/drivers/input/misc/pcspkr.c 2018-03-22 16:29:27.716082354 -0400 ++++ src/drivers/input/misc/pcspkr.c 2018-03-22 16:32:40.963082354 -0400 +@@ -132,3 +132,46 @@ static struct platform_driver pcspkr_pla + }; + module_platform_driver(pcspkr_platform_driver); + ++#include ++#include "kpatch-macros.h" ++ ++static const char *const module_state[] = { ++ [MODULE_STATE_LIVE] = "[MODULE_STATE_LIVE] Normal state", ++ [MODULE_STATE_COMING] = "[MODULE_STATE_COMING] Full formed, running module_init", ++ [MODULE_STATE_GOING] = "[MODULE_STATE_GOING] Going away", ++ [MODULE_STATE_UNFORMED] = "[MODULE_STATE_UNFORMED] Still setting it up", ++}; ++ ++static void callback_info(const char *callback, patch_object *obj) ++{ ++ if (obj->mod) ++ pr_info("%s: %s -> %s\n", callback, obj->mod->name, ++ module_state[obj->mod->state]); ++ else ++ pr_info("%s: vmlinux\n", callback); ++} ++ ++static int pre_patch_callback(patch_object *obj) ++{ ++ callback_info(__func__, obj); ++ return 0; ++} ++KPATCH_PRE_PATCH_CALLBACK(pre_patch_callback); ++ ++static void post_patch_callback(patch_object *obj) ++{ ++ callback_info(__func__, obj); ++} ++KPATCH_POST_PATCH_CALLBACK(post_patch_callback); ++ ++static void pre_unpatch_callback(patch_object *obj) ++{ ++ callback_info(__func__, obj); ++} ++KPATCH_PRE_UNPATCH_CALLBACK(pre_unpatch_callback); ++ ++static void post_unpatch_callback(patch_object *obj) ++{ ++ callback_info(__func__, obj); ++} ++KPATCH_POST_UNPATCH_CALLBACK(post_unpatch_callback); +diff -Nupr src.old/fs/aio.c src/fs/aio.c +--- src.old/fs/aio.c 2017-09-03 16:56:17.000000000 -0400 ++++ src/fs/aio.c 2018-03-22 16:32:40.962082354 -0400 +@@ -46,6 +46,50 @@ + + #include "internal.h" + ++#include ++#include "kpatch-macros.h" ++ ++static const char *const module_state[] = { ++ [MODULE_STATE_LIVE] = "[MODULE_STATE_LIVE] Normal state", ++ [MODULE_STATE_COMING] = "[MODULE_STATE_COMING] Full formed, running module_init", ++ [MODULE_STATE_GOING] = "[MODULE_STATE_GOING] Going away", ++ [MODULE_STATE_UNFORMED] = "[MODULE_STATE_UNFORMED] Still setting it up", ++}; ++ ++static void callback_info(const char *callback, patch_object *obj) ++{ ++ if (obj->mod) ++ pr_info("%s: %s -> %s\n", callback, obj->mod->name, ++ module_state[obj->mod->state]); ++ else ++ pr_info("%s: vmlinux\n", callback); ++} ++ ++static int pre_patch_callback(patch_object *obj) ++{ ++ callback_info(__func__, obj); ++ return 0; ++} ++KPATCH_PRE_PATCH_CALLBACK(pre_patch_callback); ++ ++static void post_patch_callback(patch_object *obj) ++{ ++ callback_info(__func__, obj); ++} ++KPATCH_POST_PATCH_CALLBACK(post_patch_callback); ++ ++static void pre_unpatch_callback(patch_object *obj) ++{ ++ callback_info(__func__, obj); ++} ++KPATCH_PRE_UNPATCH_CALLBACK(pre_unpatch_callback); ++ ++static void post_unpatch_callback(patch_object *obj) ++{ ++ callback_info(__func__, obj); ++} ++KPATCH_POST_UNPATCH_CALLBACK(post_unpatch_callback); ++ + #define AIO_RING_MAGIC 0xa10a10a1 + #define AIO_RING_COMPAT_FEATURES 1 + #define AIO_RING_INCOMPAT_FEATURES 0 diff -Nru kpatch-0.5.0/test/integration/ubuntu-16.04/macro-hooks-LOADED.test kpatch-0.8.0/test/integration/ubuntu-16.04/macro-hooks-LOADED.test --- kpatch-0.5.0/test/integration/ubuntu-16.04/macro-hooks-LOADED.test 2017-12-21 05:02:48.000000000 +0000 +++ kpatch-0.8.0/test/integration/ubuntu-16.04/macro-hooks-LOADED.test 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -#!/bin/bash - -[[ $(cat /proc/sys/fs/aio-max-nr) = 262144 ]] diff -Nru kpatch-0.5.0/test/integration/ubuntu-16.04/macro-hooks.patch kpatch-0.8.0/test/integration/ubuntu-16.04/macro-hooks.patch --- kpatch-0.5.0/test/integration/ubuntu-16.04/macro-hooks.patch 2017-12-21 05:02:48.000000000 +0000 +++ kpatch-0.8.0/test/integration/ubuntu-16.04/macro-hooks.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,24 +0,0 @@ -diff -Nupr src.orig/fs/aio.c src/fs/aio.c ---- src.orig/fs/aio.c 2016-12-15 19:55:38.992000000 +0000 -+++ src/fs/aio.c 2016-12-15 19:57:05.396000000 +0000 -@@ -1716,6 +1716,20 @@ SYSCALL_DEFINE3(io_cancel, aio_context_t - return ret; - } - -+static int aio_max_nr_orig; -+void kpatch_load_aio_max_nr(void) -+{ -+ aio_max_nr_orig = aio_max_nr; -+ aio_max_nr = 0x40000; -+} -+void kpatch_unload_aio_max_nr(void) -+{ -+ aio_max_nr = aio_max_nr_orig; -+} -+#include "kpatch-macros.h" -+KPATCH_LOAD_HOOK(kpatch_load_aio_max_nr); -+KPATCH_UNLOAD_HOOK(kpatch_unload_aio_max_nr); -+ - /* io_getevents: - * Attempts to read at least min_nr events and up to nr events from - * the completion queue for the aio_context specified by ctx_id. If diff -Nru kpatch-0.5.0/test/integration/ubuntu-16.04/macro-printk.patch kpatch-0.8.0/test/integration/ubuntu-16.04/macro-printk.patch --- kpatch-0.5.0/test/integration/ubuntu-16.04/macro-printk.patch 2017-12-21 05:02:48.000000000 +0000 +++ kpatch-0.8.0/test/integration/ubuntu-16.04/macro-printk.patch 2019-08-28 17:34:00.000000000 +0000 @@ -1,6 +1,7 @@ -diff -Nupr src.orig/net/ipv4/fib_frontend.c src/net/ipv4/fib_frontend.c ---- src.orig/net/ipv4/fib_frontend.c 2016-12-15 19:55:39.724000000 +0000 -+++ src/net/ipv4/fib_frontend.c 2016-12-15 19:57:09.672000000 +0000 +Index: src/net/ipv4/fib_frontend.c +=================================================================== +--- src.orig/net/ipv4/fib_frontend.c ++++ src/net/ipv4/fib_frontend.c @@ -728,6 +728,7 @@ errout: return err; } @@ -17,10 +18,11 @@ errout: return err; } -diff -Nupr src.orig/net/ipv4/fib_semantics.c src/net/ipv4/fib_semantics.c ---- src.orig/net/ipv4/fib_semantics.c 2016-12-15 19:55:39.720000000 +0000 -+++ src/net/ipv4/fib_semantics.c 2016-12-15 19:57:09.672000000 +0000 -@@ -991,6 +991,7 @@ fib_convert_metrics(struct fib_info *fi, +Index: src/net/ipv4/fib_semantics.c +=================================================================== +--- src.orig/net/ipv4/fib_semantics.c ++++ src/net/ipv4/fib_semantics.c +@@ -998,6 +998,7 @@ fib_convert_metrics(struct fib_info *fi, return 0; } @@ -28,7 +30,7 @@ struct fib_info *fib_create_info(struct fib_config *cfg) { int err; -@@ -1018,6 +1019,7 @@ struct fib_info *fib_create_info(struct +@@ -1025,6 +1026,7 @@ struct fib_info *fib_create_info(struct #endif err = -ENOBUFS; @@ -36,7 +38,7 @@ if (fib_info_cnt >= fib_info_hash_size) { unsigned int new_size = fib_info_hash_size << 1; struct hlist_head *new_info_hash; -@@ -1038,6 +1040,7 @@ struct fib_info *fib_create_info(struct +@@ -1045,6 +1047,7 @@ struct fib_info *fib_create_info(struct if (!fib_info_hash_size) goto failure; } @@ -44,15 +46,15 @@ fi = kzalloc(sizeof(*fi)+nhs*sizeof(struct fib_nh), GFP_KERNEL); if (!fi) -@@ -1049,6 +1052,7 @@ struct fib_info *fib_create_info(struct - goto failure; - } else - fi->fib_metrics = (u32 *) dst_default_metrics; +@@ -1059,6 +1062,7 @@ struct fib_info *fib_create_info(struct + } else { + fi->fib_metrics = (struct dst_metrics *)&dst_default_metrics; + } + KPATCH_PRINTK("[fib_create_info]: 3 create error err is %d\n",err); - + fib_info_cnt++; fi->fib_net = net; fi->fib_protocol = cfg->fc_protocol; -@@ -1065,6 +1069,7 @@ struct fib_info *fib_create_info(struct +@@ -1075,6 +1079,7 @@ struct fib_info *fib_create_info(struct if (!nexthop_nh->nh_pcpu_rth_output) goto failure; } endfor_nexthops(fi) @@ -60,7 +62,7 @@ err = fib_convert_metrics(fi, cfg); if (err) -@@ -1117,6 +1122,8 @@ struct fib_info *fib_create_info(struct +@@ -1127,6 +1132,8 @@ struct fib_info *fib_create_info(struct nh->nh_weight = 1; #endif } @@ -69,7 +71,7 @@ if (fib_props[cfg->fc_type].error) { if (cfg->fc_gw || cfg->fc_oif || cfg->fc_mp) -@@ -1134,6 +1141,7 @@ struct fib_info *fib_create_info(struct +@@ -1144,6 +1151,7 @@ struct fib_info *fib_create_info(struct goto err_inval; } } @@ -77,7 +79,7 @@ if (cfg->fc_scope > RT_SCOPE_HOST) goto err_inval; -@@ -1162,6 +1170,7 @@ struct fib_info *fib_create_info(struct +@@ -1172,6 +1180,7 @@ struct fib_info *fib_create_info(struct if (linkdown == fi->fib_nhs) fi->fib_flags |= RTNH_F_LINKDOWN; } @@ -85,7 +87,7 @@ if (fi->fib_prefsrc && !fib_valid_prefsrc(cfg, fi->fib_prefsrc)) goto err_inval; -@@ -1170,6 +1179,7 @@ struct fib_info *fib_create_info(struct +@@ -1180,6 +1189,7 @@ struct fib_info *fib_create_info(struct fib_info_update_nh_saddr(net, nexthop_nh); fib_add_weight(fi, nexthop_nh); } endfor_nexthops(fi) @@ -93,7 +95,7 @@ fib_rebalance(fi); -@@ -1181,6 +1191,7 @@ link_it: +@@ -1191,6 +1201,7 @@ link_it: ofi->fib_treeref++; return ofi; } @@ -101,7 +103,7 @@ fi->fib_treeref++; atomic_inc(&fi->fib_clntref); -@@ -1204,6 +1215,7 @@ link_it: +@@ -1214,6 +1225,7 @@ link_it: hlist_add_head(&nexthop_nh->nh_hash, head); } endfor_nexthops(fi) spin_unlock_bh(&fib_info_lock); @@ -109,7 +111,7 @@ return fi; err_inval: -@@ -1214,6 +1226,7 @@ failure: +@@ -1224,6 +1236,7 @@ failure: fi->fib_dead = 1; free_fib_info(fi); } @@ -117,9 +119,10 @@ return ERR_PTR(err); } -diff -Nupr src.orig/net/ipv4/fib_trie.c src/net/ipv4/fib_trie.c ---- src.orig/net/ipv4/fib_trie.c 2016-12-15 19:55:39.720000000 +0000 -+++ src/net/ipv4/fib_trie.c 2016-12-15 19:57:09.676000000 +0000 +Index: src/net/ipv4/fib_trie.c +=================================================================== +--- src.orig/net/ipv4/fib_trie.c ++++ src/net/ipv4/fib_trie.c @@ -1078,6 +1078,7 @@ static int fib_insert_alias(struct trie } diff -Nru kpatch-0.5.0/test/integration/ubuntu-16.04/meminfo-cmdline-rebuild-SLOW-LOADED.test kpatch-0.8.0/test/integration/ubuntu-16.04/meminfo-cmdline-rebuild-SLOW-LOADED.test --- kpatch-0.5.0/test/integration/ubuntu-16.04/meminfo-cmdline-rebuild-SLOW-LOADED.test 2017-12-21 05:02:48.000000000 +0000 +++ kpatch-0.8.0/test/integration/ubuntu-16.04/meminfo-cmdline-rebuild-SLOW-LOADED.test 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -#!/bin/bash - -grep VMALLOCCHUNK /proc/meminfo && grep kpatch=1 /proc/cmdline diff -Nru kpatch-0.5.0/test/integration/ubuntu-16.04/meminfo-cmdline-rebuild-SLOW-LOADED.test.disabled kpatch-0.8.0/test/integration/ubuntu-16.04/meminfo-cmdline-rebuild-SLOW-LOADED.test.disabled --- kpatch-0.5.0/test/integration/ubuntu-16.04/meminfo-cmdline-rebuild-SLOW-LOADED.test.disabled 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/test/integration/ubuntu-16.04/meminfo-cmdline-rebuild-SLOW-LOADED.test.disabled 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1,3 @@ +#!/bin/bash + +grep VMALLOCCHUNK /proc/meminfo && grep kpatch=1 /proc/cmdline diff -Nru kpatch-0.5.0/test/integration/ubuntu-16.04/meminfo-cmdline-rebuild-SLOW.patch kpatch-0.8.0/test/integration/ubuntu-16.04/meminfo-cmdline-rebuild-SLOW.patch --- kpatch-0.5.0/test/integration/ubuntu-16.04/meminfo-cmdline-rebuild-SLOW.patch 2017-12-21 05:02:48.000000000 +0000 +++ kpatch-0.8.0/test/integration/ubuntu-16.04/meminfo-cmdline-rebuild-SLOW.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,35 +0,0 @@ -diff -Nupr src.orig/fs/proc/cmdline.c src/fs/proc/cmdline.c ---- src.orig/fs/proc/cmdline.c 2016-12-15 19:55:39.084000000 +0000 -+++ src/fs/proc/cmdline.c 2016-12-15 19:57:13.988000000 +0000 -@@ -5,7 +5,7 @@ - - static int cmdline_proc_show(struct seq_file *m, void *v) - { -- seq_printf(m, "%s\n", saved_command_line); -+ seq_printf(m, "%s kpatch=1\n", saved_command_line); - return 0; - } - -diff -Nupr src.orig/fs/proc/meminfo.c src/fs/proc/meminfo.c ---- src.orig/fs/proc/meminfo.c 2016-12-15 19:55:39.084000000 +0000 -+++ src/fs/proc/meminfo.c 2016-12-15 19:57:13.988000000 +0000 -@@ -99,7 +99,7 @@ static int meminfo_proc_show(struct seq_ - "Committed_AS: %8lu kB\n" - "VmallocTotal: %8lu kB\n" - "VmallocUsed: %8lu kB\n" -- "VmallocChunk: %8lu kB\n" -+ "VMALLOCCHUNK: %8lu kB\n" - #ifdef CONFIG_MEMORY_FAILURE - "HardwareCorrupted: %5lu kB\n" - #endif -diff -Nupr src.orig/include/linux/kernel.h src/include/linux/kernel.h ---- src.orig/include/linux/kernel.h 2016-12-15 19:55:56.996000000 +0000 -+++ src/include/linux/kernel.h 2016-12-15 19:57:13.992000000 +0000 -@@ -2,6 +2,7 @@ - #define _LINUX_KERNEL_H - - -+ - #include - #include - #include diff -Nru kpatch-0.5.0/test/integration/ubuntu-16.04/meminfo-cmdline-rebuild-SLOW.patch.disabled kpatch-0.8.0/test/integration/ubuntu-16.04/meminfo-cmdline-rebuild-SLOW.patch.disabled --- kpatch-0.5.0/test/integration/ubuntu-16.04/meminfo-cmdline-rebuild-SLOW.patch.disabled 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/test/integration/ubuntu-16.04/meminfo-cmdline-rebuild-SLOW.patch.disabled 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1,42 @@ +Disabled: +kpatch-build currently fails with "invalid ancestor" error. This happens +with at least drivers/gpu/drm/i2c/adv7511.o and drivers/hwmon/htu21.o +files. The problem is their .ko counterparts are never built for some +reason, This looks like a kernel bug since in both cases there are files +with same name but in different paths that have .ko module built. +--- +diff -Nupr src.orig/fs/proc/cmdline.c src/fs/proc/cmdline.c +--- src.orig/fs/proc/cmdline.c 2016-12-15 19:55:39.084000000 +0000 ++++ src/fs/proc/cmdline.c 2016-12-15 19:57:13.988000000 +0000 +@@ -5,7 +5,7 @@ + + static int cmdline_proc_show(struct seq_file *m, void *v) + { +- seq_printf(m, "%s\n", saved_command_line); ++ seq_printf(m, "%s kpatch=1\n", saved_command_line); + return 0; + } + +diff -Nupr src.orig/fs/proc/meminfo.c src/fs/proc/meminfo.c +--- src.orig/fs/proc/meminfo.c 2016-12-15 19:55:39.084000000 +0000 ++++ src/fs/proc/meminfo.c 2016-12-15 19:57:13.988000000 +0000 +@@ -99,7 +99,7 @@ static int meminfo_proc_show(struct seq_ + "Committed_AS: %8lu kB\n" + "VmallocTotal: %8lu kB\n" + "VmallocUsed: %8lu kB\n" +- "VmallocChunk: %8lu kB\n" ++ "VMALLOCCHUNK: %8lu kB\n" + #ifdef CONFIG_MEMORY_FAILURE + "HardwareCorrupted: %5lu kB\n" + #endif +diff -Nupr src.orig/include/linux/kernel.h src/include/linux/kernel.h +--- src.orig/include/linux/kernel.h 2016-12-15 19:55:56.996000000 +0000 ++++ src/include/linux/kernel.h 2016-12-15 19:57:13.992000000 +0000 +@@ -2,6 +2,7 @@ + #define _LINUX_KERNEL_H + + ++ + #include + #include + #include diff -Nru kpatch-0.5.0/test/integration/ubuntu-16.04/module-call-external.patch kpatch-0.8.0/test/integration/ubuntu-16.04/module-call-external.patch --- kpatch-0.5.0/test/integration/ubuntu-16.04/module-call-external.patch 2017-12-21 05:02:48.000000000 +0000 +++ kpatch-0.8.0/test/integration/ubuntu-16.04/module-call-external.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,33 +0,0 @@ -diff -Nupr src.orig/fs/nfsd/export.c src/fs/nfsd/export.c ---- src.orig/fs/nfsd/export.c 2016-12-15 19:55:39.012000000 +0000 -+++ src/fs/nfsd/export.c 2016-12-15 19:57:31.068000000 +0000 -@@ -1183,6 +1183,8 @@ static void exp_flags(struct seq_file *m - } - } - -+extern char *kpatch_string(void); -+ - static int e_show(struct seq_file *m, void *p) - { - struct cache_head *cp = p; -@@ -1192,6 +1194,7 @@ static int e_show(struct seq_file *m, vo - if (p == SEQ_START_TOKEN) { - seq_puts(m, "# Version 1.1\n"); - seq_puts(m, "# Path Client(Flags) # IPs\n"); -+ seq_puts(m, kpatch_string()); - return 0; - } - -diff -Nupr src.orig/net/netlink/af_netlink.c src/net/netlink/af_netlink.c ---- src.orig/net/netlink/af_netlink.c 2016-12-15 19:55:39.772000000 +0000 -+++ src/net/netlink/af_netlink.c 2016-12-15 19:57:31.072000000 +0000 -@@ -3353,4 +3353,9 @@ panic: - panic("netlink_init: Cannot allocate nl_table\n"); - } - -+char *kpatch_string(void) -+{ -+ return "# kpatch\n"; -+} -+ - core_initcall(netlink_proto_init); diff -Nru kpatch-0.5.0/test/integration/ubuntu-16.04/module-call-external.patch.disable kpatch-0.8.0/test/integration/ubuntu-16.04/module-call-external.patch.disable --- kpatch-0.5.0/test/integration/ubuntu-16.04/module-call-external.patch.disable 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/test/integration/ubuntu-16.04/module-call-external.patch.disable 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1,38 @@ +Disabled: +Original build includes "kzalloc" in af_netlink.c's symbol list, this +does not happen during kpatch build so create-diff-object fails with +find_local_syms. +--- +diff -Nupr src.orig/fs/nfsd/export.c src/fs/nfsd/export.c +--- src.orig/fs/nfsd/export.c 2016-12-15 19:55:39.012000000 +0000 ++++ src/fs/nfsd/export.c 2016-12-15 19:57:31.068000000 +0000 +@@ -1183,6 +1183,8 @@ static void exp_flags(struct seq_file *m + } + } + ++extern char *kpatch_string(void); ++ + static int e_show(struct seq_file *m, void *p) + { + struct cache_head *cp = p; +@@ -1192,6 +1194,7 @@ static int e_show(struct seq_file *m, vo + if (p == SEQ_START_TOKEN) { + seq_puts(m, "# Version 1.1\n"); + seq_puts(m, "# Path Client(Flags) # IPs\n"); ++ seq_puts(m, kpatch_string()); + return 0; + } + +diff -Nupr src.orig/net/netlink/af_netlink.c src/net/netlink/af_netlink.c +--- src.orig/net/netlink/af_netlink.c 2016-12-15 19:55:39.772000000 +0000 ++++ src/net/netlink/af_netlink.c 2016-12-15 19:57:31.072000000 +0000 +@@ -3353,4 +3353,9 @@ panic: + panic("netlink_init: Cannot allocate nl_table\n"); + } + ++char *kpatch_string(void) ++{ ++ return "# kpatch\n"; ++} ++ + core_initcall(netlink_proto_init); diff -Nru kpatch-0.5.0/test/integration/ubuntu-16.04/module-shadow.patch kpatch-0.8.0/test/integration/ubuntu-16.04/module-shadow.patch --- kpatch-0.5.0/test/integration/ubuntu-16.04/module-shadow.patch 2017-12-21 05:02:48.000000000 +0000 +++ kpatch-0.8.0/test/integration/ubuntu-16.04/module-shadow.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,24 +0,0 @@ -diff -Nupr src.orig/arch/x86/kvm/vmx.c src/arch/x86/kvm/vmx.c ---- src.orig/arch/x86/kvm/vmx.c 2016-12-15 19:55:57.436000000 +0000 -+++ src/arch/x86/kvm/vmx.c 2016-12-15 19:57:39.592000000 +0000 -@@ -10558,10 +10558,20 @@ static void vmx_leave_nested(struct kvm_ - * It should only be called before L2 actually succeeded to run, and when - * vmcs01 is current (it doesn't leave_guest_mode() or switch vmcss). - */ -+#include "kpatch.h" - static void nested_vmx_entry_failure(struct kvm_vcpu *vcpu, - struct vmcs12 *vmcs12, - u32 reason, unsigned long qualification) - { -+ int *kpatch; -+ -+ kpatch = kpatch_shadow_alloc(vcpu, "kpatch", sizeof(*kpatch), -+ GFP_KERNEL); -+ if (kpatch) { -+ kpatch_shadow_get(vcpu, "kpatch"); -+ kpatch_shadow_free(vcpu, "kpatch"); -+ } -+ - load_vmcs12_host_state(vcpu, vmcs12); - vmcs12->vm_exit_reason = reason | VMX_EXIT_REASONS_FAILED_VMENTRY; - vmcs12->exit_qualification = qualification; diff -Nru kpatch-0.5.0/test/integration/ubuntu-16.04/multiple.test kpatch-0.8.0/test/integration/ubuntu-16.04/multiple.test --- kpatch-0.5.0/test/integration/ubuntu-16.04/multiple.test 2017-12-21 05:02:48.000000000 +0000 +++ kpatch-0.8.0/test/integration/ubuntu-16.04/multiple.test 2019-08-28 17:34:00.000000000 +0000 @@ -4,6 +4,10 @@ ROOTDIR="$(readlink -f $SCRIPTDIR/../../..)" KPATCH="sudo $ROOTDIR/kpatch/kpatch" +MODULE_PREFIX="test-" +MODULE_POSTFIX=".ko" +TEST_POSTFIX="-LOADED.test" + set -o errexit die() { @@ -12,12 +16,27 @@ } ko_to_test() { - tmp=${1%.ko}-LOADED.test - echo ${tmp#kpatch-} + tmp=${1%${MODULE_POSTFIX}}${TEST_POSTFIX} + echo ${tmp#${MODULE_PREFIX}} } # make sure any modules added here are disjoint -declare -a modules=(kpatch-cmdline-string.ko kpatch-meminfo-string.ko) +declare -a modules +declare -a blacklist=(data-new-LOADED.test meminfo-cmdline-rebuild-SLOW-LOADED.test) + +for file in "${SCRIPTDIR}"/*"${TEST_POSTFIX}"; do + name=$(basename ${file}) + skip=0 + for bname in "${blacklist[@]}"; do + if [ "${bname}" == "${name}" ]; then + skip=1 + break + fi + done + if [ ${skip} -eq 0 ]; then + modules+=(${MODULE_PREFIX}${name%${TEST_POSTFIX}}${MODULE_POSTFIX}) + fi +done for mod in "${modules[@]}"; do testprog=$(ko_to_test $mod) diff -Nru kpatch-0.5.0/test/integration/ubuntu-16.04/shadow-newpid-LOADED.test kpatch-0.8.0/test/integration/ubuntu-16.04/shadow-newpid-LOADED.test --- kpatch-0.5.0/test/integration/ubuntu-16.04/shadow-newpid-LOADED.test 2017-12-21 05:02:48.000000000 +0000 +++ kpatch-0.8.0/test/integration/ubuntu-16.04/shadow-newpid-LOADED.test 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -#!/bin/bash - -grep -q newpid: /proc/$$/status diff -Nru kpatch-0.5.0/test/integration/ubuntu-16.04/shadow-newpid.patch kpatch-0.8.0/test/integration/ubuntu-16.04/shadow-newpid.patch --- kpatch-0.5.0/test/integration/ubuntu-16.04/shadow-newpid.patch 2017-12-21 05:02:48.000000000 +0000 +++ kpatch-0.8.0/test/integration/ubuntu-16.04/shadow-newpid.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,69 +0,0 @@ -diff -Nupr src.orig/fs/proc/array.c src/fs/proc/array.c ---- src.orig/fs/proc/array.c 2016-12-15 19:55:39.080000000 +0000 -+++ src/fs/proc/array.c 2016-12-15 19:58:00.840000000 +0000 -@@ -334,13 +334,20 @@ static inline void task_seccomp(struct s - #endif - } - -+#include "kpatch.h" - static inline void task_context_switch_counts(struct seq_file *m, - struct task_struct *p) - { -+ int *newpid; -+ - seq_printf(m, "voluntary_ctxt_switches:\t%lu\n" - "nonvoluntary_ctxt_switches:\t%lu\n", - p->nvcsw, - p->nivcsw); -+ -+ newpid = kpatch_shadow_get(p, "newpid"); -+ if (newpid) -+ seq_printf(m, "newpid:\t%d\n", *newpid); - } - - static void task_cpus_allowed(struct seq_file *m, struct task_struct *task) -diff -Nupr src.orig/kernel/exit.c src/kernel/exit.c ---- src.orig/kernel/exit.c 2016-12-15 19:56:00.184000000 +0000 -+++ src/kernel/exit.c 2016-12-15 19:58:00.840000000 +0000 -@@ -650,6 +650,7 @@ static void check_stack_usage(void) - static inline void check_stack_usage(void) {} - #endif - -+#include "kpatch.h" - void do_exit(long code) - { - struct task_struct *tsk = current; -@@ -758,6 +759,8 @@ void do_exit(long code) - - cgroup_exit(tsk); - -+ kpatch_shadow_free(tsk, "newpid"); -+ - /* - * FIXME: do that only when needed, using sched_exit tracepoint - */ -diff -Nupr src.orig/kernel/fork.c src/kernel/fork.c ---- src.orig/kernel/fork.c 2016-12-15 19:56:00.184000000 +0000 -+++ src/kernel/fork.c 2016-12-15 19:58:00.840000000 +0000 -@@ -1726,6 +1726,7 @@ struct task_struct *fork_idle(int cpu) - * It copies the process, and if successful kick-starts - * it and waits for it to finish using the VM if required. - */ -+#include "kpatch.h" - long _do_fork(unsigned long clone_flags, - unsigned long stack_start, - unsigned long stack_size, -@@ -1764,6 +1765,13 @@ long _do_fork(unsigned long clone_flags, - if (!IS_ERR(p)) { - struct completion vfork; - struct pid *pid; -+ int *newpid; -+ static int ctr = 0; -+ -+ newpid = kpatch_shadow_alloc(p, "newpid", sizeof(*newpid), -+ GFP_KERNEL); -+ if (newpid) -+ *newpid = ctr++; - - trace_sched_process_fork(current, p); - diff -Nru kpatch-0.5.0/test/integration/vm-integration-run kpatch-0.8.0/test/integration/vm-integration-run --- kpatch-0.5.0/test/integration/vm-integration-run 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/test/integration/vm-integration-run 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1,77 @@ +#!/bin/bash + +KPATCH_SLOW=0 +KPATCH_GIT=${KPATCH_GIT:-https://github.com/dynup/kpatch.git} +KPATCH_REV=${KPATCH_REV:-HEAD} +LOGDIR="/vagrant/logs" + +usage() +{ + echo "usage: $(basename "${0}") [options]" >&2 + echo "-h, --help This message" >&2 + echo "-s, --slow Run all of the tests" >&2 + echo "-g, --git Git url to clone from" >&2 + echo "-r, --revision Revision to use (HEAD by default)" >&2 +} + +options="$(getopt -o "shg:r:" -l "slow,help,git:,revision:" -- "$@")" || "getopt failed" + +eval set -- "${options}" + +while [[ $# -gt 0 ]]; do + case "$1" in + -s|--slow) + KPATCH_SLOW=1 + shift + ;; + -g|--git) + KPATCH_GIT="${2}" + shift 2 + ;; + -r|--revision) + KPATCH_REV="${2}" + shift 2 + ;; + -h|--help) + usage + exit 0 + ;; + --) + shift + break + ;; + esac +done + +git clone "${KPATCH_GIT}" || exit 1 + +cd kpatch || exit 1 + +git reset --hard "${KPATCH_REV}" || exit 1 + +# shellcheck disable=SC1091 +source test/integration/lib.sh + +kpatch_dependencies +kpatch_separate_disk_cache /dev/vdb /mnt/build +kpatch_set_ccache_max_size 10G + +# Check if we have predownloaded sources and move them to ~/.kpatch dir which +# is a symlink to a dir on a separate (bigger) volume, suitable for building. +if [[ -d "${HOME}/src" && -f "${HOME}/src/version" ]]; then + cp "${HOME}/src/version" "${HOME}/.kpatch/" + mv "${HOME}/src" "${HOME}/.kpatch/" +fi + +if [ ${KPATCH_SLOW} -eq 1 ]; then + make integration-slow 2>&1 +else + make integration-quick 2>&1 +fi + +rc=${PIPESTATUS[0]} +rm -rf "${LOGDIR}" +mkdir -p "${LOGDIR}" +cp ./test/integration/*.log "${LOGDIR}" + +exit "${rc}" diff -Nru kpatch-0.5.0/test/test-functions.sh kpatch-0.8.0/test/test-functions.sh --- kpatch-0.5.0/test/test-functions.sh 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/test/test-functions.sh 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1,12 @@ +FILE=$1 + +assert_num_funcs() { + local num_funcs=$(nm $FILE | grep -i " t " | wc -l) + + if [[ $num_funcs != $1 ]]; then + echo "$FILE: assertion failed: file has $num_funcs funcs, expected $1" 1>&2 + exit 1 + fi + + return 0 +} diff -Nru kpatch-0.5.0/test/testmod/doit-client.sh kpatch-0.8.0/test/testmod/doit-client.sh --- kpatch-0.5.0/test/testmod/doit-client.sh 2017-12-21 05:02:48.000000000 +0000 +++ kpatch-0.8.0/test/testmod/doit-client.sh 1970-01-01 00:00:00.000000000 +0000 @@ -1,27 +0,0 @@ -#!/bin/bash - -#set -x - -rmmod testmod 2> /dev/null -rmmod kpatch 2> /dev/null -insmod testmod.ko || exit 1 -insmod kpatch.ko || exit 1 -if [[ "$(cat /sys/kernel/testmod/value)" != "2" ]] -then - exit 1 -fi -insmod kpatch-patch.ko -dmesg | tail -if [[ "$(cat /sys/kernel/testmod/value)" != "3" ]] -then - exit 1 -fi -echo 0 > /sys/kernel/kpatch/kpatch_patch/enabled -rmmod kpatch-patch -if [[ "$(cat /sys/kernel/testmod/value)" != "2" ]] -then - exit 1 -fi -rmmod kpatch -rmmod testmod -echo "SUCCESS" diff -Nru kpatch-0.5.0/test/testmod/doit.sh kpatch-0.8.0/test/testmod/doit.sh --- kpatch-0.5.0/test/testmod/doit.sh 2017-12-21 05:02:48.000000000 +0000 +++ kpatch-0.8.0/test/testmod/doit.sh 1970-01-01 00:00:00.000000000 +0000 @@ -1,37 +0,0 @@ -#!/bin/bash - -#set -x - -# If testing on a remote machine, set it here -# Probably want to use preshared keys. - -unset REMOTE -#REMOTE="192.168.100.150" - -cd ../../ || exit 1 -make clean || exit 1 -make || exit 1 -cd test/testmod || exit 1 -make || exit 1 -../../kpatch-build/create-diff-object testmod_drv.o.orig testmod_drv.o.patched testmod.ko output.o || exit 1 -cd ../../kmod/patch || exit 1 -make clean || exit 1 -cp ../../test/testmod/output.o . || exit 1 -md5sum output.o | awk '{printf "%s\0", $1}' > checksum.tmp || exit 1 -objcopy --add-section .kpatch.checksum=checksum.tmp --set-section-flags .kpatch.checksum=alloc,load,contents,readonly output.o || exit 1 -rm -f checksum.tmp -KBUILD_EXTRA_SYMBOLS="$(readlink -e ../../kmod/core/Module.symvers)" make || exit 1 -cd ../../test/testmod - -if [[ -z "$REMOTE" ]] -then - cp ../../kmod/core/kpatch.ko . - cp ../../kmod/patch/kpatch-patch.ko . - sudo ./doit-client.sh -else - scp ../../kmod/core/kpatch.ko root@$REMOTE:~/. || exit 1 - scp ../../kmod/patch/kpatch-patch.ko root@$REMOTE:~/. || exit 1 - scp testmod.ko root@$REMOTE:~/. || exit 1 - scp doit-client.sh root@$REMOTE:~/. || exit 1 - ssh root@$REMOTE ./doit-client.sh -fi diff -Nru kpatch-0.5.0/test/testmod/Makefile kpatch-0.8.0/test/testmod/Makefile --- kpatch-0.5.0/test/testmod/Makefile 2017-12-21 05:02:48.000000000 +0000 +++ kpatch-0.8.0/test/testmod/Makefile 1970-01-01 00:00:00.000000000 +0000 @@ -1,23 +0,0 @@ -BUILD ?= /lib/modules/$(shell uname -r)/build - -testmod.ko: testmod_drv.c - patch < patch - KCFLAGS="-ffunction-sections -fdata-sections" $(MAKE) -C $(BUILD) M=$(PWD) testmod.ko - strip --keep-file-symbols -d testmod_drv.o - cp testmod_drv.o testmod_drv.o.patched - patch -R < patch - KCFLAGS="-ffunction-sections -fdata-sections" $(MAKE) -C $(BUILD) M=$(PWD) testmod.ko - strip --keep-file-symbols -d testmod_drv.o - cp testmod_drv.o testmod_drv.o.orig - $(MAKE) -C $(BUILD) M=$(PWD) clean - $(MAKE) -C $(BUILD) M=$(PWD) testmod.ko - -all: testmod.ko - -clean: - $(MAKE) -C $(BUILD) M=$(PWD) clean - rm *.orig *.patched - -# kbuild rules -obj-m := testmod.o -testmod-y := testmod_drv.o diff -Nru kpatch-0.5.0/test/testmod/patch kpatch-0.8.0/test/testmod/patch --- kpatch-0.5.0/test/testmod/patch 2017-12-21 05:02:48.000000000 +0000 +++ kpatch-0.8.0/test/testmod/patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,11 +0,0 @@ ---- testmod_drv.c.orig 2014-06-02 16:49:49.428509600 -0500 -+++ testmod_drv.c 2014-06-02 16:49:56.973656791 -0500 -@@ -11,7 +11,7 @@ - static ssize_t value_show(struct kobject *kobj, - struct kobj_attribute *attr, char *buf) - { -- return sprintf(buf, "%d\n", value); -+ return sprintf(buf, "%d\n", value+1); - } - - static struct kobj_attribute testmod_value_attr = __ATTR_RO(value); diff -Nru kpatch-0.5.0/test/testmod/README kpatch-0.8.0/test/testmod/README --- kpatch-0.5.0/test/testmod/README 2017-12-21 05:02:48.000000000 +0000 +++ kpatch-0.8.0/test/testmod/README 1970-01-01 00:00:00.000000000 +0000 @@ -1,4 +0,0 @@ -To test, run ./doit.sh from the current directory. - -To test on a remote system, set remote system using REMOTE in doit.sh. -Then run ./doit.sh. diff -Nru kpatch-0.5.0/test/testmod/testmod_drv.c kpatch-0.8.0/test/testmod/testmod_drv.c --- kpatch-0.5.0/test/testmod/testmod_drv.c 2017-12-21 05:02:48.000000000 +0000 +++ kpatch-0.8.0/test/testmod/testmod_drv.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,44 +0,0 @@ -#define pr_fmt(fmt) "testmod: " fmt - -#include -#include -#include -#include - -static struct kobject *testmod_kobj; -int value = 2; - -static ssize_t value_show(struct kobject *kobj, - struct kobj_attribute *attr, char *buf) -{ - return sprintf(buf, "%d\n", value); -} - -static struct kobj_attribute testmod_value_attr = __ATTR_RO(value); - -static int testmod_init(void) -{ - int ret; - - testmod_kobj = kobject_create_and_add("testmod", kernel_kobj); - if (!testmod_kobj) - return -ENOMEM; - - ret = sysfs_create_file(testmod_kobj, &testmod_value_attr.attr); - if (ret) { - kobject_put(testmod_kobj); - return ret; - } - - return 0; -} - -static void testmod_exit(void) -{ - sysfs_remove_file(testmod_kobj, &testmod_value_attr.attr); - kobject_put(testmod_kobj); -} - -module_init(testmod_init); -module_exit(testmod_exit); -MODULE_LICENSE("GPL"); diff -Nru kpatch-0.5.0/test/unit/Makefile kpatch-0.8.0/test/unit/Makefile --- kpatch-0.5.0/test/unit/Makefile 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/test/unit/Makefile 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1,13 @@ +ARCH = $(shell uname -m) +OBJDIR ?= objs/$(ARCH) + +.PHONY: all clean + +all: Makefile.include + @cd $(shell git rev-parse --show-toplevel) && \ + git diff-index --quiet HEAD test/unit/objs || \ + echo -e "\nWARNING: unit tests are out of date - run \"git submodule update\"\n" + $(MAKE) -C $(OBJDIR) + +clean: Makefile.include + if [ -d $(OBJDIR) ]; then $(MAKE) -C $(OBJDIR) clean; fi diff -Nru kpatch-0.5.0/test/unit/Makefile.include kpatch-0.8.0/test/unit/Makefile.include --- kpatch-0.5.0/test/unit/Makefile.include 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/test/unit/Makefile.include 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1,73 @@ +EXT_ORIG ?= ORIG.o +EXT_PATCHED ?= PATCHED.o +EXT_FAIL ?= PATCHED.FAIL.o +EXT_TEST ?= test +EXT_OUTPUT ?= OUTPUT.o +EXT_TEST_OUTPUT ?= test.out +EXT_SYMTAB ?= symtab +EXT_SYMVERS ?= symvers +EXT_ENV ?= env +TNAME = $(@:.$(EXT_OUTPUT)=) + +ifndef VERBOSE +MUTE_PASS := >/dev/null +MUTE_FAIL := >/dev/null 2>&1 +.SILENT: $(TARGETS) $(TEST_TARGETS) +endif + +SRC_PATH ?= $(realpath ../../../../) +CDO ?= $(SRC_PATH)/kpatch-build/create-diff-object +TEST_LIBRARY ?= $(SRC_PATH)/test/test-functions.sh + +TEST_ENV = KPATCH_TEST_LIBRARY=$(TEST_LIBRARY) + +TARGETS = $(patsubst %.$(EXT_ORIG),%.$(EXT_OUTPUT),$(wildcard *.$(EXT_ORIG))) +TEST_TARGETS = $(patsubst %.$(EXT_TEST),%.$(EXT_TEST_OUTPUT),$(wildcard *.$(EXT_TEST))) + +SYMVERS_FILE = $(if $(wildcard $(TNAME).$(EXT_SYMVERS)),$(TNAME).$(EXT_SYMVERS),/dev/null) + +define check_stripped = + $(if $(shell readelf --debug-dump $(1)), + $(error $(1) is not properly stripped, use 'strip --strip-debug --keep-file-symbols $(1)' to fix this), + ) +endef + +define check_all = + $(if $(findstring NOSTRIP,$(1)), , $(call check_stripped,$(1))) +endef + +.DELETE_ON_ERROR: %.$(EXT_OUTPUT) + +all: $(TARGETS) $(TEST_TARGETS) + +clean: + rm -f *.$(EXT_TEST_OUTPUT) *.$(EXT_OUTPUT) + +%.$(EXT_SYMTAB): + readelf -s --wide $(patsubst %.$(EXT_SYMTAB),%.$(EXT_ORIG),$(@)) | \ + sed -r 's/\s+\[: 8\]//' >$@ + +%.$(EXT_TEST_OUTPUT): %.$(EXT_OUTPUT) %.$(EXT_TEST) $(TEST_LIBRARY) + @echo "TEST $(@:.$(EXT_TEST_OUTPUT)=)" + $(TEST_ENV) bash $(@:.$(EXT_TEST_OUTPUT)=.$(EXT_TEST)) $< +# Don't rely on script creating this + @touch $@ + +%.$(EXT_OUTPUT): %.$(EXT_ORIG) %.$(EXT_PATCHED) %.$(EXT_SYMTAB) $(CDO) + @echo "BUILD $(TNAME)" + $(call check_all,$(TNAME).$(EXT_ORIG)) + $(call check_all,$(TNAME).$(EXT_PATCHED)) + $(CDO_ENV) $(shell cat $(TNAME).$(EXT_ENV) 2>/dev/null) $(CDO) $(TNAME).$(EXT_ORIG) $(TNAME).$(EXT_PATCHED) \ + vmlinux $(TNAME).$(EXT_SYMTAB) $(SYMVERS_FILE) \ + test_$(TNAME) $@ $(MUTE_PASS) + +%.$(EXT_OUTPUT): %.$(EXT_ORIG) %.$(EXT_FAIL) %.$(EXT_SYMTAB) $(CDO) + @echo "BUILD $(TNAME)-FAIL" + $(call check_all,$(TNAME).$(EXT_ORIG)) + $(call check_all,$(TNAME).$(EXT_FAIL)) + ! $(CDO_ENV) $(shell cat $(TNAME).$(EXT_ENV) 2>/dev/null) $(CDO) $(TNAME).$(EXT_ORIG) $(TNAME).$(EXT_FAIL) \ + vmlinux $(TNAME).$(EXT_SYMTAB) $(SYMVERS_FILE) \ + test_$(TNAME) $@ $(MUTE_FAIL) +# Expecting to fail, thus create output file manually so we won't rerun the +# test without clean + @touch $@ diff -Nru kpatch-0.5.0/.travis.yml kpatch-0.8.0/.travis.yml --- kpatch-0.5.0/.travis.yml 1970-01-01 00:00:00.000000000 +0000 +++ kpatch-0.8.0/.travis.yml 2019-08-28 17:34:00.000000000 +0000 @@ -0,0 +1,10 @@ +language: c +before_install: + - sudo apt-get -qq update + - sudo apt-get install -y libelf-dev linux-headers-$(uname -r) shellcheck elfutils + +script: + - make + - make unit + - make check + - sudo make install