From: Jessica Yu <jeyu@redhat.com>
To: Josh Poimboeuf <jpoimboe@redhat.com>
Cc: Miroslav Benes <mbenes@suse.cz>,
Rusty Russell <rusty@rustcorp.com.au>,
Seth Jennings <sjenning@redhat.com>,
Jiri Kosina <jikos@kernel.org>, Vojtech Pavlik <vojtech@suse.com>,
linux-api@vger.kernel.org, live-patching@vger.kernel.org,
x86@kernel.org, linux-kernel@vger.kernel.org
Subject: Re: livepatch: reuse module loader code to write relocations
Date: Thu, 12 Nov 2015 15:22:44 -0500 [thread overview]
Message-ID: <20151112202243.GC5841@packer-debian-8-amd64.digitalocean.com> (raw)
In-Reply-To: <20151112174032.GG4038@treble.hsd1.ky.comcast.net>
+++ Josh Poimboeuf [12/11/15 11:40 -0600]:
>On Thu, Nov 12, 2015 at 04:27:01PM +0100, Miroslav Benes wrote:
>> On Wed, 11 Nov 2015, Jessica Yu wrote:
>>
>> > +++ Miroslav Benes [11/11/15 15:30 +0100]:
>> > > On Mon, 9 Nov 2015, Jessica Yu wrote:
>> > >
>> > > So I guess we don't need klp_reloc anymore.
>> >
>> > Yes, that's correct. I am noticing just now that I forgot to remove
>> > the klp_reloc struct definition from livepatch.h. That change will be
>> > reflected in v2...
>> >
>> > > If true, we should really
>> > > start thinking about proper documentation because there are going to be
>> > > plenty of assumptions about a patch module and we need to have it written
>> > > somewhere. Especially how the relocation sections look like.
>> >
>> > Agreed. As a first step the patch module format can perhaps be
>> > documented somewhere. Perhaps it's time we create
>> > Documentation/livepatch/? :-)
>>
>> Yes, I think so.
>>
>> > > > diff --git a/kernel/livepatch/core.c b/kernel/livepatch/core.c
>> > > > index 087a8c7..26c419f 100644
>> > > > --- a/kernel/livepatch/core.c
>> > > > +++ b/kernel/livepatch/core.c
>> > > > @@ -28,6 +28,8 @@
>> > > > #include <linux/list.h>
>> > > > #include <linux/kallsyms.h>
>> > > > #include <linux/livepatch.h>
>> > > > +#include <linux/elf.h>
>> > > > +#include <asm/cacheflush.h>
>> > > >
>> > > > /**
>> > > > * struct klp_ops - structure for tracking registered ftrace ops structs
>> > > > @@ -281,46 +283,54 @@ static int klp_find_external_symbol(struct module
>> > > > *pmod, const char *name,
>> > > > }
>> > > >
>> > > > static int klp_write_object_relocations(struct module *pmod,
>> > > > - struct klp_object *obj)
>> > > > + struct klp_object *obj,
>> > > > + struct klp_patch *patch)
>> > > > {
>> > > > - int ret;
>> > > > - struct klp_reloc *reloc;
>> > > > + int relindex, num_relas;
>> > > > + int i, ret = 0;
>> > > > + unsigned long addr;
>> > > > + unsigned int bind;
>> > > > + char *symname;
>> > > > + struct klp_reloc_sec *reloc_sec;
>> > > > + struct load_info *info;
>> > > > + Elf_Rela *rela;
>> > > > + Elf_Sym *sym, *symtab;
>> > > > + Elf_Shdr *symsect;
>> > > >
>> > > > if (WARN_ON(!klp_is_object_loaded(obj)))
>> > > > return -EINVAL;
>> > > >
>> > > > - if (WARN_ON(!obj->relocs))
>> > > > - return -EINVAL;
>> > > > -
>> > > > - for (reloc = obj->relocs; reloc->name; reloc++) {
>> > > > - if (!klp_is_module(obj)) {
>> > > > - ret = klp_verify_vmlinux_symbol(reloc->name,
>> > > > - reloc->val);
>> > > > - if (ret)
>> > > > - return ret;
>> > > > - } else {
>> > > > - /* module, reloc->val needs to be discovered */
>> > > > - if (reloc->external)
>> > > > - ret = klp_find_external_symbol(pmod,
>> > > > - reloc->name,
>> > > > - &reloc->val);
>> > > > - else
>> > > > - ret = klp_find_object_symbol(obj->mod->name,
>> > > > - reloc->name,
>> > > > - &reloc->val);
>> > > > - if (ret)
>> > > > - return ret;
>> > > > - }
>> > > > - ret = klp_write_module_reloc(pmod, reloc->type, reloc->loc,
>> > > > - reloc->val + reloc->addend);
>> > > > - if (ret) {
>> > > > - pr_err("relocation failed for symbol '%s' at 0x%016lx
>> > > > (%d)\n",
>> > > > - reloc->name, reloc->val, ret);
>> > > > - return ret;
>> > > > + info = pmod->info;
>> > > > + symsect = info->sechdrs + info->index.sym;
>> > > > + symtab = (void *)info->hdr + symsect->sh_offset;
>> > > > +
>> > > > + /* For each __klp_rela section for this object */
>> > > > + list_for_each_entry(reloc_sec, &obj->reloc_secs, list) {
>> > > > + relindex = reloc_sec->index;
>> > > > + num_relas = info->sechdrs[relindex].sh_size /
>> > > > sizeof(Elf_Rela);
>> > > > + rela = (Elf_Rela *) info->sechdrs[relindex].sh_addr;
>> > > > +
>> > > > + /* For each rela in this __klp_rela section */
>> > > > + for (i = 0; i < num_relas; i++, rela++) {
>> > > > + sym = symtab + ELF_R_SYM(rela->r_info);
>> > > > + symname = info->strtab + sym->st_name;
>> > > > + bind = ELF_ST_BIND(sym->st_info);
>> > > > +
>> > > > + if (sym->st_shndx == SHN_LIVEPATCH) {
>> > > > + if (bind == STB_LIVEPATCH_EXT)
>> > > > + ret = klp_find_external_symbol(pmod,
>> > > > symname, &addr);
>> > > > + else
>> > > > + ret =
>> > > > klp_find_object_symbol(obj->name, symname, &addr);
>> > > > + if (ret)
>> > > > + return ret;
>> > > > + sym->st_value = addr;
>> > > > + }
>> > > > }
>> > > > + ret = apply_relocate_add(info->sechdrs, info->strtab,
>> > > > + info->index.sym, relindex, pmod);
>> > > > }
>> > > >
>> > > > - return 0;
>> > > > + return ret;
>> > > > }
>> > >
>> > > Looking at this... do we even need reloc_secs in klp_object? Question is
>> > > whether we need more than one dynrela section for an object. If not then
>> > > the binding between klp_reloc_sec and an object is the only relevant thing
>> > > in the structure, be it index or objname. So we can replace the
>> > > list of structures with just the index in klp_object, or get rid of it
>> > > completely and rely on the name of dynrela section be something like
>> > > __klp_rela_{objname}.
>> >
>> > Hm, you bring up a good point. I think theoretically yes, it is
>> > possible to just have one klp_reloc_sec for each object and therefore
>> > a list is not required (I have not checked yet how difficult it would
>> > be to implement this on the kpatch-build side of things). However,
>> > considering the final format of the patch module, I think it is
>> > semantically clearer to leave it as a list, and for each object to
>> > possibly have more than one __klp_rela section.
>> >
>> > For example, say we are patching two functions in ext4. In my
>> > resulting kpatch module I will have two __klp_rela_ext4 sections, and
>> > they might look like this when we run readelf --sections:
>> >
>> > [34] __klp_rela_ext4.text.ext4_attr_store RELA ...
>> > [35] __klp_rela_ext4.text.ext4_attr_show RELA ...
>> >
>> > Then these two klp rela sections end up as two elements in the
>> > reloc_secs list for the ext4 patch object. I think this way, we can
>> > better tell which rela is being applied to what function. Might be
>> > easier to understand what's happening from the developer's point of
>> > view.
>> >
>> > > You see, we go through elf sections here which were preserved by module
>> > > loader. We even have relevant sections marked with SHF_RELA_LIVEPATCH. So
>> > > maybe all the stuff around klp_reloc_sec is not necessary.
>> > >
>> > > Thoughts?
>> >
>> > Ah, so this is where descriptive comments and documentation might have
>> > been useful :-) So I think we will still need to keep the
>> > klp_reloc_sec struct to help the patch module initialize. Though the
>> > name and objname fields aren't used in this patchset, they are used in
>> > the kpatch patch module code [1], where we iterate through each elf
>> > section, find the ones marked with SHF_RELA_LIVEPATCH, set the
>> > klp_reloc_sec's objname (which we find from the "name" field,
>> > formatted as __klp_rela_{objname}.text..). Once we have the objname
>> > set, we can then find the object to attach the reloc_sec to (i.e. add
>> > it to its list of reloc_secs).
>> >
>> > Hope that clears some things up.
>>
>> Ok, I'll try to explain myself and it is gonna be long. I'll try to
>> describe how we deal with dynrelas in klp today, how you use it in kpatch
>> (and this is the place where my knowledge can be wrong or obsolete), what
>> you propose and what I'd like to propose.
>>
>> 1. First let's look on what we have now.
>>
>> We have a patch module in which there is a section with all dynrelas
>> needed to be resolved (it was like this in kpatch some time ago and maybe
>> it is different now so just have a patience, I'll get to it). In the init
>> function of the module kpatch builds all the relevant info from dynrela
>> section. It goes through it, creates an array of klp_reloc for each object
>> and includes each dynrela record with an objname to the array of
>> klp_object with that objname. Later when we need to apply relocations for
>> patched object we just go through the list (array) of its dynrelas in
>> klp_object and call our arch-specific klp_write_module_reloc().
>>
>> Now this was probably changed in kpatch and you do not have one dynrela
>> section but one dynrela section for each patched function. Is that
>> correct? (and can you tell us what the reason for the change was? It might
>> be crucial because I might be missing something.). Which leads us to your
>> proposal...
>>
>> 2. So we have several dynrela section for one patched object. During init
>> function in a patch module kpatch once again builds needed structures from
>> these sections. Now they are called klp_reloc_sec and contain different
>> kind of info. There is no val, loc and such, only name of the symbol,
>> objname and index to dynrela section in ELF. So when you need to write
>> relocations for the patched object you go through all relevant dynrela
>> sections (because they are stored in the klp_object), all dynrela records
>> in each section and you resolve the undefined symbols. All needed info is
>> stored in ELF. Then you just call apply_relocate_add().
>>
>> 3. I propose to go one step further. I think we don't need klp_reloc_sec
>> if there is only one dynrela section for patched object (and I currently
>> cannot see why this is not possible. It is possible even with one dynrela
>> section for whole patch module, that is for all patched objects.).
>
>I think I agree that we don't need klp_reloc_sec, and that klp rela
>sections can presumably be discovered by iterating over the sections.
>
>But I don't think it matters much whether we have one klp rela section
>per object, or multiple rela sections per object. Either way, can't we
>find them when we iterate over the sections?
>
>For example, for one rela section per object, it could be named:
>
>__klp_rela.objname
>
>Or for multiple rela sections per object, they could be named:
>
>__klp_rela.objname.func1
>__klp_rela.objname.func2
>
>Either way, when iterating over the sections, we could just look for
>"__klp_rela.objname".
>
>All that said, I think I would vote for one rela section per object,
>just because it seems simpler.
Looking into this more, I think we do need one __klp_rela section per
function being patched. Each rela section is linked to the section to
which the relocations apply via the rela section's sh_info field. In
SHT_RELA sections, the sh_info field contains the section index to
which the relocs apply. We cannot have one single combined rela
section per object as the call to apply_relocate_add() simply won't
work, because we would have relocs that apply to different functions
(and hence different sections).
So I guess instead of a single field in klp_object specifying the
__klp_rela section index, we could probably just have an array of
section indices.
>>
>> In my proposal there would be nothing done in init function of the patched
>> module (albeit some optimization mentioned later). When you call
>> klp_write_object_relocations you would go through all ELF section and find
>> the relevant one for the object (it is marked with SHF_RELA_LIVEPATCH and
>> objname is in the name of the section. It is the same thing you do in 2.
>> in the init function.). Then you go through all dynrela records in the
>> section, you do the same things which you do in the proposed patch above,
>> and call apply_relocate_add.
>>
>> Now it would be crazy to go through all sections each time
>> klp_write_object_relocations is called (maybe it does not even matter but
>
>Why would that be crazy? To me it seems perfectly logical :-) It
>doesn't seem like a very expensive operation to me.
>
>> nevertheless). So klp_object could have an index to its ELF dynrela
>> section. This index can be retrieved in the init function the same way you
>> do all the stuff with klp_reloc_sec.
>>
>> If you insisted on more than one dynrela section for a patched object we
>> could have an array of indices there. Or whatever.
>>
>> It is almost the same as your proposal but in my opinion somewhat nicer.
>> We just use the info stored in ELF directly without unnecessary middle
>> layer (== klp_reloc_sec).
>>
>> Does it make sense? I hope it does. Would it work?
>
>--
>Josh
next prev parent reply other threads:[~2015-11-12 20:22 UTC|newest]
Thread overview: 88+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-11-10 4:45 [RFC PATCH 0/5] Arch-independent livepatch Jessica Yu
2015-11-10 4:45 ` [RFC PATCH 1/5] elf: add livepatch-specific elf constants Jessica Yu
2015-11-11 13:58 ` Petr Mladek
2015-11-12 15:33 ` Josh Poimboeuf
2015-11-12 15:45 ` Josh Poimboeuf
2015-11-13 6:49 ` Jessica Yu
2015-11-10 4:45 ` [RFC PATCH 2/5] module: save load_info for livepatch modules Jessica Yu
2015-11-11 8:08 ` Minfei Huang
2015-11-11 14:17 ` Miroslav Benes
2015-11-12 5:33 ` Jessica Yu
2015-11-12 10:24 ` Petr Mladek
2015-11-12 13:22 ` Miroslav Benes
2015-11-12 15:03 ` Petr Mladek
2015-11-12 17:05 ` Josh Poimboeuf
2015-11-12 22:17 ` Jessica Yu
2015-11-13 12:24 ` Miroslav Benes
2015-11-13 12:46 ` Miroslav Benes
2015-11-14 0:36 ` Jessica Yu
2015-11-16 12:12 ` Miroslav Benes
2015-11-13 12:56 ` Miroslav Benes
2015-11-14 2:09 ` Jessica Yu
2015-11-16 12:21 ` Miroslav Benes
2015-11-13 0:25 ` Jessica Yu
2015-11-11 14:31 ` [RFC PATCH 2/5] " Petr Mladek
2015-11-12 4:44 ` Jessica Yu
2015-11-12 10:05 ` Petr Mladek
2015-11-12 14:19 ` Miroslav Benes
2015-11-13 6:35 ` Jessica Yu
2015-11-13 13:07 ` Miroslav Benes
2015-11-13 8:20 ` Jessica Yu
2015-11-12 17:14 ` [RFC PATCH 2/5] " Josh Poimboeuf
2015-11-12 17:21 ` Josh Poimboeuf
2015-11-10 4:45 ` [RFC PATCH 3/5] livepatch: reuse module loader code to write relocations Jessica Yu
2015-11-10 8:13 ` Jiri Slaby
2015-11-11 14:30 ` Miroslav Benes
2015-11-11 20:07 ` Jessica Yu
2015-11-12 15:27 ` Miroslav Benes
2015-11-12 17:40 ` Josh Poimboeuf
2015-11-12 20:22 ` Jessica Yu [this message]
2015-11-12 20:32 ` Josh Poimboeuf
2015-11-13 7:15 ` Jessica Yu
2015-11-13 13:51 ` Miroslav Benes
2015-11-12 19:14 ` Jessica Yu
2015-11-12 20:35 ` Jessica Yu
2015-11-11 15:22 ` [RFC PATCH 3/5] " Petr Mladek
2015-11-11 18:27 ` Jessica Yu
2015-11-12 9:16 ` Petr Mladek
2015-11-12 17:59 ` [RFC PATCH 3/5] " Josh Poimboeuf
2015-11-10 4:45 ` [RFC PATCH 4/5] samples: livepatch: init reloc list and mark as klp module Jessica Yu
2015-11-10 8:15 ` Jiri Slaby
2015-11-10 13:50 ` Josh Poimboeuf
2015-11-10 18:37 ` Jessica Yu
2015-11-11 15:42 ` [RFC PATCH 4/5] " Petr Mladek
2015-11-12 6:02 ` Jessica Yu
2015-11-12 10:44 ` Miroslav Benes
2015-11-10 4:45 ` [RFC PATCH 5/5] livepatch: x86: remove unused relocation code Jessica Yu
2015-11-11 15:48 ` Petr Mladek
2015-11-12 18:01 ` Josh Poimboeuf
2015-11-11 14:00 ` [RFC PATCH 0/5] Arch-independent livepatch Miroslav Benes
2015-11-11 16:28 ` Josh Poimboeuf
2015-12-01 4:21 [RFC PATCH v2 0/6] (mostly) " Jessica Yu
2015-12-01 4:21 ` [RFC PATCH v2 4/6] livepatch: reuse module loader code to write relocations Jessica Yu
2015-12-01 8:43 ` Jessica Yu
2015-12-08 18:38 ` [RFC PATCH v2 4/6] " Josh Poimboeuf
2015-12-09 19:10 ` Jessica Yu
2015-12-10 14:28 ` Josh Poimboeuf
2015-12-10 21:33 ` Jessica Yu
2015-12-10 21:41 ` Josh Poimboeuf
2015-12-10 22:07 ` Jessica Yu
2015-12-16 5:40 ` Jessica Yu
2015-12-16 12:59 ` Miroslav Benes
2015-12-16 19:14 ` Jessica Yu
2015-12-17 15:45 ` Petr Mladek
2015-12-21 5:57 ` Jessica Yu
2016-01-08 19:28 [RFC PATCH v3 0/6] (mostly) Arch-independent livepatch Jessica Yu
2016-01-08 19:28 ` [RFC PATCH v3 4/6] livepatch: reuse module loader code to write relocations Jessica Yu
2016-01-11 21:33 ` Josh Poimboeuf
2016-01-11 22:35 ` Jessica Yu
2016-01-12 3:05 ` Josh Poimboeuf
2016-01-12 9:12 ` Petr Mladek
2016-01-14 5:07 ` Jessica Yu
2016-01-12 16:40 ` [RFC PATCH v3 4/6] " Miroslav Benes
2016-01-14 3:49 ` Jessica Yu
2016-01-14 9:04 ` Miroslav Benes
2016-01-13 9:19 ` [RFC PATCH v3 4/6] " Miroslav Benes
2016-01-13 18:39 ` Jessica Yu
2016-01-14 9:10 ` Miroslav Benes
2016-02-04 1:11 [RFC PATCH v4 0/6] (mostly) Arch-independent livepatch Jessica Yu
2016-02-04 1:11 ` [RFC PATCH v4 4/6] livepatch: reuse module loader code to write relocations Jessica Yu
2016-02-08 20:26 ` Josh Poimboeuf
2016-02-10 0:56 ` Jessica Yu
2016-02-09 14:01 ` [RFC PATCH v4 4/6] " Petr Mladek
2016-02-10 1:21 ` Jessica Yu
2016-03-16 19:47 [PATCH v5 0/6] (mostly) Arch-independent livepatch Jessica Yu
2016-03-16 19:47 ` [PATCH v5 4/6] livepatch: reuse module loader code to write relocations Jessica Yu
2016-03-21 13:55 ` Miroslav Benes
2016-03-21 19:18 ` Jessica Yu
2016-03-21 19:24 ` Josh Poimboeuf
2016-03-21 21:16 ` Jiri Kosina
2016-03-21 21:34 ` Josh Poimboeuf
2016-03-21 22:02 ` Jiri Kosina
2016-03-22 19:00 ` Jessica Yu
2016-03-21 16:31 ` [PATCH v5 4/6] " Petr Mladek
2016-03-21 16:46 ` Josh Poimboeuf
2016-03-21 17:36 ` Josh Poimboeuf
2016-03-21 18:07 ` Jessica Yu
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=20151112202243.GC5841@packer-debian-8-amd64.digitalocean.com \
--to=jeyu@redhat.com \
--cc=jikos@kernel.org \
--cc=jpoimboe@redhat.com \
--cc=linux-api@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=live-patching@vger.kernel.org \
--cc=mbenes@suse.cz \
--cc=rusty@rustcorp.com.au \
--cc=sjenning@redhat.com \
--cc=vojtech@suse.com \
--cc=x86@kernel.org \
/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®