From: Petr Mladek <pmladek@suse.com>
To: Jiri Kosina <jikos@kernel.org>,
Josh Poimboeuf <jpoimboe@redhat.com>,
Miroslav Benes <mbenes@suse.cz>
Cc: Jason Baron <jbaron@akamai.com>,
Joe Lawrence <joe.lawrence@redhat.com>,
Jessica Yu <jeyu@kernel.org>,
Evgenii Shatokhin <eshatokhin@virtuozzo.com>,
live-patching@vger.kernel.org, linux-kernel@vger.kernel.org,
Petr Mladek <pmladek@suse.com>
Subject: [PATCH 4/8] livepatch: Add an extra flag to distinguish registered patches
Date: Fri, 23 Mar 2018 13:00:24 +0100 [thread overview]
Message-ID: <20180323120028.31451-5-pmladek@suse.com> (raw)
In-Reply-To: <20180323120028.31451-1-pmladek@suse.com>
The initial implementation of the atomic replace feature keeps the replaced
patches on the stack. But people would like to remove the replaced patches
from different reasons that will be described in the following patch.
This patch is just a small preparation step. We will need to keep
the replaced patches registered even when they are not longer on the stack.
It is because they are typically unregistered by the module exit script.
Therefore we need to detect the registered patches another way. We could
not use kobj.state_initialized because it is racy. The kobject is destroyed
by an asynchronous call and could not be synchronized using klp_mutex.
This patch solves the problem by adding a flag into struct klp_patch.
It is manipulated under klp_mutex and therefore it is safe. It is easy
to understand and it is enough in most situations.
The function klp_is_patch_registered() is not longer needed. Though
it was renamed to klp_is_patch_on_stack() and used in __klp_enable_patch()
as a new sanity check.
This patch does not change the existing behavior.
Signed-off-by: Petr Mladek <pmladek@suse.com>
Cc: Josh Poimboeuf <jpoimboe@redhat.com>
Cc: Jessica Yu <jeyu@kernel.org>
Cc: Jiri Kosina <jikos@kernel.org>
Cc: Miroslav Benes <mbenes@suse.cz>
Cc: Jason Baron <jbaron@akamai.com>
---
include/linux/livepatch.h | 2 ++
kernel/livepatch/core.c | 24 ++++++++++++++++++------
2 files changed, 20 insertions(+), 6 deletions(-)
diff --git a/include/linux/livepatch.h b/include/linux/livepatch.h
index f28af280f9e0..d6e6d8176995 100644
--- a/include/linux/livepatch.h
+++ b/include/linux/livepatch.h
@@ -150,6 +150,7 @@ struct klp_object {
* @list: list node for global list of registered patches
* @kobj: kobject for sysfs resources
* @obj_list: dynamic list of the object entries
+ * @registered: reliable way to check registration status
* @enabled: the patch is enabled (but operation may be incomplete)
* @finish: for waiting till it is safe to remove the patch module
*/
@@ -163,6 +164,7 @@ struct klp_patch {
struct list_head list;
struct kobject kobj;
struct list_head obj_list;
+ bool registered;
bool enabled;
struct completion finish;
};
diff --git a/kernel/livepatch/core.c b/kernel/livepatch/core.c
index 18c400bd9a33..70c67a834e9a 100644
--- a/kernel/livepatch/core.c
+++ b/kernel/livepatch/core.c
@@ -45,6 +45,11 @@
*/
DEFINE_MUTEX(klp_mutex);
+/*
+ * Stack of patches. It defines the order in which the patches can be enabled.
+ * Only patches on this stack might be enabled. New patches are added when
+ * registered. They are removed when they are unregistered.
+ */
static LIST_HEAD(klp_patches);
static struct kobject *klp_root_kobj;
@@ -97,7 +102,7 @@ static void klp_find_object_module(struct klp_object *obj)
mutex_unlock(&module_mutex);
}
-static bool klp_is_patch_registered(struct klp_patch *patch)
+static bool klp_is_patch_on_stack(struct klp_patch *patch)
{
struct klp_patch *mypatch;
@@ -378,7 +383,7 @@ int klp_disable_patch(struct klp_patch *patch)
mutex_lock(&klp_mutex);
- if (!klp_is_patch_registered(patch)) {
+ if (!patch->registered) {
ret = -EINVAL;
goto err;
}
@@ -407,7 +412,11 @@ static int __klp_enable_patch(struct klp_patch *patch)
if (WARN_ON(patch->enabled))
return -EINVAL;
- /* enforce stacking: only the first disabled patch can be enabled */
+ /* Enforce stacking. */
+ if (!klp_is_patch_on_stack(patch))
+ return -EINVAL;
+
+ /* Only the first disabled patch can be enabled. */
if (patch->list.prev != &klp_patches &&
!list_prev_entry(patch, list)->enabled)
return -EBUSY;
@@ -478,7 +487,7 @@ int klp_enable_patch(struct klp_patch *patch)
mutex_lock(&klp_mutex);
- if (!klp_is_patch_registered(patch)) {
+ if (!patch->registered) {
ret = -EINVAL;
goto err;
}
@@ -519,7 +528,7 @@ static ssize_t enabled_store(struct kobject *kobj, struct kobj_attribute *attr,
mutex_lock(&klp_mutex);
- if (!klp_is_patch_registered(patch)) {
+ if (!patch->registered) {
/*
* Module with the patch could either disappear meanwhile or is
* not properly initialized yet.
@@ -528,6 +537,7 @@ static ssize_t enabled_store(struct kobject *kobj, struct kobj_attribute *attr,
goto err;
}
+
if (patch->enabled == enabled) {
/* already in requested state */
ret = -EINVAL;
@@ -1004,6 +1014,7 @@ static int klp_init_patch(struct klp_patch *patch)
}
list_add_tail(&patch->list, &klp_patches);
+ patch->registered = true;
mutex_unlock(&klp_mutex);
@@ -1034,7 +1045,7 @@ int klp_unregister_patch(struct klp_patch *patch)
mutex_lock(&klp_mutex);
- if (!klp_is_patch_registered(patch)) {
+ if (!patch->registered) {
ret = -EINVAL;
goto err;
}
@@ -1045,6 +1056,7 @@ int klp_unregister_patch(struct klp_patch *patch)
}
klp_free_patch(patch);
+ patch->registered = false;
mutex_unlock(&klp_mutex);
--
2.13.6
next prev parent reply other threads:[~2018-03-23 12:01 UTC|newest]
Thread overview: 21+ messages / expand[flat|nested] mbox.gz Atom feed top
2018-03-23 12:00 [PATCH 0/8] livepatch: Atomic replace feature Petr Mladek
2018-03-23 12:00 ` [PATCH 1/8] livepatch: Use lists to manage patches, objects and functions Petr Mladek
2018-03-23 12:00 ` [PATCH 2/8] livepatch: Free only structures with initialized kobject Petr Mladek
2018-03-23 12:00 ` [PATCH 3/8] livepatch: Add atomic replace Petr Mladek
2018-04-06 22:05 ` Josh Poimboeuf
2018-04-09 13:53 ` Miroslav Benes
2018-04-10 9:31 ` Petr Mladek
2018-03-23 12:00 ` Petr Mladek [this message]
2018-04-06 22:06 ` [PATCH 4/8] livepatch: Add an extra flag to distinguish registered patches Josh Poimboeuf
2018-04-09 14:02 ` Miroslav Benes
2018-04-10 10:56 ` Petr Mladek
2018-04-10 17:53 ` Josh Poimboeuf
2018-03-23 12:00 ` [PATCH 5/8] livepatch: Remove replaced patches from the stack Petr Mladek
2018-03-23 12:00 ` [PATCH 6/8] livepatch: Remove Nop structures when unused Petr Mladek
2018-04-06 22:07 ` Josh Poimboeuf
2018-04-10 9:14 ` Miroslav Benes
2018-04-10 11:09 ` Petr Mladek
2018-03-23 12:00 ` [PATCH 7/8] livepatch: Allow to replace even disabled patches Petr Mladek
2018-03-23 12:00 ` [PATCH 8/8] livepatch: Atomic replace and cumulative patches documentation Petr Mladek
2018-03-23 14:54 ` [PATCH 0/8] livepatch: Atomic replace feature Petr Mladek
2018-04-06 22:10 ` Josh Poimboeuf
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20180323120028.31451-5-pmladek@suse.com \
--to=pmladek@suse.com \
--cc=eshatokhin@virtuozzo.com \
--cc=jbaron@akamai.com \
--cc=jeyu@kernel.org \
--cc=jikos@kernel.org \
--cc=joe.lawrence@redhat.com \
--cc=jpoimboe@redhat.com \
--cc=linux-kernel@vger.kernel.org \
--cc=live-patching@vger.kernel.org \
--cc=mbenes@suse.cz \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox