mirror of
https://github.com/dynup/kpatch
synced 2024-12-22 21:22:07 +00:00
kpatch-build: build dynrelas or klp relas depending on kernel version
Introduce a second phase in the kpatch-build process that creates kpatch modules or livepatch modules that use the new klp rela sections depending on the kernel version being worked on. This change uses the two new programs to either create a patch module that uses dynrelas (create-kpatch-module) or a patch module that uses klp rela and arch sections + klp symbols marked with the correct Elf flags (create-klp-module). For klp patch modules, the --unique flag for ld is needed to prevent .parainstructions and .altinstructions sections from different objects from being merged, as arch_klp_init_object_loaded() applies these sections per-object.
This commit is contained in:
parent
355996e366
commit
b1cdc83d57
@ -1,6 +1,7 @@
|
||||
KPATCH_NAME ?= patch
|
||||
KPATCH_BUILD ?= /lib/modules/$(shell uname -r)/build
|
||||
KPATCH_MAKE = $(MAKE) -C $(KPATCH_BUILD) M=$(PWD)
|
||||
LDFLAGS += $(KPATCH_LDFLAGS)
|
||||
|
||||
obj-m += kpatch-$(KPATCH_NAME).o
|
||||
|
||||
|
@ -1,8 +1,12 @@
|
||||
__kpatch_funcs = ADDR(.kpatch.funcs);
|
||||
__kpatch_funcs_end = ADDR(.kpatch.funcs) + SIZEOF(.kpatch.funcs);
|
||||
|
||||
#ifdef __KPATCH_MODULE__
|
||||
__kpatch_dynrelas = ADDR(.kpatch.dynrelas);
|
||||
__kpatch_dynrelas_end = ADDR(.kpatch.dynrelas) + SIZEOF(.kpatch.dynrelas);
|
||||
__kpatch_checksum = ADDR(.kpatch.checksum);
|
||||
#endif
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
.kpatch.hooks.load : {
|
@ -88,6 +88,7 @@ cleanup() {
|
||||
[[ "$DEBUG" -eq 0 ]] && rm -rf "$TEMPDIR"
|
||||
rm -rf "$RPMTOPDIR"
|
||||
unset KCFLAGS
|
||||
unset KCPPFLAGS
|
||||
}
|
||||
|
||||
clean_cache() {
|
||||
@ -96,6 +97,26 @@ clean_cache() {
|
||||
mkdir -p "$OBJDIR"
|
||||
}
|
||||
|
||||
check_pipe_status() {
|
||||
rc="${PIPESTATUS[0]}"
|
||||
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..
|
||||
warn "$1 SIGSEGV"
|
||||
if ls core* &> /dev/null; then
|
||||
cp core* /tmp
|
||||
die "core file at /tmp/$(ls core*)"
|
||||
fi
|
||||
die "no core file found, run 'ulimit -c unlimited' and try to recreate"
|
||||
fi
|
||||
}
|
||||
|
||||
# $1 >= $2
|
||||
function version_gte {
|
||||
[ "$1" = "`echo -e "$1\n$2" | sort -rV | head -n1`" ]
|
||||
}
|
||||
|
||||
find_dirs() {
|
||||
if [[ -e "$SCRIPTDIR/create-diff-object" ]]; then
|
||||
# git repo
|
||||
@ -461,11 +482,23 @@ else
|
||||
fi
|
||||
fi
|
||||
|
||||
# Build variables - Set some defaults, then adjust features
|
||||
# according to .config and kernel version
|
||||
KBUILD_EXTRA_SYMBOLS=""
|
||||
KPATCH_LDFLAGS=""
|
||||
KPATCH_MODULE=true
|
||||
|
||||
# kernel option checking: CONFIG_DEBUG_KERNEL and CONFIG_LIVEPATCH
|
||||
grep -q "CONFIG_DEBUG_KERNEL=y" "$OBJDIR/.config" || die "kernel doesn't have 'CONFIG_DEBUG_KERNEL' enabled"
|
||||
if grep "CONFIG_LIVEPATCH=y" "$OBJDIR/.config" > /dev/null; then
|
||||
# The kernel supports livepatch.
|
||||
KBUILD_EXTRA_SYMBOLS=""
|
||||
if version_gte ${ARCHVERSION//-*/} 4.7.0; then
|
||||
# Use new .klp.rela. sections
|
||||
KPATCH_MODULE=false
|
||||
if version_gte ${ARCHVERSION//-*/} 4.9.0; then
|
||||
KPATCH_LDFLAGS="--unique=.parainstructions --unique=.altinstructions"
|
||||
fi
|
||||
fi
|
||||
else
|
||||
# No support for livepatch in the kernel. Kpatch core module is needed.
|
||||
find_core_symvers || die "unable to find Module.symvers for kpatch core module"
|
||||
@ -560,15 +593,7 @@ for i in $FILES; do
|
||||
# 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" "$OBJDIR/Module.symvers" "kpatch_${PATCHNAME//-/_}" 2>&1 |tee -a "$LOGFILE"
|
||||
rc="${PIPESTATUS[0]}"
|
||||
if [[ $rc = 139 ]]; then
|
||||
warn "create-diff-object SIGSEGV"
|
||||
if ls core* &> /dev/null; then
|
||||
cp core* /tmp
|
||||
die "core file at /tmp/$(ls core*)"
|
||||
fi
|
||||
die "no core file found, run 'ulimit -c unlimited' and try to recreate"
|
||||
fi
|
||||
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
|
||||
@ -598,6 +623,9 @@ done
|
||||
echo
|
||||
|
||||
export KCFLAGS="-I$DATADIR/patch"
|
||||
if $KPATCH_MODULE; then
|
||||
export KCPPFLAGS="-D__KPATCH_MODULE__"
|
||||
fi
|
||||
|
||||
echo "Building patch module: kpatch-$PATCHNAME.ko"
|
||||
cp "$OBJDIR/.config" "$SRCDIR"
|
||||
@ -612,14 +640,36 @@ if [[ ! -z $UBUNTU_KERNEL ]]; then
|
||||
fi
|
||||
|
||||
cd "$TEMPDIR/output"
|
||||
ld -r -o ../patch/output.o $(find . -name "*.o") >> "$LOGFILE" 2>&1 || die
|
||||
md5sum ../patch/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/output.o || die
|
||||
rm -f checksum.tmp
|
||||
ld -r $KPATCH_LDFLAGS -o ../patch/tmp_output.o $(find . -name "*.o") >> "$LOGFILE" 2>&1 || die
|
||||
|
||||
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"
|
||||
check_pipe_status create-kpatch-module
|
||||
else
|
||||
cp $TEMPDIR/patch/tmp_output.o $TEMPDIR/patch/output.o || die
|
||||
|
||||
fi
|
||||
|
||||
cd "$TEMPDIR/patch"
|
||||
KPATCH_BUILD="$SRCDIR" KPATCH_NAME="$PATCHNAME" KBUILD_EXTRA_SYMBOLS="$KBUILD_EXTRA_SYMBOLS" \
|
||||
|
||||
KPATCH_BUILD="$SRCDIR" KPATCH_NAME="$PATCHNAME" \
|
||||
KBUILD_EXTRA_SYMBOLS="$KBUILD_EXTRA_SYMBOLS" \
|
||||
KPATCH_LDFLAGS="$KPATCH_LDFLAGS" \
|
||||
make "O=$OBJDIR" >> "$LOGFILE" 2>&1 || die
|
||||
|
||||
if ! $KPATCH_MODULE; then
|
||||
if [[ -z "$KPATCH_LDFLAGS" ]]; then
|
||||
extra_flags="--no-klp-arch-sections"
|
||||
fi
|
||||
cp $TEMPDIR/patch/kpatch-$PATCHNAME.ko $TEMPDIR/patch/kpatch-tmp.ko || die
|
||||
"$TOOLSDIR"/create-klp-module $extra_flags $TEMPDIR/patch/kpatch-tmp.ko $TEMPDIR/patch/kpatch-$PATCHNAME.ko 2>&1 |tee -a "$LOGFILE"
|
||||
check_pipe_status create-klp-module
|
||||
fi
|
||||
|
||||
cp -f "$TEMPDIR/patch/kpatch-$PATCHNAME.ko" "$BASE" || die
|
||||
|
||||
[[ "$DEBUG" -eq 0 ]] && rm -f "$LOGFILE"
|
||||
|
Loading…
Reference in New Issue
Block a user