Unified · Split
| @@ -55,6 +55,14 @@ Description: · 54 unmodified lines | |||
| 55 | The object directory contains subdirectories for each function | 55 | The object directory contains subdirectories for each function |
| 56 | that is patched within the object. | 56 | that is patched within the object. |
| 57 | 57 | ||
| 58 | What: /sys/kernel/livepatch/<patch>/<object>/patched | ||
| 59 | Date: August 2022 | ||
| 60 | KernelVersion: 6.1.0 | ||
| 61 | Contact: live-patching@vger.kernel.org | ||
| 62 | Description: | ||
| 63 | An attribute which indicates whether the object is currently | ||
| 64 | patched. | ||
| 65 | |||
| 58 | What: /sys/kernel/livepatch/<patch>/<object>/<function,sympos> | 66 | What: /sys/kernel/livepatch/<patch>/<object>/<function,sympos> |
| 59 | Date: Nov 2014 | 67 | Date: Nov 2014 |
| 60 | KernelVersion: 3.19.0 | 68 | KernelVersion: 3.19.0 |
| @@ -325,6 +325,7 @@ int klp_apply_section_relocs(struct module *pmod, Elf_Shdr *sechdrs, · 324 unmodified lines | |||
| 325 | * /sys/kernel/livepatch/<patch>/transition | 325 | * /sys/kernel/livepatch/<patch>/transition |
| 326 | * /sys/kernel/livepatch/<patch>/force | 326 | * /sys/kernel/livepatch/<patch>/force |
| 327 | * /sys/kernel/livepatch/<patch>/<object> | 327 | * /sys/kernel/livepatch/<patch>/<object> |
| 328 | * /sys/kernel/livepatch/<patch>/<object>/patched | ||
| 328 | * /sys/kernel/livepatch/<patch>/<object>/<function,sympos> | 329 | * /sys/kernel/livepatch/<patch>/<object>/<function,sympos> |
| 329 | */ | 330 | */ |
| 330 | static int __klp_disable_patch(struct klp_patch *patch); | 331 | static int __klp_disable_patch(struct klp_patch *patch); |
| @@ -431,6 +432,22 @@ static struct attribute *klp_patch_attrs[] = { · 100 unmodified lines | |||
| 431 | }; | 432 | }; |
| 432 | ATTRIBUTE_GROUPS(klp_patch); | 433 | ATTRIBUTE_GROUPS(klp_patch); |
| 433 | 434 | ||
| 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 | |||
| 434 | static void klp_free_object_dynamic(struct klp_object *obj) | 451 | static void klp_free_object_dynamic(struct klp_object *obj) |
| 435 | { | 452 | { |
| 436 | kfree(obj->name); | 453 | kfree(obj->name); |
| @@ -576,6 +593,7 @@ static void klp_kobj_release_object(struct kobject *kobj) · 139 unmodified lines | |||
| 576 | static struct kobj_type klp_ktype_object = { | 593 | static struct kobj_type klp_ktype_object = { |
| 577 | .release = klp_kobj_release_object, | 594 | .release = klp_kobj_release_object, |
| 578 | .sysfs_ops = &kobj_sysfs_ops, | 595 | .sysfs_ops = &kobj_sysfs_ops, |
| 596 | .default_groups = klp_object_groups, | ||
| 579 | }; | 597 | }; |
| 580 | 598 | ||
| 581 | static void klp_kobj_release_func(struct kobject *kobj) | 599 | static void klp_kobj_release_func(struct kobject *kobj) |
| @@ -6,7 +6,8 @@ TEST_PROGS := \ · 5 unmodified lines | |||
| 6 | test-callbacks.sh \ | 6 | test-callbacks.sh \ |
| 7 | test-shadow-vars.sh \ | 7 | test-shadow-vars.sh \ |
| 8 | test-state.sh \ | 8 | test-state.sh \ |
| 9 | test-ftrace.sh | 9 | test-ftrace.sh \ |
| 10 | test-sysfs.sh | ||
| 10 | 11 | ||
| 11 | TEST_FILES := settings | 12 | TEST_FILES := settings |
| 12 | 13 | ||
| @@ -6,6 +6,7 @@ · 5 unmodified lines | |||
| 6 | 6 | ||
| 7 | MAX_RETRIES=600 | 7 | MAX_RETRIES=600 |
| 8 | RETRY_INTERVAL=".1" # seconds | 8 | RETRY_INTERVAL=".1" # seconds |
| 9 | KLP_SYSFS_DIR="/sys/kernel/livepatch" | ||
| 9 | 10 | ||
| 10 | # Kselftest framework requirement - SKIP code is 4 | 11 | # Kselftest framework requirement - SKIP code is 4 |
| 11 | ksft_skip=4 | 12 | ksft_skip=4 |
| @@ -308,3 +309,36 @@ function check_result { · 296 unmodified lines | |||
| 308 | 309 | ||
| 309 | cleanup_dmesg_file | 310 | cleanup_dmesg_file |
| 310 | } | 311 | } |
| 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 | } | ||
| @@ -0,0 +1,86 @@ | |||
| 1 | #!/bin/bash | ||
| 2 | # SPDX-License-Identifier: GPL-2.0 | ||
| 3 | # Copyright (C) 2022 Song Liu <song@kernel.org> | ||
| 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 | ||