Commit dcf9f31c authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag 'livepatching-for-6.15' of...

Merge tag 'livepatching-for-6.15' of git://git.kernel.org/pub/scm/linux/kernel/git/livepatching/livepatching

Pull livepatching updates from Petr Mladek:

 - Add a selftest for tracing of a livepatched function

 - Skip a selftest when kprobes are not using ftrace

 - Some documentation clean up

* tag 'livepatching-for-6.15' of git://git.kernel.org/pub/scm/linux/kernel/git/livepatching/livepatching:
  selftests: livepatch: test if ftrace can trace a livepatched function
  selftests: livepatch: add new ftrace helpers functions
  selftest/livepatch: Only run test-kprobe with CONFIG_KPROBES_ON_FTRACE
  docs: livepatch: move text out of code block
  livepatch: Add comment to clarify klp_add_nops()
parents 96050814 d11f0d17
Loading
Loading
Loading
Loading
+8 −5
Original line number Diff line number Diff line
@@ -217,16 +217,19 @@ livepatch relocation section refer to their respective symbols with their symbol
indices, and the original symbol indices (and thus the symtab ordering) must be
preserved in order for apply_relocate_add() to find the right symbol.

For example, take this particular rela from a livepatch module:::
For example, take this particular rela from a livepatch module::

  Relocation section '.klp.rela.btrfs.text.btrfs_feature_attr_show' at offset 0x2ba0 contains 4 entries:
      Offset             Info             Type               Symbol's Value  Symbol's Name + Addend
  000000000000001f  0000005e00000002 R_X86_64_PC32          0000000000000000 .klp.sym.vmlinux.printk,0 - 4

  This rela refers to the symbol '.klp.sym.vmlinux.printk,0', and the symbol index is encoded
  in 'Info'. Here its symbol index is 0x5e, which is 94 in decimal, which refers to the
  symbol index 94.
  And in this patch module's corresponding symbol table, symbol index 94 refers to that very symbol:
This rela refers to the symbol '.klp.sym.vmlinux.printk,0', and the symbol
index is encoded in 'Info'. Here its symbol index is 0x5e, which is 94 in
decimal, which refers to the symbol index 94.

And in this patch module's corresponding symbol table, symbol index 94 refers
to that very symbol::

  [ snip ]
  94: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT OS [0xff20] .klp.sym.vmlinux.printk,0
  [ snip ]
+6 −3
Original line number Diff line number Diff line
@@ -601,9 +601,12 @@ static int klp_add_object_nops(struct klp_patch *patch,
}

/*
 * Add 'nop' functions which simply return to the caller to run
 * the original function. The 'nop' functions are added to a
 * patch to facilitate a 'replace' mode.
 * Add 'nop' functions which simply return to the caller to run the
 * original function.
 *
 * They are added only when the atomic replace mode is used and only for
 * functions which are currently livepatched but are no longer included
 * in the new livepatch.
 */
static int klp_add_nops(struct klp_patch *patch)
{
+49 −0
Original line number Diff line number Diff line
@@ -10,6 +10,7 @@ SYSFS_KERNEL_DIR="/sys/kernel"
SYSFS_KLP_DIR="$SYSFS_KERNEL_DIR/livepatch"
SYSFS_DEBUG_DIR="$SYSFS_KERNEL_DIR/debug"
SYSFS_KPROBES_DIR="$SYSFS_DEBUG_DIR/kprobes"
SYSFS_TRACING_DIR="$SYSFS_DEBUG_DIR/tracing"

# Kselftest framework requirement - SKIP code is 4
ksft_skip=4
@@ -62,6 +63,9 @@ function push_config() {
			awk -F'[: ]' '{print "file " $1 " line " $2 " " $4}')
	FTRACE_ENABLED=$(sysctl --values kernel.ftrace_enabled)
	KPROBE_ENABLED=$(cat "$SYSFS_KPROBES_DIR/enabled")
	TRACING_ON=$(cat "$SYSFS_TRACING_DIR/tracing_on")
	CURRENT_TRACER=$(cat "$SYSFS_TRACING_DIR/current_tracer")
	FTRACE_FILTER=$(cat "$SYSFS_TRACING_DIR/set_ftrace_filter")
}

function pop_config() {
@@ -74,6 +78,17 @@ function pop_config() {
	if [[ -n "$KPROBE_ENABLED" ]]; then
		echo "$KPROBE_ENABLED" > "$SYSFS_KPROBES_DIR/enabled"
	fi
	if [[ -n "$TRACING_ON" ]]; then
		echo "$TRACING_ON" > "$SYSFS_TRACING_DIR/tracing_on"
	fi
	if [[ -n "$CURRENT_TRACER" ]]; then
		echo "$CURRENT_TRACER" > "$SYSFS_TRACING_DIR/current_tracer"
	fi
	if [[ -n "$FTRACE_FILTER" ]]; then
		echo "$FTRACE_FILTER" \
			| sed -e "/#### all functions enabled ####/d" \
			> "$SYSFS_TRACING_DIR/set_ftrace_filter"
	fi
}

function set_dynamic_debug() {
@@ -352,3 +367,37 @@ function check_sysfs_value() {
		die "Unexpected value in $path: $expected_value vs. $value"
	fi
}

# cleanup_tracing() - stop and clean up function tracing
function cleanup_tracing() {
	echo 0 > "$SYSFS_TRACING_DIR/tracing_on"
	echo "" > "$SYSFS_TRACING_DIR/set_ftrace_filter"
	echo "nop" > "$SYSFS_TRACING_DIR/current_tracer"
	echo "" > "$SYSFS_TRACING_DIR/trace"
}

# trace_function(function) - start tracing of a function
#	function - to be traced function
function trace_function() {
	local function="$1"; shift

	cleanup_tracing

	echo "function" > "$SYSFS_TRACING_DIR/current_tracer"
	echo "$function" > "$SYSFS_TRACING_DIR/set_ftrace_filter"
	echo 1 > "$SYSFS_TRACING_DIR/tracing_on"
}

# check_traced_functions(functions...) - check whether each function appeared in the trace log
#	functions - list of functions to be checked
function check_traced_functions() {
	local function

	for function in "$@"; do
		if ! grep -Fwq "$function" "$SYSFS_TRACING_DIR/trace" ; then
			die "Function ($function) did not appear in the trace"
		fi
	done

	cleanup_tracing
}
+34 −0
Original line number Diff line number Diff line
@@ -61,4 +61,38 @@ livepatch: '$MOD_LIVEPATCH': unpatching complete
% rmmod $MOD_LIVEPATCH"


# - verify livepatch can load
# - check if traces have a patched function
# - reset trace and unload livepatch

start_test "trace livepatched function and check that the live patch remains in effect"

FUNCTION_NAME="livepatch_cmdline_proc_show"

load_lp $MOD_LIVEPATCH
trace_function "$FUNCTION_NAME"

if [[ "$(cat /proc/cmdline)" == "$MOD_LIVEPATCH: this has been live patched" ]] ; then
	log "livepatch: ok"
fi

check_traced_functions "$FUNCTION_NAME"

disable_lp $MOD_LIVEPATCH
unload_lp $MOD_LIVEPATCH

check_result "% insmod test_modules/$MOD_LIVEPATCH.ko
livepatch: enabling patch '$MOD_LIVEPATCH'
livepatch: '$MOD_LIVEPATCH': initializing patching transition
livepatch: '$MOD_LIVEPATCH': starting patching transition
livepatch: '$MOD_LIVEPATCH': completing patching transition
livepatch: '$MOD_LIVEPATCH': patching complete
livepatch: ok
% echo 0 > $SYSFS_KLP_DIR/$MOD_LIVEPATCH/enabled
livepatch: '$MOD_LIVEPATCH': initializing unpatching transition
livepatch: '$MOD_LIVEPATCH': starting unpatching transition
livepatch: '$MOD_LIVEPATCH': completing unpatching transition
livepatch: '$MOD_LIVEPATCH': unpatching complete
% rmmod $MOD_LIVEPATCH"

exit 0
+2 −0
Original line number Diff line number Diff line
@@ -5,6 +5,8 @@

. $(dirname $0)/functions.sh

grep -q kprobe_ftrace_ops /proc/kallsyms || skip "test-kprobe requires CONFIG_KPROBES_ON_FTRACE"

MOD_LIVEPATCH=test_klp_livepatch
MOD_KPROBE=test_klp_kprobe