linux-kernel.vger.kernel.org archive mirror
 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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).