4:11
  #   ˆl–äY>”jC]Šq@³p\jbÑ¿Ã„®>ïÂÁ ?÷     #!/usr/bin/bash
#
# kpatch hot patch module management script
#
# Copyright (C) 2014 Seth Jennings <sjenning@redhat.com>
# Copyright (C) 2014 Josh Poimboeuf <jpoimboe@redhat.com>
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA,
# 02110-1301, USA.

# 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
RPMINSTALLDIR=/lib/kpatch
SCRIPTDIR="$(readlink -f "$(dirname "$(type -p "$0")")")"
VERSION="0.9.10"
POST_ENABLE_WAIT=15	# seconds
POST_SIGNAL_WAIT=60	# seconds
MODULE_REF_WAIT=15	# seconds

declare -A CVE_LIST

# 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" "$(fmt -w 80 <(echo "      $2"))" >&2
}

usage () {
	# ATTENTION ATTENTION ATTENTION ATTENTION ATTENTION ATTENTION
	# When changing this, please also update the man page.  Thanks!
	echo "usage: kpatch <command> [<args>]" >&2
	echo >&2
	echo "Valid commands:" >&2
	usage_cmd "install [-k|--kernel-version=<kernel version>] <module>" "install patch module to be loaded at boot"
	usage_cmd "uninstall [-k|--kernel-version=<kernel version>] <module>" "uninstall patch module"
	echo >&2
	usage_cmd "load --all" "load all installed patch modules into the running kernel"
	usage_cmd "load <module>" "load patch module into the running kernel"
	usage_cmd "unload --all (UNSUPPORTED)" "unload all patch modules from the running kernel"
	usage_cmd "unload <module> (UNSUPPORTED)" "unload patch module from the running kernel"
	echo >&2
	usage_cmd "info <module>" "show information about a patch module"
	echo >&2
	usage_cmd "list" "list installed patch modules"
	echo >&2
	usage_cmd "signal" "signal/poke any process stalling the current patch transition. This is only useful on systems that have the sysfs livepatch signal interface. On other systems, the signaling should be done automatically by the OS and this subcommand is a no-op."
	echo >&2
	usage_cmd "version" "display the kpatch version"
	exit 1
}

warn() {
	echo "kpatch: $*" >&2
}

die() {
	warn "$@"
	exit 1
}

confirm_prompt() {
	local prompt="$1"
	local answer
	while true; do
		read -rp "$prompt [Y/N] " answer
		[[ $answer == 'Y' || $answer == 'y' ]] && return 0
		[[ $answer == 'N' || $answer == 'n' ]] && return 1
	done
}

__find_module () {
	MODULE="$1"
	[[ -f "$MODULE" ]] && return

	MODULE="$INSTALLDIR/$(uname -r)/$1"
	[[ -f "$MODULE" ]] && return

	return 1
}

mod_name () {
	MODNAME="$(basename "$1")"
	MODNAME="${MODNAME%.ko}"
	MODNAME="${MODNAME//-/_}"
}

find_module () {
	arg="$1"
	if [[ "$arg" =~ \.ko ]]; then
		__find_module "$arg" || return 1
		mod_name "$MODULE"
		return
	else
		for i in "$INSTALLDIR/$(uname -r)"/*; do
			mod_name "$i"
			if [[ "$MODNAME" == "$arg" ]]; then
				MODULE="$i"
				return
			fi
		done
	fi

	return 1
}

find_core_module() {
	COREMOD="$SCRIPTDIR"/../kmod/core/kpatch.ko
	[[ -f "$COREMOD" ]] && return

	COREMOD="/usr/local/lib/kpatch/$(uname -r)/kpatch.ko"
	[[ -f "$COREMOD" ]] && return

	COREMOD="/usr/lib/kpatch/$(uname -r)/kpatch.ko"
	[[ -f "$COREMOD" ]] && return

	COREMOD="/usr/local/lib/modules/$(uname -r)/extra/kpatch/kpatch.ko"
	[[ -f "$COREMOD" ]] && return

	COREMOD="/usr/lib/modules/$(uname -r)/extra/kpatch/kpatch.ko"
	[[ -f "$COREMOD