All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/3] Livepatch module notifier cleanup
@ 2016-03-09 22:13 Jessica Yu
  2016-03-09 22:13 ` [PATCH 1/3] modules: split part of complete_formation() into prepare_coming_module() Jessica Yu
                   ` (3 more replies)
  0 siblings, 4 replies; 9+ messages in thread
From: Jessica Yu @ 2016-03-09 22:13 UTC (permalink / raw)
  To: Josh Poimboeuf, Seth Jennings, Jiri Kosina, Vojtech Pavlik,
	Miroslav Benes, Petr Mladek, Rusty Russell
  Cc: Steven Rostedt, live-patching, linux-kernel, Jessica Yu

These are the remaining 3 patches that came from the original ftrace/livepatch
module notifier patchset found here: https://lkml.org/lkml/2016/2/8/1180

Basically, the patchset does a bit of module.c cleanup (patch 1 and 2) in
preparation for the klp_module_{coming,going} calls (patch 3). We decided
to stop relying on the module notifier callchain in favor of hard-coding
the appropriate livepatch function calls that handle coming and going
modules. Hard-coding these calls will guarantee that ftrace and livepatch
exit/initialization routines are called in the correct order without
relying on module notifiers.

The patches should be nearly exactly the same as those from the previous
discussion, except in patch 3 I've added back the #if IS_ENABLED(CONFIG_LIVEPATCH)
guard in livepatch.h, and in patch 2 I decided that it might be safer to
change mod->state with the module mutex held.

Patches based on linux-next.

Previous discussion found here: https://lkml.org/lkml/2016/2/8/1180

Jessica Yu (3):
  modules: split part of complete_formation() into prepare_coming_module()
  modules: set mod->state to GOING before going notifiers are called
  livepatch/module: remove livepatch module notifier

 include/linux/livepatch.h |  13 +++++
 kernel/livepatch/core.c   | 145 ++++++++++++++++++++++------------------------
 kernel/module.c           |  39 ++++++++++---
 3 files changed, 113 insertions(+), 84 deletions(-)

-- 
2.4.3

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH 1/3] modules: split part of complete_formation() into prepare_coming_module()
  2016-03-09 22:13 [PATCH 0/3] Livepatch module notifier cleanup Jessica Yu
@ 2016-03-09 22:13 ` Jessica Yu
  2016-03-10 22:41   ` Josh Poimboeuf
  2016-03-09 22:13 ` [PATCH 2/3] modules: set mod->state to GOING before going notifiers are called Jessica Yu
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 9+ messages in thread
From: Jessica Yu @ 2016-03-09 22:13 UTC (permalink / raw)
  To: Josh Poimboeuf, Seth Jennings, Jiri Kosina, Vojtech Pavlik,
	Miroslav Benes, Petr Mladek, Rusty Russell
  Cc: Steven Rostedt, live-patching, linux-kernel, Jessica Yu

Put all actions in complete_formation() that are performed after
module->state is set to MODULE_STATE_COMING into a separate function
prepare_coming_module(). This split prepares for the removal of the
livepatch module notifiers in favor of hard-coding function calls to
klp_module_{coming,going} in the module loader.

The complete_formation -> prepare_coming_module split will also make error
handling easier since we can jump to the appropriate error label to do any
module GOING cleanup after all the COMING-actions have completed.

Signed-off-by: Jessica Yu <jeyu@redhat.com>
---
 kernel/module.c | 26 ++++++++++++++++++--------
 1 file changed, 18 insertions(+), 8 deletions(-)

diff --git a/kernel/module.c b/kernel/module.c
index 87cfeb2..1981ae0 100644
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -3312,6 +3312,14 @@ out_unlocked:
 	return err;
 }
 
+static int prepare_coming_module(struct module *mod)
+{
+	ftrace_module_enable(mod);
+	blocking_notifier_call_chain(&module_notify_list,
+				     MODULE_STATE_COMING, mod);
+	return 0;
+}
+
 static int complete_formation(struct module *mod, struct load_info *info)
 {
 	int err;
@@ -3335,9 +3343,6 @@ static int complete_formation(struct module *mod, struct load_info *info)
 	mod->state = MODULE_STATE_COMING;
 	mutex_unlock(&module_mutex);
 
-	ftrace_module_enable(mod);
-	blocking_notifier_call_chain(&module_notify_list,
-				     MODULE_STATE_COMING, mod);
 	return 0;
 
 out:
@@ -3459,13 +3464,17 @@ static int load_module(struct load_info *info, const char __user *uargs,
 	if (err)
 		goto ddebug_cleanup;
 
+	err = prepare_coming_module(mod);
+	if (err)
+		goto bug_cleanup;
+
 	/* Module is ready to execute: parsing args may do that. */
 	after_dashes = parse_args(mod->name, mod->args, mod->kp, mod->num_kp,
 				  -32768, 32767, mod,
 				  unknown_module_param_cb);
 	if (IS_ERR(after_dashes)) {
 		err = PTR_ERR(after_dashes);
-		goto bug_cleanup;
+		goto coming_cleanup;
 	} else if (after_dashes) {
 		pr_warn("%s: parameters '%s' after `--' ignored\n",
 		       mod->name, after_dashes);
@@ -3474,7 +3483,7 @@ static int load_module(struct load_info *info, const char __user *uargs,
 	/* Link in to syfs. */
 	err = mod_sysfs_setup(mod, info, mod->kp, mod->num_kp);
 	if (err < 0)
-		goto bug_cleanup;
+		goto coming_cleanup;
 
 	/* Get rid of temporary copy. */
 	free_copy(info);
@@ -3484,15 +3493,16 @@ static int load_module(struct load_info *info, const char __user *uargs,
 
 	return do_init_module(mod);
 
+ coming_cleanup:
+	blocking_notifier_call_chain(&module_notify_list,
+				     MODULE_STATE_GOING, mod);
+
  bug_cleanup:
 	/* module_bug_cleanup needs module_mutex protection */
 	mutex_lock(&module_mutex);
 	module_bug_cleanup(mod);
 	mutex_unlock(&module_mutex);
 
-	blocking_notifier_call_chain(&module_notify_list,
-				     MODULE_STATE_GOING, mod);
-
 	/* we can't deallocate the module until we clear memory protection */
 	module_disable_ro(mod);
 	module_disable_nx(mod);
-- 
2.4.3

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH 2/3] modules: set mod->state to GOING before going notifiers are called
  2016-03-09 22:13 [PATCH 0/3] Livepatch module notifier cleanup Jessica Yu
  2016-03-09 22:13 ` [PATCH 1/3] modules: split part of complete_formation() into prepare_coming_module() Jessica Yu
@ 2016-03-09 22:13 ` Jessica Yu
  2016-03-10  3:27   ` Rusty Russell
  2016-03-09 22:13 ` [PATCH 3/3] livepatch/module: remove livepatch module notifier Jessica Yu
  2016-03-10  3:27 ` [PATCH 0/3] Livepatch module notifier cleanup Rusty Russell
  3 siblings, 1 reply; 9+ messages in thread
From: Jessica Yu @ 2016-03-09 22:13 UTC (permalink / raw)
  To: Josh Poimboeuf, Seth Jennings, Jiri Kosina, Vojtech Pavlik,
	Miroslav Benes, Petr Mladek, Rusty Russell
  Cc: Steven Rostedt, live-patching, linux-kernel, Jessica Yu

In load_module(), the going notifiers are called during error handling
when an error occurs after the coming notifiers have already been called.
However, a module's state is still MODULE_STATE_COMING when the going
notifiers are called in the error path. To be consistent, also set
mod->state to MODULE_STATE_GOING before calling the going notifiers.

Signed-off-by: Jessica Yu <jeyu@redhat.com>
---
 kernel/module.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/kernel/module.c b/kernel/module.c
index 1981ae0..9e80576 100644
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -3494,6 +3494,9 @@ static int load_module(struct load_info *info, const char __user *uargs,
 	return do_init_module(mod);
 
  coming_cleanup:
+	mutex_lock(&module_mutex);
+	mod->state = MODULE_STATE_GOING;
+	mutex_unlock(&module_mutex);
 	blocking_notifier_call_chain(&module_notify_list,
 				     MODULE_STATE_GOING, mod);
 
-- 
2.4.3

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH 3/3] livepatch/module: remove livepatch module notifier
  2016-03-09 22:13 [PATCH 0/3] Livepatch module notifier cleanup Jessica Yu
  2016-03-09 22:13 ` [PATCH 1/3] modules: split part of complete_formation() into prepare_coming_module() Jessica Yu
  2016-03-09 22:13 ` [PATCH 2/3] modules: set mod->state to GOING before going notifiers are called Jessica Yu
@ 2016-03-09 22:13 ` Jessica Yu
  2016-03-10 22:45   ` Josh Poimboeuf
  2016-03-10  3:27 ` [PATCH 0/3] Livepatch module notifier cleanup Rusty Russell
  3 siblings, 1 reply; 9+ messages in thread
From: Jessica Yu @ 2016-03-09 22:13 UTC (permalink / raw)
  To: Josh Poimboeuf, Seth Jennings, Jiri Kosina, Vojtech Pavlik,
	Miroslav Benes, Petr Mladek, Rusty Russell
  Cc: Steven Rostedt, live-patching, linux-kernel, Jessica Yu

Remove the livepatch module notifier in favor of directly enabling and
disabling patches to modules in the module loader. Hard-coding the
function calls ensures that ftrace_module_enable() is run before
klp_module_coming() during module load, and that klp_module_going() is
run before ftrace_release_mod() during module unload. This way, ftrace
and livepatch code is run in the correct order during the module
load/unload sequence without dependence on the module notifier call chain.

Signed-off-by: Jessica Yu <jeyu@redhat.com>
---
 include/linux/livepatch.h |  13 +++++
 kernel/livepatch/core.c   | 145 ++++++++++++++++++++++------------------------
 kernel/module.c           |  10 ++++
 3 files changed, 92 insertions(+), 76 deletions(-)

diff --git a/include/linux/livepatch.h b/include/linux/livepatch.h
index c056797..bd830d5 100644
--- a/include/linux/livepatch.h
+++ b/include/linux/livepatch.h
@@ -24,6 +24,8 @@
 #include <linux/module.h>
 #include <linux/ftrace.h>
 
+#if IS_ENABLED(CONFIG_LIVEPATCH)
+
 #include <asm/livepatch.h>
 
 enum klp_state {
@@ -132,4 +134,15 @@ int klp_unregister_patch(struct klp_patch *);
 int klp_enable_patch(struct klp_patch *);
 int klp_disable_patch(struct klp_patch *);
 
+/* Called from the module loader during module coming/going states */
+int klp_module_coming(struct module *mod);
+void klp_module_going(struct module *mod);
+
+#else /* !CONFIG_LIVEPATCH */
+
+static inline int klp_module_coming(struct module *mod) { return 0; }
+static inline void klp_module_going(struct module *mod) { }
+
+#endif /* CONFIG_LIVEPATCH */
+
 #endif /* _LINUX_LIVEPATCH_H_ */
diff --git a/kernel/livepatch/core.c b/kernel/livepatch/core.c
index bc2c85c..e902377 100644
--- a/kernel/livepatch/core.c
+++ b/kernel/livepatch/core.c
@@ -99,12 +99,12 @@ static void klp_find_object_module(struct klp_object *obj)
 	/*
 	 * We do not want to block removal of patched modules and therefore
 	 * we do not take a reference here. The patches are removed by
-	 * a going module handler instead.
+	 * klp_module_going() instead.
 	 */
 	mod = find_module(obj->name);
 	/*
-	 * Do not mess work of the module coming and going notifiers.
-	 * Note that the patch might still be needed before the going handler
+	 * Do not mess work of klp_module_coming() and klp_module_going().
+	 * Note that the patch might still be needed before klp_module_going()
 	 * is called. Module functions can be called even in the GOING state
 	 * until mod->exit() finishes. This is especially important for
 	 * patches that modify semantic of the functions.
@@ -866,103 +866,106 @@ int klp_register_patch(struct klp_patch *patch)
 }
 EXPORT_SYMBOL_GPL(klp_register_patch);
 
-static int klp_module_notify_coming(struct klp_patch *patch,
-				     struct klp_object *obj)
+int klp_module_coming(struct module *mod)
 {
-	struct module *pmod = patch->mod;
-	struct module *mod = obj->mod;
 	int ret;
+	struct klp_patch *patch;
+	struct klp_object *obj;
 
-	ret = klp_init_object_loaded(patch, obj);
-	if (ret) {
-		pr_warn("failed to initialize patch '%s' for module '%s' (%d)\n",
-			pmod->name, mod->name, ret);
-		return ret;
-	}
+	if (WARN_ON(mod->state != MODULE_STATE_COMING))
+		return -EINVAL;
 
-	if (patch->state == KLP_DISABLED)
-		return 0;
+	mutex_lock(&klp_mutex);
+	/*
+	 * Each module has to know that klp_module_coming()
+	 * has been called. We never know what module will
+	 * get patched by a new patch.
+	 */
+	mod->klp_alive = true;
 
-	pr_notice("applying patch '%s' to loading module '%s'\n",
-		  pmod->name, mod->name);
+	list_for_each_entry(patch, &klp_patches, list) {
+		klp_for_each_object(patch, obj) {
+			if (!klp_is_module(obj) || strcmp(obj->name, mod->name))
+				continue;
 
-	ret = klp_enable_object(obj);
-	if (ret)
-		pr_warn("failed to apply patch '%s' to module '%s' (%d)\n",
-			pmod->name, mod->name, ret);
-	return ret;
-}
+			obj->mod = mod;
 
-static void klp_module_notify_going(struct klp_patch *patch,
-				    struct klp_object *obj)
-{
-	struct module *pmod = patch->mod;
-	struct module *mod = obj->mod;
+			ret = klp_init_object_loaded(patch, obj);
+			if (ret) {
+				pr_warn("failed to initialize patch '%s' for module '%s' (%d)\n",
+					patch->mod->name, obj->mod->name, ret);
+				goto err;
+			}
 
-	if (patch->state == KLP_DISABLED)
-		goto disabled;
+			if (patch->state == KLP_DISABLED)
+				break;
+
+			pr_notice("applying patch '%s' to loading module '%s'\n",
+				  patch->mod->name, obj->mod->name);
+
+			ret = klp_enable_object(obj);
+			if (ret) {
+				pr_warn("failed to apply patch '%s' to module '%s' (%d)\n",
+					patch->mod->name, obj->mod->name, ret);
+				goto err;
+			}
+
+			break;
+		}
+	}
 
-	pr_notice("reverting patch '%s' on unloading module '%s'\n",
-		  pmod->name, mod->name);
+	mutex_unlock(&klp_mutex);
 
-	klp_disable_object(obj);
+	return 0;
 
-disabled:
+err:
+	/*
+	 * If a patch is unsuccessfully applied, return
+	 * error to the module loader.
+	 */
+	pr_warn("patch '%s' failed for module '%s', refusing to load module '%s'\n",
+		patch->mod->name, obj->mod->name, obj->mod->name);
 	klp_free_object_loaded(obj);
+	mutex_unlock(&klp_mutex);
+
+	return ret;
 }
 
-static int klp_module_notify(struct notifier_block *nb, unsigned long action,
-			     void *data)
+void klp_module_going(struct module *mod)
 {
-	int ret;
-	struct module *mod = data;
 	struct klp_patch *patch;
 	struct klp_object *obj;
 
-	if (action != MODULE_STATE_COMING && action != MODULE_STATE_GOING)
-		return 0;
+	if (WARN_ON(mod->state != MODULE_STATE_GOING))
+		return;
 
 	mutex_lock(&klp_mutex);
-
 	/*
-	 * Each module has to know that the notifier has been called.
-	 * We never know what module will get patched by a new patch.
+	 * Each module has to know that klp_module_going()
+	 * has been called. We never know what module will
+	 * get patched by a new patch.
 	 */
-	if (action == MODULE_STATE_COMING)
-		mod->klp_alive = true;
-	else /* MODULE_STATE_GOING */
-		mod->klp_alive = false;
+	mod->klp_alive = false;
 
 	list_for_each_entry(patch, &klp_patches, list) {
 		klp_for_each_object(patch, obj) {
 			if (!klp_is_module(obj) || strcmp(obj->name, mod->name))
 				continue;
 
-			if (action == MODULE_STATE_COMING) {
-				obj->mod = mod;
-				ret = klp_module_notify_coming(patch, obj);
-				if (ret) {
-					obj->mod = NULL;
-					pr_warn("patch '%s' is in an inconsistent state!\n",
-						patch->mod->name);
-				}
-			} else /* MODULE_STATE_GOING */
-				klp_module_notify_going(patch, obj);
+			if (patch->state != KLP_DISABLED) {
+				pr_notice("reverting patch '%s' on unloading module '%s'\n",
+					  patch->mod->name, obj->mod->name);
+				klp_disable_object(obj);
+			}
 
+			klp_free_object_loaded(obj);
 			break;
 		}
 	}
 
 	mutex_unlock(&klp_mutex);
-
-	return 0;
 }
 
-static struct notifier_block klp_module_nb = {
-	.notifier_call = klp_module_notify,
-	.priority = INT_MIN+1, /* called late but before ftrace notifier */
-};
-
 static int __init klp_init(void)
 {
 	int ret;
@@ -973,21 +976,11 @@ static int __init klp_init(void)
 		return -EINVAL;
 	}
 
-	ret = register_module_notifier(&klp_module_nb);
-	if (ret)
-		return ret;
-
 	klp_root_kobj = kobject_create_and_add("livepatch", kernel_kobj);
-	if (!klp_root_kobj) {
-		ret = -ENOMEM;
-		goto unregister;
-	}
+	if (!klp_root_kobj)
+		return -ENOMEM;
 
 	return 0;
-
-unregister:
-	unregister_module_notifier(&klp_module_nb);
-	return ret;
 }
 
 module_init(klp_init);
diff --git a/kernel/module.c b/kernel/module.c
index 9e80576..3609fbd 100644
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -53,6 +53,7 @@
 #include <asm/sections.h>
 #include <linux/tracepoint.h>
 #include <linux/ftrace.h>
+#include <linux/livepatch.h>
 #include <linux/async.h>
 #include <linux/percpu.h>
 #include <linux/kmemleak.h>
@@ -984,6 +985,7 @@ SYSCALL_DEFINE2(delete_module, const char __user *, name_user,
 		mod->exit();
 	blocking_notifier_call_chain(&module_notify_list,
 				     MODULE_STATE_GOING, mod);
+	klp_module_going(mod);
 	ftrace_release_mod(mod);
 
 	async_synchronize_full();
@@ -3258,6 +3260,7 @@ fail:
 	module_put(mod);
 	blocking_notifier_call_chain(&module_notify_list,
 				     MODULE_STATE_GOING, mod);
+	klp_module_going(mod);
 	ftrace_release_mod(mod);
 	free_module(mod);
 	wake_up_all(&module_wq);
@@ -3314,7 +3317,13 @@ out_unlocked:
 
 static int prepare_coming_module(struct module *mod)
 {
+	int err;
+
 	ftrace_module_enable(mod);
+	err = klp_module_coming(mod);
+	if (err)
+		return err;
+
 	blocking_notifier_call_chain(&module_notify_list,
 				     MODULE_STATE_COMING, mod);
 	return 0;
@@ -3499,6 +3508,7 @@ static int load_module(struct load_info *info, const char __user *uargs,
 	mutex_unlock(&module_mutex);
 	blocking_notifier_call_chain(&module_notify_list,
 				     MODULE_STATE_GOING, mod);
+	klp_module_going(mod);
 
  bug_cleanup:
 	/* module_bug_cleanup needs module_mutex protection */
-- 
2.4.3

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* Re: [PATCH 2/3] modules: set mod->state to GOING before going notifiers are called
  2016-03-09 22:13 ` [PATCH 2/3] modules: set mod->state to GOING before going notifiers are called Jessica Yu
@ 2016-03-10  3:27   ` Rusty Russell
  2016-03-10  5:08     ` Jessica Yu
  0 siblings, 1 reply; 9+ messages in thread
From: Rusty Russell @ 2016-03-10  3:27 UTC (permalink / raw)
  To: Jessica Yu, Josh Poimboeuf, Seth Jennings, Jiri Kosina,
	Vojtech Pavlik, Miroslav Benes, Petr Mladek
  Cc: Steven Rostedt, live-patching, linux-kernel, Jessica Yu

Jessica Yu <jeyu@redhat.com> writes:
> In load_module(), the going notifiers are called during error handling
> when an error occurs after the coming notifiers have already been called.
> However, a module's state is still MODULE_STATE_COMING when the going
> notifiers are called in the error path. To be consistent, also set
> mod->state to MODULE_STATE_GOING before calling the going notifiers.
>
> Signed-off-by: Jessica Yu <jeyu@redhat.com>
> ---
>  kernel/module.c | 3 +++
>  1 file changed, 3 insertions(+)
>
> diff --git a/kernel/module.c b/kernel/module.c
> index 1981ae0..9e80576 100644
> --- a/kernel/module.c
> +++ b/kernel/module.c
> @@ -3494,6 +3494,9 @@ static int load_module(struct load_info *info, const char __user *uargs,
>  	return do_init_module(mod);
>  
>   coming_cleanup:
> +	mutex_lock(&module_mutex);
> +	mod->state = MODULE_STATE_GOING;
> +	mutex_unlock(&module_mutex);
>  	blocking_notifier_call_chain(&module_notify_list,
>  				     MODULE_STATE_GOING, mod);

Actually, reviewing this patch makes me realize it is wrong.

We rely on the state of the module being MODULE_STATE_COMING here:

        static inline int strong_try_module_get(struct module *mod)
        {
        	BUG_ON(mod && mod->state == MODULE_STATE_UNFORMED);
        	if (mod && mod->state == MODULE_STATE_COMING)
                	return -EBUSY;

We will just have to document that the notifier can be called with
a module in MODULE_STATE_COMING if it never succeeded its
initialization.

Sorry for the previously false lead,
Rusty.

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH 0/3] Livepatch module notifier cleanup
  2016-03-09 22:13 [PATCH 0/3] Livepatch module notifier cleanup Jessica Yu
                   ` (2 preceding siblings ...)
  2016-03-09 22:13 ` [PATCH 3/3] livepatch/module: remove livepatch module notifier Jessica Yu
@ 2016-03-10  3:27 ` Rusty Russell
  3 siblings, 0 replies; 9+ messages in thread
From: Rusty Russell @ 2016-03-10  3:27 UTC (permalink / raw)
  To: Jessica Yu, Josh Poimboeuf, Seth Jennings, Jiri Kosina,
	Vojtech Pavlik, Miroslav Benes, Petr Mladek
  Cc: Steven Rostedt, live-patching, linux-kernel, Jessica Yu

Jessica Yu <jeyu@redhat.com> writes:
> These are the remaining 3 patches that came from the original ftrace/livepatch
> module notifier patchset found here: https://lkml.org/lkml/2016/2/8/1180

Please add my Acked-by to the first and third.

Cheers,
Rusty.

> Basically, the patchset does a bit of module.c cleanup (patch 1 and 2) in
> preparation for the klp_module_{coming,going} calls (patch 3). We decided
> to stop relying on the module notifier callchain in favor of hard-coding
> the appropriate livepatch function calls that handle coming and going
> modules. Hard-coding these calls will guarantee that ftrace and livepatch
> exit/initialization routines are called in the correct order without
> relying on module notifiers.
>
> The patches should be nearly exactly the same as those from the previous
> discussion, except in patch 3 I've added back the #if IS_ENABLED(CONFIG_LIVEPATCH)
> guard in livepatch.h, and in patch 2 I decided that it might be safer to
> change mod->state with the module mutex held.
>
> Patches based on linux-next.
>
> Previous discussion found here: https://lkml.org/lkml/2016/2/8/1180
>
> Jessica Yu (3):
>   modules: split part of complete_formation() into prepare_coming_module()
>   modules: set mod->state to GOING before going notifiers are called
>   livepatch/module: remove livepatch module notifier
>
>  include/linux/livepatch.h |  13 +++++
>  kernel/livepatch/core.c   | 145 ++++++++++++++++++++++------------------------
>  kernel/module.c           |  39 ++++++++++---
>  3 files changed, 113 insertions(+), 84 deletions(-)
>
> -- 
> 2.4.3

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: modules: set mod->state to GOING before going notifiers are called
  2016-03-10  3:27   ` Rusty Russell
@ 2016-03-10  5:08     ` Jessica Yu
  0 siblings, 0 replies; 9+ messages in thread
From: Jessica Yu @ 2016-03-10  5:08 UTC (permalink / raw)
  To: Rusty Russell
  Cc: Josh Poimboeuf, Seth Jennings, Jiri Kosina, Vojtech Pavlik,
	Miroslav Benes, Petr Mladek, Steven Rostedt, live-patching,
	linux-kernel

+++ Rusty Russell [10/03/16 13:57 +1030]:
>Jessica Yu <jeyu@redhat.com> writes:
>> In load_module(), the going notifiers are called during error handling
>> when an error occurs after the coming notifiers have already been called.
>> However, a module's state is still MODULE_STATE_COMING when the going
>> notifiers are called in the error path. To be consistent, also set
>> mod->state to MODULE_STATE_GOING before calling the going notifiers.
>>
>> Signed-off-by: Jessica Yu <jeyu@redhat.com>
>> ---
>>  kernel/module.c | 3 +++
>>  1 file changed, 3 insertions(+)
>>
>> diff --git a/kernel/module.c b/kernel/module.c
>> index 1981ae0..9e80576 100644
>> --- a/kernel/module.c
>> +++ b/kernel/module.c
>> @@ -3494,6 +3494,9 @@ static int load_module(struct load_info *info, const char __user *uargs,
>>  	return do_init_module(mod);
>>
>>   coming_cleanup:
>> +	mutex_lock(&module_mutex);
>> +	mod->state = MODULE_STATE_GOING;
>> +	mutex_unlock(&module_mutex);
>>  	blocking_notifier_call_chain(&module_notify_list,
>>  				     MODULE_STATE_GOING, mod);
>
>Actually, reviewing this patch makes me realize it is wrong.
>
>We rely on the state of the module being MODULE_STATE_COMING here:
>
>        static inline int strong_try_module_get(struct module *mod)
>        {
>        	BUG_ON(mod && mod->state == MODULE_STATE_UNFORMED);
>        	if (mod && mod->state == MODULE_STATE_COMING)
>                	return -EBUSY;
>
>We will just have to document that the notifier can be called with
>a module in MODULE_STATE_COMING if it never succeeded its
>initialization.

Ah, thanks for catching that. I think I remember seeing this conditional and
assuming it wouldn't be a problem since GOING modules would fail in
try_module_get() (as it is does not pass the module_is_live() test) and
subsequently strong_try_module_get() would also fail.. But, I think I ought to
review how module states interact before making a change like this, so, please
ignore this patch.

Jessica

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH 1/3] modules: split part of complete_formation() into prepare_coming_module()
  2016-03-09 22:13 ` [PATCH 1/3] modules: split part of complete_formation() into prepare_coming_module() Jessica Yu
@ 2016-03-10 22:41   ` Josh Poimboeuf
  0 siblings, 0 replies; 9+ messages in thread
From: Josh Poimboeuf @ 2016-03-10 22:41 UTC (permalink / raw)
  To: Jessica Yu
  Cc: Seth Jennings, Jiri Kosina, Vojtech Pavlik, Miroslav Benes,
	Petr Mladek, Rusty Russell, Steven Rostedt, live-patching,
	linux-kernel

On Wed, Mar 09, 2016 at 05:13:55PM -0500, Jessica Yu wrote:
> Put all actions in complete_formation() that are performed after
> module->state is set to MODULE_STATE_COMING into a separate function
> prepare_coming_module(). This split prepares for the removal of the
> livepatch module notifiers in favor of hard-coding function calls to
> klp_module_{coming,going} in the module loader.
> 
> The complete_formation -> prepare_coming_module split will also make error
> handling easier since we can jump to the appropriate error label to do any
> module GOING cleanup after all the COMING-actions have completed.
> 
> Signed-off-by: Jessica Yu <jeyu@redhat.com>

Reviewed-by: Josh Poimboeuf <jpoimboe@redhat.com>


-- 
Josh

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH 3/3] livepatch/module: remove livepatch module notifier
  2016-03-09 22:13 ` [PATCH 3/3] livepatch/module: remove livepatch module notifier Jessica Yu
@ 2016-03-10 22:45   ` Josh Poimboeuf
  0 siblings, 0 replies; 9+ messages in thread
From: Josh Poimboeuf @ 2016-03-10 22:45 UTC (permalink / raw)
  To: Jessica Yu
  Cc: Seth Jennings, Jiri Kosina, Vojtech Pavlik, Miroslav Benes,
	Petr Mladek, Rusty Russell, Steven Rostedt, live-patching,
	linux-kernel

On Wed, Mar 09, 2016 at 05:13:57PM -0500, Jessica Yu wrote:
> Remove the livepatch module notifier in favor of directly enabling and
> disabling patches to modules in the module loader. Hard-coding the
> function calls ensures that ftrace_module_enable() is run before
> klp_module_coming() during module load, and that klp_module_going() is
> run before ftrace_release_mod() during module unload. This way, ftrace
> and livepatch code is run in the correct order during the module
> load/unload sequence without dependence on the module notifier call chain.
> 
> Signed-off-by: Jessica Yu <jeyu@redhat.com>
> ---
>  include/linux/livepatch.h |  13 +++++
>  kernel/livepatch/core.c   | 145 ++++++++++++++++++++++------------------------
>  kernel/module.c           |  10 ++++
>  3 files changed, 92 insertions(+), 76 deletions(-)
> 
> diff --git a/include/linux/livepatch.h b/include/linux/livepatch.h
> index c056797..bd830d5 100644
> --- a/include/linux/livepatch.h
> +++ b/include/linux/livepatch.h
> @@ -24,6 +24,8 @@
>  #include <linux/module.h>
>  #include <linux/ftrace.h>
>  
> +#if IS_ENABLED(CONFIG_LIVEPATCH)
> +
>  #include <asm/livepatch.h>
>  
>  enum klp_state {
> @@ -132,4 +134,15 @@ int klp_unregister_patch(struct klp_patch *);
>  int klp_enable_patch(struct klp_patch *);
>  int klp_disable_patch(struct klp_patch *);
>  
> +/* Called from the module loader during module coming/going states */
> +int klp_module_coming(struct module *mod);
> +void klp_module_going(struct module *mod);
> +
> +#else /* !CONFIG_LIVEPATCH */
> +
> +static inline int klp_module_coming(struct module *mod) { return 0; }
> +static inline void klp_module_going(struct module *mod) { }
> +
> +#endif /* CONFIG_LIVEPATCH */
> +
>  #endif /* _LINUX_LIVEPATCH_H_ */
> diff --git a/kernel/livepatch/core.c b/kernel/livepatch/core.c
> index bc2c85c..e902377 100644
> --- a/kernel/livepatch/core.c
> +++ b/kernel/livepatch/core.c
> @@ -99,12 +99,12 @@ static void klp_find_object_module(struct klp_object *obj)
>  	/*
>  	 * We do not want to block removal of patched modules and therefore
>  	 * we do not take a reference here. The patches are removed by
> -	 * a going module handler instead.
> +	 * klp_module_going() instead.
>  	 */
>  	mod = find_module(obj->name);
>  	/*
> -	 * Do not mess work of the module coming and going notifiers.
> -	 * Note that the patch might still be needed before the going handler
> +	 * Do not mess work of klp_module_coming() and klp_module_going().
> +	 * Note that the patch might still be needed before klp_module_going()
>  	 * is called. Module functions can be called even in the GOING state
>  	 * until mod->exit() finishes. This is especially important for
>  	 * patches that modify semantic of the functions.
> @@ -866,103 +866,106 @@ int klp_register_patch(struct klp_patch *patch)
>  }
>  EXPORT_SYMBOL_GPL(klp_register_patch);
>  
> -static int klp_module_notify_coming(struct klp_patch *patch,
> -				     struct klp_object *obj)
> +int klp_module_coming(struct module *mod)
>  {
> -	struct module *pmod = patch->mod;
> -	struct module *mod = obj->mod;
>  	int ret;
> +	struct klp_patch *patch;
> +	struct klp_object *obj;
>  
> -	ret = klp_init_object_loaded(patch, obj);
> -	if (ret) {
> -		pr_warn("failed to initialize patch '%s' for module '%s' (%d)\n",
> -			pmod->name, mod->name, ret);
> -		return ret;
> -	}
> +	if (WARN_ON(mod->state != MODULE_STATE_COMING))
> +		return -EINVAL;
>  
> -	if (patch->state == KLP_DISABLED)
> -		return 0;
> +	mutex_lock(&klp_mutex);
> +	/*
> +	 * Each module has to know that klp_module_coming()
> +	 * has been called. We never know what module will
> +	 * get patched by a new patch.
> +	 */
> +	mod->klp_alive = true;
>  
> -	pr_notice("applying patch '%s' to loading module '%s'\n",
> -		  pmod->name, mod->name);
> +	list_for_each_entry(patch, &klp_patches, list) {
> +		klp_for_each_object(patch, obj) {
> +			if (!klp_is_module(obj) || strcmp(obj->name, mod->name))
> +				continue;
>  
> -	ret = klp_enable_object(obj);
> -	if (ret)
> -		pr_warn("failed to apply patch '%s' to module '%s' (%d)\n",
> -			pmod->name, mod->name, ret);
> -	return ret;
> -}
> +			obj->mod = mod;
>  
> -static void klp_module_notify_going(struct klp_patch *patch,
> -				    struct klp_object *obj)
> -{
> -	struct module *pmod = patch->mod;
> -	struct module *mod = obj->mod;
> +			ret = klp_init_object_loaded(patch, obj);
> +			if (ret) {
> +				pr_warn("failed to initialize patch '%s' for module '%s' (%d)\n",
> +					patch->mod->name, obj->mod->name, ret);
> +				goto err;
> +			}
>  
> -	if (patch->state == KLP_DISABLED)
> -		goto disabled;
> +			if (patch->state == KLP_DISABLED)
> +				break;
> +
> +			pr_notice("applying patch '%s' to loading module '%s'\n",
> +				  patch->mod->name, obj->mod->name);
> +
> +			ret = klp_enable_object(obj);
> +			if (ret) {
> +				pr_warn("failed to apply patch '%s' to module '%s' (%d)\n",
> +					patch->mod->name, obj->mod->name, ret);
> +				goto err;
> +			}
> +
> +			break;
> +		}
> +	}
>  
> -	pr_notice("reverting patch '%s' on unloading module '%s'\n",
> -		  pmod->name, mod->name);
> +	mutex_unlock(&klp_mutex);
>  
> -	klp_disable_object(obj);
> +	return 0;
>  
> -disabled:
> +err:
> +	/*
> +	 * If a patch is unsuccessfully applied, return
> +	 * error to the module loader.
> +	 */
> +	pr_warn("patch '%s' failed for module '%s', refusing to load module '%s'\n",
> +		patch->mod->name, obj->mod->name, obj->mod->name);
>  	klp_free_object_loaded(obj);
> +	mutex_unlock(&klp_mutex);
> +
> +	return ret;
>  }
>  
> -static int klp_module_notify(struct notifier_block *nb, unsigned long action,
> -			     void *data)
> +void klp_module_going(struct module *mod)
>  {
> -	int ret;
> -	struct module *mod = data;
>  	struct klp_patch *patch;
>  	struct klp_object *obj;
>  
> -	if (action != MODULE_STATE_COMING && action != MODULE_STATE_GOING)
> -		return 0;
> +	if (WARN_ON(mod->state != MODULE_STATE_GOING))
> +		return;

If we're removing patch 2/3, then mod->state isn't necessarily GOING.  I
think the check can probably just be removed altogether.

With that fixed,

Acked-by: Josh Poimboeuf <jpoimboe@redhat.com>

-- 
Josh

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2016-03-10 22:45 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2016-03-09 22:13 [PATCH 0/3] Livepatch module notifier cleanup Jessica Yu
2016-03-09 22:13 ` [PATCH 1/3] modules: split part of complete_formation() into prepare_coming_module() Jessica Yu
2016-03-10 22:41   ` Josh Poimboeuf
2016-03-09 22:13 ` [PATCH 2/3] modules: set mod->state to GOING before going notifiers are called Jessica Yu
2016-03-10  3:27   ` Rusty Russell
2016-03-10  5:08     ` Jessica Yu
2016-03-09 22:13 ` [PATCH 3/3] livepatch/module: remove livepatch module notifier Jessica Yu
2016-03-10 22:45   ` Josh Poimboeuf
2016-03-10  3:27 ` [PATCH 0/3] Livepatch module notifier cleanup Rusty Russell

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.