mirror of
https://github.com/dynup/kpatch
synced 2025-02-20 11:57:00 +00:00
kpatch: better support for livepatch modules
Livepatch modules can be supported with minimal changes to the kpatch script. Adjust for appropriate sysfs paths, core-patching code (in kernel for livepatch, kpatch.ko for kpatch), and checksum verification (only verify the checksum if it exists). Fixes #479.
This commit is contained in:
parent
c27b3206cf
commit
b55dfb7dee
@ -27,6 +27,14 @@ INSTALLDIR=/var/lib/kpatch
|
|||||||
SCRIPTDIR="$(readlink -f $(dirname $(type -p $0)))"
|
SCRIPTDIR="$(readlink -f $(dirname $(type -p $0)))"
|
||||||
VERSION="0.3.4"
|
VERSION="0.3.4"
|
||||||
|
|
||||||
|
# Livepatch is built into the kernel, if it's not present
|
||||||
|
# we must use kpatch core module.
|
||||||
|
if [[ -e /sys/kernel/livepatch ]] ; then
|
||||||
|
SYSFS="/sys/kernel/livepatch"
|
||||||
|
else
|
||||||
|
SYSFS="/sys/kernel/kpatch/patches"
|
||||||
|
fi
|
||||||
|
|
||||||
usage_cmd() {
|
usage_cmd() {
|
||||||
printf ' %-20s\n %s\n' "$1" "$2" >&2
|
printf ' %-20s\n %s\n' "$1" "$2" >&2
|
||||||
}
|
}
|
||||||
@ -116,8 +124,8 @@ find_core_module() {
|
|||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
core_module_loaded () {
|
core_loaded () {
|
||||||
grep -q "T kpatch_register" /proc/kallsyms
|
grep -q -e "T klp_register_patch" -e "T kpatch_register" /proc/kallsyms
|
||||||
}
|
}
|
||||||
|
|
||||||
get_module_name () {
|
get_module_name () {
|
||||||
@ -129,16 +137,20 @@ verify_module_checksum () {
|
|||||||
[[ -z $modname ]] && return 1
|
[[ -z $modname ]] && return 1
|
||||||
|
|
||||||
checksum=$(readelf -p .kpatch.checksum $1 | grep '\[.*\]' | awk '{print $3}')
|
checksum=$(readelf -p .kpatch.checksum $1 | grep '\[.*\]' | awk '{print $3}')
|
||||||
[[ -z $checksum ]] && return 1
|
|
||||||
|
|
||||||
sysfs_checksum=$(cat /sys/kernel/kpatch/patches/${modname}/checksum)
|
# Fail checksum match only if both exist and diverge
|
||||||
|
if [[ ! -z $checksum ]] && [[ -e "$SYSFS/${modname}/checksum" ]] ; then
|
||||||
|
sysfs_checksum=$(cat $SYSFS/${modname}/checksum)
|
||||||
[[ $checksum == $sysfs_checksum ]] || return 1
|
[[ $checksum == $sysfs_checksum ]] || return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
load_module () {
|
load_module () {
|
||||||
local module="$1"
|
local module="$1"
|
||||||
|
|
||||||
if ! core_module_loaded; then
|
if ! core_loaded; then
|
||||||
if modprobe -q kpatch; then
|
if modprobe -q kpatch; then
|
||||||
echo "loaded core module"
|
echo "loaded core module"
|
||||||
else
|
else
|
||||||
@ -149,7 +161,7 @@ load_module () {
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
local modname=$(get_module_name $module)
|
local modname=$(get_module_name $module)
|
||||||
local moddir=/sys/kernel/kpatch/patches/$modname
|
local moddir="$SYSFS/$modname"
|
||||||
if [[ -d $moddir ]] ; then
|
if [[ -d $moddir ]] ; then
|
||||||
if [[ $(cat "${moddir}/enabled") -eq 0 ]]; then
|
if [[ $(cat "${moddir}/enabled") -eq 0 ]]; then
|
||||||
if verify_module_checksum $module; then # same checksum
|
if verify_module_checksum $module; then # same checksum
|
||||||
@ -191,7 +203,7 @@ load_module () {
|
|||||||
unload_module () {
|
unload_module () {
|
||||||
PATCH="${1//-/_}"
|
PATCH="${1//-/_}"
|
||||||
PATCH="${PATCH%.ko}"
|
PATCH="${PATCH%.ko}"
|
||||||
ENABLED=/sys/kernel/kpatch/patches/"$PATCH"/enabled
|
ENABLED="$SYSFS/$PATCH/enabled"
|
||||||
[[ -e "$ENABLED" ]] || die "patch module $1 is not loaded"
|
[[ -e "$ENABLED" ]] || die "patch module $1 is not loaded"
|
||||||
if [[ $(cat "$ENABLED") -eq 1 ]]; then
|
if [[ $(cat "$ENABLED") -eq 1 ]]; then
|
||||||
echo "disabling patch module: $PATCH"
|
echo "disabling patch module: $PATCH"
|
||||||
@ -233,7 +245,7 @@ case "$1" in
|
|||||||
[[ "$#" -ne 2 ]] && usage
|
[[ "$#" -ne 2 ]] && usage
|
||||||
case "$2" in
|
case "$2" in
|
||||||
"--all")
|
"--all")
|
||||||
for module in /sys/kernel/kpatch/patches/*; do
|
for module in $SYSFS/*; do
|
||||||
[[ -e $module ]] || continue
|
[[ -e $module ]] || continue
|
||||||
unload_module $(basename $module) || die "failed to unload module $module"
|
unload_module $(basename $module) || die "failed to unload module $module"
|
||||||
done
|
done
|
||||||
@ -320,7 +332,7 @@ case "$1" in
|
|||||||
"list")
|
"list")
|
||||||
[[ "$#" -ne 1 ]] && usage
|
[[ "$#" -ne 1 ]] && usage
|
||||||
echo "Loaded patch modules:"
|
echo "Loaded patch modules:"
|
||||||
for module in /sys/kernel/kpatch/patches/*; do
|
for module in $SYSFS/*; do
|
||||||
if [[ -e $module ]] && [[ $(cat $module/enabled) -eq 1 ]]; then
|
if [[ -e $module ]] && [[ $(cat $module/enabled) -eq 1 ]]; then
|
||||||
echo $(basename "$module")
|
echo $(basename "$module")
|
||||||
fi
|
fi
|
||||||
|
Loading…
Reference in New Issue
Block a user