kpatch, kpatch-build, kpatch-gcc: quote all variables

Without proper quoting kpatch fails if the argument contains spaces, the
other scripts might be affected as well.

Not all new quotes are strictly necessary but they were added for
consistency with the existing code and to prevent copy & paste errors in
the future.

There's one conversion which is not straight-forward:

-       grepname=$grepname\\\.o
+       grepname="$grepname\.o"

There are different quoting rules with and without the double quotes.
This commit is contained in:
Simon Ruderich 2017-09-21 20:46:20 +02:00
parent 9017bfd32d
commit 08fa04bb0d
3 changed files with 214 additions and 214 deletions

View File

@ -35,7 +35,7 @@
# - Runs kpatch tools to create and link the patch kernel module # - Runs kpatch tools to create and link the patch kernel module
BASE="$PWD" BASE="$PWD"
SCRIPTDIR="$(readlink -f $(dirname $(type -p $0)))" SCRIPTDIR="$(readlink -f "$(dirname "$(type -p "$0")")")"
ARCH="$(uname -m)" ARCH="$(uname -m)"
ARCHVERSION="$(uname -r)" ARCHVERSION="$(uname -r)"
CPUS="$(getconf _NPROCESSORS_ONLN)" CPUS="$(getconf _NPROCESSORS_ONLN)"
@ -57,13 +57,13 @@ warn() {
} }
die() { die() {
if [[ -z $1 ]]; then if [[ -z "$1" ]]; then
msg="kpatch build failed" msg="kpatch build failed"
else else
msg="$1" msg="$1"
fi fi
if [[ -e $LOGFILE ]]; then if [[ -e "$LOGFILE" ]]; then
warn "$msg. Check $LOGFILE for more details." warn "$msg. Check $LOGFILE for more details."
else else
warn "$msg." warn "$msg."
@ -99,11 +99,11 @@ cleanup() {
remove_patches remove_patches
# If $SRCDIR was a git repo, make sure git actually sees that # If $SRCDIR was a git repo, make sure git actually sees that
# we've reverted our patch(es). # we've reverted our patch(es).
[[ -d $SRCDIR/.git ]] && (cd $SRCDIR && git update-index -q --refresh) [[ -d "$SRCDIR/.git" ]] && (cd "$SRCDIR" && git update-index -q --refresh)
# restore original .config and vmlinux if they were removed with mrproper # restore original .config and vmlinux if they were removed with mrproper
[[ -e $TEMPDIR/.config ]] && mv -f $TEMPDIR/.config $SRCDIR/ [[ -e "$TEMPDIR/.config" ]] && mv -f "$TEMPDIR/.config" "$SRCDIR/"
[[ -e $TEMPDIR/vmlinux ]] && mv -f $TEMPDIR/vmlinux $SRCDIR/ [[ -e "$TEMPDIR/vmlinux" ]] && mv -f "$TEMPDIR/vmlinux" "$SRCDIR/"
[[ "$DEBUG" -eq 0 ]] && rm -rf "$TEMPDIR" [[ "$DEBUG" -eq 0 ]] && rm -rf "$TEMPDIR"
rm -rf "$RPMTOPDIR" rm -rf "$RPMTOPDIR"
@ -118,7 +118,7 @@ clean_cache() {
check_pipe_status() { check_pipe_status() {
rc="${PIPESTATUS[0]}" rc="${PIPESTATUS[0]}"
if [[ $rc = 139 ]]; then if [[ "$rc" = 139 ]]; then
# There doesn't seem to be a consistent/portable way of # There doesn't seem to be a consistent/portable way of
# accessing the last executed command in bash, so just # accessing the last executed command in bash, so just
# pass in the script name for now.. # pass in the script name for now..
@ -140,11 +140,11 @@ find_dirs() {
if [[ -e "$SCRIPTDIR/create-diff-object" ]]; then if [[ -e "$SCRIPTDIR/create-diff-object" ]]; then
# git repo # git repo
TOOLSDIR="$SCRIPTDIR" TOOLSDIR="$SCRIPTDIR"
DATADIR="$(readlink -f $SCRIPTDIR/../kmod)" DATADIR="$(readlink -f "$SCRIPTDIR/../kmod")"
elif [[ -e "$SCRIPTDIR/../libexec/kpatch/create-diff-object" ]]; then elif [[ -e "$SCRIPTDIR/../libexec/kpatch/create-diff-object" ]]; then
# installation path # installation path
TOOLSDIR="$(readlink -f $SCRIPTDIR/../libexec/kpatch)" TOOLSDIR="$(readlink -f "$SCRIPTDIR/../libexec/kpatch")"
DATADIR="$(readlink -f $SCRIPTDIR/../share/kpatch)" DATADIR="$(readlink -f "$SCRIPTDIR/../share/kpatch")"
else else
return 1 return 1
fi fi
@ -157,10 +157,10 @@ find_core_symvers() {
SYMVERSFILE="$DATADIR/core/Module.symvers" SYMVERSFILE="$DATADIR/core/Module.symvers"
elif [[ -e "$SCRIPTDIR/../libexec/kpatch/create-diff-object" ]]; then elif [[ -e "$SCRIPTDIR/../libexec/kpatch/create-diff-object" ]]; then
# installation path # installation path
if [[ -e $SCRIPTDIR/../lib/kpatch/$ARCHVERSION/Module.symvers ]]; then if [[ -e "$SCRIPTDIR/../lib/kpatch/$ARCHVERSION/Module.symvers" ]]; then
SYMVERSFILE="$(readlink -f $SCRIPTDIR/../lib/kpatch/$ARCHVERSION/Module.symvers)" SYMVERSFILE="$(readlink -f "$SCRIPTDIR/../lib/kpatch/$ARCHVERSION/Module.symvers")"
elif [[ -e /lib/modules/$ARCHVERSION/extra/kpatch/Module.symvers ]]; then elif [[ -e /lib/modules/$ARCHVERSION/extra/kpatch/Module.symvers ]]; then
SYMVERSFILE="$(readlink -f /lib/modules/$ARCHVERSION/extra/kpatch/Module.symvers)" SYMVERSFILE="$(readlink -f "/lib/modules/$ARCHVERSION/extra/kpatch/Module.symvers")"
fi fi
fi fi
@ -169,9 +169,9 @@ find_core_symvers() {
gcc_version_check() { gcc_version_check() {
# ensure gcc version matches that used to build the kernel # ensure gcc version matches that used to build the kernel
local gccver=$(gcc --version |head -n1 |cut -d' ' -f3-) local gccver="$(gcc --version |head -n1 |cut -d' ' -f3-)"
local kgccver=$(readelf -p .comment $VMLINUX |grep GCC: | tr -s ' ' | cut -d ' ' -f6-) local kgccver="$(readelf -p .comment "$VMLINUX" |grep GCC: | tr -s ' ' | cut -d ' ' -f6-)"
if [[ $gccver != $kgccver ]]; then if [[ "$gccver" != "$kgccver" ]]; then
warn "gcc/kernel version mismatch" warn "gcc/kernel version mismatch"
echo "gcc version: $gccver" echo "gcc version: $gccver"
echo "kernel version: $kgccver" echo "kernel version: $kgccver"
@ -186,12 +186,12 @@ gcc_version_check() {
# <linux>/arch/powerpc/tools/gcc-check-mprofile-kernel.sh # <linux>/arch/powerpc/tools/gcc-check-mprofile-kernel.sh
# #
# Postpone the check to the kernel build instead of duplicating it here. # Postpone the check to the kernel build instead of duplicating it here.
if [[ $ARCH = "ppc64le" ]]; then if [[ "$ARCH" = "ppc64le" ]]; then
return return
else else
# ensure gcc version is >= 4.8 # ensure gcc version is >= 4.8
gccver=$(echo $gccver |cut -d'.' -f1,2) gccver="$(echo "$gccver" |cut -d'.' -f1,2)"
if [[ $gccver < 4.8 ]]; then if [[ "$gccver" < 4.8 ]]; then
warn "gcc >= 4.8 required" warn "gcc >= 4.8 required"
return 1 return 1
fi fi
@ -201,7 +201,7 @@ gcc_version_check() {
} }
find_special_section_data_ppc64le() { find_special_section_data_ppc64le() {
SPECIAL_VARS=$(readelf -wi "$VMLINUX" | SPECIAL_VARS="$(readelf -wi "$VMLINUX" |
gawk --non-decimal-data ' gawk --non-decimal-data '
BEGIN { f = b = e = 0 } BEGIN { f = b = e = 0 }
@ -221,25 +221,25 @@ find_special_section_data_ppc64le() {
e == 1 {printf("export EX_STRUCT_SIZE=%d\n", $4); e = 2} e == 1 {printf("export EX_STRUCT_SIZE=%d\n", $4); e = 2}
# Bail out once we have everything # Bail out once we have everything
f == 2 && b == 2 && e == 2 {exit}') f == 2 && b == 2 && e == 2 {exit}')"
[[ -n $SPECIAL_VARS ]] && eval "$SPECIAL_VARS" [[ -n "$SPECIAL_VARS" ]] && eval "$SPECIAL_VARS"
[[ -z $FIXUP_STRUCT_SIZE ]] && die "can't find special struct fixup_entry size" [[ -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 "$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 "$EX_STRUCT_SIZE" ]] && die "can't find special struct exception_table_entry size"
return return
} }
find_special_section_data() { find_special_section_data() {
if [[ $ARCH = "ppc64le" ]]; then if [[ "$ARCH" = "ppc64le" ]]; then
find_special_section_data_ppc64le find_special_section_data_ppc64le
return return
fi fi
[[ $CONFIG_PARAVIRT -eq 0 ]] && AWK_OPTIONS="-vskip_p=1" [[ "$CONFIG_PARAVIRT" -eq 0 ]] && AWK_OPTIONS="-vskip_p=1"
SPECIAL_VARS=$(readelf -wi "$VMLINUX" | SPECIAL_VARS="$(readelf -wi "$VMLINUX" |
gawk --non-decimal-data $AWK_OPTIONS ' gawk --non-decimal-data $AWK_OPTIONS '
BEGIN { a = b = p = e = 0 } BEGIN { a = b = p = e = 0 }
@ -262,64 +262,64 @@ find_special_section_data() {
e == 1 {printf("export EX_STRUCT_SIZE=%d\n", $4); e = 2} e == 1 {printf("export EX_STRUCT_SIZE=%d\n", $4); e = 2}
# Bail out once we have everything # 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 {exit}')"
[[ -n $SPECIAL_VARS ]] && eval "$SPECIAL_VARS" [[ -n "$SPECIAL_VARS" ]] && eval "$SPECIAL_VARS"
[[ -z $ALT_STRUCT_SIZE ]] && die "can't find special struct alt_instr size" [[ -z "$ALT_STRUCT_SIZE" ]] && die "can't find special struct alt_instr size"
[[ -z $BUG_STRUCT_SIZE ]] && die "can't find special struct bug_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 paravirt_patch_site 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 "$PARA_STRUCT_SIZE" && "$CONFIG_PARAVIRT" -ne 0 ]] && die "can't find special struct paravirt_patch_site size"
return return
} }
find_parent_obj() { find_parent_obj() {
dir=$(dirname $1) dir="$(dirname "$1")"
absdir=$(readlink -f $dir) absdir="$(readlink -f "$dir")"
pwddir=$(readlink -f .) pwddir="$(readlink -f .)"
pdir=${absdir#$pwddir/} pdir="${absdir#$pwddir/}"
file=$(basename $1) file="$(basename "$1")"
grepname=${1%.o} grepname="${1%.o}"
grepname=$grepname\\\.o grepname="$grepname\.o"
if [[ $DEEP_FIND -eq 1 ]]; then if [[ "$DEEP_FIND" -eq 1 ]]; then
num=0 num=0
if [[ -n $last_deep_find ]]; then if [[ -n "$last_deep_find" ]]; then
parent=$(grep -l $grepname $last_deep_find/.*.cmd | grep -v $pdir/.${file}.cmd |head -n1) parent="$(grep -l "$grepname" "$last_deep_find"/.*.cmd | grep -v "$pdir/.${file}.cmd" |head -n1)"
num=$(grep -l $grepname $last_deep_find/.*.cmd | grep -v $pdir/.${file}.cmd |wc -l) num="$(grep -l "$grepname" "$last_deep_find"/.*.cmd | grep -v "$pdir/.${file}.cmd" |wc -l)"
fi fi
if [[ $num -eq 0 ]]; then if [[ "$num" -eq 0 ]]; then
parent=$(find * -name ".*.cmd" | xargs grep -l $grepname | grep -v $pdir/.${file}.cmd |head -n1) parent="$(find * -name ".*.cmd" | xargs grep -l "$grepname" | grep -v "$pdir/.${file}.cmd" |head -n1)"
num=$(find * -name ".*.cmd" | xargs grep -l $grepname | grep -v $pdir/.${file}.cmd | wc -l) num="$(find * -name ".*.cmd" | xargs grep -l "$grepname" | grep -v "$pdir/.${file}.cmd" | wc -l)"
[[ $num -eq 1 ]] && last_deep_find=$(dirname $parent) [[ "$num" -eq 1 ]] && last_deep_find="$(dirname "$parent")"
fi fi
else else
parent=$(grep -l $grepname $dir/.*.cmd | grep -v $dir/.${file}.cmd |head -n1) parent="$(grep -l "$grepname" "$dir"/.*.cmd | grep -v "$dir/.${file}.cmd" |head -n1)"
num=$(grep -l $grepname $dir/.*.cmd | grep -v $dir/.${file}.cmd | wc -l) num="$(grep -l "$grepname" "$dir"/.*.cmd | grep -v "$dir/.${file}.cmd" | wc -l)"
fi fi
[[ $num -eq 0 ]] && PARENT="" && return [[ "$num" -eq 0 ]] && PARENT="" && return
[[ $num -gt 1 ]] && ERROR_IF_DIFF="two parent matches for $1" [[ "$num" -gt 1 ]] && ERROR_IF_DIFF="two parent matches for $1"
dir=$(dirname $parent) dir="$(dirname "$parent")"
PARENT=$(basename $parent) PARENT="$(basename "$parent")"
PARENT=${PARENT#.} PARENT="${PARENT#.}"
PARENT=${PARENT%.cmd} PARENT="${PARENT%.cmd}"
PARENT=$dir/$PARENT PARENT="$dir/$PARENT"
[[ ! -e $PARENT ]] && die "ERROR: can't find parent $PARENT for $1" [[ ! -e "$PARENT" ]] && die "ERROR: can't find parent $PARENT for $1"
} }
find_kobj() { find_kobj() {
arg=$1 arg="$1"
KOBJFILE=$arg KOBJFILE="$arg"
DEEP_FIND=0 DEEP_FIND=0
ERROR_IF_DIFF= ERROR_IF_DIFF=
while true; do while true; do
find_parent_obj $KOBJFILE find_parent_obj "$KOBJFILE"
[[ -n $PARENT ]] && DEEP_FIND=0 [[ -n "$PARENT" ]] && DEEP_FIND=0
if [[ -z $PARENT ]]; then if [[ -z "$PARENT" ]]; then
[[ $KOBJFILE = *.ko ]] && return [[ "$KOBJFILE" = *.ko ]] && return
case $KOBJFILE in case "$KOBJFILE" in
*/built-in.o|\ */built-in.o|\
arch/x86/lib/lib.a|\ arch/x86/lib/lib.a|\
arch/x86/kernel/head*.o|\ arch/x86/kernel/head*.o|\
@ -329,13 +329,13 @@ find_kobj() {
KOBJFILE=vmlinux KOBJFILE=vmlinux
return return
esac esac
if [[ $DEEP_FIND -eq 0 ]]; then if [[ "$DEEP_FIND" -eq 0 ]]; then
DEEP_FIND=1 DEEP_FIND=1
continue; continue;
fi fi
die "invalid ancestor $KOBJFILE for $arg" die "invalid ancestor $KOBJFILE for $arg"
fi fi
KOBJFILE=$PARENT KOBJFILE="$PARENT"
done done
} }
@ -343,11 +343,11 @@ find_kobj() {
# is replaced with '-'. Also truncate to 48 chars so the full name fits in the # is replaced with '-'. Also truncate to 48 chars so the full name fits in the
# kernel's 56-byte module name array. # kernel's 56-byte module name array.
module_name_string() { module_name_string() {
echo ${1//[^a-zA-Z0-9_-]/-} |cut -c 1-48 echo "${1//[^a-zA-Z0-9_-]/-}" |cut -c 1-48
} }
usage() { usage() {
echo "usage: $(basename $0) [options] <patch1 ... patchN>" >&2 echo "usage: $(basename "$0") [options] <patch1 ... patchN>" >&2
echo " patchN Input patchfile(s)" >&2 echo " patchN Input patchfile(s)" >&2
echo " -h, --help Show this help message" >&2 echo " -h, --help Show this help message" >&2
echo " -r, --sourcerpm Specify kernel source RPM" >&2 echo " -r, --sourcerpm Specify kernel source RPM" >&2
@ -363,7 +363,7 @@ usage() {
echo " (not recommended)" >&2 echo " (not recommended)" >&2
} }
options=$(getopt -o hr:s:c:v:j:t:n:o:d -l "help,sourcerpm:,sourcedir:,config:,vmlinux:,jobs:,target:,name:,output:,debug,skip-gcc-check,skip-cleanup" -- "$@") || die "getopt failed" options="$(getopt -o hr:s:c:v:j:t:n:o:d -l "help,sourcerpm:,sourcedir:,config:,vmlinux:,jobs:,target:,name:,output:,debug,skip-gcc-check,skip-cleanup" -- "$@")" || die "getopt failed"
eval set -- "$options" eval set -- "$options"
@ -375,25 +375,25 @@ while [[ $# -gt 0 ]]; do
;; ;;
-r|--sourcerpm) -r|--sourcerpm)
[[ ! -f "$2" ]] && die "source rpm '$2' not found" [[ ! -f "$2" ]] && die "source rpm '$2' not found"
SRCRPM=$(readlink -f "$2") SRCRPM="$(readlink -f "$2")"
shift shift
rpmname=$(basename "$SRCRPM") rpmname="$(basename "$SRCRPM")"
ARCHVERSION=${rpmname%.src.rpm}.$(uname -m) ARCHVERSION="${rpmname%.src.rpm}.$(uname -m)"
ARCHVERSION=${ARCHVERSION#kernel-} ARCHVERSION="${ARCHVERSION#kernel-}"
;; ;;
-s|--sourcedir) -s|--sourcedir)
[[ ! -d "$2" ]] && die "source dir '$2' not found" [[ ! -d "$2" ]] && die "source dir '$2' not found"
USERSRCDIR=$(readlink -f "$2") USERSRCDIR="$(readlink -f "$2")"
shift shift
;; ;;
-c|--config) -c|--config)
[[ ! -f "$2" ]] && die "config file '$2' not found" [[ ! -f "$2" ]] && die "config file '$2' not found"
CONFIGFILE=$(readlink -f "$2") CONFIGFILE="$(readlink -f "$2")"
shift shift
;; ;;
-v|--vmlinux) -v|--vmlinux)
[[ ! -f "$2" ]] && die "vmlinux file '$2' not found" [[ ! -f "$2" ]] && die "vmlinux file '$2' not found"
VMLINUX=$(readlink -f "$2") VMLINUX="$(readlink -f "$2")"
shift shift
;; ;;
-j|--jobs) -j|--jobs)
@ -406,12 +406,12 @@ while [[ $# -gt 0 ]]; do
shift shift
;; ;;
-n|--name) -n|--name)
MODNAME=$(module_name_string "$2") MODNAME="$(module_name_string "$2")"
shift shift
;; ;;
-o|--output) -o|--output)
[[ ! -d "$2" ]] && die "output dir '$2' not found" [[ ! -d "$2" ]] && die "output dir '$2' not found"
BASE=$(readlink -f "$2") BASE="$(readlink -f "$2")"
shift shift
;; ;;
-d|--debug) -d|--debug)
@ -430,7 +430,7 @@ while [[ $# -gt 0 ]]; do
*) *)
[[ "$1" = "--" ]] && shift && continue [[ "$1" = "--" ]] && shift && continue
[[ ! -f "$1" ]] && die "patch file '$1' not found" [[ ! -f "$1" ]] && die "patch file '$1' not found"
PATCH_LIST+=($(readlink -f "$1")) PATCH_LIST+=("$(readlink -f "$1")")
;; ;;
esac esac
shift shift
@ -447,50 +447,50 @@ mkdir -p "$TEMPDIR" || die "Couldn't create $TEMPDIR"
rm -rf "$TEMPDIR"/* rm -rf "$TEMPDIR"/*
rm -f "$LOGFILE" rm -f "$LOGFILE"
if [[ -n $USERSRCDIR ]]; then if [[ -n "$USERSRCDIR" ]]; then
SRCDIR="$USERSRCDIR" SRCDIR="$USERSRCDIR"
[[ -z $VMLINUX ]] && VMLINUX="$SRCDIR"/vmlinux [[ -z "$VMLINUX" ]] && VMLINUX="$SRCDIR"/vmlinux
[[ ! -e "$VMLINUX" ]] && die "can't find vmlinux" [[ ! -e "$VMLINUX" ]] && die "can't find vmlinux"
# Extract the target kernel version from vmlinux in this case. # Extract the target kernel version from vmlinux in this case.
ARCHVERSION=$(strings "$VMLINUX" | grep -e "^Linux version" | awk '{ print($3); }') ARCHVERSION="$(strings "$VMLINUX" | grep -e "^Linux version" | awk '{ print($3); }')"
fi fi
[[ $SKIPCLEANUP -eq 0 ]] && trap cleanup EXIT INT TERM HUP [[ "$SKIPCLEANUP" -eq 0 ]] && trap cleanup EXIT INT TERM HUP
KVER=${ARCHVERSION%%-*} KVER="${ARCHVERSION%%-*}"
if [[ $ARCHVERSION =~ - ]]; then if [[ "$ARCHVERSION" =~ - ]]; then
KREL=${ARCHVERSION##*-} KREL="${ARCHVERSION##*-}"
KREL=${KREL%.*} KREL="${KREL%.*}"
fi fi
[[ -z $TARGETS ]] && TARGETS="vmlinux modules" [[ -z "$TARGETS" ]] && TARGETS="vmlinux modules"
source /etc/os-release source /etc/os-release
DISTRO=$ID DISTRO="$ID"
if [[ $DISTRO = fedora ]] || [[ $DISTRO = rhel ]] || [[ $DISTRO = ol ]] || [[ $DISTRO = centos ]]; then if [[ "$DISTRO" = fedora ]] || [[ "$DISTRO" = rhel ]] || [[ "$DISTRO" = ol ]] || [[ "$DISTRO" = centos ]]; then
[[ -z $VMLINUX ]] && VMLINUX=/usr/lib/debug/lib/modules/$ARCHVERSION/vmlinux [[ -z "$VMLINUX" ]] && VMLINUX="/usr/lib/debug/lib/modules/$ARCHVERSION/vmlinux"
[[ -e "$VMLINUX" ]] || die "kernel-debuginfo-$ARCHVERSION not installed" [[ -e "$VMLINUX" ]] || die "kernel-debuginfo-$ARCHVERSION not installed"
export PATH=/usr/lib64/ccache:$PATH export PATH="/usr/lib64/ccache:$PATH"
elif [[ $DISTRO = ubuntu ]] || [[ $DISTRO = debian ]]; then elif [[ "$DISTRO" = ubuntu ]] || [[ "$DISTRO" = debian ]]; then
[[ -z $VMLINUX ]] && VMLINUX=/usr/lib/debug/boot/vmlinux-$ARCHVERSION [[ -z "$VMLINUX" ]] && VMLINUX="/usr/lib/debug/boot/vmlinux-$ARCHVERSION"
if [[ $DISTRO = ubuntu ]]; then if [[ "$DISTRO" = ubuntu ]]; then
[[ -e "$VMLINUX" ]] || die "linux-image-$ARCHVERSION-dbgsym not installed" [[ -e "$VMLINUX" ]] || die "linux-image-$ARCHVERSION-dbgsym not installed"
elif [[ $DISTRO = debian ]]; then elif [[ "$DISTRO" = debian ]]; then
[[ -e "$VMLINUX" ]] || die "linux-image-$ARCHVERSION-dbg not installed" [[ -e "$VMLINUX" ]] || die "linux-image-$ARCHVERSION-dbg not installed"
fi fi
export PATH=/usr/lib/ccache:$PATH export PATH="/usr/lib/ccache:$PATH"
fi fi
find_dirs || die "can't find supporting tools" find_dirs || die "can't find supporting tools"
if [[ $SKIPGCCCHECK -eq 0 ]]; then if [[ "$SKIPGCCCHECK" -eq 0 ]]; then
gcc_version_check || die gcc_version_check || die
fi fi
@ -498,13 +498,13 @@ if [[ -n "$USERSRCDIR" ]]; then
echo "Using source directory at $USERSRCDIR" echo "Using source directory at $USERSRCDIR"
# save vmlinux before it gets removed with mrproper # save vmlinux before it gets removed with mrproper
[[ "$VMLINUX" -ef "$SRCDIR"/vmlinux ]] && cp -f "$VMLINUX" $TEMPDIR/vmlinux && VMLINUX=$TEMPDIR/vmlinux [[ "$VMLINUX" -ef "$SRCDIR"/vmlinux ]] && cp -f "$VMLINUX" "$TEMPDIR/vmlinux" && VMLINUX="$TEMPDIR/vmlinux"
elif [[ -e "$SRCDIR"/.config ]] && [[ -e "$VERSIONFILE" ]] && [[ $(cat "$VERSIONFILE") = $ARCHVERSION ]]; then elif [[ -e "$SRCDIR"/.config ]] && [[ -e "$VERSIONFILE" ]] && [[ "$(cat "$VERSIONFILE")" = "$ARCHVERSION" ]]; then
echo "Using cache at $SRCDIR" echo "Using cache at $SRCDIR"
else else
if [[ $DISTRO = fedora ]] || [[ $DISTRO = rhel ]] || [[ $DISTRO = ol ]] || [[ $DISTRO = centos ]]; then if [[ "$DISTRO" = fedora ]] || [[ "$DISTRO" = rhel ]] || [[ "$DISTRO" = ol ]] || [[ "$DISTRO" = centos ]]; then
echo "Fedora/Red Hat distribution detected" echo "Fedora/Red Hat distribution detected"
rpm -q --quiet rpmdevtools || die "rpmdevtools not installed" rpm -q --quiet rpmdevtools || die "rpmdevtools not installed"
@ -513,8 +513,8 @@ else
echo "Downloading kernel source for $ARCHVERSION" echo "Downloading kernel source for $ARCHVERSION"
if [[ -z "$SRCRPM" ]]; then if [[ -z "$SRCRPM" ]]; then
if [[ $DISTRO = fedora ]]; then if [[ "$DISTRO" = fedora ]]; then
wget -P $TEMPDIR http://kojipkgs.fedoraproject.org/packages/kernel/$KVER/$KREL/src/kernel-$KVER-$KREL.src.rpm >> "$LOGFILE" 2>&1 || die wget -P "$TEMPDIR" "http://kojipkgs.fedoraproject.org/packages/kernel/$KVER/$KREL/src/kernel-$KVER-$KREL.src.rpm" >> "$LOGFILE" 2>&1 || die
else else
rpm -q --quiet yum-utils || die "yum-utils not installed" rpm -q --quiet yum-utils || die "yum-utils not installed"
yumdownloader --source --destdir "$TEMPDIR" "kernel-$ARCHVERSION" >> "$LOGFILE" 2>&1 || die yumdownloader --source --destdir "$TEMPDIR" "kernel-$ARCHVERSION" >> "$LOGFILE" 2>&1 || die
@ -536,37 +536,37 @@ else
echo "-${ARCHVERSION##*-}" > "$SRCDIR/localversion" || die echo "-${ARCHVERSION##*-}" > "$SRCDIR/localversion" || die
fi fi
echo $ARCHVERSION > "$VERSIONFILE" || die echo "$ARCHVERSION" > "$VERSIONFILE" || die
elif [[ $DISTRO = ubuntu ]] || [[ $DISTRO = debian ]]; then elif [[ "$DISTRO" = ubuntu ]] || [[ "$DISTRO" = debian ]]; then
echo "Debian/Ubuntu distribution detected" echo "Debian/Ubuntu distribution detected"
if [[ $DISTRO = ubuntu ]]; then if [[ "$DISTRO" = ubuntu ]]; then
# url may be changed for a different mirror # url may be changed for a different mirror
url="http://archive.ubuntu.com/ubuntu/pool/main/l" url="http://archive.ubuntu.com/ubuntu/pool/main/l"
sublevel="SUBLEVEL = 0" sublevel="SUBLEVEL = 0"
UBUNTU_KERNEL=1 UBUNTU_KERNEL=1
elif [[ $DISTRO = debian ]]; then elif [[ "$DISTRO" = debian ]]; then
# url may be changed for a different mirror # url may be changed for a different mirror
url="http://ftp.debian.org/debian/pool/main/l" url="http://ftp.debian.org/debian/pool/main/l"
sublevel="SUBLEVEL =" sublevel="SUBLEVEL ="
fi fi
pkgname="$(dpkg-query -W -f='${Source}' linux-image-$ARCHVERSION)" pkgname="$(dpkg-query -W -f='${Source}' "linux-image-$ARCHVERSION")"
pkgver="$(dpkg-query -W -f='${Version}' linux-image-$ARCHVERSION)" pkgver="$(dpkg-query -W -f='${Version}' "linux-image-$ARCHVERSION")"
dscname="${pkgname}_${pkgver}.dsc" dscname="${pkgname}_${pkgver}.dsc"
clean_cache clean_cache
cd $TEMPDIR cd "$TEMPDIR"
echo "Downloading and unpacking the kernel source for $ARCHVERSION" echo "Downloading and unpacking the kernel source for $ARCHVERSION"
# Download source deb pkg # Download source deb pkg
(dget -u "$url/${pkgname}/${dscname}" 2>&1) >> "$LOGFILE" || die "dget: Could not fetch/unpack $url/${pkgname}/${dscname}" (dget -u "$url/${pkgname}/${dscname}" 2>&1) >> "$LOGFILE" || die "dget: Could not fetch/unpack $url/${pkgname}/${dscname}"
mv ${pkgname}-$KVER "$SRCDIR" || die mv "${pkgname}-$KVER" "$SRCDIR" || die
cp "/boot/config-${ARCHVERSION}" "$SRCDIR/.config" || die cp "/boot/config-${ARCHVERSION}" "$SRCDIR/.config" || die
if [[ "$ARCHVERSION" == *-* ]]; then if [[ "$ARCHVERSION" == *-* ]]; then
echo "-${ARCHVERSION#*-}" > "$SRCDIR/localversion" || die echo "-${ARCHVERSION#*-}" > "$SRCDIR/localversion" || die
@ -574,7 +574,7 @@ else
# for some reason the Ubuntu kernel versions don't follow the # for some reason the Ubuntu kernel versions don't follow the
# upstream SUBLEVEL; they are always at SUBLEVEL 0 # upstream SUBLEVEL; they are always at SUBLEVEL 0
sed -i "s/^SUBLEVEL.*/${sublevel}/" "$SRCDIR/Makefile" || die sed -i "s/^SUBLEVEL.*/${sublevel}/" "$SRCDIR/Makefile" || die
echo $ARCHVERSION > "$VERSIONFILE" || die echo "$ARCHVERSION" > "$VERSIONFILE" || die
else else
die "Unsupported distribution" die "Unsupported distribution"
@ -582,9 +582,9 @@ else
fi fi
# save .config before it gets removed with mrproper # save .config before it gets removed with mrproper
[[ -z $CONFIGFILE ]] && CONFIGFILE="$SRCDIR"/.config [[ -z "$CONFIGFILE" ]] && CONFIGFILE="$SRCDIR"/.config
[[ ! -e "$CONFIGFILE" ]] && die "can't find config file" [[ ! -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" "$TEMPDIR" && CONFIGFILE="$TEMPDIR"/.config
# Build variables - Set some defaults, then adjust features # Build variables - Set some defaults, then adjust features
# according to .config and kernel version # according to .config and kernel version
@ -596,10 +596,10 @@ KPATCH_MODULE=true
grep -q "CONFIG_DEBUG_INFO=y" "$CONFIGFILE" || die "kernel doesn't have 'CONFIG_DEBUG_INFO' enabled" grep -q "CONFIG_DEBUG_INFO=y" "$CONFIGFILE" || die "kernel doesn't have 'CONFIG_DEBUG_INFO' enabled"
if grep -q "CONFIG_LIVEPATCH=y" "$CONFIGFILE"; then if grep -q "CONFIG_LIVEPATCH=y" "$CONFIGFILE"; then
# The kernel supports livepatch. # The kernel supports livepatch.
if version_gte ${ARCHVERSION//-*/} 4.7.0; then if version_gte "${ARCHVERSION//-*/}" 4.7.0; then
# Use new .klp.rela. sections # Use new .klp.rela. sections
KPATCH_MODULE=false KPATCH_MODULE=false
if version_gte ${ARCHVERSION//-*/} 4.9.0; then if version_gte "${ARCHVERSION//-*/}" 4.9.0; then
KPATCH_LDFLAGS="--unique=.parainstructions --unique=.altinstructions" KPATCH_LDFLAGS="--unique=.parainstructions --unique=.altinstructions"
fi fi
fi fi
@ -626,7 +626,7 @@ remove_patches
cp -LR "$DATADIR/patch" "$TEMPDIR" || die cp -LR "$DATADIR/patch" "$TEMPDIR" || die
if [[ $ARCH = "ppc64le" ]]; then if [[ "$ARCH" = "ppc64le" ]]; then
ARCH_KCFLAGS="-mcmodel=large" ARCH_KCFLAGS="-mcmodel=large"
fi fi
@ -645,7 +645,7 @@ CROSS_COMPILE="$TOOLSDIR/kpatch-gcc " make "-j$CPUS" $TARGETS >> "$LOGFILE" 2>&1
echo "Building patched kernel" echo "Building patched kernel"
apply_patches apply_patches
mkdir -p "$TEMPDIR/orig" "$TEMPDIR/patched" mkdir -p "$TEMPDIR/orig" "$TEMPDIR/patched"
KPATCH_GCC_TEMPDIR=$TEMPDIR KPATCH_GCC_TEMPDIR="$TEMPDIR"
export KPATCH_GCC_TEMPDIR export KPATCH_GCC_TEMPDIR
CROSS_COMPILE="$TOOLSDIR/kpatch-gcc " \ CROSS_COMPILE="$TOOLSDIR/kpatch-gcc " \
KBUILD_MODPOST_WARN=1 \ KBUILD_MODPOST_WARN=1 \
@ -660,7 +660,7 @@ fi
for i in $(cat "$TEMPDIR/changed_objs") for i in $(cat "$TEMPDIR/changed_objs")
do do
mkdir -p "$TEMPDIR/patched/$(dirname $i)" || die mkdir -p "$TEMPDIR/patched/$(dirname "$i")" || die
cp -f "$SRCDIR/$i" "$TEMPDIR/patched/$i" || die cp -f "$SRCDIR/$i" "$TEMPDIR/patched/$i" || die
done done
@ -669,9 +669,9 @@ echo "Extracting new and modified ELF sections"
# - For single input .patch, use the patch filename # - For single input .patch, use the patch filename
# - For multiple input .patches, use "patch" # - For multiple input .patches, use "patch"
# - Prefix with "kpatch" or "livepatch" accordingly # - Prefix with "kpatch" or "livepatch" accordingly
if [[ -z $MODNAME ]] ; then if [[ -z "$MODNAME" ]] ; then
if [[ ${#PATCH_LIST[@]} -eq 1 ]]; then if [[ "${#PATCH_LIST[@]}" -eq 1 ]]; then
MODNAME=$(basename "${PATCH_LIST[0]}") MODNAME="$(basename "${PATCH_LIST[0]}")"
if [[ "$MODNAME" =~ \.patch$ ]] || [[ "$MODNAME" =~ \.diff$ ]]; then if [[ "$MODNAME" =~ \.patch$ ]] || [[ "$MODNAME" =~ \.diff$ ]]; then
MODNAME="${MODNAME%.*}" MODNAME="${MODNAME%.*}"
fi fi
@ -679,13 +679,13 @@ if [[ -z $MODNAME ]] ; then
MODNAME="patch" MODNAME="patch"
fi fi
if $KPATCH_MODULE; then if "$KPATCH_MODULE"; then
MODNAME="kpatch-$MODNAME" MODNAME="kpatch-$MODNAME"
else else
MODNAME="livepatch-$MODNAME" MODNAME="livepatch-$MODNAME"
fi fi
MODNAME=$(module_name_string "$MODNAME") MODNAME="$(module_name_string "$MODNAME")"
fi fi
FILES="$(cat "$TEMPDIR/changed_objs")" FILES="$(cat "$TEMPDIR/changed_objs")"
cd "$TEMPDIR" cd "$TEMPDIR"
@ -697,55 +697,55 @@ for i in $FILES; do
# In RHEL 7 based kernels, copy_user_64.o misuses the .fixup section, # In RHEL 7 based kernels, copy_user_64.o misuses the .fixup section,
# which confuses create-diff-object. It's fine to skip it, it's an # which confuses create-diff-object. It's fine to skip it, it's an
# assembly file anyway. # assembly file anyway.
[[ $DISTRO = rhel ]] || [[ $DISTRO = centos ]] || [[ $DISTRO = ol ]] && \ [[ "$DISTRO" = rhel ]] || [[ "$DISTRO" = centos ]] || [[ "$DISTRO" = ol ]] && \
[[ $i = arch/x86/lib/copy_user_64.o ]] && continue [[ "$i" = arch/x86/lib/copy_user_64.o ]] && continue
[[ $i = usr/initramfs_data.o ]] && continue [[ "$i" = usr/initramfs_data.o ]] && continue
mkdir -p "output/$(dirname $i)" mkdir -p "output/$(dirname "$i")"
cd "$SRCDIR" cd "$SRCDIR"
find_kobj $i find_kobj "$i"
if [[ $KOBJFILE = vmlinux ]]; then if [[ "$KOBJFILE" = vmlinux ]]; then
KOBJFILE=$VMLINUX KOBJFILE="$VMLINUX"
else else
KOBJFILE="$TEMPDIR/module/$KOBJFILE" KOBJFILE="$TEMPDIR/module/$KOBJFILE"
fi fi
cd $TEMPDIR cd "$TEMPDIR"
if [[ -e "orig/$i" ]]; then if [[ -e "orig/$i" ]]; then
# create-diff-object orig.o patched.o kernel-object output.o Module.symvers patch-mod-name # 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" \ "$TOOLSDIR"/create-diff-object "orig/$i" "patched/$i" "$KOBJFILE" \
"output/$i" "$SRCDIR/Module.symvers" "${MODNAME//-/_}" 2>&1 |tee -a "$LOGFILE" "output/$i" "$SRCDIR/Module.symvers" "${MODNAME//-/_}" 2>&1 |tee -a "$LOGFILE"
check_pipe_status create-diff-object check_pipe_status create-diff-object
# create-diff-object returns 3 if no functional change is found # create-diff-object returns 3 if no functional change is found
[[ $rc -eq 0 ]] || [[ $rc -eq 3 ]] || ERROR=$(expr $ERROR "+" 1) [[ "$rc" -eq 0 ]] || [[ "$rc" -eq 3 ]] || ERROR="$(expr $ERROR "+" 1)"
if [[ $rc -eq 0 ]]; then if [[ "$rc" -eq 0 ]]; then
[[ -n $ERROR_IF_DIFF ]] && die $ERROR_IF_DIFF [[ -n "$ERROR_IF_DIFF" ]] && die "$ERROR_IF_DIFF"
CHANGED=1 CHANGED=1
objnames[${#objnames[@]}]=$KOBJFILE objnames[${#objnames[@]}]="$KOBJFILE"
fi fi
else else
cp -f "patched/$i" "output/$i" cp -f "patched/$i" "output/$i"
objnames[${#objnames[@]}]=$KOBJFILE objnames[${#objnames[@]}]="$KOBJFILE"
fi fi
done done
if [[ $ERROR -ne 0 ]]; then if [[ "$ERROR" -ne 0 ]]; then
die "$ERROR error(s) encountered" die "$ERROR error(s) encountered"
fi fi
if [[ $CHANGED -eq 0 ]]; then if [[ "$CHANGED" -eq 0 ]]; then
die "no functional changes found" die "no functional changes found"
fi fi
echo -n "Patched objects:" echo -n "Patched objects:"
for i in $(echo "${objnames[@]}" | tr ' ' '\n' | sort -u | tr '\n' ' ') for i in $(echo "${objnames[@]}" | tr ' ' '\n' | sort -u | tr '\n' ' ')
do do
echo -n " $(basename $i)" echo -n " $(basename "$i")"
done done
echo echo
export KCFLAGS="-I$DATADIR/patch $ARCH_KCFLAGS" export KCFLAGS="-I$DATADIR/patch $ARCH_KCFLAGS"
if $KPATCH_MODULE; then if "$KPATCH_MODULE"; then
export KCPPFLAGS="-D__KPATCH_MODULE__" export KCPPFLAGS="-D__KPATCH_MODULE__"
fi fi
@ -753,25 +753,25 @@ echo "Building patch module: $MODNAME.ko"
cd "$SRCDIR" cd "$SRCDIR"
make prepare >> "$LOGFILE" 2>&1 || die make prepare >> "$LOGFILE" 2>&1 || die
if [[ ! -z $UBUNTU_KERNEL ]]; then if [[ ! -z "$UBUNTU_KERNEL" ]]; then
# UBUNTU: add UTS_UBUNTU_RELEASE_ABI to utsrelease.h after regenerating it # UBUNTU: add UTS_UBUNTU_RELEASE_ABI to utsrelease.h after regenerating it
UBUNTU_ABI=${ARCHVERSION#*-} UBUNTU_ABI="${ARCHVERSION#*-}"
UBUNTU_ABI=${UBUNTU_ABI%-*} UBUNTU_ABI="${UBUNTU_ABI%-*}"
echo "#define UTS_UBUNTU_RELEASE_ABI "$UBUNTU_ABI"" >> "$SRCDIR"/include/generated/utsrelease.h echo "#define UTS_UBUNTU_RELEASE_ABI "$UBUNTU_ABI"" >> "$SRCDIR"/include/generated/utsrelease.h
fi fi
cd "$TEMPDIR/output" cd "$TEMPDIR/output"
ld -r $KPATCH_LDFLAGS -o ../patch/tmp_output.o $(find . -name "*.o") >> "$LOGFILE" 2>&1 || die ld -r $KPATCH_LDFLAGS -o ../patch/tmp_output.o $(find . -name "*.o") >> "$LOGFILE" 2>&1 || die
if $KPATCH_MODULE; then if "$KPATCH_MODULE"; then
# Add .kpatch.checksum for kpatch script # Add .kpatch.checksum for kpatch script
md5sum ../patch/tmp_output.o | awk '{printf "%s\0", $1}' > checksum.tmp || die md5sum ../patch/tmp_output.o | awk '{printf "%s\0", $1}' > checksum.tmp || die
objcopy --add-section .kpatch.checksum=checksum.tmp --set-section-flags .kpatch.checksum=alloc,load,contents,readonly ../patch/tmp_output.o || die objcopy --add-section .kpatch.checksum=checksum.tmp --set-section-flags .kpatch.checksum=alloc,load,contents,readonly ../patch/tmp_output.o || die
rm -f checksum.tmp rm -f checksum.tmp
"$TOOLSDIR"/create-kpatch-module $TEMPDIR/patch/tmp_output.o $TEMPDIR/patch/output.o 2>&1 |tee -a "$LOGFILE" "$TOOLSDIR"/create-kpatch-module "$TEMPDIR"/patch/tmp_output.o "$TEMPDIR"/patch/output.o 2>&1 |tee -a "$LOGFILE"
check_pipe_status create-kpatch-module check_pipe_status create-kpatch-module
else else
cp $TEMPDIR/patch/tmp_output.o $TEMPDIR/patch/output.o || die cp "$TEMPDIR"/patch/tmp_output.o "$TEMPDIR"/patch/output.o || die
fi fi
cd "$TEMPDIR/patch" cd "$TEMPDIR/patch"
@ -781,12 +781,12 @@ KBUILD_EXTRA_SYMBOLS="$KBUILD_EXTRA_SYMBOLS" \
KPATCH_LDFLAGS="$KPATCH_LDFLAGS" \ KPATCH_LDFLAGS="$KPATCH_LDFLAGS" \
make >> "$LOGFILE" 2>&1 || die make >> "$LOGFILE" 2>&1 || die
if ! $KPATCH_MODULE; then if ! "$KPATCH_MODULE"; then
if [[ -z "$KPATCH_LDFLAGS" ]]; then if [[ -z "$KPATCH_LDFLAGS" ]]; then
extra_flags="--no-klp-arch-sections" extra_flags="--no-klp-arch-sections"
fi fi
cp $TEMPDIR/patch/$MODNAME.ko $TEMPDIR/patch/tmp.ko || die cp "$TEMPDIR/patch/$MODNAME.ko" "$TEMPDIR/patch/tmp.ko" || die
"$TOOLSDIR"/create-klp-module $extra_flags $TEMPDIR/patch/tmp.ko $TEMPDIR/patch/$MODNAME.ko 2>&1 |tee -a "$LOGFILE" "$TOOLSDIR"/create-klp-module $extra_flags "$TEMPDIR/patch/tmp.ko" "$TEMPDIR/patch/$MODNAME.ko" 2>&1 |tee -a "$LOGFILE"
check_pipe_status create-klp-module check_pipe_status create-klp-module
fi fi

View File

@ -14,13 +14,13 @@ declare -a args=("$@")
if [[ "$TOOLCHAINCMD" = "gcc" ]] ; then if [[ "$TOOLCHAINCMD" = "gcc" ]] ; then
while [ "$#" -gt 0 ]; do while [ "$#" -gt 0 ]; do
if [ "$1" = "-o" ]; then if [ "$1" = "-o" ]; then
obj=$2 obj="$2"
# skip copying the temporary .o files created by # skip copying the temporary .o files created by
# recordmcount.pl # recordmcount.pl
[[ $obj = */.tmp_mc_*.o ]] && break; [[ "$obj" = */.tmp_mc_*.o ]] && break;
[[ $obj = */.tmp_*.o ]] && obj=${obj/.tmp_/} [[ "$obj" = */.tmp_*.o ]] && obj="${obj/.tmp_/}"
case "$obj" in case "$obj" in
*.mod.o|\ *.mod.o|\
*built-in.o|\ *built-in.o|\
@ -43,8 +43,8 @@ if [[ "$TOOLCHAINCMD" = "gcc" ]] ; then
break break
;; ;;
*.o) *.o)
mkdir -p "$KPATCH_GCC_TEMPDIR/orig/$(dirname $obj)" mkdir -p "$KPATCH_GCC_TEMPDIR/orig/$(dirname "$obj")"
[[ -e $obj ]] && cp -f "$obj" "$KPATCH_GCC_TEMPDIR/orig/$obj" [[ -e "$obj" ]] && cp -f "$obj" "$KPATCH_GCC_TEMPDIR/orig/$obj"
echo "$obj" >> "$KPATCH_GCC_TEMPDIR/changed_objs" echo "$obj" >> "$KPATCH_GCC_TEMPDIR/changed_objs"
break break
;; ;;
@ -58,10 +58,10 @@ if [[ "$TOOLCHAINCMD" = "gcc" ]] ; then
elif [[ "$TOOLCHAINCMD" = "ld" ]] ; then elif [[ "$TOOLCHAINCMD" = "ld" ]] ; then
while [ "$#" -gt 0 ]; do while [ "$#" -gt 0 ]; do
if [ "$1" = "-o" ]; then if [ "$1" = "-o" ]; then
obj=$2 obj="$2"
case "$obj" in case "$obj" in
*.ko) *.ko)
mkdir -p "$KPATCH_GCC_TEMPDIR/module/$(dirname $obj)" mkdir -p "$KPATCH_GCC_TEMPDIR/module/$(dirname "$obj")"
cp -f "$obj" "$KPATCH_GCC_TEMPDIR/module/$obj" cp -f "$obj" "$KPATCH_GCC_TEMPDIR/module/$obj"
break break
;; ;;

View File

@ -24,7 +24,7 @@
# displaying information about kernel patch modules installed on the system. # displaying information about kernel patch modules installed on the system.
INSTALLDIR=/var/lib/kpatch INSTALLDIR=/var/lib/kpatch
SCRIPTDIR="$(readlink -f $(dirname $(type -p $0)))" SCRIPTDIR="$(readlink -f "$(dirname "$(type -p "$0")")")"
VERSION="0.4.0" VERSION="0.4.0"
# Livepatch is built into the kernel, if it's not present # Livepatch is built into the kernel, if it's not present
@ -74,14 +74,14 @@ __find_module () {
MODULE="$1" MODULE="$1"
[[ -f "$MODULE" ]] && return [[ -f "$MODULE" ]] && return
MODULE=$INSTALLDIR/$(uname -r)/"$1" MODULE="$INSTALLDIR/$(uname -r)/$1"
[[ -f "$MODULE" ]] && return [[ -f "$MODULE" ]] && return
return 1 return 1
} }
mod_name () { mod_name () {
MODNAME="$(basename $1)" MODNAME="$(basename "$1")"
MODNAME="${MODNAME%.ko}" MODNAME="${MODNAME%.ko}"
MODNAME="${MODNAME//-/_}" MODNAME="${MODNAME//-/_}"
} }
@ -93,9 +93,9 @@ find_module () {
mod_name "$MODULE" mod_name "$MODULE"
return return
else else
for i in $INSTALLDIR/$(uname -r)/*; do for i in "$INSTALLDIR/$(uname -r)"/*; do
mod_name "$i" mod_name "$i"
if [[ $MODNAME == $arg ]]; then if [[ "$MODNAME" == "$arg" ]]; then
MODULE="$i" MODULE="$i"
return return
fi fi
@ -129,19 +129,19 @@ core_loaded () {
} }
get_module_name () { get_module_name () {
echo $(readelf -p .gnu.linkonce.this_module $1 | grep '\[.*\]' | awk '{print $3}') echo "$(readelf -p .gnu.linkonce.this_module "$1" | grep '\[.*\]' | awk '{print $3}')"
} }
verify_module_checksum () { verify_module_checksum () {
modname=$(get_module_name $1) modname="$(get_module_name "$1")"
[[ -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}')"
# Fail checksum match only if both exist and diverge # Fail checksum match only if both exist and diverge
if [[ ! -z $checksum ]] && [[ -e "$SYSFS/${modname}/checksum" ]] ; then if [[ ! -z "$checksum" ]] && [[ -e "$SYSFS/${modname}/checksum" ]] ; then
sysfs_checksum=$(cat $SYSFS/${modname}/checksum) sysfs_checksum="$(cat "$SYSFS/${modname}/checksum")"
[[ $checksum == $sysfs_checksum ]] || return 1 [[ "$checksum" == "$sysfs_checksum" ]] || return 1
fi fi
return 0 return 0
@ -160,13 +160,13 @@ load_module () {
fi fi
fi fi
local modname=$(get_module_name $module) local modname="$(get_module_name "$module")"
local moddir="$SYSFS/$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
echo "module already loaded, re-enabling" echo "module already loaded, re-enabling"
echo 1 > ${moddir}/enabled || die "failed to re-enable module $modname" echo 1 > "${moddir}/enabled" || die "failed to re-enable module $modname"
return return
else else
die "error: cannot re-enable patch module $modname, cannot verify checksum match" die "error: cannot re-enable patch module $modname, cannot verify checksum match"
@ -179,10 +179,10 @@ load_module () {
echo "loading patch module: $module" echo "loading patch module: $module"
local i=0 local i=0
while true; do while true; do
out=$(insmod "$module" 2>&1) out="$(insmod "$module" 2>&1)"
[[ -z $out ]] && break [[ -z "$out" ]] && break
echo $out 1>&2 echo "$out" 1>&2
[[ ! $out =~ "Device or resource busy" ]] && [[ ! "$out" =~ "Device or resource busy" ]] &&
die "failed to load module $module" die "failed to load module $module"
# "Device or resource busy" means the activeness safety check # "Device or resource busy" means the activeness safety check
@ -205,20 +205,20 @@ unload_module () {
PATCH="${PATCH%.ko}" PATCH="${PATCH%.ko}"
ENABLED="$SYSFS/$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"
echo 0 > $ENABLED || die "can't disable $PATCH" echo 0 > "$ENABLED" || die "can't disable $PATCH"
fi fi
echo "unloading patch module: $PATCH" echo "unloading patch module: $PATCH"
# ignore any error here because rmmod can fail if the module used # ignore any error here because rmmod can fail if the module used
# KPATCH_FORCE_UNSAFE. # KPATCH_FORCE_UNSAFE.
rmmod $PATCH 2> /dev/null || return 0 rmmod "$PATCH" 2> /dev/null || return 0
} }
get_module_version() { get_module_version() {
MODVER=$(modinfo -F vermagic "$1") || return 1 MODVER="$(modinfo -F vermagic "$1")" || return 1
MODVER=${MODVER/ */} MODVER="${MODVER/ */}"
} }
unset MODULE unset MODULE
@ -228,7 +228,7 @@ case "$1" in
[[ "$#" -ne 2 ]] && usage [[ "$#" -ne 2 ]] && usage
case "$2" in case "$2" in
"--all") "--all")
for i in "$INSTALLDIR"/$(uname -r)/*.ko; do for i in "$INSTALLDIR/$(uname -r)"/*.ko; do
[[ -e "$i" ]] || continue [[ -e "$i" ]] || continue
load_module "$i" || die "failed to load module $i" load_module "$i" || die "failed to load module $i"
done done
@ -245,26 +245,26 @@ case "$1" in
[[ "$#" -ne 2 ]] && usage [[ "$#" -ne 2 ]] && usage
case "$2" in case "$2" in
"--all") "--all")
for module in $SYSFS/*; 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
;; ;;
*) *)
unload_module "$(basename $2)" || die "failed to unload module $2" unload_module "$(basename "$2")" || die "failed to unload module $2"
;; ;;
esac esac
;; ;;
"install") "install")
KVER=$(uname -r) KVER="$(uname -r)"
shift shift
options=$(getopt -o k: -l "kernel-version:" -- "$@") || die "getopt failed" options="$(getopt -o k: -l "kernel-version:" -- "$@")" || die "getopt failed"
eval set -- "$options" eval set -- "$options"
while [[ $# -gt 0 ]]; do while [[ $# -gt 0 ]]; do
case "$1" in case "$1" in
-k|--kernel-version) -k|--kernel-version)
KVER=$2 KVER="$2"
shift shift
;; ;;
--) --)
@ -276,75 +276,75 @@ case "$1" in
done done
[[ ! -e "$PATCH" ]] && die "$PATCH doesn't exist" [[ ! -e "$PATCH" ]] && die "$PATCH doesn't exist"
[[ ${PATCH: -3} == ".ko" ]] || die "$PATCH isn't a .ko file" [[ "${PATCH: -3}" == ".ko" ]] || die "$PATCH isn't a .ko file"
get_module_version "$PATCH" || die "modinfo failed" get_module_version "$PATCH" || die "modinfo failed"
[[ $KVER != $MODVER ]] && die "invalid module version $MODVER for kernel $KVER" [[ "$KVER" != "$MODVER" ]] && die "invalid module version $MODVER for kernel $KVER"
[[ -e $INSTALLDIR/$KVER/$(basename "$PATCH") ]] && die "$PATCH is already installed" [[ -e "$INSTALLDIR/$KVER/$(basename "$PATCH")" ]] && die "$PATCH is already installed"
echo "installing $PATCH ($KVER)" echo "installing $PATCH ($KVER)"
mkdir -p $INSTALLDIR/$KVER || die "failed to create install directory" mkdir -p "$INSTALLDIR/$KVER" || die "failed to create install directory"
cp -f "$PATCH" $INSTALLDIR/$KVER || die "failed to install module $PATCH" cp -f "$PATCH" "$INSTALLDIR/$KVER" || die "failed to install module $PATCH"
systemctl enable kpatch.service systemctl enable kpatch.service
;; ;;
"uninstall") "uninstall")
KVER=$(uname -r) KVER="$(uname -r)"
shift shift
options=$(getopt -o k: -l "kernel-version:" -- "$@") || die "getopt failed" options="$(getopt -o k: -l "kernel-version:" -- "$@")" || die "getopt failed"
eval set -- "$options" eval set -- "$options"
while [[ $# -gt 0 ]]; do while [[ $# -gt 0 ]]; do
case "$1" in case "$1" in
-k|--kernel-version) -k|--kernel-version)
KVER=$2 KVER="$2"
shift shift
;; ;;
--) --)
[[ -z "$2" ]] && die "no module file specified" [[ -z "$2" ]] && die "no module file specified"
PATCH="$2" PATCH="$2"
[[ "$PATCH" != $(basename "$PATCH") ]] && die "please supply patch module name without path" [[ "$PATCH" != "$(basename "$PATCH")" ]] && die "please supply patch module name without path"
;; ;;
esac esac
shift shift
done done
MODULE=$INSTALLDIR/$KVER/"$PATCH" MODULE="$INSTALLDIR/$KVER/$PATCH"
if [[ ! -f "$MODULE" ]]; then if [[ ! -f "$MODULE" ]]; then
mod_name "$PATCH" mod_name "$PATCH"
PATCHNAME=$MODNAME PATCHNAME="$MODNAME"
for i in $INSTALLDIR/$KVER/*; do for i in "$INSTALLDIR/$KVER"/*; do
mod_name "$i" mod_name "$i"
if [[ $MODNAME == $PATCHNAME ]]; then if [[ "$MODNAME" == "$PATCHNAME" ]]; then
MODULE="$i" MODULE="$i"
break break
fi fi
done done
fi fi
[[ ! -e $MODULE ]] && die "$PATCH is not installed for kernel $KVER" [[ ! -e "$MODULE" ]] && die "$PATCH is not installed for kernel $KVER"
echo "uninstalling $PATCH ($KVER)" echo "uninstalling $PATCH ($KVER)"
rm -f $MODULE || die "failed to uninstall module $PATCH" rm -f "$MODULE" || die "failed to uninstall module $PATCH"
;; ;;
"list") "list")
[[ "$#" -ne 1 ]] && usage [[ "$#" -ne 1 ]] && usage
echo "Loaded patch modules:" echo "Loaded patch modules:"
for module in $SYSFS/*; 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
done done
echo "" echo ""
echo "Installed patch modules:" echo "Installed patch modules:"
for kdir in $INSTALLDIR/*; do for kdir in "$INSTALLDIR"/*; do
[[ -e "$kdir" ]] || continue [[ -e "$kdir" ]] || continue
for module in $kdir/*; do for module in "$kdir"/*; do
[[ -e "$module" ]] || continue [[ -e "$module" ]] || continue
mod_name "$module" mod_name "$module"
echo "$MODNAME ($(basename $kdir))" echo "$MODNAME ($(basename "$kdir"))"
done done
done done
;; ;;