Skip to content

Commit

Permalink
kpatch-build: use original vmlinux
Browse files Browse the repository at this point in the history
There's at least one case in the kernel (ddebug_proc_show) where the
compiled instructions are affected by the source file path given to gcc.
Which means that compiling the kernel with O= will result in many of the
function addresses changing.  This causes a mismatch between the locally
compiled vmlinux and the original vmlinux, which is very dangerous,
since we need the addresses to be correct.

The easy fix is just to use the original vmlinux for all the function
addresses.

Other potential ways to fix it which we might want to consider in the
future:

- use a combination of the old System.map and the new vmlinux to find
  the addresses.  The function ordering should be the same.  For
  non-duplicate symbols, use System.map.  For duplicate symbols, use
  vmlinux to find what order the symbol comes in.  e.g. the 2nd
  occurrence of foo() in System.map.  It adds a little complexity to the
  lookup code, but seems safe and wouldn't require the kernel debuginfo
  package.  However, this may not help us for patching modules.

- do something similar at runtime, i.e. use kallsyms_lookup_name for
  non-dups and kallsyms_on_each_symbol for dups, and look for the nth
  occurrence of the symbol (value of n is decided at build time).  This
  has the complexity of the previous option but it's done at runtime
  rather than build time, so... why?  Doing it at build time is better.

- compile the kernel in place.  This basically means no more caching
  because recompiling with --function-sections causes everything to be
  recompiled again.  This is bad for kpatch developers' SSDs...
  • Loading branch information
jpoimboe committed May 17, 2014
1 parent bf4be47 commit 5c98ec6
Show file tree
Hide file tree
Showing 2 changed files with 13 additions and 3 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ Install the dependencies for the "kpatch-build" command:

sudo yum install rpmdevtools pesign yum-utils
sudo yum-builddep kernel
sudo debuginfo-install kernel

# optional, but highly recommended
sudo yum install ccache
Expand Down
15 changes: 12 additions & 3 deletions kpatch-build/kpatch-build
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ usage() {
echo " -r, --sourcerpm Specify kernel source RPM" >&2
echo " -s, --sourcedir Specify kernel source directory" >&2
echo " -c, --config Specify kernel config file" >&2
echo " -v, --vmlinux Specify original vmlinux" >&2
echo " -d, --debug Keep scratch files in /tmp" >&2
}

Expand Down Expand Up @@ -119,6 +120,11 @@ while [[ $# -gt 0 ]]; do
shift
[[ ! -f "$CONFIGFILE" ]] && die "config file $CONFIGFILE not found"
;;
-v|--vmlinux)
VMLINUX=$(readlink -f "$2")
shift
[[ ! -f "$VMLINUX" ]] && die "vmlinux file $VMLINUX not found"
;;
-d|--debug)
echo "DEBUG mode enabled"
DEBUG=1
Expand Down Expand Up @@ -158,6 +164,9 @@ find_dirs || die "can't find supporting tools"

[[ -e "$SYMVERSFILE" ]] || die "can't find core module Module.symvers"

[[ -z $VMLINUX ]] && VMLINUX=/usr/lib/debug/lib/modules/${ARCHVERSION}/vmlinux
[[ -e "$VMLINUX" ]] || die "kernel-debuginfo not installed"

if [[ -n "$USERSRCDIR" ]]; then
SRCDIR="$CACHEDIR/src"
OBJDIR="$CACHEDIR/obj"
Expand Down Expand Up @@ -209,6 +218,7 @@ else
elif [[ $ID = ubuntu ]]; then

echo "Debian/Ubuntu distribution detected"

cd $TEMPDIR
echo "Downloading and unpacking kernel source for $ARCHVERSION"
apt-get source linux || die "'apt-get source linux' failed. you may need to run 'apt-get install dpkg-dev'"
Expand All @@ -234,7 +244,6 @@ echo "Building original kernel"
make mrproper >> "$LOGFILE" 2>&1 || die
make "-j$CPUS" vmlinux "O=$OBJDIR" >> "$LOGFILE" 2>&1 || die
cp -LR "$DATADIR/patch" "$TEMPDIR" || die
cp "$OBJDIR/vmlinux" "$TEMPDIR" || die

echo "Building patched kernel"
patch -N -p1 < "$APPLIEDPATCHFILE" >> "$LOGFILE" 2>&1 || die
Expand Down Expand Up @@ -286,10 +295,10 @@ make prepare >> "$LOGFILE" 2>&1 || die
cd "$TEMPDIR/output"
ld -r -o ../patch/output.o $FILES >> "$LOGFILE" 2>&1 || die
cd "$TEMPDIR/patch"
"$TOOLSDIR"/add-patches-section output.o ../vmlinux >> "$LOGFILE" 2>&1 || die
"$TOOLSDIR"/add-patches-section output.o "$VMLINUX" >> "$LOGFILE" 2>&1 || die
KPATCH_BUILD="$SRCDIR" KPATCH_NAME="$PATCHNAME" KBUILD_EXTRA_SYMBOLS="$SYMVERSFILE" make "O=$OBJDIR" >> "$LOGFILE" 2>&1 || die
$STRIPCMD "kpatch-$PATCHNAME.ko" >> "$LOGFILE" 2>&1 || die
"$TOOLSDIR"/link-vmlinux-syms "kpatch-$PATCHNAME.ko" ../vmlinux >> "$LOGFILE" 2>&1 || die
"$TOOLSDIR"/link-vmlinux-syms "kpatch-$PATCHNAME.ko" "$VMLINUX" >> "$LOGFILE" 2>&1 || die

cp -f "$TEMPDIR/patch/kpatch-$PATCHNAME.ko" "$BASE" || die

Expand Down

0 comments on commit 5c98ec6

Please sign in to comment.