Skip to content

Commit d2d721e

Browse files
committed
Merge tag 'livepatching-for-6.11' of git://git.kernel.org/pub/scm/linux/kernel/git/livepatching/livepatching
Pull livepatching update from Petr Mladek: - show patch->replace flag in sysfs - add or improve few selftests * tag 'livepatching-for-6.11' of git://git.kernel.org/pub/scm/linux/kernel/git/livepatching/livepatching: livepatch: Replace snprintf() with sysfs_emit() selftests/livepatch: Add selftests for "replace" sysfs attribute livepatch: Add "replace" sysfs attribute selftests: livepatch: Test atomic replace against multiple modules selftests/livepatch: define max test-syscall processes
2 parents 28bbe4e + ea5377e commit d2d721e

File tree

5 files changed

+163
-53
lines changed

5 files changed

+163
-53
lines changed

Documentation/ABI/testing/sysfs-kernel-livepatch

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,14 @@ Description:
4747
disabled when the feature is used. See
4848
Documentation/livepatch/livepatch.rst for more information.
4949

50+
What: /sys/kernel/livepatch/<patch>/replace
51+
Date: Jun 2024
52+
KernelVersion: 6.11.0
53+
Contact: live-patching@vger.kernel.org
54+
Description:
55+
An attribute which indicates whether the patch supports
56+
atomic-replace.
57+
5058
What: /sys/kernel/livepatch/<patch>/<object>
5159
Date: Nov 2014
5260
KernelVersion: 3.19.0

kernel/livepatch/core.c

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -346,6 +346,7 @@ int klp_apply_section_relocs(struct module *pmod, Elf_Shdr *sechdrs,
346346
* /sys/kernel/livepatch/<patch>/enabled
347347
* /sys/kernel/livepatch/<patch>/transition
348348
* /sys/kernel/livepatch/<patch>/force
349+
* /sys/kernel/livepatch/<patch>/replace
349350
* /sys/kernel/livepatch/<patch>/<object>
350351
* /sys/kernel/livepatch/<patch>/<object>/patched
351352
* /sys/kernel/livepatch/<patch>/<object>/<function,sympos>
@@ -401,7 +402,7 @@ static ssize_t enabled_show(struct kobject *kobj,
401402
struct klp_patch *patch;
402403

403404
patch = container_of(kobj, struct klp_patch, kobj);
404-
return snprintf(buf, PAGE_SIZE-1, "%d\n", patch->enabled);
405+
return sysfs_emit(buf, "%d\n", patch->enabled);
405406
}
406407

407408
static ssize_t transition_show(struct kobject *kobj,
@@ -410,8 +411,7 @@ static ssize_t transition_show(struct kobject *kobj,
410411
struct klp_patch *patch;
411412

412413
patch = container_of(kobj, struct klp_patch, kobj);
413-
return snprintf(buf, PAGE_SIZE-1, "%d\n",
414-
patch == klp_transition_patch);
414+
return sysfs_emit(buf, "%d\n", patch == klp_transition_patch);
415415
}
416416

417417
static ssize_t force_store(struct kobject *kobj, struct kobj_attribute *attr,
@@ -443,13 +443,24 @@ static ssize_t force_store(struct kobject *kobj, struct kobj_attribute *attr,
443443
return count;
444444
}
445445

446+
static ssize_t replace_show(struct kobject *kobj,
447+
struct kobj_attribute *attr, char *buf)
448+
{
449+
struct klp_patch *patch;
450+
451+
patch = container_of(kobj, struct klp_patch, kobj);
452+
return sysfs_emit(buf, "%d\n", patch->replace);
453+
}
454+
446455
static struct kobj_attribute enabled_kobj_attr = __ATTR_RW(enabled);
447456
static struct kobj_attribute transition_kobj_attr = __ATTR_RO(transition);
448457
static struct kobj_attribute force_kobj_attr = __ATTR_WO(force);
458+
static struct kobj_attribute replace_kobj_attr = __ATTR_RO(replace);
449459
static struct attribute *klp_patch_attrs[] = {
450460
&enabled_kobj_attr.attr,
451461
&transition_kobj_attr.attr,
452462
&force_kobj_attr.attr,
463+
&replace_kobj_attr.attr,
453464
NULL
454465
};
455466
ATTRIBUTE_GROUPS(klp_patch);

tools/testing/selftests/livepatch/test-livepatch.sh

Lines changed: 89 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@
44

55
. $(dirname $0)/functions.sh
66

7-
MOD_LIVEPATCH=test_klp_livepatch
7+
MOD_LIVEPATCH1=test_klp_livepatch
8+
MOD_LIVEPATCH2=test_klp_syscall
9+
MOD_LIVEPATCH3=test_klp_callbacks_demo
810
MOD_REPLACE=test_klp_atomic_replace
911

1012
setup_config
@@ -16,33 +18,33 @@ setup_config
1618

1719
start_test "basic function patching"
1820

19-
load_lp $MOD_LIVEPATCH
21+
load_lp $MOD_LIVEPATCH1
2022

21-
if [[ "$(cat /proc/cmdline)" != "$MOD_LIVEPATCH: this has been live patched" ]] ; then
23+
if [[ "$(cat /proc/cmdline)" != "$MOD_LIVEPATCH1: this has been live patched" ]] ; then
2224
echo -e "FAIL\n\n"
2325
die "livepatch kselftest(s) failed"
2426
fi
2527

26-
disable_lp $MOD_LIVEPATCH
27-
unload_lp $MOD_LIVEPATCH
28+
disable_lp $MOD_LIVEPATCH1
29+
unload_lp $MOD_LIVEPATCH1
2830

29-
if [[ "$(cat /proc/cmdline)" == "$MOD_LIVEPATCH: this has been live patched" ]] ; then
31+
if [[ "$(cat /proc/cmdline)" == "$MOD_LIVEPATCH1: this has been live patched" ]] ; then
3032
echo -e "FAIL\n\n"
3133
die "livepatch kselftest(s) failed"
3234
fi
3335

34-
check_result "% insmod test_modules/$MOD_LIVEPATCH.ko
35-
livepatch: enabling patch '$MOD_LIVEPATCH'
36-
livepatch: '$MOD_LIVEPATCH': initializing patching transition
37-
livepatch: '$MOD_LIVEPATCH': starting patching transition
38-
livepatch: '$MOD_LIVEPATCH': completing patching transition
39-
livepatch: '$MOD_LIVEPATCH': patching complete
40-
% echo 0 > /sys/kernel/livepatch/$MOD_LIVEPATCH/enabled
41-
livepatch: '$MOD_LIVEPATCH': initializing unpatching transition
42-
livepatch: '$MOD_LIVEPATCH': starting unpatching transition
43-
livepatch: '$MOD_LIVEPATCH': completing unpatching transition
44-
livepatch: '$MOD_LIVEPATCH': unpatching complete
45-
% rmmod $MOD_LIVEPATCH"
36+
check_result "% insmod test_modules/$MOD_LIVEPATCH1.ko
37+
livepatch: enabling patch '$MOD_LIVEPATCH1'
38+
livepatch: '$MOD_LIVEPATCH1': initializing patching transition
39+
livepatch: '$MOD_LIVEPATCH1': starting patching transition
40+
livepatch: '$MOD_LIVEPATCH1': completing patching transition
41+
livepatch: '$MOD_LIVEPATCH1': patching complete
42+
% echo 0 > /sys/kernel/livepatch/$MOD_LIVEPATCH1/enabled
43+
livepatch: '$MOD_LIVEPATCH1': initializing unpatching transition
44+
livepatch: '$MOD_LIVEPATCH1': starting unpatching transition
45+
livepatch: '$MOD_LIVEPATCH1': completing unpatching transition
46+
livepatch: '$MOD_LIVEPATCH1': unpatching complete
47+
% rmmod $MOD_LIVEPATCH1"
4648

4749

4850
# - load a livepatch that modifies the output from /proc/cmdline and
@@ -53,7 +55,7 @@ livepatch: '$MOD_LIVEPATCH': unpatching complete
5355

5456
start_test "multiple livepatches"
5557

56-
load_lp $MOD_LIVEPATCH
58+
load_lp $MOD_LIVEPATCH1
5759

5860
grep 'live patched' /proc/cmdline > /dev/kmsg
5961
grep 'live patched' /proc/meminfo > /dev/kmsg
@@ -69,62 +71,84 @@ unload_lp $MOD_REPLACE
6971
grep 'live patched' /proc/cmdline > /dev/kmsg
7072
grep 'live patched' /proc/meminfo > /dev/kmsg
7173

72-
disable_lp $MOD_LIVEPATCH
73-
unload_lp $MOD_LIVEPATCH
74+
disable_lp $MOD_LIVEPATCH1
75+
unload_lp $MOD_LIVEPATCH1
7476

7577
grep 'live patched' /proc/cmdline > /dev/kmsg
7678
grep 'live patched' /proc/meminfo > /dev/kmsg
7779

78-
check_result "% insmod test_modules/$MOD_LIVEPATCH.ko
79-
livepatch: enabling patch '$MOD_LIVEPATCH'
80-
livepatch: '$MOD_LIVEPATCH': initializing patching transition
81-
livepatch: '$MOD_LIVEPATCH': starting patching transition
82-
livepatch: '$MOD_LIVEPATCH': completing patching transition
83-
livepatch: '$MOD_LIVEPATCH': patching complete
84-
$MOD_LIVEPATCH: this has been live patched
80+
check_result "% insmod test_modules/$MOD_LIVEPATCH1.ko
81+
livepatch: enabling patch '$MOD_LIVEPATCH1'
82+
livepatch: '$MOD_LIVEPATCH1': initializing patching transition
83+
livepatch: '$MOD_LIVEPATCH1': starting patching transition
84+
livepatch: '$MOD_LIVEPATCH1': completing patching transition
85+
livepatch: '$MOD_LIVEPATCH1': patching complete
86+
$MOD_LIVEPATCH1: this has been live patched
8587
% insmod test_modules/$MOD_REPLACE.ko replace=0
8688
livepatch: enabling patch '$MOD_REPLACE'
8789
livepatch: '$MOD_REPLACE': initializing patching transition
8890
livepatch: '$MOD_REPLACE': starting patching transition
8991
livepatch: '$MOD_REPLACE': completing patching transition
9092
livepatch: '$MOD_REPLACE': patching complete
91-
$MOD_LIVEPATCH: this has been live patched
93+
$MOD_LIVEPATCH1: this has been live patched
9294
$MOD_REPLACE: this has been live patched
9395
% echo 0 > /sys/kernel/livepatch/$MOD_REPLACE/enabled
9496
livepatch: '$MOD_REPLACE': initializing unpatching transition
9597
livepatch: '$MOD_REPLACE': starting unpatching transition
9698
livepatch: '$MOD_REPLACE': completing unpatching transition
9799
livepatch: '$MOD_REPLACE': unpatching complete
98100
% rmmod $MOD_REPLACE
99-
$MOD_LIVEPATCH: this has been live patched
100-
% echo 0 > /sys/kernel/livepatch/$MOD_LIVEPATCH/enabled
101-
livepatch: '$MOD_LIVEPATCH': initializing unpatching transition
102-
livepatch: '$MOD_LIVEPATCH': starting unpatching transition
103-
livepatch: '$MOD_LIVEPATCH': completing unpatching transition
104-
livepatch: '$MOD_LIVEPATCH': unpatching complete
105-
% rmmod $MOD_LIVEPATCH"
101+
$MOD_LIVEPATCH1: this has been live patched
102+
% echo 0 > /sys/kernel/livepatch/$MOD_LIVEPATCH1/enabled
103+
livepatch: '$MOD_LIVEPATCH1': initializing unpatching transition
104+
livepatch: '$MOD_LIVEPATCH1': starting unpatching transition
105+
livepatch: '$MOD_LIVEPATCH1': completing unpatching transition
106+
livepatch: '$MOD_LIVEPATCH1': unpatching complete
107+
% rmmod $MOD_LIVEPATCH1"
106108

107109

108110
# - load a livepatch that modifies the output from /proc/cmdline and
109111
# verify correct behavior
110-
# - load an atomic replace livepatch and verify that only the second is active
111-
# - remove the first livepatch and verify that the atomic replace livepatch
112-
# is still active
112+
# - load two additional livepatches and check the number of livepatch modules
113+
# applied
114+
# - load an atomic replace livepatch and check that the other three modules were
115+
# disabled
116+
# - remove all livepatches besides the atomic replace one and verify that the
117+
# atomic replace livepatch is still active
113118
# - remove the atomic replace livepatch and verify that none are active
114119

115120
start_test "atomic replace livepatch"
116121

117-
load_lp $MOD_LIVEPATCH
122+
load_lp $MOD_LIVEPATCH1
118123

119124
grep 'live patched' /proc/cmdline > /dev/kmsg
120125
grep 'live patched' /proc/meminfo > /dev/kmsg
121126

127+
for mod in $MOD_LIVEPATCH2 $MOD_LIVEPATCH3; do
128+
load_lp "$mod"
129+
done
130+
131+
mods=(/sys/kernel/livepatch/*)
132+
nmods=${#mods[@]}
133+
if [ "$nmods" -ne 3 ]; then
134+
die "Expecting three modules listed, found $nmods"
135+
fi
136+
122137
load_lp $MOD_REPLACE replace=1
123138

124139
grep 'live patched' /proc/cmdline > /dev/kmsg
125140
grep 'live patched' /proc/meminfo > /dev/kmsg
126141

127-
unload_lp $MOD_LIVEPATCH
142+
mods=(/sys/kernel/livepatch/*)
143+
nmods=${#mods[@]}
144+
if [ "$nmods" -ne 1 ]; then
145+
die "Expecting only one moduled listed, found $nmods"
146+
fi
147+
148+
# These modules were disabled by the atomic replace
149+
for mod in $MOD_LIVEPATCH3 $MOD_LIVEPATCH2 $MOD_LIVEPATCH1; do
150+
unload_lp "$mod"
151+
done
128152

129153
grep 'live patched' /proc/cmdline > /dev/kmsg
130154
grep 'live patched' /proc/meminfo > /dev/kmsg
@@ -135,21 +159,37 @@ unload_lp $MOD_REPLACE
135159
grep 'live patched' /proc/cmdline > /dev/kmsg
136160
grep 'live patched' /proc/meminfo > /dev/kmsg
137161

138-
check_result "% insmod test_modules/$MOD_LIVEPATCH.ko
139-
livepatch: enabling patch '$MOD_LIVEPATCH'
140-
livepatch: '$MOD_LIVEPATCH': initializing patching transition
141-
livepatch: '$MOD_LIVEPATCH': starting patching transition
142-
livepatch: '$MOD_LIVEPATCH': completing patching transition
143-
livepatch: '$MOD_LIVEPATCH': patching complete
144-
$MOD_LIVEPATCH: this has been live patched
162+
check_result "% insmod test_modules/$MOD_LIVEPATCH1.ko
163+
livepatch: enabling patch '$MOD_LIVEPATCH1'
164+
livepatch: '$MOD_LIVEPATCH1': initializing patching transition
165+
livepatch: '$MOD_LIVEPATCH1': starting patching transition
166+
livepatch: '$MOD_LIVEPATCH1': completing patching transition
167+
livepatch: '$MOD_LIVEPATCH1': patching complete
168+
$MOD_LIVEPATCH1: this has been live patched
169+
% insmod test_modules/$MOD_LIVEPATCH2.ko
170+
livepatch: enabling patch '$MOD_LIVEPATCH2'
171+
livepatch: '$MOD_LIVEPATCH2': initializing patching transition
172+
livepatch: '$MOD_LIVEPATCH2': starting patching transition
173+
livepatch: '$MOD_LIVEPATCH2': completing patching transition
174+
livepatch: '$MOD_LIVEPATCH2': patching complete
175+
% insmod test_modules/$MOD_LIVEPATCH3.ko
176+
livepatch: enabling patch '$MOD_LIVEPATCH3'
177+
livepatch: '$MOD_LIVEPATCH3': initializing patching transition
178+
$MOD_LIVEPATCH3: pre_patch_callback: vmlinux
179+
livepatch: '$MOD_LIVEPATCH3': starting patching transition
180+
livepatch: '$MOD_LIVEPATCH3': completing patching transition
181+
$MOD_LIVEPATCH3: post_patch_callback: vmlinux
182+
livepatch: '$MOD_LIVEPATCH3': patching complete
145183
% insmod test_modules/$MOD_REPLACE.ko replace=1
146184
livepatch: enabling patch '$MOD_REPLACE'
147185
livepatch: '$MOD_REPLACE': initializing patching transition
148186
livepatch: '$MOD_REPLACE': starting patching transition
149187
livepatch: '$MOD_REPLACE': completing patching transition
150188
livepatch: '$MOD_REPLACE': patching complete
151189
$MOD_REPLACE: this has been live patched
152-
% rmmod $MOD_LIVEPATCH
190+
% rmmod $MOD_LIVEPATCH3
191+
% rmmod $MOD_LIVEPATCH2
192+
% rmmod $MOD_LIVEPATCH1
153193
$MOD_REPLACE: this has been live patched
154194
% echo 0 > /sys/kernel/livepatch/$MOD_REPLACE/enabled
155195
livepatch: '$MOD_REPLACE': initializing unpatching transition

tools/testing/selftests/livepatch/test-syscall.sh

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,10 @@ setup_config
1515

1616
start_test "patch getpid syscall while being heavily hammered"
1717

18-
for i in $(seq 1 $(getconf _NPROCESSORS_ONLN)); do
18+
NPROC=$(getconf _NPROCESSORS_ONLN)
19+
MAXPROC=128
20+
21+
for i in $(seq 1 $(($NPROC < $MAXPROC ? $NPROC : $MAXPROC))); do
1922
./test_klp-call_getpid &
2023
pids[$i]="$!"
2124
done

tools/testing/selftests/livepatch/test-sysfs.sh

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ check_sysfs_rights "$MOD_LIVEPATCH" "" "drwxr-xr-x"
1818
check_sysfs_rights "$MOD_LIVEPATCH" "enabled" "-rw-r--r--"
1919
check_sysfs_value "$MOD_LIVEPATCH" "enabled" "1"
2020
check_sysfs_rights "$MOD_LIVEPATCH" "force" "--w-------"
21+
check_sysfs_rights "$MOD_LIVEPATCH" "replace" "-r--r--r--"
2122
check_sysfs_rights "$MOD_LIVEPATCH" "transition" "-r--r--r--"
2223
check_sysfs_value "$MOD_LIVEPATCH" "transition" "0"
2324
check_sysfs_rights "$MOD_LIVEPATCH" "vmlinux/patched" "-r--r--r--"
@@ -83,4 +84,51 @@ test_klp_callbacks_demo: post_unpatch_callback: vmlinux
8384
livepatch: 'test_klp_callbacks_demo': unpatching complete
8485
% rmmod test_klp_callbacks_demo"
8586

87+
start_test "sysfs test replace enabled"
88+
89+
MOD_LIVEPATCH=test_klp_atomic_replace
90+
load_lp $MOD_LIVEPATCH replace=1
91+
92+
check_sysfs_rights "$MOD_LIVEPATCH" "replace" "-r--r--r--"
93+
check_sysfs_value "$MOD_LIVEPATCH" "replace" "1"
94+
95+
disable_lp $MOD_LIVEPATCH
96+
unload_lp $MOD_LIVEPATCH
97+
98+
check_result "% insmod test_modules/$MOD_LIVEPATCH.ko replace=1
99+
livepatch: enabling patch '$MOD_LIVEPATCH'
100+
livepatch: '$MOD_LIVEPATCH': initializing patching transition
101+
livepatch: '$MOD_LIVEPATCH': starting patching transition
102+
livepatch: '$MOD_LIVEPATCH': completing patching transition
103+
livepatch: '$MOD_LIVEPATCH': patching complete
104+
% echo 0 > /sys/kernel/livepatch/$MOD_LIVEPATCH/enabled
105+
livepatch: '$MOD_LIVEPATCH': initializing unpatching transition
106+
livepatch: '$MOD_LIVEPATCH': starting unpatching transition
107+
livepatch: '$MOD_LIVEPATCH': completing unpatching transition
108+
livepatch: '$MOD_LIVEPATCH': unpatching complete
109+
% rmmod $MOD_LIVEPATCH"
110+
111+
start_test "sysfs test replace disabled"
112+
113+
load_lp $MOD_LIVEPATCH replace=0
114+
115+
check_sysfs_rights "$MOD_LIVEPATCH" "replace" "-r--r--r--"
116+
check_sysfs_value "$MOD_LIVEPATCH" "replace" "0"
117+
118+
disable_lp $MOD_LIVEPATCH
119+
unload_lp $MOD_LIVEPATCH
120+
121+
check_result "% insmod test_modules/$MOD_LIVEPATCH.ko replace=0
122+
livepatch: enabling patch '$MOD_LIVEPATCH'
123+
livepatch: '$MOD_LIVEPATCH': initializing patching transition
124+
livepatch: '$MOD_LIVEPATCH': starting patching transition
125+
livepatch: '$MOD_LIVEPATCH': completing patching transition
126+
livepatch: '$MOD_LIVEPATCH': patching complete
127+
% echo 0 > /sys/kernel/livepatch/$MOD_LIVEPATCH/enabled
128+
livepatch: '$MOD_LIVEPATCH': initializing unpatching transition
129+
livepatch: '$MOD_LIVEPATCH': starting unpatching transition
130+
livepatch: '$MOD_LIVEPATCH': completing unpatching transition
131+
livepatch: '$MOD_LIVEPATCH': unpatching complete
132+
% rmmod $MOD_LIVEPATCH"
133+
86134
exit 0

0 commit comments

Comments
 (0)