1
0

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()
This commit is contained in:
Linus Torvalds
2025-03-27 19:26:10 -07:00
5 changed files with 99 additions and 8 deletions

View File

@@ -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 ]

View File

@@ -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)
{

View File

@@ -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
}

View File

@@ -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

View File

@@ -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