[RFC PATCH 1/2] livepatch: implement patch versioning

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Add a simple livepatch versioning policy to the livepatch core.  For
those klp_patches with non-zero version, only load those with higher
versions than the livepatch core's latest-version.  Livepatches may opt
out of the policy altogether (i.e. patches always load and do not update
latest-version) by specifying klp_patch.version=0.

Signed-off-by: Joe Lawrence <joe.lawrence@xxxxxxxxxx>
---
 .../ABI/testing/sysfs-kernel-livepatch        |  14 ++
 Documentation/livepatch/versioning.txt        |  31 ++++
 include/linux/livepatch.h                     |   2 +
 kernel/livepatch/core.c                       |  55 ++++++
 kernel/livepatch/core.h                       |   1 +
 kernel/livepatch/transition.c                 |   6 +
 lib/livepatch/Makefile                        |   6 +-
 lib/livepatch/test_klp_version_0.c            |  34 ++++
 lib/livepatch/test_klp_version_1.c            |  34 ++++
 lib/livepatch/test_klp_version_2.c            |  34 ++++
 lib/livepatch/test_klp_version_3.c            |  34 ++++
 tools/testing/selftests/livepatch/Makefile    |   3 +-
 .../selftests/livepatch/test-versions.sh      | 172 ++++++++++++++++++
 13 files changed, 424 insertions(+), 2 deletions(-)
 create mode 100644 Documentation/livepatch/versioning.txt
 create mode 100644 lib/livepatch/test_klp_version_0.c
 create mode 100644 lib/livepatch/test_klp_version_1.c
 create mode 100644 lib/livepatch/test_klp_version_2.c
 create mode 100644 lib/livepatch/test_klp_version_3.c
 create mode 100755 tools/testing/selftests/livepatch/test-versions.sh

diff --git a/Documentation/ABI/testing/sysfs-kernel-livepatch b/Documentation/ABI/testing/sysfs-kernel-livepatch
index 85db352f68f9..bc4475062446 100644
--- a/Documentation/ABI/testing/sysfs-kernel-livepatch
+++ b/Documentation/ABI/testing/sysfs-kernel-livepatch
@@ -8,6 +8,13 @@ Description:
 		The /sys/kernel/livepatch directory contains subdirectories for
 		each loaded live patch module.
 
+What:		/sys/kernel/livepatch/latest_version
+Date:		Feb 2019
+KernelVersion:	5.0.0
+Contact:	live-patching@xxxxxxxxxxxxxxx
+Description:
+		The highest version of any currently enabled patch.
+
 What:		/sys/kernel/livepatch/<patch>
 Date:		Nov 2014
 KernelVersion:	3.19.0
@@ -25,6 +32,13 @@ Description:
 		code is currently applied.  Writing 0 will disable the patch
 		while writing 1 will re-enable the patch.
 
+What:		/sys/kernel/livepatch/<patch>/version
+Date:		Feb 2019
+KernelVersion:	5.0.0
+Contact:	live-patching@xxxxxxxxxxxxxxx
+Description:
+		Patch version number (unsigned).
+
 What:		/sys/kernel/livepatch/<patch>/transition
 Date:		Feb 2017
 KernelVersion:	4.12.0
diff --git a/Documentation/livepatch/versioning.txt b/Documentation/livepatch/versioning.txt
new file mode 100644
index 000000000000..de94fa6e37f7
--- /dev/null
+++ b/Documentation/livepatch/versioning.txt
@@ -0,0 +1,31 @@
+====================
+Livepatch versioning
+====================
+
+Livepatches can alter the system state in ways that require awareness from
+subsequent livepatches.  For example, livepatch FOO may change the semantic of
+data structure X or function Y.  If a second livepatch BAR is subsequently
+loaded and replaces or relies on the functionality in livepatch FOO, it will
+need to consider these semantic changes to operate safely.  Livepatch
+versioning provides a means to facilitate this.
+
+The klp_patch structure contains a 'version' value that may be used to resolve
+compatibility concerns between livepatch modules.  The livepatching core
+enforces a simple policy:
+
+  - The livepatch core keeps a 'latest-version' value, equal to the highest
+    version from the set of livepatches that are currently enabled.  It is
+    recalculated when livepatches are enabled and disabled.
+
+  - On klp_patch_enable(), the patch version is inspected and must be greater
+    than the livepatch core's latest-version: if it is not, the livepatch
+    module will fail to load and the latest-version remains unchanged.
+
+  - Livepatches with no version, i.e. klp_patch.version=0, are exempt from
+    this policy and may always be loaded, regardless of the latest-version.
+    The latest-version remains unchanged when such patches are loaded.
+
+Returning to the earlier example, the klp_patch.version value may be used by
+livepatch FOO to indicate special consideration will be required from future
+livepatches.  In turn, livepatch BAR's higher version value indicates that it
+does indeed succeed livepatch FOO and that it is safe to load.
diff --git a/include/linux/livepatch.h b/include/linux/livepatch.h
index 53551f470722..70d5354e11a8 100644
--- a/include/linux/livepatch.h
+++ b/include/linux/livepatch.h
@@ -150,6 +150,7 @@ struct klp_object {
  * struct klp_patch - patch structure for live patching
  * @mod:	reference to the live patch module
  * @objs:	object entries for kernel objects to be patched
+ * @version:	patch version number
  * @replace:	replace all actively used patches
  * @list:	list node for global list of actively used patches
  * @kobj:	kobject for sysfs resources
@@ -164,6 +165,7 @@ struct klp_patch {
 	/* external */
 	struct module *mod;
 	struct klp_object *objs;
+	unsigned int version;
 	bool replace;
 
 	/* internal */
diff --git a/kernel/livepatch/core.c b/kernel/livepatch/core.c
index fe1993399823..cc120b5018e1 100644
--- a/kernel/livepatch/core.c
+++ b/kernel/livepatch/core.c
@@ -54,6 +54,11 @@ LIST_HEAD(klp_patches);
 
 static struct kobject *klp_root_kobj;
 
+/*
+ * The latest klp_patch.version currently loaded
+ */
+unsigned int latest_version;
+
 static bool klp_is_module(struct klp_object *obj)
 {
 	return obj->name;
@@ -310,13 +315,39 @@ static int klp_write_object_relocations(struct module *pmod,
  * Sysfs Interface
  *
  * /sys/kernel/livepatch
+ * /sys/kernel/livepatch/latest_version
  * /sys/kernel/livepatch/<patch>
  * /sys/kernel/livepatch/<patch>/enabled
  * /sys/kernel/livepatch/<patch>/transition
  * /sys/kernel/livepatch/<patch>/force
+ * /sys/kernel/livepatch/<patch>/version
  * /sys/kernel/livepatch/<patch>/<object>
  * /sys/kernel/livepatch/<patch>/<object>/<function,sympos>
  */
+
+static ssize_t latest_version_show(struct kobject *kobj,
+				   struct kobj_attribute *attr, char *buf)
+{
+	int ret;
+
+	mutex_lock(&klp_mutex);
+	ret = snprintf(buf, PAGE_SIZE-1, "%d\n", latest_version);
+	mutex_unlock(&klp_mutex);
+
+	return ret;
+}
+
+static struct kobj_attribute latest_version_kobj_attr =
+	__ATTR_RO(latest_version);
+static struct attribute *klp_sysfs_attrs[] = {
+	&latest_version_kobj_attr.attr,
+	NULL,
+};
+
+static struct attribute_group attr_group = {
+	.attrs = klp_sysfs_attrs,
+};
+
 static int __klp_disable_patch(struct klp_patch *patch);
 
 static ssize_t enabled_store(struct kobject *kobj, struct kobj_attribute *attr,
@@ -381,6 +412,15 @@ static ssize_t transition_show(struct kobject *kobj,
 			patch == klp_transition_patch);
 }
 
+static ssize_t version_show(struct kobject *kobj,
+				   struct kobj_attribute *attr, char *buf)
+{
+	struct klp_patch *patch;
+
+	patch = container_of(kobj, struct klp_patch, kobj);
+	return snprintf(buf, PAGE_SIZE-1, "%d\n", patch->version);
+}
+
 static ssize_t force_store(struct kobject *kobj, struct kobj_attribute *attr,
 			   const char *buf, size_t count)
 {
@@ -412,10 +452,12 @@ static ssize_t force_store(struct kobject *kobj, struct kobj_attribute *attr,
 
 static struct kobj_attribute enabled_kobj_attr = __ATTR_RW(enabled);
 static struct kobj_attribute transition_kobj_attr = __ATTR_RO(transition);
+static struct kobj_attribute version_kobj_attr = __ATTR_RO(version);
 static struct kobj_attribute force_kobj_attr = __ATTR_WO(force);
 static struct attribute *klp_patch_attrs[] = {
 	&enabled_kobj_attr.attr,
 	&transition_kobj_attr.attr,
+	&version_kobj_attr.attr,
 	&force_kobj_attr.attr,
 	NULL
 };
@@ -1010,6 +1052,13 @@ int klp_enable_patch(struct klp_patch *patch)
 
 	mutex_lock(&klp_mutex);
 
+	if (patch->version && patch->version <= latest_version) {
+		pr_err("Livepatch klp_patch.version=%u <= latest_version=%u, not loading\n",
+			patch->version, latest_version);
+		mutex_unlock(&klp_mutex);
+		return -EINVAL;
+	}
+
 	ret = klp_init_patch_early(patch);
 	if (ret) {
 		mutex_unlock(&klp_mutex);
@@ -1246,6 +1295,12 @@ static int __init klp_init(void)
 	if (!klp_root_kobj)
 		return -ENOMEM;
 
+	ret = sysfs_create_group(klp_root_kobj, &attr_group);
+	if (ret) {
+		kobject_put(klp_root_kobj);
+		return -ENOMEM;
+	}
+
 	return 0;
 }
 
diff --git a/kernel/livepatch/core.h b/kernel/livepatch/core.h
index e6200f38701f..306bd9240c24 100644
--- a/kernel/livepatch/core.h
+++ b/kernel/livepatch/core.h
@@ -6,6 +6,7 @@
 
 extern struct mutex klp_mutex;
 extern struct list_head klp_patches;
+extern unsigned int latest_version;
 
 void klp_free_patch_start(struct klp_patch *patch);
 void klp_discard_replaced_patches(struct klp_patch *new_patch);
diff --git a/kernel/livepatch/transition.c b/kernel/livepatch/transition.c
index 183b2086ba03..99aa0d554da6 100644
--- a/kernel/livepatch/transition.c
+++ b/kernel/livepatch/transition.c
@@ -80,6 +80,7 @@ static void klp_synchronize_transition(void)
  */
 static void klp_complete_transition(void)
 {
+	struct klp_patch *patch;
 	struct klp_object *obj;
 	struct klp_func *func;
 	struct task_struct *g, *task;
@@ -143,6 +144,11 @@ static void klp_complete_transition(void)
 	pr_notice("'%s': %s complete\n", klp_transition_patch->mod->name,
 		  klp_target_state == KLP_PATCHED ? "patching" : "unpatching");
 
+	latest_version = 0;
+	list_for_each_entry(patch, &klp_patches, list)
+		if (patch->enabled && patch->version > latest_version)
+			latest_version = patch->version;
+
 	klp_target_state = KLP_UNDEFINED;
 	klp_transition_patch = NULL;
 }
diff --git a/lib/livepatch/Makefile b/lib/livepatch/Makefile
index 26900ddaef82..6890dadd4d0e 100644
--- a/lib/livepatch/Makefile
+++ b/lib/livepatch/Makefile
@@ -8,7 +8,11 @@ obj-$(CONFIG_TEST_LIVEPATCH) += test_klp_atomic_replace.o \
 				test_klp_callbacks_busy.o \
 				test_klp_callbacks_mod.o \
 				test_klp_livepatch.o \
-				test_klp_shadow_vars.o
+				test_klp_shadow_vars.o \
+				test_klp_version_0.o \
+				test_klp_version_1.o \
+				test_klp_version_2.o \
+				test_klp_version_3.o
 
 # Target modules to be livepatched require CC_FLAGS_FTRACE
 CFLAGS_test_klp_callbacks_busy.o	+= $(CC_FLAGS_FTRACE)
diff --git a/lib/livepatch/test_klp_version_0.c b/lib/livepatch/test_klp_version_0.c
new file mode 100644
index 000000000000..5beb72df1539
--- /dev/null
+++ b/lib/livepatch/test_klp_version_0.c
@@ -0,0 +1,34 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (C) 2019 Joe Lawrence <joe.lawrence@xxxxxxxxxx>
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/livepatch.h>
+
+static struct klp_object objs[] = {
+	{ }
+};
+
+static struct klp_patch patch = {
+	.mod = THIS_MODULE,
+	.objs = objs,
+	.version = 0,
+};
+
+static int test_klp_version_0_init(void)
+{
+	return klp_enable_patch(&patch);
+}
+
+static void test_klp_version_0_exit(void)
+{
+}
+
+module_init(test_klp_version_0_init);
+module_exit(test_klp_version_0_exit);
+MODULE_LICENSE("GPL");
+MODULE_INFO(livepatch, "Y");
+MODULE_AUTHOR("Joe Lawrence <joe.lawrence@xxxxxxxxxx>");
+MODULE_DESCRIPTION("Livepatch test: patch versioning, v0");
diff --git a/lib/livepatch/test_klp_version_1.c b/lib/livepatch/test_klp_version_1.c
new file mode 100644
index 000000000000..311fd8381b42
--- /dev/null
+++ b/lib/livepatch/test_klp_version_1.c
@@ -0,0 +1,34 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (C) 2019 Joe Lawrence <joe.lawrence@xxxxxxxxxx>
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/livepatch.h>
+
+static struct klp_object objs[] = {
+	{ }
+};
+
+static struct klp_patch patch = {
+	.mod = THIS_MODULE,
+	.objs = objs,
+	.version = 1,
+};
+
+static int test_klp_version_1_init(void)
+{
+	return klp_enable_patch(&patch);
+}
+
+static void test_klp_version_1_exit(void)
+{
+}
+
+module_init(test_klp_version_1_init);
+module_exit(test_klp_version_1_exit);
+MODULE_LICENSE("GPL");
+MODULE_INFO(livepatch, "Y");
+MODULE_AUTHOR("Joe Lawrence <joe.lawrence@xxxxxxxxxx>");
+MODULE_DESCRIPTION("Livepatch test: patch versioning, v1");
diff --git a/lib/livepatch/test_klp_version_2.c b/lib/livepatch/test_klp_version_2.c
new file mode 100644
index 000000000000..d004f00be705
--- /dev/null
+++ b/lib/livepatch/test_klp_version_2.c
@@ -0,0 +1,34 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (C) 2019 Joe Lawrence <joe.lawrence@xxxxxxxxxx>
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/livepatch.h>
+
+static struct klp_object objs[] = {
+	{ }
+};
+
+static struct klp_patch patch = {
+	.mod = THIS_MODULE,
+	.objs = objs,
+	.version = 2,
+};
+
+static int test_klp_version_2_init(void)
+{
+	return klp_enable_patch(&patch);
+}
+
+static void test_klp_version_2_exit(void)
+{
+}
+
+module_init(test_klp_version_2_init);
+module_exit(test_klp_version_2_exit);
+MODULE_LICENSE("GPL");
+MODULE_INFO(livepatch, "Y");
+MODULE_AUTHOR("Joe Lawrence <joe.lawrence@xxxxxxxxxx>");
+MODULE_DESCRIPTION("Livepatch test: patch versioning, v2");
diff --git a/lib/livepatch/test_klp_version_3.c b/lib/livepatch/test_klp_version_3.c
new file mode 100644
index 000000000000..b773489d0c24
--- /dev/null
+++ b/lib/livepatch/test_klp_version_3.c
@@ -0,0 +1,34 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (C) 2019 Joe Lawrence <joe.lawrence@xxxxxxxxxx>
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/livepatch.h>
+
+static struct klp_object objs[] = {
+	{ }
+};
+
+static struct klp_patch patch = {
+	.mod = THIS_MODULE,
+	.objs = objs,
+	.version = 3,
+};
+
+static int test_klp_version_3_init(void)
+{
+	return klp_enable_patch(&patch);
+}
+
+static void test_klp_version_3_exit(void)
+{
+}
+
+module_init(test_klp_version_3_init);
+module_exit(test_klp_version_3_exit);
+MODULE_LICENSE("GPL");
+MODULE_INFO(livepatch, "Y");
+MODULE_AUTHOR("Joe Lawrence <joe.lawrence@xxxxxxxxxx>");
+MODULE_DESCRIPTION("Livepatch test: patch versioning, v3");
diff --git a/tools/testing/selftests/livepatch/Makefile b/tools/testing/selftests/livepatch/Makefile
index af4aee79bebb..d4fa03153dea 100644
--- a/tools/testing/selftests/livepatch/Makefile
+++ b/tools/testing/selftests/livepatch/Makefile
@@ -3,6 +3,7 @@
 TEST_GEN_PROGS := \
 	test-livepatch.sh \
 	test-callbacks.sh \
-	test-shadow-vars.sh
+	test-shadow-vars.sh \
+	test-versions.sh
 
 include ../lib.mk
diff --git a/tools/testing/selftests/livepatch/test-versions.sh b/tools/testing/selftests/livepatch/test-versions.sh
new file mode 100755
index 000000000000..f8f6636b1874
--- /dev/null
+++ b/tools/testing/selftests/livepatch/test-versions.sh
@@ -0,0 +1,172 @@
+#!/bin/bash
+# SPDX-License-Identifier: GPL-2.0
+# Copyright (C) 2019 Joe Lawrence <joe.lawrence@xxxxxxxxxx>
+
+. $(dirname $0)/functions.sh
+
+MOD_VERSION_0=test_klp_version_0
+MOD_VERSION_1=test_klp_version_1
+MOD_VERSION_2=test_klp_version_2
+MOD_VERSION_3=test_klp_version_3
+
+set_dynamic_debug
+
+function latest_version_to_dmesg() {
+	echo "livepatch: latest_version=$(cat /sys/kernel/livepatch/latest_version)" > /dev/kmsg 2> /dev/null
+}
+
+# TEST: increasing livepatch version numbers
+#
+
+echo -n "TEST: increasing livepatch version numbers ... "
+dmesg -C
+
+load_lp $MOD_VERSION_1
+latest_version_to_dmesg
+
+load_lp $MOD_VERSION_2
+latest_version_to_dmesg
+
+load_lp $MOD_VERSION_3
+latest_version_to_dmesg
+
+disable_lp $MOD_VERSION_3
+latest_version_to_dmesg
+unload_lp $MOD_VERSION_3
+
+disable_lp $MOD_VERSION_2
+latest_version_to_dmesg
+unload_lp $MOD_VERSION_2
+
+disable_lp $MOD_VERSION_1
+latest_version_to_dmesg
+unload_lp $MOD_VERSION_1
+
+check_result "% modprobe $MOD_VERSION_1
+livepatch: enabling patch '$MOD_VERSION_1'
+livepatch: '$MOD_VERSION_1': initializing patching transition
+livepatch: '$MOD_VERSION_1': starting patching transition
+livepatch: '$MOD_VERSION_1': completing patching transition
+livepatch: '$MOD_VERSION_1': patching complete
+livepatch: latest_version=1
+% modprobe $MOD_VERSION_2
+livepatch: enabling patch '$MOD_VERSION_2'
+livepatch: '$MOD_VERSION_2': initializing patching transition
+livepatch: '$MOD_VERSION_2': starting patching transition
+livepatch: '$MOD_VERSION_2': completing patching transition
+livepatch: '$MOD_VERSION_2': patching complete
+livepatch: latest_version=2
+% modprobe $MOD_VERSION_3
+livepatch: enabling patch '$MOD_VERSION_3'
+livepatch: '$MOD_VERSION_3': initializing patching transition
+livepatch: '$MOD_VERSION_3': starting patching transition
+livepatch: '$MOD_VERSION_3': completing patching transition
+livepatch: '$MOD_VERSION_3': patching complete
+livepatch: latest_version=3
+% echo 0 > /sys/kernel/livepatch/$MOD_VERSION_3/enabled
+livepatch: '$MOD_VERSION_3': initializing unpatching transition
+livepatch: '$MOD_VERSION_3': starting unpatching transition
+livepatch: '$MOD_VERSION_3': completing unpatching transition
+livepatch: '$MOD_VERSION_3': unpatching complete
+livepatch: latest_version=2
+% rmmod $MOD_VERSION_3
+% echo 0 > /sys/kernel/livepatch/$MOD_VERSION_2/enabled
+livepatch: '$MOD_VERSION_2': initializing unpatching transition
+livepatch: '$MOD_VERSION_2': starting unpatching transition
+livepatch: '$MOD_VERSION_2': completing unpatching transition
+livepatch: '$MOD_VERSION_2': unpatching complete
+livepatch: latest_version=1
+% rmmod $MOD_VERSION_2
+% echo 0 > /sys/kernel/livepatch/$MOD_VERSION_1/enabled
+livepatch: '$MOD_VERSION_1': initializing unpatching transition
+livepatch: '$MOD_VERSION_1': starting unpatching transition
+livepatch: '$MOD_VERSION_1': completing unpatching transition
+livepatch: '$MOD_VERSION_1': unpatching complete
+livepatch: latest_version=0
+% rmmod $MOD_VERSION_1"
+
+
+# TEST: verify version 0 can be loaded anytime
+#
+
+echo -n "TEST: verify version 0 can be loaded anytime ... "
+dmesg -C
+
+load_lp $MOD_VERSION_2
+latest_version_to_dmesg
+
+load_lp $MOD_VERSION_0
+latest_version_to_dmesg
+
+disable_lp $MOD_VERSION_0
+latest_version_to_dmesg
+unload_lp $MOD_VERSION_0
+
+disable_lp $MOD_VERSION_2
+latest_version_to_dmesg
+unload_lp $MOD_VERSION_2
+
+check_result "% modprobe $MOD_VERSION_2
+livepatch: enabling patch '$MOD_VERSION_2'
+livepatch: '$MOD_VERSION_2': initializing patching transition
+livepatch: '$MOD_VERSION_2': starting patching transition
+livepatch: '$MOD_VERSION_2': completing patching transition
+livepatch: '$MOD_VERSION_2': patching complete
+livepatch: latest_version=2
+% modprobe $MOD_VERSION_0
+livepatch: enabling patch '$MOD_VERSION_0'
+livepatch: '$MOD_VERSION_0': initializing patching transition
+livepatch: '$MOD_VERSION_0': starting patching transition
+livepatch: '$MOD_VERSION_0': completing patching transition
+livepatch: '$MOD_VERSION_0': patching complete
+livepatch: latest_version=2
+% echo 0 > /sys/kernel/livepatch/$MOD_VERSION_0/enabled
+livepatch: '$MOD_VERSION_0': initializing unpatching transition
+livepatch: '$MOD_VERSION_0': starting unpatching transition
+livepatch: '$MOD_VERSION_0': completing unpatching transition
+livepatch: '$MOD_VERSION_0': unpatching complete
+livepatch: latest_version=2
+% rmmod $MOD_VERSION_0
+% echo 0 > /sys/kernel/livepatch/$MOD_VERSION_2/enabled
+livepatch: '$MOD_VERSION_2': initializing unpatching transition
+livepatch: '$MOD_VERSION_2': starting unpatching transition
+livepatch: '$MOD_VERSION_2': completing unpatching transition
+livepatch: '$MOD_VERSION_2': unpatching complete
+livepatch: latest_version=0
+% rmmod $MOD_VERSION_2"
+
+
+# TEST: verify lower versions can't be loaded
+#
+
+echo -n "TEST: verify lower versions can't be loaded ... "
+dmesg -C
+
+load_lp $MOD_VERSION_2
+latest_version_to_dmesg
+
+load_failing_mod $MOD_VERSION_1
+latest_version_to_dmesg
+
+disable_lp $MOD_VERSION_2
+latest_version_to_dmesg
+unload_lp $MOD_VERSION_2
+
+check_result "% modprobe $MOD_VERSION_2
+livepatch: enabling patch '$MOD_VERSION_2'
+livepatch: '$MOD_VERSION_2': initializing patching transition
+livepatch: '$MOD_VERSION_2': starting patching transition
+livepatch: '$MOD_VERSION_2': completing patching transition
+livepatch: '$MOD_VERSION_2': patching complete
+livepatch: latest_version=2
+% modprobe $MOD_VERSION_1
+livepatch: Livepatch klp_patch.version=1 <= latest_version=2, not loading
+modprobe: ERROR: could not insert '$MOD_VERSION_1': Invalid argument
+livepatch: latest_version=2
+% echo 0 > /sys/kernel/livepatch/$MOD_VERSION_2/enabled
+livepatch: '$MOD_VERSION_2': initializing unpatching transition
+livepatch: '$MOD_VERSION_2': starting unpatching transition
+livepatch: '$MOD_VERSION_2': completing unpatching transition
+livepatch: '$MOD_VERSION_2': unpatching complete
+livepatch: latest_version=0
+% rmmod $MOD_VERSION_2"
-- 
2.20.1




[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [Linux Kernel]     [Linux NFS]     [Linux NILFS]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux SCSI]

  Powered by Linux