All of lore.kernel.org
 help / color / mirror / Atom feed
From: Evgenii Shatokhin <eshatokhin@virtuozzo.com>
To: Miroslav Benes <mbenes@suse.cz>, Josh Poimboeuf <jpoimboe@redhat.com>
Cc: Jiri Kosina <jikos@kernel.org>,
	Chris J Arges <chris.j.arges@canonical.com>, <jeyu@redhat.com>,
	<live-patching@vger.kernel.org>,
	Linux Kernel Mailing List <linux-kernel@vger.kernel.org>,
	<pmladek@suse.cz>
Subject: Re: Bug with paravirt ops and livepatches
Date: Tue, 5 Apr 2016 16:53:49 +0300	[thread overview]
Message-ID: <5703C36D.4090306@virtuozzo.com> (raw)
In-Reply-To: <alpine.LNX.2.00.1604051445530.1180@pobox.suse.cz>

05.04.2016 16:07, Miroslav Benes пишет:
> On Mon, 4 Apr 2016, Josh Poimboeuf wrote:
>
>> So I think this doesn't fix the problem.  Dynamic relocations are
>> applied to the "patch module", whereas the above code deals with the
>> initialization order of the "patched module".  This distinction
>> originally confused me as well, until Jessica set me straight.
>>
>> Let me try to illustrate the problem with an example.  Imagine you have
>> a patch module P which applies a patch to module M.  P replaces M's
>> function F with a new function F', which uses paravirt ops.
>>
>> 1) Patch P is loaded before module M.  P's new function F' has an
>>     instruction which is patched by apply_paravirt(), even though the
>>     patch hasn't been applied yet.
>>
>> 2) Module M is loaded.  Before applying the patch, livepatch tries to
>>     apply a klp_reloc to the instruction in F' which was already patched
>>     by apply_paravirt() in step 1.  This results in undefined behavior
>>     because it tries to patch the original instruction but instead
>>     patches the new paravirt instruction.
>>
>> So the above patch makes no difference because the paravirt module
>> loading order doesn't really matter.
>
> Hi,
>
> we are trying really hard to understand the actual culprit here and as it
> is quite confusing I have several questions/comments...
>
> 1. can you provide dynrela sections of the patch module from
> https://github.com/dynup/kpatch/issues/580? What is interesting is that
> kvm_arch_vm_ioctl() function contains rela records only for trivial (==
> exported) symbols from the first look. The problem should be there only if
> you want to patch a function which reference some paravirt_ops unexported
> symbol. For that symbol dynrela should be created.

As far as I understand it, create-diff-object does not check if a symbol 
is exported or not when a patch for a module rather than for vmlinux is 
being prepared.

In such cases, it only checks if the referenced global symbol is defined 
somewhere in that module and if not, creates a dynrela for it.

The code is in kpatch_create_dynamic_rela_sections() from 
https://github.com/dynup/kpatch/blob/master/kpatch-build/create-diff-object.c.

>
> 2. I am almost 100 percent sure that the second problem Chris mentions in
> github post is something different. If he patches only kvm_arch_vm_ioctl()
> so that it calls his exported __kvm_arch_vm_ioctl() duplicate there is no
> problem. Because it is a trivial livepatching case. There are no dynrelas
> and no alternatives in the patch module. The crash is suspicious and we
> have a problem somewhere. Chris, can you please provide more info about
> that? That is how exactly you used kallsyms_lookup_name() and so on...
>
> 3. Now I'll try to explain what really happens here... because of 1. and
> the way the alternatives and relocations are implemented the only
> problematic case is when one wants to patch a module which introduces its
> own alternatives. Which is probably the case of KVM. Why?
>
> When alternative is used, the call to some pv_*_ops.function is placed
> somewhere. The address of this location is stored in a separate elf
> section and when apply_paravirt() is called it takes the address and
> place the new code there (or it does not, it depends :)). When the
> alternative is in some module and pv_*_ops is exported, which is the
> usual case, there is no problem. No dynrela needs to be used when a user
> wants to patch such function with the alternative.
>
> The only problem is when the function uses unexported pv_*_ops (or some
> other alternative symbol) from its own object file. When the user wants to
> patch this one there is a need for dynrela.
>
> So what really happens is that we load a patch module, we do not apply
> our relocations but we do apply alternatives to the patch module, which is
> problematic because there is a reference to something which is not yet
> resolved (that is unexported pv_*_ops). When a patched module arrives we
> happily resolve relocations but since we do not apply alternatives again
> there is a rubbish in the patching code.
>
> Is this all correct?
>
>> Jessica proposed some novel fixes here:
>>
>>     https://github.com/dynup/kpatch/issues/580#issuecomment-183001652
>
> Yes, I think that fix should be the same we have for relocations. To
> postpone the alternatives applications. Maybe it is even possible to do it
> in a similar way. And yes on one hand it is gonna be ugly, on the other
> hand it is gonna be consistent with relocations.
>
>> I think the *real* problem here (and one that we've seen before) is that
>> we have a feature which allows you to load a patch to a module before
>> loading the module itself.  That really goes against the grain of how
>> module dependencies work.  It has already given us several headaches and
>> it makes the livepatch code a lot more complex.
>>
>> I really think we need to take another hard look about whether it's
>> really worth it.  My current feeling is that it's not.
>
> I can only say that maybe about 1/3 of kgraft patches we currently have
> are for modules (1/3 is probably not correct but it is definitely
> non-trivial number). It would be really unfortunate to load all the
> to-be-patched modules when a patch module is applied.
>
> This does not mean that we cannot solve it in another way as you propose
> below. I have to think about it.
>
> Miroslav
>
>> If we were able to get rid of that "feature", yes, the livepatch code
>> would be simpler, but there might be another awesome benefit: I suspect
>> we'd also be able to get rid of the need for specialized patch creation
>> tooling like kpatch-build.  Instead I think we could just specify
>> klp_relocs info in the source code of the patch, and just use kbuild to
>> build the patch module.  Not only would the livepatch code be simpler
>> (and much easier to wrap your head around), but the user space tooling
>> could be *vastly* simpler.
>>
>> Of course, removing that feature might create some headaches for the
>> user.  It is nice to be able to load a big cumulative patch without
>> having to load all the dependencies first.  But maybe there are things
>> we could do to make the dependency problem more manageable.  e.g.,
>> splitting up patch modules to be per-object?  requiring the user to load
>> modules they don't need?  patching or replacing the module on disk?
>> copying the new module to a new locaiton and telling modprobe where to
>> find it?
>>
>> I don't have all the answers but I think we should take a hard look at
>> some of these other approaches.
>>
>> --
>> Josh
>>

Regards,
Evgenii

  reply	other threads:[~2016-04-05 17:26 UTC|newest]

Thread overview: 25+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-03-29 12:05 Bug with paravirt ops and livepatches Chris J Arges
2016-03-29 13:01 ` Miroslav Benes
2016-03-29 13:05   ` Jiri Kosina
2016-04-01 15:01     ` Jiri Kosina
2016-04-01 15:46       ` Miroslav Benes
2016-04-01 16:01         ` Chris J Arges
2016-04-01 19:07         ` Chris J Arges
2016-04-01 19:35           ` Jiri Kosina
2016-04-04 16:14             ` Josh Poimboeuf
2016-04-04 17:58               ` Jessica Yu
2016-04-05 13:07               ` Miroslav Benes
2016-04-05 13:53                 ` Evgenii Shatokhin [this message]
2016-04-05 14:24                 ` Josh Poimboeuf
2016-04-05 19:19                 ` Jessica Yu
2016-04-06  8:30                   ` Miroslav Benes
2016-04-06  8:43                     ` Miroslav Benes
2016-04-06  9:09                       ` Miroslav Benes
2016-04-06 17:23                       ` Jessica Yu
2016-04-06 16:55                   ` Jessica Yu
2016-04-05 23:27                 ` Chris J Arges
2016-04-06  9:09                   ` Miroslav Benes
2016-04-06 10:38                     ` Chris J Arges
2016-04-06 12:09                       ` Miroslav Benes
2016-04-06 13:48                         ` Chris J Arges
2016-04-06 14:17                           ` Miroslav Benes

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=5703C36D.4090306@virtuozzo.com \
    --to=eshatokhin@virtuozzo.com \
    --cc=chris.j.arges@canonical.com \
    --cc=jeyu@redhat.com \
    --cc=jikos@kernel.org \
    --cc=jpoimboe@redhat.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=live-patching@vger.kernel.org \
    --cc=mbenes@suse.cz \
    --cc=pmladek@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 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.