From 458e83d02810ee2697b509bf4ea30c570a5151ed Mon Sep 17 00:00:00 2001 From: Zhixiong Chi Date: Wed, 26 Oct 2022 00:58:41 -0700 Subject: [PATCH] kpatch: Support the customized order for module load With adding the configfile, now we can use customized order to load the livepatched kernel modules instead of the original alphabetical order when the command 'kpatch load --all' is executed. If the configfile is empty, then the behavior is still to load the module as the original style(alphabetical order). The first column in the config file is the module to be loaded. The second column is the dependency which must be loaded first, and it can be ignored if the dependency is null. Signed-off-by: Zhixiong Chi --- Makefile.inc | 1 + contrib/Makefile | 3 ++ contrib/kpatch-load.conf | 5 ++++ kpatch/kpatch | 59 ++++++++++++++++++++++++++++++++++++---- 4 files changed, 63 insertions(+), 5 deletions(-) create mode 100644 contrib/kpatch-load.conf diff --git a/Makefile.inc b/Makefile.inc index 259127c..8280182 100644 --- a/Makefile.inc +++ b/Makefile.inc @@ -15,6 +15,7 @@ LIBEXECDIR = $(DESTDIR)$(PREFIX)/$(LIBEXEC)/kpatch DATADIR = $(DESTDIR)$(PREFIX)/share/kpatch MANDIR = $(DESTDIR)$(PREFIX)/share/man/man1 SYSTEMDDIR = $(DESTDIR)$(PREFIX)/lib/systemd/system +SYSCONFDIR = $(DESTDIR)/etc UPSTARTDIR = $(DESTDIR)/etc/init LOCALSTATEDIR = $(DESTDIR)/var diff --git a/contrib/Makefile b/contrib/Makefile index 0b0eeeb..1e43b39 100644 --- a/contrib/Makefile +++ b/contrib/Makefile @@ -9,9 +9,12 @@ install: all $(INSTALL) -d $(UPSTARTDIR) $(INSTALL) -m 0644 kpatch.conf $(UPSTARTDIR) sed -i 's~PREFIX~$(PREFIX)~' $(UPSTARTDIR)/kpatch.conf + $(INSTALL) -d $(SYSCONFDIR) + $(INSTALL) -m 0644 kpatch-load.conf $(SYSCONFDIR) uninstall: $(RM) $(SYSTEMDDIR)/kpatch.service $(RM) $(UPSTARTDIR)/kpatch.conf + $(RM) $(SYSCONFDIR)/kpatch-load.conf clean: diff --git a/contrib/kpatch-load.conf b/contrib/kpatch-load.conf new file mode 100644 index 0000000..fdaebb0 --- /dev/null +++ b/contrib/kpatch-load.conf @@ -0,0 +1,5 @@ +# Please write the whole filename including .ko +# InstallMod Dependmod1,Dependmod2 +# eg: abc.ko +# eg: abc.ko def.ko +# eg: abc.ko def.ko,ghi.ko diff --git a/kpatch/kpatch b/kpatch/kpatch index e4624f5..4b65892 100755 --- a/kpatch/kpatch +++ b/kpatch/kpatch @@ -23,7 +23,8 @@ # This is the kpatch user script that manages installing, loading, and # displaying information about kernel patch modules installed on the system. -INSTALLDIR=/var/lib/kpatch +INSTALLDIR="/var/lib/kpatch" +CONFIGFILE="/etc/kpatch-load.conf" SCRIPTDIR="$(readlink -f "$(dirname "$(type -p "$0")")")" VERSION="0.9.5" POST_ENABLE_WAIT=15 # seconds @@ -67,6 +68,15 @@ warn() { echo "kpatch: $*" >&2 } +warn_load() { + local tty_specific_colour_on tty_specific_colour_off + if [[ -t 2 ]] ; then + tty_specific_colour_on=$'\033[1;33m' + tty_specific_colour_off=$'\033[0m' + fi + echo "${tty_specific_colour_on}kpatch: $*${tty_specific_colour_off}" >&2 +} + die() { warn "$@" exit 1 @@ -443,6 +453,18 @@ get_module_version() { MODVER="${MODVER/ */}" } +is_installed() { + local RDEPS=$1 + for item in "${RDEPS[@]}"; do + item="${item%*.ko}" + if ! lsmod | awk '{print $1}' | grep -q "${item//-/_}"; then + warn_load "Module Dependency: ${item} Is Not Loaded!" + return 1 + fi + done + return 0 +} + unset MODULE # Initialize the $SYSFS var. This only works if the core module has been @@ -456,10 +478,37 @@ case "$1" in [[ "$#" -ne 2 ]] && usage case "$2" in "--all") - for i in "$INSTALLDIR/$(uname -r)"/*.ko; do - [[ -e "$i" ]] || continue - load_module "$i" || die "failed to load module $i" - done + [[ -e "${CONFIGFILE}" ]] || die "Kpatch modules load configfile ${CONFIGFILE} could NOT be found!" + if [[ -n $(awk '{if(!NF || /^#/){next}}1' "${CONFIGFILE}") ]]; then + awk '{if(!NF || /^#/){next}}1' "${CONFIGFILE}" | while read -r line; do + INSTALLMOD=${line%% *} + RDEPSMODS=${line#*.ko} + RDEPS_ARRAY=$(echo "${RDEPSMODS}" | tr ',' ' ') + + if [[ "${INSTALLMOD: -3}" != ".ko" ]]; then + warn_load "Module ${INSTALLMOD} missing .ko filename suffix" + continue + fi + + if [[ ! -e "${INSTALLDIR}/$(uname -r)/${INSTALLMOD}" ]]; then + warn_load "Skipping ${INSTALLMOD}, cannot find it in ${INSTALLDIR}/$(uname -r)/" + continue + fi + + if [[ "${RDEPS_ARRAY}" ]] && ! is_installed "${RDEPS_ARRAY}"; then + warn_load "Skipping load of ${INSTALLMOD} due to missing dependency module(s)" + continue + fi + + MOD_FULLPATH="${INSTALLDIR}/$(uname -r)/${INSTALLMOD}" + load_module "${MOD_FULLPATH}" || die "Failed to load module ${MOD_FULLPATH}" + done + else + for i in "${INSTALLDIR}/$(uname -r)"/*.ko; do + [[ -e "${i}" ]] || continue + load_module "${i}" || die "Failed to load module ${i}" + done + fi ;; *) PATCH="$2" -- 2.25.1