0
  ;   lY> T +qţO<am_J2R PwqLZ7 :!    #!/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
SCRIPTDIR="$(readlink -f "$(dirname "$(type -p "$0")")")"
VERSION="0.6.1"
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
}

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"
	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" ]] && return

	return 1
}

core_loaded () {
	grep -q -e "T klp_enable_patch" -e "T kpatch_register" /proc/kallsyms
}

get_module_name () {
	readelf -p .gnu.linkonce.this_module "$1" | grep '\[.*\]' | awk '{print $3}'
}

init_sysfs_var() {
	# If the kernel is confi