Skip to content

Commit 59b2a38

Browse files
committed
Merge branch 'for-6.1/sysfs-patched-object' into for-linus
2 parents 857300b + ff1b80e commit 59b2a38

File tree

5 files changed

+148
-1
lines changed

5 files changed

+148
-1
lines changed

Documentation/ABI/testing/sysfs-kernel-livepatch

+8
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,14 @@ Description:
5555
The object directory contains subdirectories for each function
5656
that is patched within the object.
5757

58+
What: /sys/kernel/livepatch/<patch>/<object>/patched
59+
Date: August 2022
60+
KernelVersion: 6.1.0
61+
62+
Description:
63+
An attribute which indicates whether the object is currently
64+
patched.
65+
5866
What: /sys/kernel/livepatch/<patch>/<object>/<function,sympos>
5967
Date: Nov 2014
6068
KernelVersion: 3.19.0

kernel/livepatch/core.c

+18
Original file line numberDiff line numberDiff line change
@@ -325,6 +325,7 @@ int klp_apply_section_relocs(struct module *pmod, Elf_Shdr *sechdrs,
325325
* /sys/kernel/livepatch/<patch>/transition
326326
* /sys/kernel/livepatch/<patch>/force
327327
* /sys/kernel/livepatch/<patch>/<object>
328+
* /sys/kernel/livepatch/<patch>/<object>/patched
328329
* /sys/kernel/livepatch/<patch>/<object>/<function,sympos>
329330
*/
330331
static int __klp_disable_patch(struct klp_patch *patch);
@@ -431,6 +432,22 @@ static struct attribute *klp_patch_attrs[] = {
431432
};
432433
ATTRIBUTE_GROUPS(klp_patch);
433434

435+
static ssize_t patched_show(struct kobject *kobj,
436+
struct kobj_attribute *attr, char *buf)
437+
{
438+
struct klp_object *obj;
439+
440+
obj = container_of(kobj, struct klp_object, kobj);
441+
return sysfs_emit(buf, "%d\n", obj->patched);
442+
}
443+
444+
static struct kobj_attribute patched_kobj_attr = __ATTR_RO(patched);
445+
static struct attribute *klp_object_attrs[] = {
446+
&patched_kobj_attr.attr,
447+
NULL,
448+
};
449+
ATTRIBUTE_GROUPS(klp_object);
450+
434451
static void klp_free_object_dynamic(struct klp_object *obj)
435452
{
436453
kfree(obj->name);
@@ -576,6 +593,7 @@ static void klp_kobj_release_object(struct kobject *kobj)
576593
static struct kobj_type klp_ktype_object = {
577594
.release = klp_kobj_release_object,
578595
.sysfs_ops = &kobj_sysfs_ops,
596+
.default_groups = klp_object_groups,
579597
};
580598

581599
static void klp_kobj_release_func(struct kobject *kobj)

tools/testing/selftests/livepatch/Makefile

+2-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@ TEST_PROGS := \
66
test-callbacks.sh \
77
test-shadow-vars.sh \
88
test-state.sh \
9-
test-ftrace.sh
9+
test-ftrace.sh \
10+
test-sysfs.sh
1011

1112
TEST_FILES := settings
1213

tools/testing/selftests/livepatch/functions.sh

+34
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
MAX_RETRIES=600
88
RETRY_INTERVAL=".1" # seconds
9+
KLP_SYSFS_DIR="/sys/kernel/livepatch"
910

1011
# Kselftest framework requirement - SKIP code is 4
1112
ksft_skip=4
@@ -308,3 +309,36 @@ function check_result {
308309

309310
cleanup_dmesg_file
310311
}
312+
313+
# check_sysfs_rights(modname, rel_path, expected_rights) - check sysfs
314+
# path permissions
315+
# modname - livepatch module creating the sysfs interface
316+
# rel_path - relative path of the sysfs interface
317+
# expected_rights - expected access rights
318+
function check_sysfs_rights() {
319+
local mod="$1"; shift
320+
local rel_path="$1"; shift
321+
local expected_rights="$1"; shift
322+
323+
local path="$KLP_SYSFS_DIR/$mod/$rel_path"
324+
local rights=$(/bin/stat --format '%A' "$path")
325+
if test "$rights" != "$expected_rights" ; then
326+
die "Unexpected access rights of $path: $expected_rights vs. $rights"
327+
fi
328+
}
329+
330+
# check_sysfs_value(modname, rel_path, expected_value) - check sysfs value
331+
# modname - livepatch module creating the sysfs interface
332+
# rel_path - relative path of the sysfs interface
333+
# expected_value - expected value read from the file
334+
function check_sysfs_value() {
335+
local mod="$1"; shift
336+
local rel_path="$1"; shift
337+
local expected_value="$1"; shift
338+
339+
local path="$KLP_SYSFS_DIR/$mod/$rel_path"
340+
local value=`cat $path`
341+
if test "$value" != "$expected_value" ; then
342+
die "Unexpected value in $path: $expected_value vs. $value"
343+
fi
344+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
#!/bin/bash
2+
# SPDX-License-Identifier: GPL-2.0
3+
# Copyright (C) 2022 Song Liu <[email protected]>
4+
5+
. $(dirname $0)/functions.sh
6+
7+
MOD_LIVEPATCH=test_klp_livepatch
8+
9+
setup_config
10+
11+
# - load a livepatch and verifies the sysfs entries work as expected
12+
13+
start_test "sysfs test"
14+
15+
load_lp $MOD_LIVEPATCH
16+
17+
check_sysfs_rights "$MOD_LIVEPATCH" "" "drwxr-xr-x"
18+
check_sysfs_rights "$MOD_LIVEPATCH" "enabled" "-rw-r--r--"
19+
check_sysfs_value "$MOD_LIVEPATCH" "enabled" "1"
20+
check_sysfs_rights "$MOD_LIVEPATCH" "force" "--w-------"
21+
check_sysfs_rights "$MOD_LIVEPATCH" "transition" "-r--r--r--"
22+
check_sysfs_value "$MOD_LIVEPATCH" "transition" "0"
23+
check_sysfs_rights "$MOD_LIVEPATCH" "vmlinux/patched" "-r--r--r--"
24+
check_sysfs_value "$MOD_LIVEPATCH" "vmlinux/patched" "1"
25+
26+
disable_lp $MOD_LIVEPATCH
27+
28+
unload_lp $MOD_LIVEPATCH
29+
30+
check_result "% modprobe $MOD_LIVEPATCH
31+
livepatch: enabling patch '$MOD_LIVEPATCH'
32+
livepatch: '$MOD_LIVEPATCH': initializing patching transition
33+
livepatch: '$MOD_LIVEPATCH': starting patching transition
34+
livepatch: '$MOD_LIVEPATCH': completing patching transition
35+
livepatch: '$MOD_LIVEPATCH': patching complete
36+
% echo 0 > /sys/kernel/livepatch/$MOD_LIVEPATCH/enabled
37+
livepatch: '$MOD_LIVEPATCH': initializing unpatching transition
38+
livepatch: '$MOD_LIVEPATCH': starting unpatching transition
39+
livepatch: '$MOD_LIVEPATCH': completing unpatching transition
40+
livepatch: '$MOD_LIVEPATCH': unpatching complete
41+
% rmmod $MOD_LIVEPATCH"
42+
43+
start_test "sysfs test object/patched"
44+
45+
MOD_LIVEPATCH=test_klp_callbacks_demo
46+
MOD_TARGET=test_klp_callbacks_mod
47+
load_lp $MOD_LIVEPATCH
48+
49+
# check the "patch" file changes as target module loads/unloads
50+
check_sysfs_value "$MOD_LIVEPATCH" "$MOD_TARGET/patched" "0"
51+
load_mod $MOD_TARGET
52+
check_sysfs_value "$MOD_LIVEPATCH" "$MOD_TARGET/patched" "1"
53+
unload_mod $MOD_TARGET
54+
check_sysfs_value "$MOD_LIVEPATCH" "$MOD_TARGET/patched" "0"
55+
56+
disable_lp $MOD_LIVEPATCH
57+
unload_lp $MOD_LIVEPATCH
58+
59+
check_result "% modprobe test_klp_callbacks_demo
60+
livepatch: enabling patch 'test_klp_callbacks_demo'
61+
livepatch: 'test_klp_callbacks_demo': initializing patching transition
62+
test_klp_callbacks_demo: pre_patch_callback: vmlinux
63+
livepatch: 'test_klp_callbacks_demo': starting patching transition
64+
livepatch: 'test_klp_callbacks_demo': completing patching transition
65+
test_klp_callbacks_demo: post_patch_callback: vmlinux
66+
livepatch: 'test_klp_callbacks_demo': patching complete
67+
% modprobe test_klp_callbacks_mod
68+
livepatch: applying patch 'test_klp_callbacks_demo' to loading module 'test_klp_callbacks_mod'
69+
test_klp_callbacks_demo: pre_patch_callback: test_klp_callbacks_mod -> [MODULE_STATE_COMING] Full formed, running module_init
70+
test_klp_callbacks_demo: post_patch_callback: test_klp_callbacks_mod -> [MODULE_STATE_COMING] Full formed, running module_init
71+
test_klp_callbacks_mod: test_klp_callbacks_mod_init
72+
% rmmod test_klp_callbacks_mod
73+
test_klp_callbacks_mod: test_klp_callbacks_mod_exit
74+
test_klp_callbacks_demo: pre_unpatch_callback: test_klp_callbacks_mod -> [MODULE_STATE_GOING] Going away
75+
livepatch: reverting patch 'test_klp_callbacks_demo' on unloading module 'test_klp_callbacks_mod'
76+
test_klp_callbacks_demo: post_unpatch_callback: test_klp_callbacks_mod -> [MODULE_STATE_GOING] Going away
77+
% echo 0 > /sys/kernel/livepatch/test_klp_callbacks_demo/enabled
78+
livepatch: 'test_klp_callbacks_demo': initializing unpatching transition
79+
test_klp_callbacks_demo: pre_unpatch_callback: vmlinux
80+
livepatch: 'test_klp_callbacks_demo': starting unpatching transition
81+
livepatch: 'test_klp_callbacks_demo': completing unpatching transition
82+
test_klp_callbacks_demo: post_unpatch_callback: vmlinux
83+
livepatch: 'test_klp_callbacks_demo': unpatching complete
84+
% rmmod test_klp_callbacks_demo"
85+
86+
exit 0

0 commit comments

Comments
 (0)