Skip to content

Commit

Permalink
[new] livepatch/selftests: add klp-convert
Browse files Browse the repository at this point in the history
Add a simple klp-convert livepatch selftest that exercises various
symbol homonym sympos scenarios.

Signed-off-by: Joe Lawrence <joe.lawrence@redhat.com>
  • Loading branch information
joe-lawrence committed Mar 18, 2019
1 parent 33aff6e commit b0d858b
Show file tree
Hide file tree
Showing 6 changed files with 321 additions and 0 deletions.
10 changes: 10 additions & 0 deletions lib/livepatch/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,26 @@
LIVEPATCH_test_klp_atomic_replace.o := y
LIVEPATCH_test_klp_callbacks_demo.o := y
LIVEPATCH_test_klp_callbacks_demo2.o := y
LIVEPATCH_test_klp_convert1.o := y
LIVEPATCH_test_klp_convert2.o := y
LIVEPATCH_test_klp_livepatch.o := y

obj-$(CONFIG_TEST_LIVEPATCH) += test_klp_atomic_replace.o \
test_klp_callbacks_demo.o \
test_klp_callbacks_demo2.o \
test_klp_callbacks_busy.o \
test_klp_callbacks_mod.o \
test_klp_convert1.o \
test_klp_convert2.o \
test_klp_convert_mod.o \
test_klp_livepatch.o \
test_klp_shadow_vars.o

test_klp_convert_mod-y := \
test_klp_convert_mod_a.o \
test_klp_convert_mod_b.o

# Target modules to be livepatched require CC_FLAGS_FTRACE
CFLAGS_test_klp_callbacks_busy.o += $(CC_FLAGS_FTRACE)
CFLAGS_test_klp_callbacks_mod.o += $(CC_FLAGS_FTRACE)
CFLAGS_test_klp_convert_mod.o += $(CC_FLAGS_FTRACE)
106 changes: 106 additions & 0 deletions lib/livepatch/test_klp_convert1.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
// SPDX-License-Identifier: GPL-2.0
// Copyright (C) 2019 Joe Lawrence <joe.lawrence@redhat.com>

#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/livepatch.h>

/* klp-convert symbols - vmlinux */
extern char *saved_command_line;
/* klp-convert symbols - test_klp_convert_mod.ko */
extern char driver_name[];
extern char homonym_string[];
extern const char *get_homonym_string(void);
extern const char *get_driver_name(void);

void print_saved_command_line(void)
{
pr_info("saved_command_line, 0: %s\n", saved_command_line);
}

void print_driver_name(void)
{
pr_info("driver_name, 0: %s\n", driver_name);
pr_info("get_driver_name(), 0: %s\n", get_driver_name());
}

void print_homonym_string(void)
{
pr_info("homonym_string, 1: %s\n", homonym_string);
pr_info("get_homonym_string(), 1: %s\n", get_homonym_string());
}

/*
* saved_command_line is a unique symbol, so the sympos annotation is
* optional. Provide to test that sympos=0 works correctly.
*/
KLP_MODULE_RELOC(vmlinux) vmlinux_relocs[] = {
KLP_SYMPOS(saved_command_line, 0)
};

/*
* driver_name symbols can be found in vmlinux (multiple) and also
* test_klp_convert_mod, therefore the annotation is required to
* clarify that we want the one from test_klp_convert_mod.
*
* test_klp_convert_mod contains multiple homonym_string and
* get_homonym_string symbols, test resolving the first set here and
* the others in test_klp_convert2.c
*
* get_driver_name is a uniquely named symbol, test that sympos=0
* work correctly.
*/
KLP_MODULE_RELOC(test_klp_convert_mod) test_klp_convert_mod_relocs_a[] = {
KLP_SYMPOS(driver_name, 0)
KLP_SYMPOS(homonym_string, 1)
KLP_SYMPOS(get_homonym_string, 1)
KLP_SYMPOS(get_driver_name, 0)
};

static struct klp_func funcs[] = {
{
}, { }
};

static struct klp_object objs[] = {
{
/* name being NULL means vmlinux */
.funcs = funcs,
},
{
.name = "test_klp_convert_mod",
.funcs = funcs,
}, { }
};

static struct klp_patch patch = {
.mod = THIS_MODULE,
.objs = objs,
};

static int test_klp_convert_init(void)
{
int ret;

ret = klp_enable_patch(&patch);
if (ret)
return ret;

print_saved_command_line();
print_driver_name();
print_homonym_string();

return 0;
}

static void test_klp_convert_exit(void)
{
}

module_init(test_klp_convert_init);
module_exit(test_klp_convert_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Joe Lawrence <joe.lawrence@redhat.com>");
MODULE_DESCRIPTION("Livepatch test: klp-convert1");
103 changes: 103 additions & 0 deletions lib/livepatch/test_klp_convert2.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
// SPDX-License-Identifier: GPL-2.0
// Copyright (C) 2019 Joe Lawrence <joe.lawrence@redhat.com>

#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/livepatch.h>

/* klp-convert symbols - vmlinux */
extern char *saved_command_line;
/* klp-convert symbols - test_klp_convert_mod.ko */
extern char driver_name[];
extern char homonym_string[];
extern const char *get_homonym_string(void);
extern const char *get_driver_name(void);

void print_saved_command_line(void)
{
pr_info("saved_command_line (auto): %s\n", saved_command_line);
}

void print_driver_name(void)
{
pr_info("driver_name, 0: %s\n", driver_name);
pr_info("get_driver_name(), (auto): %s\n", get_driver_name());
}

void print_homonym_string(void)
{
pr_info("homonym_string, 2: %s\n", homonym_string);
pr_info("get_homonym_string(), 2: %s\n", get_homonym_string());
}

/*
* saved_command_line is a uniquely named symbol, so the sympos
* annotation is optional. Skip it and test that klp-convert can
* resolve the symbol on its own.
*/

/*
* driver_name symbols can be found in vmlinux (multiple) and also
* test_klp_convert_mod, therefore the annotation is required to
* clarify that we want the one from test_klp_convert_mod.
*
* test_klp_convert_mod contains multiple homonym_string symbols,
* test_klp_convert1.c resolved to the first one, resolve to the
* second one here.
*
* get_driver_name is a uniquely named symbol, test klp-convert can
* resolve it automatically.
*/
KLP_MODULE_RELOC(test_klp_convert_mod) test_klp_convert_mod_relocs_a[] = {
KLP_SYMPOS(driver_name, 0)
KLP_SYMPOS(homonym_string, 2)
KLP_SYMPOS(get_homonym_string, 2)
};

static struct klp_func funcs[] = {
{
}, { }
};

static struct klp_object objs[] = {
{
/* name being NULL means vmlinux */
.funcs = funcs,
},
{
.name = "test_klp_convert_mod",
.funcs = funcs,
}, { }
};

static struct klp_patch patch = {
.mod = THIS_MODULE,
.objs = objs,
};

static int test_klp_convert_init(void)
{
int ret;

ret = klp_enable_patch(&patch);
if (ret)
return ret;

print_saved_command_line();
print_driver_name();
print_homonym_string();

return 0;
}

static void test_klp_convert_exit(void)
{
}

module_init(test_klp_convert_init);
module_exit(test_klp_convert_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Joe Lawrence <joe.lawrence@redhat.com>");
MODULE_DESCRIPTION("Livepatch test: klp-convert2");
25 changes: 25 additions & 0 deletions lib/livepatch/test_klp_convert_mod_a.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// SPDX-License-Identifier: GPL-2.0
// Copyright (C) 2019 Joe Lawrence <joe.lawrence@redhat.com>

#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt

#include <linux/module.h>
#include <linux/kernel.h>

/* Unique symbols that don't need sympos annotation */
static const char driver_name[] = KBUILD_MODNAME;
__used static const char *get_driver_name(void)
{
return driver_name;
}

/* Common symbol names that need sympos */
static const char homonym_string[] = "homonym string A";
__used static const char *get_homonym_string(void)
{
return homonym_string;
}

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Joe Lawrence <joe.lawrence@redhat.com>");
MODULE_DESCRIPTION("Livepatch test: klp-convert module");
13 changes: 13 additions & 0 deletions lib/livepatch/test_klp_convert_mod_b.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// SPDX-License-Identifier: GPL-2.0
// Copyright (C) 2019 Joe Lawrence <joe.lawrence@redhat.com>

/*
* A second compilation unit to provide another set of similarly named
* symbols, forcing a livepatch to use sympos annotations.
*/

static char homonym_string[] = "homonym string B";
__used static char *get_homonym_string(void)
{
return homonym_string;
}
64 changes: 64 additions & 0 deletions tools/testing/selftests/livepatch/test-livepatch.sh
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@

MOD_LIVEPATCH=test_klp_livepatch
MOD_REPLACE=test_klp_atomic_replace
MOD_KLP_CONVERT_MOD=test_klp_convert_mod
MOD_KLP_CONVERT1=test_klp_convert1
MOD_KLP_CONVERT2=test_klp_convert2

set_dynamic_debug

Expand Down Expand Up @@ -165,4 +168,65 @@ livepatch: '$MOD_REPLACE': unpatching complete
% rmmod $MOD_REPLACE"


# TEST: klp-convert symbols
# - load a livepatch that modifies the output from /proc/cmdline
# including a reference to vmlinux-local symbol that klp-convert
# will process
# - verify correct behavior
# - unload the livepatch and make sure the patch was removed

echo -n "TEST: klp-convert symbols ... "
dmesg -C

saved_cmdline=$(cat /proc/cmdline)

load_mod $MOD_KLP_CONVERT_MOD

load_lp $MOD_KLP_CONVERT1
disable_lp $MOD_KLP_CONVERT1
unload_lp $MOD_KLP_CONVERT1

load_lp $MOD_KLP_CONVERT2
disable_lp $MOD_KLP_CONVERT2
unload_lp $MOD_KLP_CONVERT2

unload_mod $MOD_KLP_CONVERT_MOD

check_result "% modprobe $MOD_KLP_CONVERT_MOD
% modprobe $MOD_KLP_CONVERT1
livepatch: enabling patch '$MOD_KLP_CONVERT1'
livepatch: '$MOD_KLP_CONVERT1': initializing patching transition
livepatch: '$MOD_KLP_CONVERT1': starting patching transition
$MOD_KLP_CONVERT1: saved_command_line, 0: $saved_cmdline
$MOD_KLP_CONVERT1: driver_name, 0: $MOD_KLP_CONVERT_MOD
$MOD_KLP_CONVERT1: get_driver_name(), 0: $MOD_KLP_CONVERT_MOD
$MOD_KLP_CONVERT1: homonym_string, 1: homonym string A
$MOD_KLP_CONVERT1: get_homonym_string(), 1: homonym string A
livepatch: '$MOD_KLP_CONVERT1': completing patching transition
livepatch: '$MOD_KLP_CONVERT1': patching complete
% echo 0 > /sys/kernel/livepatch/$MOD_KLP_CONVERT1/enabled
livepatch: '$MOD_KLP_CONVERT1': initializing unpatching transition
livepatch: '$MOD_KLP_CONVERT1': starting unpatching transition
livepatch: '$MOD_KLP_CONVERT1': completing unpatching transition
livepatch: '$MOD_KLP_CONVERT1': unpatching complete
% rmmod $MOD_KLP_CONVERT1
% modprobe $MOD_KLP_CONVERT2
livepatch: enabling patch '$MOD_KLP_CONVERT2'
livepatch: '$MOD_KLP_CONVERT2': initializing patching transition
livepatch: '$MOD_KLP_CONVERT2': starting patching transition
$MOD_KLP_CONVERT2: saved_command_line (auto): $saved_cmdline
$MOD_KLP_CONVERT2: driver_name, 0: $MOD_KLP_CONVERT_MOD
$MOD_KLP_CONVERT2: get_driver_name(), (auto): $MOD_KLP_CONVERT_MOD
$MOD_KLP_CONVERT2: homonym_string, 2: homonym string B
$MOD_KLP_CONVERT2: get_homonym_string(), 2: homonym string B
livepatch: '$MOD_KLP_CONVERT2': completing patching transition
livepatch: '$MOD_KLP_CONVERT2': patching complete
% echo 0 > /sys/kernel/livepatch/$MOD_KLP_CONVERT2/enabled
livepatch: '$MOD_KLP_CONVERT2': initializing unpatching transition
livepatch: '$MOD_KLP_CONVERT2': starting unpatching transition
livepatch: '$MOD_KLP_CONVERT2': completing unpatching transition
livepatch: '$MOD_KLP_CONVERT2': unpatching complete
% rmmod $MOD_KLP_CONVERT2
% rmmod $MOD_KLP_CONVERT_MOD"

exit 0

0 comments on commit b0d858b

Please sign in to comment.