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
BASE="$PWD"
SCRIPTDIR="$(readlink -f $(dirname $(type -p $0)))"
SCRIPTDIR="$(readlink -f "$(dirname "$(type -p "$0")")")"
ARCH="$(uname -m)"
ARCHVERSION="$(uname -r)"
CPUS="$(getconf _NPROCESSORS_ONLN)"
@ -57,13 +57,13 @@ warn() {
}
die() {
if [[ -z $1 ]]; then
if [[ -z "$1" ]]; then
msg="kpatch build failed"
else
msg="$1"
fi
if [[ -e $LOGFILE ]]; then
if [[ -e "$LOGFILE" ]]; then
warn "$msg. Check $LOGFILE for more details."
else
warn "$msg."
@ -99,11 +99,11 @@ cleanup() {
remove_patches
# If $SRCDIR was a git repo, make sure git actually sees that
# 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
[[ -e $TEMPDIR/.config ]] && mv -f $TEMPDIR/.config $SRCDIR/
[[ -e $TEMPDIR/vmlinux ]] && mv -f $TEMPDIR/vmlinux $SRCDIR/
[[ -e "$TEMPDIR/.config" ]] && mv -f "$TEMPDIR/.config" "$SRCDIR/"
[[ -e "$TEMPDIR/vmlinux" ]] && mv -f "$TEMPDIR/vmlinux" "$SRCDIR/"
[[ "$DEBUG" -eq 0 ]] && rm -rf "$TEMPDIR"
rm -rf "$RPMTOPDIR"
@ -118,7 +118,7 @@ clean_cache() {
check_pipe_status() {
rc="${PIPESTATUS[0]}"
if [[ $rc = 139 ]]; then
if [[ "$rc" = 139 ]]; then
# There doesn't seem to be a consistent/portable way of
# accessing the last executed command in bash, so just
# pass in the script name for now..
@ -140,11 +140,11 @@ find_dirs() {
if [[ -e "$SCRIPTDIR/create-diff-object" ]]; then
# git repo
TOOLSDIR="$SCRIPTDIR"
DATADIR="$(readlink -f $SCRIPTDIR/../kmod)"
DATADIR="$(readlink -f "$SCRIPTDIR/../kmod")"
elif [[ -e "$SCRIPTDIR/../libexec/kpatch/create-diff-object" ]]; then
# installation path
TOOLSDIR="$(readlink -f $SCRIPTDIR/../libexec/kpatch)"
DATADIR="$(readlink -f $SCRIPTDIR/../share/kpatch)"
TOOLSDIR="$(readlink -f "$SCRIPTDIR/../libexec/kpatch")"
DATADIR="$(readlink -f "$SCRIPTDIR/../share/kpatch")"
else
return 1
fi
@ -157,10 +157,10 @@ find_core_symvers() {
SYMVERSFILE="$DATADIR/core/Module.symvers"
elif [[ -e "$SCRIPTDIR/../libexec/kpatch/create-diff-object" ]]; then
# installation path
if [[ -e $SCRIPTDIR/../lib/kpatch/$ARCHVERSION/Module.symvers ]]; then
SYMVERSFILE="$(readlink -f $SCRIPTDIR/../lib/kpatch/$ARCHVERSION/Module.symvers)"
if [[ -e "$SCRIPTDIR/../lib/kpatch/$ARCHVERSION/Module.symvers" ]]; then
SYMVERSFILE="$(readlink -f "$SCRIPTDIR/../lib/kpatch/$ARCHVERSION/Module.symvers")"
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
@ -169,9 +169,9 @@ find_core_symvers() {
gcc_version_check() {
# ensure gcc version matches that used to build the kernel
local gccver=$(gcc --version |head -n1 |cut -d' ' -f3-)
local kgccver=$(readelf -p .comment $VMLINUX |grep GCC: | tr -s ' ' | cut -d ' ' -f6-)
if [[ $gccver != $kgccver ]]; then
local gccver="$(gcc --version |head -n1 |cut -d' ' -f3-)"
local kgccver="$(readelf -p .comment "$VMLINUX" |grep GCC: | tr -s ' ' | cut -d ' ' -f6-)"
if [[ "$gccver" != "$kgccver" ]]; then
warn "gcc/kernel version mismatch"
echo "gcc version: $gccver"
echo "kernel version: $kgccver"
@ -186,12 +186,12 @@ gcc_version_check() {
# <linux>/arch/powerpc/tools/gcc-check-mprofile-kernel.sh
#
# Postpone the check to the kernel build instead of duplicating it here.
if [[ $ARCH = "ppc64le" ]]; then
if [[ "$ARCH" = "ppc64le" ]]; then
return
else
# ensure gcc version is >= 4.8
gccver=$(echo $gccver |cut -d'.' -f1,2)
if [[ $gccver < 4.8 ]]; then
gccver="$(echo "$gccver" |cut -d'.' -f1,2)"
if [[ "$gccver" < 4.8 ]]; then
warn "gcc >= 4.8 required"
return 1
fi
@ -201,7 +201,7 @@ gcc_version_check() {
}
find_special_section_data_ppc64le() {
SPECIAL_VARS=$(readelf -wi "$VMLINUX" |
SPECIAL_VARS="$(readelf -wi "$VMLINUX" |
gawk --non-decimal-data '
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}
# 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 $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 "$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 "$EX_STRUCT_SIZE" ]] && die "can't find special struct exception_table_entry size"
return
}
find_special_section_data() {
if [[ $ARCH = "ppc64le" ]]; then
if [[ "$ARCH" = "ppc64le" ]]; then
find_special_section_data_ppc64le
return
fi
[[ $CONFIG_PARAVIRT -eq 0 ]] && AWK_OPTIONS="-vskip_p=1"
SPECIAL_VARS=$(readelf -wi "$VMLINUX" |
[[ "$CONFIG_PARAVIRT" -eq 0 ]] && AWK_OPTIONS="-vskip_p=1"
SPECIAL_VARS="$(readelf -wi "$VMLINUX" |
gawk --non-decimal-data $AWK_OPTIONS '
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}
# 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 $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 $PARA_STRUCT_SIZE && $CONFIG_PARAVIRT -ne 0 ]] && die "can't find special struct paravirt_patch_site 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 "$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"
return
}
find_parent_obj() {
dir=$(dirname $1)
absdir=$(readlink -f $dir)
pwddir=$(readlink -f .)
pdir=${absdir#$pwddir/}
file=$(basename $1)
grepname=${1%.o}
grepname=$grepname\\\.o
if [[ $DEEP_FIND -eq 1 ]]; then
dir="$(dirname "$1")"
absdir="$(readlink -f "$dir")"
pwddir="$(readlink -f .)"
pdir="${absdir#$pwddir/}"
file="$(basename "$1")"
grepname="${1%.o}"
grepname="$grepname\.o"
if [[ "$DEEP_FIND" -eq 1 ]]; then
num=0
if [[ -n $last_deep_find ]]; then
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)
if [[ -n "$last_deep_find" ]]; then
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)"
fi
if [[ $num -eq 0 ]]; then
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 -eq 1 ]] && last_deep_find=$(dirname $parent)
if [[ "$num" -eq 0 ]]; then
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" -eq 1 ]] && last_deep_find="$(dirname "$parent")"
fi
else
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)
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)"
fi
[[ $num -eq 0 ]] && PARENT="" && return
[[ $num -gt 1 ]] && ERROR_IF_DIFF="two parent matches for $1"
[[ "$num" -eq 0 ]] && PARENT="" && return
[[ "$num" -gt 1 ]] && ERROR_IF_DIFF="two parent matches for $1"
dir=$(dirname $parent)
PARENT=$(basename $parent)
PARENT=${PARENT#.}
PARENT=${PARENT%.cmd}
PARENT=$dir/$PARENT
[[ ! -e $PARENT ]] && die "ERROR: can't find parent $PARENT for $1"
dir="$(dirname "$parent")"
PARENT="$(basename "$parent")"
PARENT="${PARENT#.}"
PARENT="${PARENT%.cmd}"
PARENT="$dir/$PARENT"
[[ ! -e "$PARENT" ]] && die "ERROR: can't find parent $PARENT for $1"
}
find_kobj() {
arg=$1
KOBJFILE=$arg
arg="$1"
KOBJFILE="$arg"
DEEP_FIND=0
ERROR_IF_DIFF=
while true; do
find_parent_obj $KOBJFILE
[[ -n $PARENT ]] && DEEP_FIND=0
if [[ -z $PARENT ]]; then
[[ $KOBJFILE = *.ko ]] && return
case $KOBJFILE in
find_parent_obj "$KOBJFILE"
[[ -n "$PARENT" ]] && DEEP_FIND=0
if [[ -z "$PARENT" ]]; then
[[ "$KOBJFILE" = *.ko ]] && return
case "$KOBJFILE" in
*/built-in.o|\
arch/x86/lib/lib.a|\
arch/x86/kernel/head*.o|\
@ -329,13 +329,13 @@ find_kobj() {
KOBJFILE=vmlinux
return
esac
if [[ $DEEP_FIND -eq 0 ]]; then
if [[ "$DEEP_FIND" -eq 0 ]]; then
DEEP_FIND=1
continue;
fi
die "invalid ancestor $KOBJFILE for $arg"
fi
KOBJFILE=$PARENT
KOBJFILE="$PARENT"
done
}
@ -343,11 +343,11 @@ find_kobj() {
# is replaced with '-'. Also truncate to 48 chars so the full name fits in the
# kernel's 56-byte module name array.
module_name_string() {
echo ${1//[^a-zA-Z0-9_-]/-} |cut -c 1-48
echo "${1//[^a-zA-Z0-9_-]/-}" |cut -c 1-48
}
usage() {
echo "usage: $(basename $0) [options] <patch1 ... patchN>" >&2
echo "usage: $(basename "$0") [options] <patch1 ... patchN>" >&2
echo " patchN Input patchfile(s)" >&2
echo " -h, --help Show this help message" >&2
echo " -r, --sourcerpm Specify kernel source RPM" >&2
@ -363,7 +363,7 @@ usage() {
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"
@ -375,25 +375,25 @@ while [[ $# -gt 0 ]]; do
;;
-r|--sourcerpm)
[[ ! -f "$2" ]] && die "source rpm '$2' not found"
SRCRPM=$(readlink -f "$2")
SRCRPM="$(readlink -f "$2")"
shift
rpmname=$(basename "$SRCRPM")
ARCHVERSION=${rpmname%.src.rpm}.$(uname -m)
ARCHVERSION=${ARCHVERSION#kernel-}
rpmname="$(basename "$SRCRPM")"
ARCHVERSION="${rpmname%.src.rpm}.$(uname -m)"
ARCHVERSION="${ARCHVERSION#kernel-}"
;;
-s|--sourcedir)
[[ ! -d "$2" ]] && die "source dir '$2' not found"
USERSRCDIR=$(readlink -f "$2")
USERSRCDIR="$(readlink -f "$2")"
shift
;;
-c|--config)
[[ ! -f "$2" ]] && die "config file '$2' not found"
CONFIGFILE=$(readlink -f "$2")
CONFIGFILE="$(readlink -f "$2")"
shift
;;
-v|--vmlinux)
[[ ! -f "$2" ]] && die "vmlinux file '$2' not found"
VMLINUX=$(readlink -f "$2")
VMLINUX="$(readlink -f "$2")"
shift
;;
-j|--jobs)
@ -406,12 +406,12 @@ while [[ $# -gt 0 ]]; do
shift
;;
-n|--name)
MODNAME=$(module_name_string "$2")
MODNAME="$(module_name_string "$2")"
shift
;;
-o|--output)
[[ ! -d "$2" ]] && die "output dir '$2' not found"
BASE=$(readlink -f "$2")
BASE="$(readlink -f "$2")"
shift
;;
-d|--debug)
@ -430,7 +430,7 @@ while [[ $# -gt 0 ]]; do
*)
[[ "$1" = "--" ]] && shift && continue
[[ ! -f "$1" ]] && die "patch file '$1' not found"
PATCH_LIST+=($(readlink -f "$1"))
PATCH_LIST+=("$(readlink -f "$1")")
;;
esac
shift
@ -447,50 +447,50 @@ mkdir -p "$TEMPDIR" || die "Couldn't create $TEMPDIR"
rm -rf "$TEMPDIR"/*
rm -f "$LOGFILE"
if [[ -n $USERSRCDIR ]]; then
if [[ -n "$USERSRCDIR" ]]; then
SRCDIR="$USERSRCDIR"
[[ -z $VMLINUX ]] && VMLINUX="$SRCDIR"/vmlinux
[[ -z "$VMLINUX" ]] && VMLINUX="$SRCDIR"/vmlinux
[[ ! -e "$VMLINUX" ]] && die "can't find vmlinux"
# 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
[[ $SKIPCLEANUP -eq 0 ]] && trap cleanup EXIT INT TERM HUP
[[ "$SKIPCLEANUP" -eq 0 ]] && trap cleanup EXIT INT TERM HUP
KVER=${ARCHVERSION%%-*}
if [[ $ARCHVERSION =~ - ]]; then
KREL=${ARCHVERSION##*-}
KREL=${KREL%.*}
KVER="${ARCHVERSION%%-*}"
if [[ "$ARCHVERSION" =~ - ]]; then
KREL="${ARCHVERSION##*-}"
KREL="${KREL%.*}"
fi
[[ -z $TARGETS ]] && TARGETS="vmlinux modules"
[[ -z "$TARGETS" ]] && TARGETS="vmlinux modules"
source /etc/os-release
DISTRO=$ID
if [[ $DISTRO = fedora ]] || [[ $DISTRO = rhel ]] || [[ $DISTRO = ol ]] || [[ $DISTRO = centos ]]; then
[[ -z $VMLINUX ]] && VMLINUX=/usr/lib/debug/lib/modules/$ARCHVERSION/vmlinux
DISTRO="$ID"
if [[ "$DISTRO" = fedora ]] || [[ "$DISTRO" = rhel ]] || [[ "$DISTRO" = ol ]] || [[ "$DISTRO" = centos ]]; then
[[ -z "$VMLINUX" ]] && VMLINUX="/usr/lib/debug/lib/modules/$ARCHVERSION/vmlinux"
[[ -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
[[ -z $VMLINUX ]] && VMLINUX=/usr/lib/debug/boot/vmlinux-$ARCHVERSION
elif [[ "$DISTRO" = ubuntu ]] || [[ "$DISTRO" = debian ]]; then
[[ -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"
elif [[ $DISTRO = debian ]]; then
elif [[ "$DISTRO" = debian ]]; then
[[ -e "$VMLINUX" ]] || die "linux-image-$ARCHVERSION-dbg not installed"
fi
export PATH=/usr/lib/ccache:$PATH
export PATH="/usr/lib/ccache:$PATH"
fi
find_dirs || die "can't find supporting tools"
if [[ $SKIPGCCCHECK -eq 0 ]]; then
if [[ "$SKIPGCCCHECK" -eq 0 ]]; then
gcc_version_check || die
fi
@ -498,13 +498,13 @@ if [[ -n "$USERSRCDIR" ]]; then
echo "Using source directory at $USERSRCDIR"
# 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"
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"
rpm -q --quiet rpmdevtools || die "rpmdevtools not installed"
@ -513,8 +513,8 @@ else
echo "Downloading kernel source for $ARCHVERSION"
if [[ -z "$SRCRPM" ]]; 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
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
else
rpm -q --quiet yum-utils || die "yum-utils not installed"
yumdownloader --source --destdir "$TEMPDIR" "kernel-$ARCHVERSION" >> "$LOGFILE" 2>&1 || die
@ -536,37 +536,37 @@ else
echo "-${ARCHVERSION##*-}" > "$SRCDIR/localversion" || die
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"
if [[ $DISTRO = ubuntu ]]; then
if [[ "$DISTRO" = ubuntu ]]; then
# url may be changed for a different mirror
url="http://archive.ubuntu.com/ubuntu/pool/main/l"
sublevel="SUBLEVEL = 0"
UBUNTU_KERNEL=1
elif [[ $DISTRO = debian ]]; then
elif [[ "$DISTRO" = debian ]]; then
# url may be changed for a different mirror
url="http://ftp.debian.org/debian/pool/main/l"
sublevel="SUBLEVEL ="
fi
pkgname="$(dpkg-query -W -f='${Source}' linux-image-$ARCHVERSION)"
pkgver="$(dpkg-query -W -f='${Version}' linux-image-$ARCHVERSION)"
pkgname="$(dpkg-query -W -f='${Source}' "linux-image-$ARCHVERSION")"
pkgver="$(dpkg-query -W -f='${Version}' "linux-image-$ARCHVERSION")"
dscname="${pkgname}_${pkgver}.dsc"
clean_cache
cd $TEMPDIR
cd "$TEMPDIR"
echo "Downloading and unpacking the kernel source for $ARCHVERSION"
# Download source deb pkg
(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
if [[ "$ARCHVERSION" == *-* ]]; then
echo "-${ARCHVERSION#*-}" > "$SRCDIR/localversion" || die
@ -574,7 +574,7 @@ else
# for some reason the Ubuntu kernel versions don't follow the
# upstream SUBLEVEL; they are always at SUBLEVEL 0
sed -i "s/^SUBLEVEL.*/${sublevel}/" "$SRCDIR/Makefile" || die
echo $ARCHVERSION > "$VERSIONFILE" || die
echo "$ARCHVERSION" > "$VERSIONFILE" || die
else
die "Unsupported distribution"
@ -582,9 +582,9 @@ else
fi
# 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"
[[ "$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
# 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"
if grep -q "CONFIG_LIVEPATCH=y" "$CONFIGFILE"; then
# 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
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"
fi
fi
@ -626,7 +626,7 @@ remove_patches
cp -LR "$DATADIR/patch" "$TEMPDIR" || die
if [[ $ARCH = "ppc64le" ]]; then
if [[ "$ARCH" = "ppc64le" ]]; then
ARCH_KCFLAGS="-mcmodel=large"
fi
@ -645,7 +645,7 @@ CROSS_COMPILE="$TOOLSDIR/kpatch-gcc " make "-j$CPUS" $TARGETS >> "$LOGFILE" 2>&1
echo "Building patched kernel"
apply_patches
mkdir -p "$TEMPDIR/orig" "$TEMPDIR/patched"
KPATCH_GCC_TEMPDIR=$TEMPDIR
KPATCH_GCC_TEMPDIR="$TEMPDIR"
export KPATCH_GCC_TEMPDIR
CROSS_COMPILE="$TOOLSDIR/kpatch-gcc " \
KBUILD_MODPOST_WARN=1 \
@ -660,7 +660,7 @@ fi
for i in $(cat "$TEMPDIR/changed_objs")
do
mkdir -p "$TEMPDIR/patched/$(dirname $i)" || die
mkdir -p "$TEMPDIR/patched/$(dirname "$i")" || die
cp -f "$SRCDIR/$i" "$TEMPDIR/patched/$i" || die
done
@ -669,9 +669,9 @@ echo "Extracting new and modified ELF sections"
# - For single input .patch, use the patch filename
# - For multiple input .patches, use "patch"
# - Prefix with "kpatch" or "livepatch" accordingly
if [[ -z $MODNAME ]] ; then
if [[ ${#PATCH_LIST[@]} -eq 1 ]]; then
MODNAME=$(basename "${PATCH_LIST[0]}")
if [[ -z "$MODNAME" ]] ; then
if [[ "${#PATCH_LIST[@]}" -eq 1 ]]; then
MODNAME="$(basename "${PATCH_LIST[0]}")"
if [[ "$MODNAME" =~ \.patch$ ]] || [[ "$MODNAME" =~ \.diff$ ]]; then
MODNAME="${MODNAME%.*}"
fi
@ -679,13 +679,13 @@ if [[ -z $MODNAME ]] ; then
MODNAME="patch"
fi
if $KPATCH_MODULE; then
if "$KPATCH_MODULE"; then
MODNAME="kpatch-$MODNAME"
else
MODNAME="livepatch-$MODNAME"
fi
MODNAME=$(module_name_string "$MODNAME")
MODNAME="$(module_name_string "$MODNAME")"
fi
FILES="$(cat "$TEMPDIR/changed_objs")"
cd "$TEMPDIR"
@ -697,55 +697,55 @@ for i in $FILES; do
# 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
# assembly file anyway.
[[ $DISTRO = rhel ]] || [[ $DISTRO = centos ]] || [[ $DISTRO = ol ]] && \
[[ $i = arch/x86/lib/copy_user_64.o ]] && continue
[[ "$DISTRO" = rhel ]] || [[ "$DISTRO" = centos ]] || [[ "$DISTRO" = ol ]] && \
[[ "$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"
find_kobj $i
if [[ $KOBJFILE = vmlinux ]]; then
KOBJFILE=$VMLINUX
find_kobj "$i"
if [[ "$KOBJFILE" = vmlinux ]]; then
KOBJFILE="$VMLINUX"
else
KOBJFILE="$TEMPDIR/module/$KOBJFILE"
fi
cd $TEMPDIR
cd "$TEMPDIR"
if [[ -e "orig/$i" ]]; then
# 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" \
"output/$i" "$SRCDIR/Module.symvers" "${MODNAME//-/_}" 2>&1 |tee -a "$LOGFILE"
check_pipe_status create-diff-object
# create-diff-object returns 3 if no functional change is found
[[ $rc -eq 0 ]] || [[ $rc -eq 3 ]] || ERROR=$(expr $ERROR "+" 1)
if [[ $rc -eq 0 ]]; then
[[ -n $ERROR_IF_DIFF ]] && die $ERROR_IF_DIFF
[[ "$rc" -eq 0 ]] || [[ "$rc" -eq 3 ]] || ERROR="$(expr $ERROR "+" 1)"
if [[ "$rc" -eq 0 ]]; then
[[ -n "$ERROR_IF_DIFF" ]] && die "$ERROR_IF_DIFF"
CHANGED=1
objnames[${#objnames[@]}]=$KOBJFILE
objnames[${#objnames[@]}]="$KOBJFILE"
fi
else
cp -f "patched/$i" "output/$i"
objnames[${#objnames[@]}]=$KOBJFILE
objnames[${#objnames[@]}]="$KOBJFILE"
fi
done
if [[ $ERROR -ne 0 ]]; then
if [[ "$ERROR" -ne 0 ]]; then
die "$ERROR error(s) encountered"
fi
if [[ $CHANGED -eq 0 ]]; then
if [[ "$CHANGED" -eq 0 ]]; then
die "no functional changes found"
fi
echo -n "Patched objects:"
for i in $(echo "${objnames[@]}" | tr ' ' '\n' | sort -u | tr '\n' ' ')
do
echo -n " $(basename $i)"
echo -n " $(basename "$i")"
done
echo
export KCFLAGS="-I$DATADIR/patch $ARCH_KCFLAGS"
if $KPATCH_MODULE; then
if "$KPATCH_MODULE"; then
export KCPPFLAGS="-D__KPATCH_MODULE__"
fi
@ -753,25 +753,25 @@ echo "Building patch module: $MODNAME.ko"
cd "$SRCDIR"
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_ABI=${ARCHVERSION#*-}
UBUNTU_ABI=${UBUNTU_ABI%-*}
UBUNTU_ABI="${ARCHVERSION#*-}"
UBUNTU_ABI="${UBUNTU_ABI%-*}"
echo "#define UTS_UBUNTU_RELEASE_ABI "$UBUNTU_ABI"" >> "$SRCDIR"/include/generated/utsrelease.h
fi
cd "$TEMPDIR/output"
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
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
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
else
cp $TEMPDIR/patch/tmp_output.o $TEMPDIR/patch/output.o || die
cp "$TEMPDIR"/patch/tmp_output.o "$TEMPDIR"/patch/output.o || die
fi
cd "$TEMPDIR/patch"
@ -781,12 +781,12 @@ KBUILD_EXTRA_SYMBOLS="$KBUILD_EXTRA_SYMBOLS" \
KPATCH_LDFLAGS="$KPATCH_LDFLAGS" \
make >> "$LOGFILE" 2>&1 || die
if ! $KPATCH_MODULE; then
if ! "$KPATCH_MODULE"; then
if [[ -z "$KPATCH_LDFLAGS" ]]; then
extra_flags="--no-klp-arch-sections"
fi
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"
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"
check_pipe_status create-klp-module
fi

View File

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

View File

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