Skip to content
Permalink
Browse files
livepatch/selftests: add klp-convert
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 authored and intel-lab-lkp committed Feb 16, 2022
1 parent a5e79e0 commit ea5129d2a3f776835ce3721f966f72d39426188c
Show file tree
Hide file tree
Showing 7 changed files with 416 additions and 0 deletions.
@@ -7,8 +7,15 @@ obj-$(CONFIG_TEST_LIVEPATCH) += test_klp_atomic_replace.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_state.o \
test_klp_state2.o \
test_klp_state3.o

test_klp_convert_mod-y := \
test_klp_convert_mod_a.o \
test_klp_convert_mod_b.o
@@ -0,0 +1,14 @@
/* SPDX-License-Identifier: GPL-2.0 */

#ifndef _TEST_KLP_CONVERT_
#define _TEST_KLP_CONVERT_

/* 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 *test_klp_get_driver_name(void);

#endif
@@ -0,0 +1,113 @@
// 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>
#include "test_klp_convert.h"

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("test_klp_get_driver_name(), 0: %s\n", test_klp_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());
}

/* provide a sysfs handle to invoke debug functions */
static int print_debug;
static int print_debug_set(const char *val, const struct kernel_param *kp)
{
print_saved_command_line();
print_driver_name();
print_homonym_string();

return 0;
}
static const struct kernel_param_ops print_debug_ops = {
.set = print_debug_set,
.get = param_get_int,
};
module_param_cb(print_debug, &print_debug_ops, &print_debug, 0200);
MODULE_PARM_DESC(print_debug, "print klp-convert debugging info");

/*
* 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
*
* test_klp_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(test_klp_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;

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");
MODULE_INFO(livepatch, "Y");
@@ -0,0 +1,110 @@
// 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>
#include "test_klp_convert.h"

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("test_klp_get_driver_name(), (auto): %s\n", test_klp_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());
}

/* provide a sysfs handle to invoke debug functions */
static int print_debug;
static int print_debug_set(const char *val, const struct kernel_param *kp)
{
print_saved_command_line();
print_driver_name();
print_homonym_string();

return 0;
}
static const struct kernel_param_ops print_debug_ops = {
.set = print_debug_set,
.get = param_get_int,
};
module_param_cb(print_debug, &print_debug_ops, &print_debug, 0200);
MODULE_PARM_DESC(print_debug, "print klp-convert debugging info");

/*
* 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.
*
* test_klp_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;

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");
MODULE_INFO(livepatch, "Y");
@@ -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 *test_klp_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");
@@ -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 const char homonym_string[] = "homonym string B";
__used static const char *get_homonym_string(void)
{
return homonym_string;
}

0 comments on commit ea5129d

Please sign in to comment.