All of lore.kernel.org
 help / color / mirror / Atom feed
From: Jessica Yu <jeyu@redhat.com>
To: Josh Poimboeuf <jpoimboe@redhat.com>
Cc: Jiri Kosina <jikos@kernel.org>,
	Chris J Arges <chris.j.arges@canonical.com>,
	Miroslav Benes <mbenes@suse.cz>,
	eugene.shatokhin@rosalab.ru, 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: Mon, 4 Apr 2016 13:58:45 -0400	[thread overview]
Message-ID: <20160404175844.GA18550@packer-debian-8-amd64.digitalocean.com> (raw)
In-Reply-To: <20160404161428.3qap2i4vpgda66iw@treble.redhat.com>

+++ Josh Poimboeuf [04/04/16 11:14 -0500]:
>On Fri, Apr 01, 2016 at 09:35:34PM +0200, Jiri Kosina wrote:
>> On Fri, 1 Apr 2016, Chris J Arges wrote:
>>
>> > Loading, please wait...
>> > starting version 229
>> > [    1.182869] random: udevadm urandom read with 2 bits of entropy available
>> > [    1.241404] BUG: unable to handle kernel paging request at ffffffffc000f35f
>>
>> Gah, we surely can't change pages with RO PTE. Thanks for such a prompt
>> testing. You do have CONFIG_DEBUG_SET_MODULE_RONX set, don't you?
>>
>> The patch below should fix that by marking the module RO (and relevant
>> parts NX) only when it's guaranteed that .text is not going to be modified
>> any more (and includes the error handling fix Miroslav spotted as well).
>>
>> Thanks.
>>
>>
>>
>> diff --git a/kernel/module.c b/kernel/module.c
>> index 5f71aa6..430606d 100644
>> --- a/kernel/module.c
>> +++ b/kernel/module.c
>> @@ -3211,7 +3211,7 @@ int __weak module_finalize(const Elf_Ehdr *hdr,
>>  	return 0;
>>  }
>>
>> -static int post_relocation(struct module *mod, const struct load_info *info)
>> +static void post_relocation(struct module *mod, const struct load_info *info)
>>  {
>>  	/* Sort exception table now relocations are done. */
>>  	sort_extable(mod->extable, mod->extable + mod->num_exentries);
>> @@ -3222,9 +3222,6 @@ static int post_relocation(struct module *mod, const struct load_info *info)
>>
>>  	/* Setup kallsyms-specific fields. */
>>  	add_kallsyms(mod, info);
>> -
>> -	/* Arch-specific module finalizing. */
>> -	return module_finalize(info->hdr, info->sechdrs, mod);
>>  }
>>
>>  /* Is this module of this name done loading?  No locks held. */
>> @@ -3441,10 +3438,6 @@ static int complete_formation(struct module *mod, struct load_info *info)
>>  	/* This relies on module_mutex for list integrity. */
>>  	module_bug_finalize(info->hdr, info->sechdrs, mod);
>>
>> -	/* Set RO and NX regions */
>> -	module_enable_ro(mod);
>> -	module_enable_nx(mod);
>> -
>>  	/* Mark state as coming so strong_try_module_get() ignores us,
>>  	 * but kallsyms etc. can see us. */
>>  	mod->state = MODULE_STATE_COMING;
>> @@ -3562,9 +3555,7 @@ static int load_module(struct load_info *info, const char __user *uargs,
>>  	if (err < 0)
>>  		goto free_modinfo;
>>
>> -	err = post_relocation(mod, info);
>> -	if (err < 0)
>> -		goto free_modinfo;
>> +	post_relocation(mod, info);
>>
>>  	flush_module_icache(mod);
>>
>> @@ -3589,6 +3580,15 @@ static int load_module(struct load_info *info, const char __user *uargs,
>>  	if (err)
>>  		goto bug_cleanup;
>>
>> +	/* Arch-specific module finalizing. */
>> +	err = module_finalize(info->hdr, info->sechdrs, mod);
>> +	if (err)
>> +		goto coming_cleanup;
>> +
>> +	/* Set RO and NX regions */
>> +	module_enable_ro(mod);
>> +	module_enable_nx(mod);
>> +
>>  	/* 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,
>
>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.

Yup, exactly, the crux of the issue is the fact that we're hacking the
module load order and delying certain operations (e.g. applying
relocations) in order to allow patching of a not-yet-loaded module.

In this case, the problem can be briefly summarized as follows:
For any patch module, apply_paravirt/alternatives needs to come after
apply_relocate_add (recall that these operations affect the
replacement functions in the patch module). Right now we have it the
other way around: apply_paravirt() is patching our replacement
functions in module_finalize() before the to-be-patched module is
loaded and apply_relocate_add() can be called. 

The hack fix I had involved delaying the apply_paravirt() call
(basically calling is_livepatch_module() in the x86 code, and skipping
the paravirt/alternative calls if true), and when the to-be-patched
module loads, having livepatch finish up those apply_{paravirt,alternative}
calls just before apply_relocate_add(). Unfortunately this involved
adding arch-specific code :-\, but I'm not sure there are really any
elegant solutions out there to this problem.

Jessica

  reply	other threads:[~2016-04-04 17:58 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 [this message]
2016-04-05 13:07               ` Miroslav Benes
2016-04-05 13:53                 ` Evgenii Shatokhin
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=20160404175844.GA18550@packer-debian-8-amd64.digitalocean.com \
    --to=jeyu@redhat.com \
    --cc=chris.j.arges@canonical.com \
    --cc=eugene.shatokhin@rosalab.ru \
    --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.