Skip to content

Commit

Permalink
Merge tag 'livepatching-for-6.15' of git://git.kernel.org/pub/scm/lin…
Browse files Browse the repository at this point in the history
…ux/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()
  • Loading branch information
Linus Torvalds committed Mar 28, 2025
2 parents 9605081 + d11f0d1 commit dcf9f31
Show file tree
Hide file tree
Showing 5 changed files with 99 additions and 8 deletions.
13 changes: 8 additions & 5 deletions Documentation/livepatch/module-elf-format.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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 ]
Expand Down
9 changes: 6 additions & 3 deletions kernel/livepatch/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand Down
49 changes: 49 additions & 0 deletions tools/testing/selftests/livepatch/functions.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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() {
Expand All @@ -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() {
Expand Down Expand Up @@ -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 changes: 34 additions & 0 deletions tools/testing/selftests/livepatch/test-ftrace.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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 changes: 2 additions & 0 deletions tools/testing/selftests/livepatch/test-kprobe.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down

0 comments on commit dcf9f31

Please sign in to comment.