diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..7ec6711 --- /dev/null +++ b/Makefile @@ -0,0 +1,21 @@ +include Makefile.inc + +SUBDIRS = kpatch-build kpatch kmod +BUILD_DIRS = $(SUBDIRS:%=build-%) +INSTALL_DIRS = $(SUBDIRS:%=install-%) +CLEAN_DIRS = $(SUBDIRS:%=clean-%) + +.PHONY: $(SUBDIRS) $(BUILD_DIRS) $(INSTALL_DIRS) $(CLEAN_DIRS) + + +all: $(BUILD_DIRS) +$(BUILD_DIRS): + $(MAKE) -C $(@:build-%=%) + +install: $(INSTALL_DIRS) +$(INSTALL_DIRS): + $(MAKE) -C $(@:install-%=%) install + +clean: $(CLEAN_DIRS) +$(CLEAN_DIRS): + $(MAKE) -C $(@:clean-%=%) clean diff --git a/Makefile.inc b/Makefile.inc new file mode 100644 index 0000000..e32efe9 --- /dev/null +++ b/Makefile.inc @@ -0,0 +1,12 @@ +SHELL = /bin/sh +CC = gcc + +INSTALL = /usr/bin/install + +PREFIX ?= /usr/local +SBINDIR = $(DESTDIR)$(PREFIX)/sbin +LIBEXECDIR = $(DESTDIR)$(PREFIX)/libexec/kpatch +DATADIR = $(DESTDIR)$(PREFIX)/share/kpatch + +.PHONY: all install clean +.DEFAULT: all diff --git a/README b/README index 0c337d5..4262674 100644 --- a/README +++ b/README @@ -12,20 +12,30 @@ scale-out, run on a single machine and are very downtime sensitive or require a heavyweight approval process and notification of workload users in the event of downtime. + +INSTALLATION + +The default install prefix is in /usr/local. + + make + sudo make install + + QUICK START NOTE: While kpatch is designed to work with any recent Linux -kernel on any distribution, these quick start instructions -currently only work on Fedora. +kernel on any distribution, the "kpatch build" command currently +only works on Fedora. First make a patch against the kernel tree, e.g. foo.patch. Then: - sudo kpatch-build/kpatch-build ~/foo.patch - insmod kpatch.ko kpatch-foo.ko + sudo /usr/local/sbin/kpatch build foo.patch + sudo insmod kpatch.ko kpatch-foo.ko Voila, your kernel is patched. + LICENSE kpatch is under the GPLv2 license. diff --git a/kmod/Makefile b/kmod/Makefile new file mode 100644 index 0000000..2ff48cc --- /dev/null +++ b/kmod/Makefile @@ -0,0 +1,11 @@ +include ../Makefile.inc + +all: + +install: + $(INSTALL) -d $(DATADIR)/core + $(INSTALL) -m 644 core/* $(DATADIR)/core + $(INSTALL) -d $(DATADIR)/patch + $(INSTALL) -m 644 patch/* $(DATADIR)/patch + +clean: diff --git a/kmod/core/Makefile b/kmod/core/Makefile index ac83fe4..9a2a411 100644 --- a/kmod/core/Makefile +++ b/kmod/core/Makefile @@ -1,9 +1,7 @@ +# make rules KPATCH_BUILD ?= /usr/lib/modules/$(shell uname -r)/build KPATCH_MAKE = $(MAKE) -C $(KPATCH_BUILD) M=$(PWD) -obj-m := kpatch.o -kpatch-y := core.o trampoline.o - kpatch.ko: core.c trampoline.S $(KPATCH_MAKE) kpatch.ko @@ -12,3 +10,8 @@ all: kpatch.ko clean: $(RM) -Rf .*.o.cmd .*.ko.cmd .tmp_versions *.o *.ko *.mod.c \ Module.symvers + + +# kbuild rules +obj-m := kpatch.o +kpatch-y := core.o trampoline.o diff --git a/kpatch-build/Makefile b/kpatch-build/Makefile index de0f15f..8235e53 100644 --- a/kpatch-build/Makefile +++ b/kpatch-build/Makefile @@ -1,15 +1,19 @@ -CFLAGS=-I../kmod/core +include ../Makefile.inc -all: create-diff-object add-patches-section link-vmlinux-syms +CFLAGS = -I../kmod/core +LDFLAGS = -lelf -create-diff-object: create-diff-object.c - $(CC) $(CFLAGS) -o $@ $^ -lelf +TARGETS = create-diff-object add-patches-section link-vmlinux-syms -add-patches-section: add-patches-section.c - $(CC) $(CFLAGS) -o $@ $^ -lelf -link-vmlinux-syms: link-vmlinux-syms.c - $(CC) $(CFLAGS) -o $@ $^ -lelf +all: $(TARGETS) + +%: %.c + $(CC) $(CFLAGS) $^ -o $@ $(LDFLAGS) + +install: all + $(INSTALL) -d $(LIBEXECDIR) + $(INSTALL) $(TARGETS) kpatch-build $(LIBEXECDIR) clean: - $(RM) -Rf create-diff-object add-patches-section link-vmlinux-syms + $(RM) $(TARGETS) diff --git a/kpatch-build/kpatch-build b/kpatch-build/kpatch-build index deac711..f504cba 100755 --- a/kpatch-build/kpatch-build +++ b/kpatch-build/kpatch-build @@ -24,7 +24,8 @@ BASE=$PWD LOGFILE=$PWD/kpatch-build.log -TOOLSDIR=$BASE/kpatch-build +TOOLSDIR=/usr/local/libexec/kpatch +DATADIR=/usr/local/share/kpatch ARCHVERSION=$(uname -r) DISTROVERSION=${ARCHVERSION%*.*} CPUS=$(grep -c ^processor /proc/cpuinfo) @@ -39,8 +40,8 @@ cleanup() { } die() { - echo "kpatch encountered an error" - echo "check kpatch-build.log" + echo "ERROR: kpatch build failed" + echo "check kpatch-build.log for more details" exit 1 } @@ -65,9 +66,6 @@ fi cleanup -echo "Building tools" -make -C $TOOLSDIR >> $LOGFILE 2>&1 || die - TEMPDIR=`mktemp -d` || die if [ -f "$KSRCDIR_CACHE" ] @@ -103,7 +101,7 @@ else tar czf $KSRCDIR_CACHE -C $KSRCDIR_DIR $ARCHVERSION fi -cp -R $BASE/kmod/patch/* $BASE/kmod/core $TEMPDIR || die +cp -R $DATADIR/core $DATADIR/patch $TEMPDIR || die cp vmlinux $TEMPDIR || die echo "Building patched kernel" @@ -153,12 +151,13 @@ KPATCH_BUILD=$KSRCDIR make >> $LOGFILE 2>&1 || die cd .. echo "Building patch module: kpatch-$PATCHNAME.ko" -ld -r -o output.o output/* >> $LOGFILE 2>&1 || die -$TOOLSDIR/add-patches-section output.o vmlinux >> $LOGFILE 2>&1 || die +cd patch +ld -r -o output.o ../output/* >> $LOGFILE 2>&1 || die +$TOOLSDIR/add-patches-section output.o ../vmlinux >> $LOGFILE 2>&1 || die KPATCH_BASEDIR=$TEMPDIR/core KPATCH_BUILD=$KSRCDIR KPATCH_NAME=$PATCHNAME make >> $LOGFILE 2>&1 || die strip -d 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 echo "SUCCESS" -cp -f $TEMPDIR/kpatch-$PATCHNAME.ko $TEMPDIR/core/kpatch.ko $BASE +cp -f $TEMPDIR/patch/kpatch-$PATCHNAME.ko $TEMPDIR/core/kpatch.ko $BASE cleanup diff --git a/kpatch/Makefile b/kpatch/Makefile new file mode 100644 index 0000000..2e345c7 --- /dev/null +++ b/kpatch/Makefile @@ -0,0 +1,9 @@ +include ../Makefile.inc + +all: + +install: all + $(INSTALL) -d $(SBINDIR) + $(INSTALL) kpatch $(SBINDIR) + +clean: diff --git a/kpatch/kpatch b/kpatch/kpatch index 6fcb06a..4340184 100755 --- a/kpatch/kpatch +++ b/kpatch/kpatch @@ -18,6 +18,7 @@ KERNELRELEASE=$(uname -r) VARDIR=/var/lib/kpatch/$KERNELRELEASE USRDIR=/usr/lib/kpatch/$KERNELRELEASE +TOOLSDIR=/usr/local/libexec/kpatch usage () { echo "usage:" @@ -27,6 +28,7 @@ usage () { echo "kpatch unload [--all | MODULE]" echo "kpatch list" echo "kpatch info MODULE" + echo "kpatch build PATCH" exit 1 } @@ -172,6 +174,11 @@ case $1 in echo "Hotfix information for ${2%.*}:" modinfo $DIR/available/$MODFILE ;; +"build") + [ $# -ne 2 ] && usage + $TOOLSDIR/kpatch-build $2 + [ $? -ne 0 ] && exit 3 + ;; *) echo "subcommand $1 not recognized" usage