lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <10ccbeb0f4bcd7d0a10cc9b9bd12fdc4894f83ee.1746821544.git.jpoimboe@kernel.org>
Date: Fri,  9 May 2025 13:17:23 -0700
From: Josh Poimboeuf <jpoimboe@...nel.org>
To: x86@...nel.org
Cc: linux-kernel@...r.kernel.org,
	Petr Mladek <pmladek@...e.com>,
	Miroslav Benes <mbenes@...e.cz>,
	Joe Lawrence <joe.lawrence@...hat.com>,
	live-patching@...r.kernel.org,
	Song Liu <song@...nel.org>,
	laokz <laokz@...mail.com>,
	Jiri Kosina <jikos@...nel.org>,
	Marcos Paulo de Souza <mpdesouza@...e.com>,
	Weinan Liu <wnliu@...gle.com>,
	Fazla Mehrab <a.mehrab@...edance.com>,
	Chen Zhongjin <chenzhongjin@...wei.com>,
	Puranjay Mohan <puranjay@...nel.org>
Subject: [PATCH v2 59/62] livepatch/klp-build: Introduce klp-build script for generating livepatch modules

Add a klp-build script which automates the generation of a livepatch
module from a source .patch file by performing the following steps:

  - Builds an original kernel with -function-sections and
    -fdata-sections, plus objtool function checksumming.

  - Applies the .patch file and rebuilds the kernel using the same
    options.

  - Runs 'objtool klp diff' to detect changed functions and generate
    intermediate binary diff objects.

  - Builds a kernel module which links the diff objects with some
    livepatch module init code (scripts/livepatch/init.c).

  - Finalizes the livepatch module (aka work around linker wreckage)
    using 'objtool klp post-link'.

Signed-off-by: Josh Poimboeuf <jpoimboe@...nel.org>
---
 scripts/livepatch/klp-build | 697 ++++++++++++++++++++++++++++++++++++
 1 file changed, 697 insertions(+)
 create mode 100755 scripts/livepatch/klp-build

diff --git a/scripts/livepatch/klp-build b/scripts/livepatch/klp-build
new file mode 100755
index 000000000000..ebbece6f6b8d
--- /dev/null
+++ b/scripts/livepatch/klp-build
@@ -0,0 +1,697 @@
+#!/bin/bash
+# SPDX-License-Identifier: GPL-2.0
+#
+# Build a livepatch module
+#
+
+# shellcheck disable=SC1090
+
+if (( BASH_VERSINFO[0] < 4 \
+	|| (BASH_VERSINFO[0] == 4 && BASH_VERSINFO[1] < 4) )); then
+		echo "error: this script requires bash 4.4+" >&2
+	exit 1
+fi
+
+set -o errexit
+set -o errtrace
+set -o pipefail
+set -o nounset
+
+# Allow doing 'cmd | mapfile -t array' instead of 'mapfile -t array < <(cmd)'.
+# This helps keep execution in pipes so pipefail+errexit can catch errors.
+shopt -s lastpipe
+
+unset SKIP_CLEANUP XTRACE
+REPLACE=1
+SHORT_CIRCUIT=0
+shopt -o xtrace | grep -q 'on' && XTRACE=1
+# Avoid removing the previous $TMP_DIR until args have been fully processed.
+KEEP_TMP=1
+
+CPUS="$(getconf _NPROCESSORS_ONLN)"
+VERBOSE="-s"
+
+
+SCRIPT="$(basename "$0")"
+SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
+FIX_PATCH_LINES="$SCRIPT_DIR/fix-patch-lines"
+
+SRC="$(pwd)"
+OBJ="$(pwd)"
+
+CONFIG="$OBJ/.config"
+TMP_DIR="$OBJ/klp-tmp"
+
+ORIG_DIR="$TMP_DIR/orig"
+PATCHED_DIR="$TMP_DIR/patched"
+DIFF_DIR="$TMP_DIR/diff"
+KMOD_DIR="$TMP_DIR/kmod"
+
+STASH_DIR="$TMP_DIR/stash"
+TIMESTAMP="$TMP_DIR/timestamp"
+PATCH_TMP_DIR="$TMP_DIR/tmp"
+
+KLP_DIFF_LOG="$DIFF_DIR/diff.log"
+
+grep0() {
+	command grep "$@" || true
+}
+
+status() {
+	echo "$*"
+}
+
+warn() {
+	echo "error: $(basename "$SCRIPT"): $*" >&2
+}
+
+die() {
+	warn "$@"
+	exit 1
+}
+
+declare -a STASHED_FILES
+
+stash_file() {
+	local file="$1"
+	local rel_file="${file#"$SRC"/}"
+
+	[[ ! -e "$file" ]] && die "no file to stash: $file"
+
+	mkdir -p "$STASH_DIR/$(dirname "$rel_file")"
+	cp -f "$file" "$STASH_DIR/$rel_file"
+
+	STASHED_FILES+=("$rel_file")
+}
+
+restore_files() {
+	local file
+
+	for file in "${STASHED_FILES[@]}"; do
+		mv -f "$STASH_DIR/$file" "$SRC/$file" || warn "can't restore file: $file"
+	done
+
+	STASHED_FILES=()
+}
+
+cleanup() {
+	set +o nounset
+	revert_patches "--recount"
+	restore_files
+	[[ "$KEEP_TMP" -eq 0 ]] && rm -rf "$TMP_DIR"
+	true
+}
+
+trap_err() {
+	warn "line ${BASH_LINENO[0]}: '$BASH_COMMAND'"
+}
+
+trap cleanup  EXIT INT TERM HUP
+trap trap_err ERR
+
+__usage() {
+	cat <<EOF
+Usage: $SCRIPT [OPTIONS] PATCH_FILE(s)
+Generate a livepatch module.
+
+Options:
+   -o, --output <file.ko>	Output file [default: livepatch-<patch-name>.ko]
+       --no-replace		Disable livepatch atomic replace
+   -v, --verbose		Pass V=1 to kernel/module builds
+
+Advanced Options:
+   -S, --short-circuit=STEP	Start at build step (requires prior --keep-tmp)
+				   1|orig	Build original kernel (default)
+				   2|patched	Build patched kernel
+				   3|diff	Diff objects
+				   4|kmod	Build patch module
+   -T, --keep-tmp		Preserve tmp dir on exit
+
+EOF
+}
+
+usage() {
+	__usage >&2
+}
+
+process_args() {
+	local keep_tmp=0
+	local short
+	local long
+	local args
+
+	short="ho:vS:T"
+	long="help,output:,no-replace,verbose,short-circuit:,keep-tmp"
+
+	args=$(getopt --options "$short" --longoptions "$long" -- "$@") || {
+		echo; usage; exit
+	}
+	eval set -- "$args"
+
+	while true; do
+		case "$1" in
+			-h | --help)
+				usage
+				exit 0
+				;;
+			-o | --output)
+				[[ "$2" != *.ko ]] && die "output filename should end with .ko"
+				OUTFILE="$2"
+				NAME="$(basename "$OUTFILE")"
+				NAME="${NAME%.ko}"
+				NAME="$(module_name_string "$NAME")"
+				shift 2
+				;;
+			--no-replace)
+				REPLACE=0
+				shift
+				;;
+			-v | --verbose)
+				VERBOSE="V=1"
+				shift
+				;;
+			-S | --short-circuit)
+				[[ ! -d "$TMP_DIR" ]] && die "--short-circuit requires preserved klp-tmp dir"
+				keep_tmp=1
+				case "$2" in
+					1 | orig)	SHORT_CIRCUIT=1; ;;
+					2 | patched)	SHORT_CIRCUIT=2; ;;
+					3 | diff)	SHORT_CIRCUIT=3; ;;
+					4 | mod)	SHORT_CIRCUIT=4; ;;
+					*)		die "invalid short-circuit step '$2'" ;;
+				esac
+				shift 2
+				;;
+			-T | --keep-tmp)
+				keep_tmp=1
+				shift
+				;;
+			--)
+				shift
+				break
+				;;
+			*)
+				usage
+				exit 1
+				;;
+		esac
+	done
+
+	if [[ $# -eq 0 ]]; then
+		usage
+		exit 1
+	fi
+
+	KEEP_TMP="$keep_tmp"
+	PATCHES=("$@")
+}
+
+# temporarily disable xtrace for especially verbose code
+xtrace_save() {
+	[[ -v XTRACE ]] && set +x
+	return 0
+}
+
+xtrace_restore() {
+	[[ -v XTRACE ]] && set -x
+	return 0
+}
+
+validate_config() {
+	xtrace_save "reading .config"
+	source "$CONFIG" || die "no .config file in $(dirname "$CONFIG")"
+	xtrace_restore
+
+	[[ -v CONFIG_LIVEPATCH ]]			\
+		|| die "CONFIG_LIVEPATCH not enabled"
+
+	[[ -v CONFIG_GCC_PLUGIN_LATENT_ENTROPY ]]	\
+		&& die "kernel option 'CONFIG_GCC_PLUGIN_LATENT_ENTROPY' not supported"
+
+	[[ -v CONFIG_GCC_PLUGIN_RANDSTRUCT ]]		\
+		&& die "kernel option 'CONFIG_GCC_PLUGIN_RANDSTRUCT' not supported"
+
+	return 0
+}
+
+# Only allow alphanumerics and '_' and '-' in the module name.  Everything else
+# is replaced with '-'.  Also truncate to 55 chars so the full name + NUL
+# terminator fits in the kernel's 56-byte module name array.
+module_name_string() {
+	echo "${1//[^a-zA-Z0-9_-]/-}" | cut -c 1-55
+}
+
+# If the module name wasn't specified on the cmdline with --output, give it a
+# name based on the patch name.
+set_module_name() {
+	[[ -v NAME ]] && return 0
+
+	if [[ "${#PATCHES[@]}" -eq 1 ]]; then
+		NAME="$(basename "${PATCHES[0]}")"
+		NAME="${NAME%.*}"
+	else
+		NAME="patch"
+	fi
+
+	NAME="livepatch-$NAME"
+	NAME="$(module_name_string "$NAME")"
+
+	OUTFILE="$NAME.ko"
+}
+
+# Hardcode the value printed by the localversion script to prevent patch
+# application from appending it with '+' due to a dirty git working tree.
+set_kernelversion() {
+	local file="$SRC/scripts/setlocalversion"
+	local localversion
+
+	stash_file "$file"
+
+	localversion="$(cd "$SRC" && make --no-print-directory kernelversion)"
+	localversion="$(cd "$SRC" && KERNELVERSION="$localversion" ./scripts/setlocalversion)"
+	[[ -z "$localversion" ]] && die "setlocalversion failed"
+
+	echo "echo $localversion" > "$file"
+}
+
+get_patch_files() {
+	local patch="$1"
+
+	grep0 -E '^(--- |\+\+\+ )' "$patch"			\
+		| gawk '{print $2}'				\
+		| sed 's|^[^/]*/||'				\
+		| sort -u
+}
+
+# Make sure git re-stats the changed files
+git_refresh() {
+	local patch="$1"
+	local files=()
+
+	[[ ! -d "$SRC/.git" ]] && return
+
+	get_patch_files "$patch" | mapfile -t files
+
+	(
+		cd "$SRC"
+		git update-index -q --refresh -- "${files[@]}"
+	)
+}
+
+check_unsupported_patches() {
+	local patch
+
+	for patch in "${PATCHES[@]}"; do
+		local files=()
+
+		get_patch_files "$patch" | mapfile -t files
+
+		for file in "${files[@]}"; do
+			case "$file" in
+				lib/*|*.S)
+					die "unsupported patch to $file"
+					;;
+			esac
+		done
+	done
+}
+
+apply_patch() {
+	local patch="$1"
+	shift
+	local extra_args=("$@")
+
+	[[ ! -f "$patch" ]] && die "$patch doesn't exist"
+
+	( cd "$SRC" && git apply "${extra_args[@]}" "$patch" )
+
+	APPLIED_PATCHES+=("$patch")
+}
+
+revert_patch() {
+	local patch="$1"
+	shift
+	local extra_args=("$@")
+	local tmp=()
+
+	( cd "$SRC" && git apply --reverse "${extra_args[@]}" "$patch" )
+	git_refresh "$patch"
+
+	for p in "${APPLIED_PATCHES[@]}"; do
+		[[ "$p" == "$patch" ]] && continue
+		tmp+=("$p")
+	done
+
+	APPLIED_PATCHES=("${tmp[@]}")
+}
+
+apply_patches() {
+	local patch
+
+	for patch in "${PATCHES[@]}"; do
+		apply_patch "$patch"
+	done
+}
+
+revert_patches() {
+	local extra_args=("$@")
+	local patches=("${APPLIED_PATCHES[@]}")
+
+	for (( i=${#patches[@]}-1 ; i>=0 ; i-- )) ; do
+		revert_patch "${patches[$i]}" "${extra_args[@]}"
+	done
+
+	APPLIED_PATCHES=()
+
+	# Make sure git actually sees the patches have been reverted.
+	[[ -d "$SRC/.git" ]] && (cd "$SRC" && git update-index -q --refresh)
+}
+
+validate_patches() {
+	check_unsupported_patches
+	apply_patches
+	revert_patches
+}
+
+do_init() {
+	# We're not yet smart enough to handle anything other than in-tree
+	# builds in pwd.
+	[[ ! "$SRC" -ef "$SCRIPT_DIR/../.." ]] && die "please run from the kernel root directory"
+	[[ ! "$OBJ" -ef "$SCRIPT_DIR/../.." ]] && die "please run from the kernel root directory"
+
+	(( SHORT_CIRCUIT <= 1 )) && rm -rf "$TMP_DIR"
+	mkdir -p "$TMP_DIR"
+
+	APPLIED_PATCHES=()
+
+	[[ -x "$FIX_PATCH_LINES" ]] || die "can't find fix-patch-lines"
+
+	validate_config
+	set_module_name
+	set_kernelversion
+}
+
+# Refresh the patch hunk headers, specifically the line numbers and counts.
+refresh_patch() {
+	local patch="$1"
+	local tmpdir="$PATCH_TMP_DIR"
+	local files=()
+
+	rm -rf "$tmpdir"
+	mkdir -p "$tmpdir/a"
+	mkdir -p "$tmpdir/b"
+
+	# Find all source files affected by the patch
+	grep0 -E '^(--- |\+\+\+ )[^ /]+' "$patch"	|
+		sed -E 's/(--- |\+\+\+ )[^ /]+\///'	|
+		sort | uniq | mapfile -t files
+
+	# Copy orig source files to 'a'
+	( cd "$SRC" && echo "${files[@]}" | xargs cp --parents --target-directory="$tmpdir/a" )
+
+	# Copy patched source files to 'b'
+	apply_patch "$patch" --recount
+	( cd "$SRC" && echo "${files[@]}" | xargs cp --parents --target-directory="$tmpdir/b" )
+	revert_patch "$patch" --recount
+
+	# Diff 'a' and 'b' to make a clean patch
+	( cd "$tmpdir" && git diff --no-index --no-prefix a b > "$patch" ) || true
+}
+
+# Copy the patches to a temporary directory, fix their lines so as not to
+# affect the __LINE__ macro for otherwise unchanged functions further down the
+# file, and update $PATCHES to point to the fixed patches.
+fix_patches() {
+	local idx
+	local i
+
+	rm -f "$TMP_DIR"/*.patch
+
+	idx=0001
+	for i in "${!PATCHES[@]}"; do
+		local old_patch="${PATCHES[$i]}"
+		local tmp_patch="$TMP_DIR/tmp.patch"
+		local patch="${PATCHES[$i]}"
+		local new_patch
+
+		new_patch="$TMP_DIR/$idx-fixed-$(basename "$patch")"
+
+		cp -f "$old_patch" "$tmp_patch"
+		refresh_patch "$tmp_patch"
+		"$FIX_PATCH_LINES" "$tmp_patch" > "$new_patch"
+		refresh_patch "$new_patch"
+
+		PATCHES[i]="$new_patch"
+
+		rm -f "$tmp_patch"
+		idx=$(printf "%04d" $(( 10#$idx + 1 )))
+	done
+}
+
+build_kernel() {
+	local log="$TMP_DIR/build.log"
+	local objtool_args=()
+	local cmd=()
+
+	objtool_args=("--checksum")
+	[[ -v OBJTOOL_ARGS ]] && objtool_args+=("${OBJTOOL_ARGS}")
+
+	cmd=("make")
+
+	# When a patch to a kernel module references a newly created unexported
+	# symbol which lives in vmlinux or another kernel module, the patched
+	# kernel build fails with the following error:
+	#
+	#   ERROR: modpost: "klp_string" [fs/xfs/xfs.ko] undefined!
+	#
+	# The undefined symbols are working as designed in that case.  They get
+	# resolved later when the livepatch module build link pulls all the
+	# disparate objects together into the same kernel module.
+	#
+	# It would be good to have a way to tell modpost to skip checking for
+	# undefined symbols altogether.  For now, just convert the error to a
+	# warning with KBUILD_MODPOST_WARN, and grep out the warning to avoid
+	# confusing the user.
+	#
+	cmd+=("KBUILD_MODPOST_WARN=1")
+
+	cmd+=("$VERBOSE")
+	cmd+=("-j$CPUS")
+	cmd+=("KCFLAGS=-ffunction-sections -fdata-sections")
+	cmd+=("OBJTOOL_ARGS=${objtool_args[*]}")
+	cmd+=("vmlinux")
+	cmd+=("modules")
+
+	(
+		cd "$SRC"
+		"${cmd[@]}"							\
+			> >(tee -a "$log")					\
+			2> >(tee -a "$log" | grep0 -v "modpost.*undefined!" >&2)
+	)
+}
+
+find_objects() {
+	local opts=("$@")
+
+	# Find root-level vmlinux.o and non-root-level .ko files,
+	# excluding klp-tmp/ and .git/
+	find "$OBJ" \( -path "$TMP_DIR" -o -path "$OBJ/.git" -o	-regex "$OBJ/[^/][^/]*\.ko" \) -prune -o \
+		    -type f "${opts[@]}"				\
+		    \( -name "*.ko" -o -path "$OBJ/vmlinux.o" \)	\
+		    -printf '%P\n'
+}
+
+# Copy all objects (.o archives) to $ORIG_DIR
+copy_orig_objects() {
+
+	rm -rf "$ORIG_DIR"
+	mkdir -p "$ORIG_DIR"
+
+	(
+		cd "$OBJ"
+		find_objects						\
+			| sed 's/\.ko$/.o/'				\
+			| xargs cp --parents --target-directory="$ORIG_DIR"
+	)
+
+	mv -f "$TMP_DIR/build.log" "$ORIG_DIR"
+	touch "$TIMESTAMP"
+}
+
+# Copy all changed objects to $PATCHED_DIR
+copy_patched_objects() {
+	local found
+	local files=()
+	local opts=()
+
+	rm -rf "$PATCHED_DIR"
+	mkdir -p "$PATCHED_DIR"
+
+	# Note this doesn't work with some configs, thus the 'cmp' below.
+	opts=("-newer")
+	opts+=("$TIMESTAMP")
+
+	find_objects "${opts[@]}" | mapfile -t files
+
+	xtrace_save "processing all objects"
+	for _file in "${files[@]}"; do
+		local rel_file="${_file/.ko/.o}"
+		local file="$OBJ/$rel_file"
+		local orig_file="$ORIG_DIR/$rel_file"
+		local patched_file="$PATCHED_DIR/$rel_file"
+
+		[[ ! -f "$file" ]] && die "missing $(basename "$file") for $_file"
+
+		cmp -s "$orig_file" "$file" && continue
+
+		mkdir -p "$(dirname "$patched_file")"
+		cp -f "$file" "$patched_file"
+		found=1
+	done
+	xtrace_restore
+
+	[[ -n "$found" ]] || die "no changes detected"
+
+	mv -f "$TMP_DIR/build.log" "$PATCHED_DIR"
+}
+
+# Diff changed objects, writing output object to $DIFF_DIR
+diff_objects() {
+	local log="$KLP_DIFF_LOG"
+	local files=()
+
+	rm -rf "$DIFF_DIR"
+	mkdir -p "$DIFF_DIR"
+
+	find "$PATCHED_DIR" -type f -name "*.o" | mapfile -t files
+	[[ ${#files[@]} -eq 0 ]] && die "no changes detected"
+
+	# Diff all changed objects
+	for file in "${files[@]}"; do
+		local rel_file="${file#"$PATCHED_DIR"/}"
+		local orig_file="$rel_file"
+		local patched_file="$PATCHED_DIR/$rel_file"
+		local out_file="$DIFF_DIR/$rel_file"
+		local cmd=()
+
+		mkdir -p "$(dirname "$out_file")"
+
+		cmd=("$SRC/tools/objtool/objtool")
+		cmd+=("klp")
+		cmd+=("diff")
+		cmd+=("$orig_file")
+		cmd+=("$patched_file")
+		cmd+=("$out_file")
+
+		(
+			cd "$ORIG_DIR"
+			"${cmd[@]}"							\
+				> >(tee -a "$log")					\
+				2> >(tee -a "$log" >&2)					\
+				|| die "objtool klp diff failed"
+		)
+	done
+}
+
+# Build and post-process livepatch module in $KMOD_DIR
+build_patch_module() {
+	local makefile="$KMOD_DIR/Kbuild"
+	local log="$KMOD_DIR/build.log"
+	local cflags=()
+	local files=()
+	local cmd=()
+
+	rm -rf "$KMOD_DIR"
+	mkdir -p "$KMOD_DIR"
+
+	cp -f "$SRC/scripts/livepatch/init.c" "$KMOD_DIR"
+
+	echo "obj-m := $NAME.o" > "$makefile"
+	echo -n "$NAME-y := init.o" >> "$makefile"
+
+	find "$DIFF_DIR" -type f -name "*.o" | mapfile -t files
+	[[ ${#files[@]} -eq 0 ]] && die "no changes detected"
+
+	for file in "${files[@]}"; do
+		local rel_file="${file#"$DIFF_DIR"/}"
+		local kmod_file="$KMOD_DIR/$rel_file"
+		local cmd_file
+
+		mkdir -p "$(dirname "$kmod_file")"
+		cp -f "$file" "$kmod_file"
+
+		# Tell kbuild this is a prebuilt object
+		cp -f "$file" "${kmod_file}_shipped"
+
+		echo -n " $rel_file" >> "$makefile"
+
+		cmd_file="$ORIG_DIR/$(dirname "$rel_file")/.$(basename "$rel_file").cmd"
+		[[ -e "$cmd_file" ]] && cp -f "$cmd_file" "$(dirname "$kmod_file")"
+	done
+
+	echo >> "$makefile"
+
+	cflags=("-ffunction-sections")
+	cflags+=("-fdata-sections")
+	[[ $REPLACE -eq 0 ]] && cflags+=("-DKLP_NO_REPLACE")
+
+	cmd=("make")
+	cmd+=("$VERBOSE")
+	cmd+=("-j$CPUS")
+	cmd+=("--directory=.")
+	cmd+=("M=$KMOD_DIR")
+	cmd+=("KCFLAGS=${cflags[*]}")
+
+	# Build a "normal" kernel module with init.c and the diffed objects
+	(
+		cd "$SRC"
+		"${cmd[@]}"							\
+			>  >(tee -a "$log")					\
+			2> >(tee -a "$log" >&2)
+	)
+
+	# Save off the intermediate binary for debugging
+	cp -f "$KMOD_DIR/$NAME.ko" "$KMOD_DIR/$NAME.ko.orig"
+
+	# Fix (and work around) linker wreckage for klp syms / relocs
+	"$SRC/tools/objtool/objtool" klp post-link "$KMOD_DIR/$NAME.ko" || die "objtool klp post-link failed"
+
+	cp -f "$KMOD_DIR/$NAME.ko" "$OUTFILE"
+}
+
+
+################################################################################
+
+process_args "$@"
+do_init
+
+if (( SHORT_CIRCUIT <= 1 )); then
+	status "Building original kernel"
+	validate_patches
+	build_kernel
+	status "Copying original object files"
+	copy_orig_objects
+fi
+
+if (( SHORT_CIRCUIT <= 2 )); then
+	status "Fixing patches"
+	fix_patches
+	apply_patches
+	status "Building patched kernel"
+	build_kernel
+	revert_patches
+	status "Copying patched object files"
+	copy_patched_objects
+fi
+
+if (( SHORT_CIRCUIT <= 3 )); then
+	status "Diffing objects"
+	diff_objects
+fi
+
+if (( SHORT_CIRCUIT <= 4 )); then
+	status "Building patch module: $OUTFILE"
+	build_patch_module
+fi
+
+status "SUCCESS"
-- 
2.49.0


Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ