[rh8] livepatch: added minimal support for failure injection

Submitted by Evgenii Shatokhin on April 24, 2020, 4:39 p.m.

Details

Message ID 20200424163906.8553-1-eshatokhin@virtuozzo.com
State New
Series "livepatch: added minimal support for failure injection"
Headers show

Commit Message

Evgenii Shatokhin April 24, 2020, 4:39 p.m.
It can be useful when testing loading and replacement of live kernel
patches. It may be needed to check that, if loading of a patch fails,
the system remains in a consistent state.

Livepatch subsystem will now create file 'livepatch/fail_apply' in
debugfs. If one writes 1 (or whatever else kstrtobool() takes as "yes")
to it, the attempts to apply live patches will fail with -EBUSY. The
currently loaded patches remain loaded.

Writing 0 to livepatch/fail_apply disables injection of such failures.

Livepatch is more likely to apply a patch successfully than the old
KPatch core used in VZ7. However, it can still refuse to load a valid
patch with -EBUSY if another patch is currently being processed.

Failure injection added here mimics that behaviour.

Done in the scope of https://jira.sw.ru/browse/PSBM-102582.

Signed-off-by: Evgenii Shatokhin <eshatokhin@virtuozzo.com>
---
 kernel/livepatch/core.c | 16 ++++++++++++++++
 1 file changed, 16 insertions(+)

Patch hide | download patch | download mbox

diff --git a/kernel/livepatch/core.c b/kernel/livepatch/core.c
index 6fa022cce4bf..00ead77e58ba 100644
--- a/kernel/livepatch/core.c
+++ b/kernel/livepatch/core.c
@@ -30,6 +30,7 @@ 
 #include <linux/elf.h>
 #include <linux/moduleloader.h>
 #include <linux/completion.h>
+#include <linux/debugfs.h>
 #include <asm/cacheflush.h>
 #include "core.h"
 #include "patch.h"
@@ -82,6 +83,13 @@  static void klp_init_patch_list(struct klp_patch *patch)
 		klp_init_object_list(patch, obj);
 }
 
+/*
+ * Can be set via livepatch/fail_apply file in debugfs.
+ * If set, livepatch will fail with -EBUSY when requested to apply a patch.
+ * Might be useful for testing and debugging livepatch.
+ */
+static bool fail_apply;
+
 static bool klp_is_module(struct klp_object *obj)
 {
 	return obj->name;
@@ -467,6 +475,9 @@  static int __klp_enable_patch(struct klp_patch *patch)
 	if (klp_transition_patch)
 		return -EBUSY;
 
+	if (fail_apply)
+		return -EBUSY;
+
 	if (WARN_ON(patch->enabled))
 		return -EINVAL;
 
@@ -1375,6 +1386,7 @@  void klp_module_going(struct module *mod)
 static int __init klp_init(void)
 {
 	int ret;
+	struct dentry *d;
 
 	ret = klp_check_compiler_support();
 	if (ret) {
@@ -1386,6 +1398,10 @@  static int __init klp_init(void)
 	if (!klp_root_kobj)
 		return -ENOMEM;
 
+	d = debugfs_create_dir("livepatch", NULL);
+	if (d)
+		debugfs_create_bool("fail_apply", 0644, d, &fail_apply);
+
 	return 0;
 }