From: Minfei Huang <mnfhuang@gmail.com>
To: Minfei Huang <mhuang@redhat.com>
Cc: jpoimboe@redhat.com, sjenning@redhat.com, jkosina@suse.cz,
vojtech@suse.cz, live-patching@vger.kernel.org,
linux-kernel@vger.kernel.org
Subject: Re: [PATCH] livepatch: Fix the issue to make livepatch enable/disable patch correctly
Date: Wed, 22 Jul 2015 21:17:22 +0800 [thread overview]
Message-ID: <20150722131603.GA22351@t440s.lenovo> (raw)
In-Reply-To: <1436950506-5252-1-git-send-email-mhuang@redhat.com>
Could someone help to review this patch?
Thanks
Minfei
On 07/15/15 at 04:55pm, Minfei Huang wrote:
> From: Minfei Huang <mnfhuang@gmail.com>
>
> Livepatch will obey the stacking rule to enable/disable the patch. It
> only allows to enable the patch, when it is the fist disabled patch,
> disable the patch, when it is the last enabled patch.
>
> In the livepatch code, it uses list to gather the all of the patches.
> And we do not know whether the previous/next patch is patched to the
> same modules or vmlinux in that way.
>
> According to above rule, livepatch will make incorrect decision to
> enable/disable the patch. Following is an example to show how livepatch
> does.
>
> - install the livepatch example module which is in samples/livepatch.
> - install the third part kernel module
> - install the livepatch module which is patched to the third part module
> - disable the livepatch example module
>
> We can find that we can not disable livepatch example module, although
> it is the last enabled patch.
>
> To fix this issue, we will find the corresponding patch which is patched
> to the same modules or vmlinux, when we enable/disable the patch.
>
> Signed-off-by: Minfei Huang <mnfhuang@gmail.com>
> ---
> kernel/livepatch/core.c | 55 +++++++++++++++++++++++++++++++++++++++++++++----
> 1 file changed, 51 insertions(+), 4 deletions(-)
>
> diff --git a/kernel/livepatch/core.c b/kernel/livepatch/core.c
> index 6e53441..d59aec7 100644
> --- a/kernel/livepatch/core.c
> +++ b/kernel/livepatch/core.c
> @@ -429,6 +429,27 @@ err:
> return ret;
> }
>
> +static bool is_patched_to_same(struct klp_patch *p1, struct klp_patch *p2)
> +{
> + struct klp_object *obj1, *obj2;
> + bool is_mod1, is_mod2;
> +
> + klp_for_each_object(p1, obj1) {
> + klp_for_each_object(p2, obj2) {
> + is_mod1 = !!klp_is_module(obj1);
> + is_mod2 = !!klp_is_module(obj2);
> +
> + if (is_mod1 && is_mod2) {
> + if (!strcmp(obj1->name, obj2->name))
> + return true;
> + } else if (!is_mod1 && !is_mod2)
> + return true;
> + }
> + }
> +
> + return false;
> +}
> +
> static void klp_disable_object(struct klp_object *obj)
> {
> struct klp_func *func;
> @@ -463,13 +484,26 @@ static int klp_enable_object(struct klp_object *obj)
> return 0;
> }
>
> +struct klp_patch *get_next_patch(struct klp_patch *patch)
> +{
> + struct klp_patch *p = patch;
> +
> + list_for_each_entry_continue(p, &klp_patches, list) {
> + if (is_patched_to_same(p, patch))
> + return p;
> + }
> +
> + return NULL;
> +}
> +
> static int __klp_disable_patch(struct klp_patch *patch)
> {
> + struct klp_patch *p;
> struct klp_object *obj;
>
> /* enforce stacking: only the last enabled patch can be disabled */
> - if (!list_is_last(&patch->list, &klp_patches) &&
> - list_next_entry(patch, list)->state == KLP_ENABLED)
> + p = get_next_patch(patch);
> + if (p && (p->state == KLP_ENABLED))
> return -EBUSY;
>
> pr_notice("disabling patch '%s'\n", patch->mod->name);
> @@ -516,8 +550,21 @@ err:
> }
> EXPORT_SYMBOL_GPL(klp_disable_patch);
>
> +struct klp_patch *get_prev_patch(struct klp_patch *patch)
> +{
> + struct klp_patch *p = patch;
> +
> + list_for_each_entry_continue_reverse(p, &klp_patches, list) {
> + if (is_patched_to_same(p, patch))
> + return p;
> + }
> +
> + return NULL;
> +}
> +
> static int __klp_enable_patch(struct klp_patch *patch)
> {
> + struct klp_patch *p;
> struct klp_object *obj;
> int ret;
>
> @@ -525,8 +572,8 @@ static int __klp_enable_patch(struct klp_patch *patch)
> return -EINVAL;
>
> /* enforce stacking: only the first disabled patch can be enabled */
> - if (patch->list.prev != &klp_patches &&
> - list_prev_entry(patch, list)->state == KLP_DISABLED)
> + p = get_prev_patch(patch);
> + if (p && (p->state == KLP_DISABLED))
> return -EBUSY;
>
> pr_notice_once("tainting kernel with TAINT_LIVEPATCH\n");
> --
> 2.2.2
>
next prev parent reply other threads:[~2015-07-22 13:17 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-07-15 8:55 Minfei Huang
2015-07-22 13:17 ` Minfei Huang [this message]
2015-07-22 14:40 ` Josh Poimboeuf
2015-07-23 4:02 ` Minfei Huang
2015-07-23 18:07 ` Revisiting patch dependencies Josh Poimboeuf
2015-07-24 1:23 ` Minfei Huang
2015-07-24 20:44 ` Jiri Kosina
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=20150722131603.GA22351@t440s.lenovo \
--to=mnfhuang@gmail.com \
--cc=jkosina@suse.cz \
--cc=jpoimboe@redhat.com \
--cc=linux-kernel@vger.kernel.org \
--cc=live-patching@vger.kernel.org \
--cc=mhuang@redhat.com \
--cc=sjenning@redhat.com \
--cc=vojtech@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
all inboxes | Powered by JetHome®